summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-13 05:27:47 +0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-13 05:27:47 +0400
commitb981d8b3f5e008ff10d993be633ad00564fc22cd (patch)
treee292dc07b22308912cf6a58354a608b9e5e8e1fd /drivers/media
parentb11d2127c4893a7315d1e16273bc8560049fa3ca (diff)
parent2b9e0aae1d50e880c58d46788e5e3ebd89d75d62 (diff)
downloadlinux-b981d8b3f5e008ff10d993be633ad00564fc22cd.tar.xz
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/macintosh/adbhid.c
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/Kconfig74
-rw-r--r--drivers/media/common/Kconfig2
-rw-r--r--drivers/media/common/ir-functions.c28
-rw-r--r--drivers/media/common/ir-keymaps.c62
-rw-r--r--drivers/media/common/saa7146_core.c42
-rw-r--r--drivers/media/common/saa7146_fops.c5
-rw-r--r--drivers/media/common/saa7146_i2c.c23
-rw-r--r--drivers/media/common/saa7146_vbi.c9
-rw-r--r--drivers/media/common/saa7146_video.c19
-rw-r--r--drivers/media/dvb/b2c2/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c4
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c7
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig2
-rw-r--r--drivers/media/dvb/bt8xx/Makefile2
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c1
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h7
-rw-r--r--drivers/media/dvb/bt8xx/dst.c2
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c6
-rw-r--r--drivers/media/dvb/cinergyT2/Makefile2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c28
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c105
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c7
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c125
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h15
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c37
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c56
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig31
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile8
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-fe.c1488
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-remote.c157
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-script.h203
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.c1141
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.h3496
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c18
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700.h5
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c23
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c676
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c53
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb.h1
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c21
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c28
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c79
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h32
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h11
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.c7
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk-fe.c84
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c93
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.h32
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c127
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.h5
-rw-r--r--drivers/media/dvb/dvb-usb/opera1.c25
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c8
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig33
-rw-r--r--drivers/media/dvb/frontends/Makefile6
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c1
-rw-r--r--drivers/media/dvb/frontends/cx22700.c1
-rw-r--r--drivers/media/dvb/frontends/cx22702.c1
-rw-r--r--drivers/media/dvb/frontends/cx24110.c1
-rw-r--r--drivers/media/dvb/frontends/cx24123.c3
-rw-r--r--drivers/media/dvb/frontends/dib0070.c580
-rw-r--r--drivers/media/dvb/frontends/dib0070.h44
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c1
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c192
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c727
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c908
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h14
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.h57
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c357
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h73
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c1
-rw-r--r--drivers/media/dvb/frontends/isl6421.c1
-rw-r--r--drivers/media/dvb/frontends/l64781.c1
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c1
-rw-r--r--drivers/media/dvb/frontends/lnbp21.c1
-rw-r--r--drivers/media/dvb/frontends/mt2060.c1
-rw-r--r--drivers/media/dvb/frontends/mt2131.c314
-rw-r--r--drivers/media/dvb/frontends/mt2131.h54
-rw-r--r--drivers/media/dvb/frontends/mt2131_priv.h49
-rw-r--r--drivers/media/dvb/frontends/mt2266.c287
-rw-r--r--drivers/media/dvb/frontends/mt2266.h37
-rw-r--r--drivers/media/dvb/frontends/mt312.c1
-rw-r--r--drivers/media/dvb/frontends/mt352.c1
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c24
-rw-r--r--drivers/media/dvb/frontends/nxt200x.h3
-rw-r--r--drivers/media/dvb/frontends/or51132.c2
-rw-r--r--drivers/media/dvb/frontends/or51211.c32
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c729
-rw-r--r--drivers/media/dvb/frontends/s5h1409.h73
-rw-r--r--drivers/media/dvb/frontends/sp8870.c1
-rw-r--r--drivers/media/dvb/frontends/sp887x.c1
-rw-r--r--drivers/media/dvb/frontends/stv0297.c4
-rw-r--r--drivers/media/dvb/frontends/stv0299.c3
-rw-r--r--drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--drivers/media/dvb/frontends/tda10023.c12
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c1
-rw-r--r--drivers/media/dvb/frontends/tda10086.c1
-rw-r--r--drivers/media/dvb/frontends/tda8083.c9
-rw-r--r--drivers/media/dvb/frontends/ves1820.c4
-rw-r--r--drivers/media/dvb/frontends/zl10353.c1
-rw-r--r--drivers/media/dvb/pluto2/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig2
-rw-r--r--drivers/media/dvb/ttpci/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/av7110.c18
-rw-r--r--drivers/media/dvb/ttpci/av7110.h1
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c20
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c4
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c36
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c5
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c8
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c33
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c1
-rw-r--r--drivers/media/dvb/ttusb-budget/Makefile2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c1
-rw-r--r--drivers/media/dvb/ttusb-dec/Makefile2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c1
-rw-r--r--drivers/media/radio/Kconfig28
-rw-r--r--drivers/media/radio/radio-aimslab.c3
-rw-r--r--drivers/media/radio/radio-aztech.c1
-rw-r--r--drivers/media/radio/radio-cadet.c4
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c4
-rw-r--r--drivers/media/radio/radio-gemtek.c619
-rw-r--r--drivers/media/radio/radio-rtrack2.c1
-rw-r--r--drivers/media/radio/radio-sf16fmi.c1
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c1
-rw-r--r--drivers/media/radio/radio-terratec.c3
-rw-r--r--drivers/media/radio/radio-trust.c1
-rw-r--r--drivers/media/radio/radio-typhoon.c1
-rw-r--r--drivers/media/video/Kconfig24
-rw-r--r--drivers/media/video/Makefile30
-rw-r--r--drivers/media/video/adv7170.c8
-rw-r--r--drivers/media/video/adv7175.c8
-rw-r--r--drivers/media/video/arv.c3
-rw-r--r--drivers/media/video/bt819.c9
-rw-r--r--drivers/media/video/bt856.c8
-rw-r--r--drivers/media/video/bt866.c2
-rw-r--r--drivers/media/video/bt8xx/Kconfig2
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c720
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c65
-rw-r--r--drivers/media/video/bt8xx/bttv-gpio.c6
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c1
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c5
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c35
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c6
-rw-r--r--drivers/media/video/bt8xx/bttv.h4
-rw-r--r--drivers/media/video/bt8xx/bttvp.h8
-rw-r--r--drivers/media/video/btcx-risc.c1
-rw-r--r--drivers/media/video/bw-qcam.c18
-rw-r--r--drivers/media/video/c-qcam.c4
-rw-r--r--drivers/media/video/cafe_ccic.c56
-rw-r--r--drivers/media/video/compat_ioctl32.c5
-rw-r--r--drivers/media/video/cpia.c1
-rw-r--r--drivers/media/video/cpia2/cpia2_core.c13
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c9
-rw-r--r--drivers/media/video/cx2341x.c19
-rw-r--r--drivers/media/video/cx23885/Kconfig20
-rw-r--r--drivers/media/video/cx23885/Makefile9
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c280
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c1530
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c213
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c382
-rw-r--r--drivers/media/video/cx23885/cx23885-reg.h431
-rw-r--r--drivers/media/video/cx23885/cx23885.h301
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c75
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c98
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h6
-rw-r--r--drivers/media/video/cx88/Kconfig6
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c315
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c45
-rw-r--r--drivers/media/video/cx88/cx88-cards.c243
-rw-r--r--drivers/media/video/cx88/cx88-core.c222
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c147
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c52
-rw-r--r--drivers/media/video/cx88/cx88-input.c43
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c146
-rw-r--r--drivers/media/video/cx88/cx88-reg.h35
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c22
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c13
-rw-r--r--drivers/media/video/cx88/cx88-video.c171
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c17
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.h7
-rw-r--r--drivers/media/video/cx88/cx88.h47
-rw-r--r--drivers/media/video/dpc7146.c5
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c7
-rw-r--r--drivers/media/video/et61x251/Kconfig2
-rw-r--r--drivers/media/video/et61x251/et61x251.h23
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c232
-rw-r--r--drivers/media/video/et61x251/et61x251_sensor.h8
-rw-r--r--drivers/media/video/et61x251/et61x251_tas5130d1b.c2
-rw-r--r--drivers/media/video/ir-kbd-i2c.c89
-rw-r--r--drivers/media/video/ivtv/Kconfig22
-rw-r--r--drivers/media/video/ivtv/Makefile5
-rw-r--r--drivers/media/video/ivtv/ivtv-audio.c74
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.c84
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h67
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.c16
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c362
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h687
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c211
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-firmware.c29
-rw-r--r--drivers/media/video/ivtv/ivtv-firmware.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c29
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.h7
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c37
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c224
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c356
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.h27
-rw-r--r--drivers/media/video/ivtv/ivtv-mailbox.c47
-rw-r--r--drivers/media/video/ivtv/ivtv-mailbox.h8
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.c119
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.h13
-rw-r--r--drivers/media/video/ivtv/ivtv-routing.c (renamed from drivers/media/video/ivtv/ivtv-video.c)90
-rw-r--r--drivers/media/video/ivtv/ivtv-routing.h (renamed from drivers/media/video/ivtv/ivtv-audio.h)12
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c159
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-udma.c46
-rw-r--r--drivers/media/video/ivtv/ivtv-udma.h5
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c292
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.h9
-rw-r--r--drivers/media/video/ivtv/ivtv-version.h7
-rw-r--r--drivers/media/video/ivtv/ivtv-video.h24
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c55
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.h21
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c1190
-rw-r--r--drivers/media/video/msp3400-driver.c28
-rw-r--r--drivers/media/video/mt20xx.c335
-rw-r--r--drivers/media/video/mt20xx.h37
-rw-r--r--drivers/media/video/mxb.c4
-rw-r--r--drivers/media/video/ov511.c81
-rw-r--r--drivers/media/video/ov7670.c10
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c1
-rw-r--r--drivers/media/video/planb.c33
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debug.h53
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debugifc.c16
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c310
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h12
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c63
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-std.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c218
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c2
-rw-r--r--drivers/media/video/pwc/pwc-if.c194
-rw-r--r--drivers/media/video/pwc/pwc.h5
-rw-r--r--drivers/media/video/saa5249.c8
-rw-r--r--drivers/media/video/saa6588.c1
-rw-r--r--drivers/media/video/saa7110.c4
-rw-r--r--drivers/media/video/saa7111.c8
-rw-r--r--drivers/media/video/saa7114.c10
-rw-r--r--drivers/media/video/saa7127.c10
-rw-r--r--drivers/media/video/saa7134/Kconfig6
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c19
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c106
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c214
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c192
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c26
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c43
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c30
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c47
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c7
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c210
-rw-r--r--drivers/media/video/saa7134/saa7134.h31
-rw-r--r--drivers/media/video/saa7185.c8
-rw-r--r--drivers/media/video/saa7191.c4
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h9
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c286
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c214
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c88
-rw-r--r--drivers/media/video/stradis.c2
-rw-r--r--drivers/media/video/stv680.c58
-rw-r--r--drivers/media/video/tcm825x.c928
-rw-r--r--drivers/media/video/tcm825x.h199
-rw-r--r--drivers/media/video/tda8290.c560
-rw-r--r--drivers/media/video/tda8290.h54
-rw-r--r--drivers/media/video/tda9887.c111
-rw-r--r--drivers/media/video/tea5761.c320
-rw-r--r--drivers/media/video/tea5761.h47
-rw-r--r--drivers/media/video/tea5767.c203
-rw-r--r--drivers/media/video/tea5767.h47
-rw-r--r--drivers/media/video/tuner-core.c307
-rw-r--r--drivers/media/video/tuner-driver.h99
-rw-r--r--drivers/media/video/tuner-i2c.h70
-rw-r--r--drivers/media/video/tuner-simple.c408
-rw-r--r--drivers/media/video/tuner-simple.h46
-rw-r--r--drivers/media/video/tuner-types.c30
-rw-r--r--drivers/media/video/tvaudio.c5
-rw-r--r--drivers/media/video/tveeprom.c9
-rw-r--r--drivers/media/video/tvmixer.c6
-rw-r--r--drivers/media/video/tvp5150.c2
-rw-r--r--drivers/media/video/usbvideo/konicawc.c2
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c4
-rw-r--r--drivers/media/video/usbvideo/vicam.c184
-rw-r--r--drivers/media/video/usbvision/usbvision-cards.c9
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c44
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c4
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c1681
-rw-r--r--drivers/media/video/usbvision/usbvision.h13
-rw-r--r--drivers/media/video/v4l1-compat.c1
-rw-r--r--drivers/media/video/v4l2-common.c25
-rw-r--r--drivers/media/video/v4l2-int-device.c158
-rw-r--r--drivers/media/video/videobuf-core.c (renamed from drivers/media/video/video-buf.c)785
-rw-r--r--drivers/media/video/videobuf-dma-sg.c726
-rw-r--r--drivers/media/video/videobuf-dvb.c (renamed from drivers/media/video/video-buf-dvb.c)9
-rw-r--r--drivers/media/video/videobuf-vmalloc.c370
-rw-r--r--drivers/media/video/videodev.c39
-rw-r--r--drivers/media/video/vino.c7
-rw-r--r--drivers/media/video/vivi.c351
-rw-r--r--drivers/media/video/vp27smpx.c212
-rw-r--r--drivers/media/video/w9968cf.c3
-rw-r--r--drivers/media/video/wm8739.c2
-rw-r--r--drivers/media/video/wm8775.c2
-rw-r--r--drivers/media/video/zc0301/Kconfig2
-rw-r--r--drivers/media/video/zc0301/zc0301.h21
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c150
-rw-r--r--drivers/media/video/zc0301/zc0301_pas202bcb.c1
-rw-r--r--drivers/media/video/zc0301/zc0301_pb0330.c1
-rw-r--r--drivers/media/video/zc0301/zc0301_sensor.h2
-rw-r--r--drivers/media/video/zoran.h5
-rw-r--r--drivers/media/video/zoran_card.c64
-rw-r--r--drivers/media/video/zoran_card.h8
-rw-r--r--drivers/media/video/zoran_device.c69
-rw-r--r--drivers/media/video/zoran_driver.c327
-rw-r--r--drivers/media/video/zoran_procfs.c9
-rw-r--r--drivers/media/video/zr36016.c4
-rw-r--r--drivers/media/video/zr36050.c6
-rw-r--r--drivers/media/video/zr36060.c6
-rw-r--r--drivers/media/video/zr364xx.c18
344 files changed, 27835 insertions, 8706 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 624b21cef5b3..dd9bd4310c84 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -69,19 +69,89 @@ source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
depends on I2C
+ select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
+ select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
+ select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
+ select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
+ select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
+
+menuconfig VIDEO_TUNER_CUSTOMIZE
+ bool "Customize analog tuner modules to build"
+ depends on VIDEO_TUNER
+ help
+ This allows the user to deselect tuner drivers unnecessary
+ for their hardware from the build. Use this option with care
+ as deselecting tuner drivers which are in fact necessary will
+ result in V4L devices which cannot be tuned due to lack of
+ driver support
+
+ If unsure say N.
+
+if VIDEO_TUNER_CUSTOMIZE
+
+config TUNER_MT20XX
+ tristate "Microtune 2032 / 2050 tuners"
+ depends on I2C
+ default m if VIDEO_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the MT2032 / MT2050 tuner.
+
+config TUNER_TDA8290
+ tristate "TDA 8290+8275(a) tuner combo"
+ depends on I2C
+ default m if VIDEO_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for Philips TDA8290+8275(a) tuner.
+
+config TUNER_TEA5761
+ tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
+ depends on I2C && EXPERIMENTAL
+ default m if VIDEO_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the Philips TEA5761 radio tuner.
+
+config TUNER_TEA5767
+ tristate "TEA 5767 radio tuner"
+ depends on I2C
+ default m if VIDEO_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the Philips TEA5767 radio tuner.
+
+config TUNER_SIMPLE
+ tristate "Simple tuner support"
+ depends on I2C
+ default m if VIDEO_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for various simple tuners.
+
+endif # VIDEO_TUNER_CUSTOMIZE
-config VIDEO_BUF
+config VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_DMA_SG
depends on PCI
+ select VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_VMALLOC
+ select VIDEOBUF_GEN
tristate
-config VIDEO_BUF_DVB
+config VIDEOBUF_DVB
tristate
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_SG
config VIDEO_BTCX
tristate
+config VIDEO_IR_I2C
+ tristate
+
config VIDEO_IR
tristate
+ select VIDEO_IR_I2C if I2C
config VIDEO_TVEEPROM
tristate
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index 5c63c8e24ee7..c5092ef1082f 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -5,5 +5,5 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV
tristate
depends on VIDEO_DEV
- select VIDEO_BUF
+ select VIDEOBUF_DMA_SG
select VIDEO_SAA7146
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index fcb194135627..e7c3ab951a44 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -21,7 +21,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/jiffies.h>
#include <media/ir-common.h>
@@ -107,21 +106,20 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
}
/* -------------------------------------------------------------------------- */
-
+/* extract mask bits out of data and pack them into the result */
u32 ir_extract_bits(u32 data, u32 mask)
{
- int mbit, vbit;
- u32 value;
+ u32 vbit = 1, value = 0;
+
+ do {
+ if (mask&1) {
+ if (data&1)
+ value |= vbit;
+ vbit<<=1;
+ }
+ data>>=1;
+ } while (mask>>=1);
- value = 0;
- vbit = 0;
- for (mbit = 0; mbit < 32; mbit++) {
- if (!(mask & ((u32)1 << mbit)))
- continue;
- if (data & ((u32)1 << mbit))
- value |= (1 << vbit);
- vbit++;
- }
return value;
}
@@ -346,8 +344,8 @@ void ir_rc5_timer_end(unsigned long data)
}
/* Set/reset key-up timer */
- timeout = current_jiffies + (500 + ir->rc5_key_timeout
- * HZ) / 1000;
+ timeout = current_jiffies +
+ msecs_to_jiffies(ir->rc5_key_timeout);
mod_timer(&ir->timer_keyup, timeout);
/* Save code for repeat test */
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index cbd1184b5219..aefcf28da1ca 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -20,7 +20,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/input.h>
#include <media/ir-common.h>
@@ -1783,3 +1782,64 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_tt_1500);
+
+/* DViCO FUSION HDTV MCE remote */
+IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = {
+
+ [ 0x0b ] = KEY_1,
+ [ 0x17 ] = KEY_2,
+ [ 0x1b ] = KEY_3,
+ [ 0x07 ] = KEY_4,
+ [ 0x50 ] = KEY_5,
+ [ 0x54 ] = KEY_6,
+ [ 0x48 ] = KEY_7,
+ [ 0x4c ] = KEY_8,
+ [ 0x58 ] = KEY_9,
+ [ 0x03 ] = KEY_0,
+
+ [ 0x5e ] = KEY_OK,
+ [ 0x51 ] = KEY_UP,
+ [ 0x53 ] = KEY_DOWN,
+ [ 0x5b ] = KEY_LEFT,
+ [ 0x5f ] = KEY_RIGHT,
+
+ [ 0x02 ] = KEY_TV, /* Labeled DTV on remote */
+ [ 0x0e ] = KEY_MP3,
+ [ 0x1a ] = KEY_DVD,
+ [ 0x1e ] = KEY_FAVORITES, /* Labeled CPF on remote */
+ [ 0x16 ] = KEY_SETUP,
+ [ 0x46 ] = KEY_POWER2, /* TV On/Off button on remote */
+ [ 0x0a ] = KEY_EPG, /* Labeled Guide on remote */
+
+ [ 0x49 ] = KEY_BACK,
+ [ 0x59 ] = KEY_INFO, /* Labeled MORE on remote */
+ [ 0x4d ] = KEY_MENU, /* Labeled DVDMENU on remote */
+ [ 0x55 ] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */
+
+ [ 0x0f ] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */
+ [ 0x12 ] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */
+ [ 0x42 ] = KEY_ENTER, /* Labeled START with a green
+ * MS windows logo on remote */
+
+ [ 0x15 ] = KEY_VOLUMEUP,
+ [ 0x05 ] = KEY_VOLUMEDOWN,
+ [ 0x11 ] = KEY_CHANNELUP,
+ [ 0x09 ] = KEY_CHANNELDOWN,
+
+ [ 0x52 ] = KEY_CAMERA,
+ [ 0x5a ] = KEY_TUNER,
+ [ 0x19 ] = KEY_OPEN,
+
+ [ 0x13 ] = KEY_MODE, /* 4:3 16:9 select */
+ [ 0x1f ] = KEY_ZOOM,
+
+ [ 0x43 ] = KEY_REWIND,
+ [ 0x47 ] = KEY_PLAYPAUSE,
+ [ 0x4f ] = KEY_FASTFORWARD,
+ [ 0x57 ] = KEY_MUTE,
+ [ 0x0d ] = KEY_STOP,
+ [ 0x01 ] = KEY_RECORD,
+ [ 0x4e ] = KEY_POWER,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index ef3e54cd9407..365a22118a09 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -27,7 +27,7 @@ static int saa7146_num;
unsigned int saa7146_debug;
-module_param(saa7146_debug, int, 0644);
+module_param(saa7146_debug, uint, 0644);
MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
#if 0
@@ -100,7 +100,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
* general helper functions
****************************************************************************/
-/* this is videobuf_vmalloc_to_sg() from video-buf.c
+/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
may be triggered on highmem machines */
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
@@ -130,10 +130,10 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
/********************************************************************************/
/* common page table functions */
-char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
+void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
{
int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
- char *mem = vmalloc_32(length);
+ void *mem = vmalloc_32(length);
int slen = 0;
if (NULL == mem)
@@ -168,7 +168,7 @@ err_null:
return NULL;
}
-void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt)
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, void *mem, struct saa7146_pgtable *pt)
{
pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
saa7146_pgtable_free(pci, pt);
@@ -248,10 +248,11 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
static irqreturn_t interrupt_hw(int irq, void *dev_id)
{
struct saa7146_dev *dev = dev_id;
- u32 isr = 0;
+ u32 isr;
+ u32 ack_isr;
/* read out the interrupt status register */
- isr = saa7146_read(dev, ISR);
+ ack_isr = isr = saa7146_read(dev, ISR);
/* is this our interrupt? */
if ( 0 == isr ) {
@@ -259,8 +260,6 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
return IRQ_NONE;
}
- saa7146_write(dev, ISR, isr);
-
if( 0 != (dev->ext)) {
if( 0 != (dev->ext->irq_mask & isr )) {
if( 0 != dev->ext->irq_func ) {
@@ -283,21 +282,16 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
isr &= ~MASK_28;
}
if (0 != (isr & (MASK_16|MASK_17))) {
- u32 status = saa7146_read(dev, I2C_STATUS);
- if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
- SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
- /* only wake up if we expect something */
- if( 0 != dev->i2c_op ) {
- u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2;
- u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f;
- DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr));
- dev->i2c_op = 0;
- wake_up(&dev->i2c_wq);
- } else {
- DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
- }
+ SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+ /* only wake up if we expect something */
+ if (0 != dev->i2c_op) {
+ dev->i2c_op = 0;
+ wake_up(&dev->i2c_wq);
} else {
- DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
+ u32 psr = saa7146_read(dev, PSR);
+ u32 ssr = saa7146_read(dev, SSR);
+ printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+ dev->name, isr, psr, ssr);
}
isr &= ~(MASK_16|MASK_17);
}
@@ -306,6 +300,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
ERR(("disabling interrupt source(s)!\n"));
SAA7146_IER_DISABLE(dev,isr);
}
+ saa7146_write(dev, ISR, ack_isr);
return IRQ_HANDLED;
}
@@ -548,7 +543,6 @@ EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
EXPORT_SYMBOL_GPL(saa7146_setgpio);
-EXPORT_SYMBOL_GPL(saa7146_i2c_transfer);
EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
EXPORT_SYMBOL_GPL(saa7146_debug);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index b4770aecc01d..67d1b1b1b254 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -53,13 +53,14 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
struct saa7146_buf *buf)
{
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
DEB_EE(("dev:%p, buf:%p\n",dev,buf));
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_unmap(q, &buf->vb.dma);
- videobuf_dma_free(&buf->vb.dma);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
buf->vb.state = STATE_NEEDS_INIT;
}
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 8c85efc26527..7e7689afae62 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -202,7 +202,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
/* a signal arrived */
return -ERESTARTSYS;
- printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
+ printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+ dev->name, __FUNCTION__);
return -EIO;
}
status = saa7146_read(dev, I2C_STATUS);
@@ -219,7 +220,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
break;
}
if (time_after(jiffies,timeout)) {
- printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
+ printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+ dev->name, __FUNCTION__);
return -EIO;
}
}
@@ -235,7 +237,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
/* this is normal when probing the bus
* (no answer from nonexisistant device...)
*/
- DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
+ printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+ dev->name, __FUNCTION__);
return -EIO;
}
if (++trial < 50 && short_delay)
@@ -246,8 +249,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
}
/* give a detailed status report */
- if ( 0 != (status & SAA7146_I2C_ERR)) {
-
+ if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
+ SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
+ SAA7146_I2C_AL | SAA7146_I2C_ERR |
+ SAA7146_I2C_BUSY)) ) {
+
+ if ( 0 == (status & SAA7146_I2C_ERR) ||
+ 0 == (status & SAA7146_I2C_BUSY) ) {
+ /* it may take some time until ERR goes high - ignore */
+ DEB_I2C(("unexpected i2c status %04x\n", status));
+ }
if( 0 != (status & SAA7146_I2C_SPERR) ) {
DEB_I2C(("error due to invalid start/stop condition.\n"));
}
@@ -277,7 +288,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
return 0;
}
-int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
+static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
{
int i = 0, count = 0;
u32* buffer = dev->d_i2c.cpu_addr;
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 063608462ebe..6103484e4442 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -165,7 +165,7 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf
/* we don't wait here for the first field anymore. this is different from the video
capture and might cause that the first buffer is only half filled (with only
one field). but since this is some sort of streaming data, this is not that negative.
- but by doing this, we can use the whole engine from video-buf.c... */
+ but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
/*
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
@@ -239,6 +239,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
saa7146_dma_free(dev,q,buf);
if (STATE_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;
@@ -250,7 +252,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
err = videobuf_iolock(q,&buf->vb, NULL);
if (err)
goto oops;
- err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+ err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
+ dma->sglist, dma->sglen);
if (0 != err)
return err;
}
@@ -404,7 +407,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
fh->vbi_fmt.start[1] = 312;
fh->vbi_fmt.count[1] = 16;
- videobuf_queue_init(&fh->vbi_q, &vbi_qops,
+ videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index e3d04a4cef4d..f245a3b2ef47 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -594,8 +594,9 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
{
struct pci_dev *pci = dev->pci;
- struct scatterlist *list = buf->vb.dma.sglist;
- int length = buf->vb.dma.sglen;
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ struct scatterlist *list = dma->sglist;
+ int length = dma->sglen;
struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
@@ -655,7 +656,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
/* if we have a user buffer, the first page may not be
aligned to a page boundary. */
- pt1->offset = buf->vb.dma.sglist->offset;
+ pt1->offset = list->offset;
pt2->offset = pt1->offset+o1;
pt3->offset = pt1->offset+o2;
@@ -889,9 +890,9 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
DEB_EE(("VIDIOC_QUERYCAP\n"));
- strcpy(cap->driver, "saa7146 v4l2");
- strlcpy(cap->card, dev->ext->name, sizeof(cap->card));
- sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
+ strcpy((char *)cap->driver, "saa7146 v4l2");
+ strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
+ sprintf((char *)cap->bus_info,"PCI:%s", pci_name(dev->pci));
cap->version = SAA7146_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
@@ -968,7 +969,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
memset(f,0,sizeof(*f));
f->index = index;
- strlcpy(f->description,formats[index].name,sizeof(f->description));
+ strlcpy((char *)f->description,formats[index].name,sizeof(f->description));
f->pixelformat = formats[index].pixelformat;
break;
}
@@ -1211,6 +1212,8 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
mutex_unlock(&q->lock);
return err;
}
+
+ gbuffers = err;
memset(mbuf,0,sizeof(*mbuf));
mbuf->frames = gbuffers;
mbuf->size = gbuffers * gbufsize;
@@ -1411,7 +1414,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
- videobuf_queue_init(&fh->video_q, &video_qops,
+ videobuf_queue_pci_init(&fh->video_q, &video_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index a0dcd59da76e..3197aeb61d1f 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -1,7 +1,7 @@
config DVB_B2C2_FLEXCOP
tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
depends on DVB_CORE && I2C
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index bff00b58bf65..e97ff60a1eff 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -12,4 +12,4 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
b2c2-flexcop-usb-objs = flexcop-usb.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index b02c2fd65baa..0378fd646591 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -500,13 +500,13 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the air atsc 2nd generation (nxt2002) */
if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2;
- dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
+ dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else
/* try the air atsc 3nd generation (lgdt3303) */
if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC3;
- dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_lg_tdvs_h06xf);
+ dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
} else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index 02a0ea6e1c17..6bf858a436c9 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -135,6 +135,13 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
int i, ret = 0;
+ /* Some drivers use 1 byte or 0 byte reads as probes, which this
+ * driver doesn't support. These probes will always fail, so this
+ * hack makes them always succeed. If one knew how, it would of
+ * course be better to actually do the read. */
+ if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+ return 1;
+
if (mutex_lock_interruptible(&fc->i2c_mutex))
return -ERESTARTSYS;
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index cfd6fb729a61..ea666174e988 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -7,7 +7,7 @@ config DVB_BT8XX
select DVB_CX24110 if !DVB_FE_CUSTOMISE
select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select FW_LOADER
help
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
index 9d197efb481d..84cf70504d17 100644
--- a/drivers/media/dvb/bt8xx/Makefile
+++ b/drivers/media/dvb/bt8xx/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index df72b4b8ee10..eca602d9b3de 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -28,7 +28,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/io.h>
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index f685bc129609..d593bc145628 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -149,11 +149,10 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
void bt878_stop(struct bt878 *bt);
#if defined(__powerpc__) /* big-endian */
-extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
+static inline void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
{
- __asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val),
- "r"(addr));
- __asm__ __volatile__("eieio":::"memory");
+ st_le32(addr, val);
+ eieio();
}
#define bmtwrite(dat,adr) io_st_le32((adr),(dat))
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index e908e3cf1e50..b7a17e69ca4d 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1652,7 +1652,7 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
static int dst_tune_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters* p,
unsigned int mode_flags,
- int *delay,
+ unsigned int *delay,
fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 4f1c09bee538..dedd30a8356b 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -21,7 +21,6 @@
#include <linux/bitops.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -611,7 +610,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL) {
dvb_attach(dvb_pll_attach, card->fe, 0x61,
- card->i2c_adapter, &dvb_pll_lg_tdvs_h06xf);
+ card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF);
dprintk ("dvb_bt8xx: lgdt330x detected\n");
}
break;
@@ -692,6 +691,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
case BTTV_BOARD_PC_HDTV:
card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
+ if (card->fe != NULL)
+ dvb_attach(dvb_pll_attach, card->fe, 0x61,
+ card->i2c_adapter, DVB_PLL_FCV1236D);
break;
}
diff --git a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile
index c51aece20f9f..d762d8cb0cf1 100644
--- a/drivers/media/dvb/cinergyT2/Makefile
+++ b/drivers/media/dvb/cinergyT2/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index b40af48a2edb..5a12b5679556 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -548,19 +548,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- unsigned int mask = 0;
+ unsigned int mask = 0;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
poll_wait(file, &cinergyt2->poll_wq, wait);
- if (cinergyt2->pending_fe_events != 0)
+ if (cinergyt2->pending_fe_events != 0)
mask |= (POLLIN | POLLRDNORM | POLLPRI);
mutex_unlock(&cinergyt2->sem);
- return mask;
+ return mask;
}
@@ -829,7 +829,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
input_dev->id.version = 1;
- input_dev->cdev.dev = &cinergyt2->udev->dev;
+ input_dev->dev.parent = &cinergyt2->udev->dev;
err = input_register_device(input_dev);
if (err) {
@@ -905,12 +905,11 @@ static int cinergyt2_probe (struct usb_interface *intf,
struct cinergyt2 *cinergyt2;
int err;
- if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
+ if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
dprintk(1, "out of memory?!?\n");
return -ENOMEM;
}
- memset (cinergyt2, 0, sizeof (struct cinergyt2));
usb_set_intfdata (intf, (void *) cinergyt2);
mutex_init(&cinergyt2->sem);
@@ -1000,18 +999,17 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
return -ERESTARTSYS;
- if (1) {
- cinergyt2_suspend_rc(cinergyt2);
- cancel_rearming_delayed_work(&cinergyt2->query_work);
+ cinergyt2_suspend_rc(cinergyt2);
+ cancel_rearming_delayed_work(&cinergyt2->query_work);
- mutex_lock(&cinergyt2->sem);
- if (cinergyt2->streaming)
- cinergyt2_stop_stream_xfer(cinergyt2);
- cinergyt2_sleep(cinergyt2, 1);
- mutex_unlock(&cinergyt2->sem);
- }
+ mutex_lock(&cinergyt2->sem);
+ if (cinergyt2->streaming)
+ cinergyt2_stop_stream_xfer(cinergyt2);
+ cinergyt2_sleep(cinergyt2, 1);
+ mutex_unlock(&cinergyt2->sem);
mutex_unlock(&cinergyt2->wq_sem);
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 275df65fde99..f94bc31e3b33 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -24,7 +24,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/poll.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
@@ -97,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
if (avail > todo)
avail = todo;
- ret = dvb_ringbuffer_read(src, buf, avail, 1);
+ ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
if (ret < 0)
break;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 2a03bf53cb29..084a508a03da 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -32,11 +32,11 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
+#include <linux/kthread.h>
#include "dvb_ca_en50221.h"
#include "dvb_ringbuffer.h"
@@ -140,13 +140,7 @@ struct dvb_ca_private {
wait_queue_head_t wait_queue;
/* PID of the monitoring thread */
- pid_t thread_pid;
-
- /* Wait queue used when shutting thread down */
- wait_queue_head_t thread_queue;
-
- /* Flag indicating when thread should exit */
- unsigned int exit:1;
+ struct task_struct *thread;
/* Flag indicating if the CA device is open */
unsigned int open:1;
@@ -175,7 +169,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * e
* @param nlen Number of bytes in needle.
* @return Pointer into haystack needle was found at, or NULL if not found.
*/
-static u8 *findstr(u8 * haystack, int hlen, u8 * needle, int nlen)
+static char *findstr(char * haystack, int hlen, char * needle, int nlen)
{
int i;
@@ -482,7 +476,7 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
}
/* check it contains the correct DVB string */
- dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8);
+ dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8);
if (dvb_str == NULL)
return -EINVAL;
if (tupleLength < ((dvb_str - (char *) tuple) + 12))
@@ -513,8 +507,8 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
ca->slot_info[slot].config_option = tuple[0] & 0x3f;
/* OK, check it contains the correct strings */
- if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
- (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
+ if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
+ (findstr((char *)tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
break;
got_cftableentry = 1;
@@ -902,28 +896,10 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
ca->wakeup = 1;
mb();
- wake_up_interruptible(&ca->thread_queue);
+ wake_up_process(ca->thread);
}
/**
- * Used by the CA thread to determine if an early wakeup is necessary
- *
- * @param ca CA instance.
- */
-static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private *ca)
-{
- if (ca->wakeup) {
- ca->wakeup = 0;
- return 1;
- }
- if (ca->exit)
- return 1;
-
- return 0;
-}
-
-
-/**
* Update the delay used by the thread.
*
* @param ca CA instance.
@@ -982,7 +958,6 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
static int dvb_ca_en50221_thread(void *data)
{
struct dvb_ca_private *ca = data;
- char name[15];
int slot;
int flags;
int status;
@@ -991,28 +966,17 @@ static int dvb_ca_en50221_thread(void *data)
dprintk("%s\n", __FUNCTION__);
- /* setup kernel thread */
- snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
-
- lock_kernel();
- daemonize(name);
- sigfillset(&current->blocked);
- unlock_kernel();
-
/* choose the correct initial delay */
dvb_ca_en50221_thread_update_delay(ca);
/* main loop */
- while (!ca->exit) {
+ while (!kthread_should_stop()) {
/* sleep for a bit */
- if (!ca->wakeup) {
- flags = wait_event_interruptible_timeout(ca->thread_queue,
- dvb_ca_en50221_thread_should_wakeup(ca),
- ca->delay);
- if ((flags == -ERESTARTSYS) || ca->exit) {
- /* got signal or quitting */
- break;
- }
+ while (!ca->wakeup) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(ca->delay);
+ if (kthread_should_stop())
+ return 0;
}
ca->wakeup = 0;
@@ -1181,10 +1145,6 @@ static int dvb_ca_en50221_thread(void *data)
}
}
- /* completed */
- ca->thread_pid = 0;
- mb();
- wake_up_interruptible(&ca->thread_queue);
return 0;
}
@@ -1300,7 +1260,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
struct dvb_ca_private *ca = dvbdev->priv;
u8 slot, connection_id;
int status;
- char fragbuf[HOST_LINK_BUF_SIZE];
+ u8 fragbuf[HOST_LINK_BUF_SIZE];
int fragpos = 0;
int fraglen;
unsigned long timeout;
@@ -1486,7 +1446,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
}
if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
- buf + pktlen, fraglen, 1)) < 0) {
+ (u8 *)buf + pktlen, fraglen, 1)) < 0) {
goto exit;
}
pktlen += fraglen;
@@ -1536,8 +1496,10 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
return -EIO;
err = dvb_generic_open(inode, file);
- if (err < 0)
+ if (err < 0) {
+ module_put(ca->pub->owner);
return err;
+ }
for (i = 0; i < ca->slot_count; i++) {
@@ -1570,7 +1532,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_ca_private *ca = dvbdev->priv;
- int err = 0;
+ int err;
dprintk("%s\n", __FUNCTION__);
@@ -1582,7 +1544,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
module_put(ca->pub->owner);
- return 0;
+ return err;
}
@@ -1682,9 +1644,6 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
goto error;
}
init_waitqueue_head(&ca->wait_queue);
- ca->thread_pid = 0;
- init_waitqueue_head(&ca->thread_queue);
- ca->exit = 0;
ca->open = 0;
ca->wakeup = 0;
ca->next_read_slot = 0;
@@ -1710,14 +1669,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
mb();
/* create a kthread for monitoring this CA device */
-
- ret = kernel_thread(dvb_ca_en50221_thread, ca, 0);
-
- if (ret < 0) {
- printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret);
+ ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i",
+ ca->dvbdev->adapter->num, ca->dvbdev->id);
+ if (IS_ERR(ca->thread)) {
+ ret = PTR_ERR(ca->thread);
+ printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
+ ret);
goto error;
}
- ca->thread_pid = ret;
return 0;
error:
@@ -1748,17 +1707,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
dprintk("%s\n", __FUNCTION__);
/* shutdown the thread if there was one */
- if (ca->thread_pid) {
- if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
- printk("dvb_ca_release adapter %d: thread PID %d already died\n",
- ca->dvbdev->adapter->num, ca->thread_pid);
- } else {
- ca->exit = 1;
- mb();
- dvb_ca_en50221_thread_wakeup(ca);
- wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0);
- }
- }
+ kthread_stop(ca->thread);
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 6d8d1c3df863..7959020f9317 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -373,13 +373,10 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
{
struct dvb_demux_feed *feed;
- struct list_head *pos, *head = &demux->feed_list;
u16 pid = ts_pid(buf);
int dvr_done = 0;
- list_for_each(pos, head) {
- feed = list_entry(pos, struct dvb_demux_feed, list_head);
-
+ list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
continue;
@@ -1068,7 +1065,7 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
if (mutex_lock_interruptible(&dvbdemux->mutex))
return -ERESTARTSYS;
- dvb_dmx_swfilter(dvbdemux, buf, count);
+ dvb_dmx_swfilter(dvbdemux, (u8 *)buf, count);
mutex_unlock(&dvbdemux->mutex);
if (signal_pending(current))
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index b6c7f6610ec5..b203640ef1c5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -32,7 +32,6 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/list.h>
#include <linux/freezer.h>
#include <linux/jiffies.h>
@@ -43,7 +42,7 @@
#include "dvbdev.h"
static int dvb_frontend_debug;
-static int dvb_shutdown_timeout = 5;
+static int dvb_shutdown_timeout;
static int dvb_force_auto_inversion;
static int dvb_override_tune_delay;
static int dvb_powerdown_on_sleep = 1;
@@ -138,7 +137,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
dprintk ("%s\n", __FUNCTION__);
- if (down_interruptible (&events->sem))
+ if (mutex_lock_interruptible (&events->mtx))
return;
wp = (events->eventw + 1) % MAX_EVENT;
@@ -159,7 +158,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
events->eventw = wp;
- up (&events->sem);
+ mutex_unlock(&events->mtx);
e->status = status;
@@ -197,7 +196,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
return ret;
}
- if (down_interruptible (&events->sem))
+ if (mutex_lock_interruptible (&events->mtx))
return -ERESTARTSYS;
memcpy (event, &events->events[events->eventr],
@@ -205,7 +204,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
events->eventr = (events->eventr + 1) % MAX_EVENT;
- up (&events->sem);
+ mutex_unlock(&events->mtx);
return 0;
}
@@ -574,10 +573,9 @@ restart:
dvb_frontend_swzigzag(fe);
}
- if (dvb_shutdown_timeout) {
- if (dvb_powerdown_on_sleep)
- if (fe->ops.set_voltage)
- fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+ if (dvb_powerdown_on_sleep) {
+ if (fe->ops.set_voltage)
+ fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
if (fe->ops.tuner_ops.sleep) {
fe->ops.tuner_ops.sleep(fe);
if (fe->ops.i2c_gate_ctrl)
@@ -697,6 +695,65 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
return 0;
}
+static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
+ u32 *freq_min, u32 *freq_max)
+{
+ *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
+
+ if (fe->ops.info.frequency_max == 0)
+ *freq_max = fe->ops.tuner_ops.info.frequency_max;
+ else if (fe->ops.tuner_ops.info.frequency_max == 0)
+ *freq_max = fe->ops.info.frequency_max;
+ else
+ *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
+
+ if (*freq_min == 0 || *freq_max == 0)
+ printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n",
+ fe->dvb->num);
+}
+
+static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *parms)
+{
+ u32 freq_min;
+ u32 freq_max;
+
+ /* range check: frequency */
+ dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
+ if ((freq_min && parms->frequency < freq_min) ||
+ (freq_max && parms->frequency > freq_max)) {
+ printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n",
+ fe->dvb->num, parms->frequency, freq_min, freq_max);
+ return -EINVAL;
+ }
+
+ /* range check: symbol rate */
+ if (fe->ops.info.type == FE_QPSK) {
+ if ((fe->ops.info.symbol_rate_min &&
+ parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
+ (fe->ops.info.symbol_rate_max &&
+ parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) {
+ printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
+ fe->dvb->num, parms->u.qpsk.symbol_rate,
+ fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
+ return -EINVAL;
+ }
+
+ } else if (fe->ops.info.type == FE_QAM) {
+ if ((fe->ops.info.symbol_rate_min &&
+ parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
+ (fe->ops.info.symbol_rate_max &&
+ parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) {
+ printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
+ fe->dvb->num, parms->u.qam.symbol_rate,
+ fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
@@ -707,7 +764,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
dprintk ("%s\n", __FUNCTION__);
- if (!fe || fepriv->exit)
+ if (fepriv->exit)
return -ENODEV;
if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
@@ -722,6 +779,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_GET_INFO: {
struct dvb_frontend_info* info = parg;
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
+ dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
* do it, it is done for it. */
@@ -883,6 +941,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_SET_FRONTEND: {
struct dvb_frontend_tune_settings fetunesettings;
+ if (dvb_frontend_check_parameters(fe, parg) < 0) {
+ err = -EINVAL;
+ break;
+ }
+
memcpy (&fepriv->parameters, parg,
sizeof (struct dvb_frontend_parameters));
@@ -992,18 +1055,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
dprintk ("%s\n", __FUNCTION__);
- if ((ret = dvb_generic_open (inode, file)) < 0)
- return ret;
-
- if (fe->ops.ts_bus_ctrl) {
- if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
- dvb_generic_release (inode, file);
+ if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+ if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
return ret;
- }
}
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if ((ret = dvb_generic_open (inode, file)) < 0)
+ goto err1;
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
/* normal tune mode when opened R/W */
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
fepriv->tone = -1;
@@ -1011,13 +1071,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
ret = dvb_frontend_start (fe);
if (ret)
- dvb_generic_release (inode, file);
+ goto err2;
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
}
return ret;
+
+err2:
+ dvb_generic_release(inode, file);
+err1:
+ if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
+ fe->ops.ts_bus_ctrl(fe, 0);
+ return ret;
}
static int dvb_frontend_release(struct inode *inode, struct file *file)
@@ -1032,16 +1099,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
fepriv->release_jiffies = jiffies;
- if (fe->ops.ts_bus_ctrl)
- fe->ops.ts_bus_ctrl (fe, 0);
-
ret = dvb_generic_release (inode, file);
- if (dvbdev->users==-1 && fepriv->exit==1) {
- fops_put(file->f_op);
- file->f_op = NULL;
- wake_up(&dvbdev->wait_queue);
+ if (dvbdev->users == -1) {
+ if (fepriv->exit == 1) {
+ fops_put(file->f_op);
+ file->f_op = NULL;
+ wake_up(&dvbdev->wait_queue);
+ }
+ if (fe->ops.ts_bus_ctrl)
+ fe->ops.ts_bus_ctrl(fe, 0);
}
+
return ret;
}
@@ -1080,7 +1149,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->sem);
init_waitqueue_head (&fepriv->wait_queue);
init_waitqueue_head (&fepriv->events.wait_queue);
- init_MUTEX (&fepriv->events.sem);
+ mutex_init(&fepriv->events.mtx);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index f233d78bc364..a5262e852c82 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -35,6 +35,7 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <linux/dvb/frontend.h>
@@ -61,6 +62,13 @@ struct dvb_tuner_info {
u32 bandwidth_step;
};
+struct analog_parameters {
+ unsigned int frequency;
+ unsigned int mode;
+ unsigned int audmode;
+ u64 std;
+};
+
struct dvb_tuner_ops {
struct dvb_tuner_info info;
@@ -71,6 +79,7 @@ struct dvb_tuner_ops {
/** This is for simple PLLs - set all parameters in one go. */
int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+ int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
@@ -79,7 +88,9 @@ struct dvb_tuner_ops {
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
#define TUNER_STATUS_LOCKED 1
+#define TUNER_STATUS_STEREO 2
int (*get_status)(struct dvb_frontend *fe, u32 *status);
+ int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
/** These are provided seperately from set_params in order to facilitate silicon
* tuners which require sophisticated tuning loops, controlling each parameter seperately. */
@@ -103,7 +114,7 @@ struct dvb_frontend_ops {
int (*tune)(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
unsigned int mode_flags,
- int *delay,
+ unsigned int *delay,
fe_status_t *status);
/* get frontend tuning algorithm from the module */
int (*get_frontend_algo)(struct dvb_frontend *fe);
@@ -142,7 +153,7 @@ struct dvb_fe_events {
int eventr;
int overflow;
wait_queue_head_t wait_queue;
- struct semaphore sem;
+ struct mutex mtx;
};
struct dvb_frontend {
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 4ebf33a5ffa2..a33eb5988c42 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -347,7 +347,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
{
struct dvb_net_priv *priv = dev->priv;
unsigned long skipped = 0L;
- u8 *ts, *ts_end, *from_where = NULL, ts_remain = 0, how_much = 0, new_ts = 1;
+ const u8 *ts, *ts_end, *from_where = NULL;
+ u8 ts_remain = 0, how_much = 0, new_ts = 1;
struct ethhdr *ethh = NULL;
#ifdef ULE_DEBUG
@@ -356,15 +357,10 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
static unsigned char *ule_where = ule_hist, ule_dump = 0;
#endif
- if (dev == NULL) {
- printk( KERN_ERR "NO netdev struct!\n" );
- return;
- }
-
/* For all TS cells in current buffer.
* Appearently, we are called for every single TS cell.
*/
- for (ts = (char *)buf, ts_end = (char *)buf + buf_len; ts < ts_end; /* no default incr. */ ) {
+ for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) {
if (new_ts) {
/* We are about to process a new TS cell. */
@@ -799,7 +795,8 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
}
-static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
+static void dvb_net_sec(struct net_device *dev,
+ const u8 *pkt, int pkt_len)
{
u8 *eth;
struct sk_buff *skb;
@@ -901,7 +898,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
* we rely on the DVB API definition where exactly one complete
* section is delivered in buffer1
*/
- dvb_net_sec (dev, (u8*) buffer1, buffer1_len);
+ dvb_net_sec (dev, buffer1, buffer1_len);
return 0;
}
@@ -1223,10 +1220,17 @@ static struct net_device_stats * dvb_net_get_stats(struct net_device *dev)
return &((struct dvb_net_priv*) dev->priv)->stats;
}
+static const struct header_ops dvb_header_ops = {
+ .create = eth_header,
+ .parse = eth_header_parse,
+ .rebuild = eth_rebuild_header,
+};
+
static void dvb_net_setup(struct net_device *dev)
{
ether_setup(dev);
+ dev->header_ops = &dvb_header_ops;
dev->open = dvb_net_open;
dev->stop = dvb_net_stop;
dev->hard_start_xmit = dvb_net_tx;
@@ -1235,7 +1239,7 @@ static void dvb_net_setup(struct net_device *dev)
dev->set_mac_address = dvb_net_set_mac;
dev->mtu = 4096;
dev->mc_count = 0;
- dev->hard_header_cache = NULL;
+
dev->flags |= IFF_NOARP;
}
@@ -1444,18 +1448,9 @@ static int dvb_net_close(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct dvb_net *dvbnet = dvbdev->priv;
- if (!dvbdev)
- return -ENODEV;
-
- if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
- dvbdev->readers++;
- } else {
- dvbdev->writers++;
- }
-
- dvbdev->users++;
+ dvb_generic_release(inode, file);
- if(dvbdev->users == 1 && dvbnet->exit==1) {
+ if(dvbdev->users == 1 && dvbnet->exit == 1) {
fops_put(file->f_op);
file->f_op = NULL;
wake_up(&dvbdev->wait_queue);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a9fa3337dd81..18738faecbbc 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -59,18 +58,13 @@ static struct class *dvb_class;
static struct dvb_device* dvbdev_find_device (int minor)
{
- struct list_head *entry;
+ struct dvb_adapter *adap;
- list_for_each (entry, &dvb_adapter_list) {
- struct list_head *entry0;
- struct dvb_adapter *adap;
- adap = list_entry (entry, struct dvb_adapter, list_head);
- list_for_each (entry0, &adap->device_list) {
- struct dvb_device *dev;
- dev = list_entry (entry0, struct dvb_device, list_head);
+ list_for_each_entry(adap, &dvb_adapter_list, list_head) {
+ struct dvb_device *dev;
+ list_for_each_entry(dev, &adap->device_list, list_head)
if (nums2minor(adap->num, dev->type, dev->id) == minor)
return dev;
- }
}
return NULL;
@@ -109,10 +103,7 @@ static struct file_operations dvb_device_fops =
.open = dvb_device_open,
};
-static struct cdev dvb_device_cdev = {
- .kobj = {.name = "dvb", },
- .owner = THIS_MODULE,
-};
+static struct cdev dvb_device_cdev;
int dvb_generic_open(struct inode *inode, struct file *file)
{
@@ -180,13 +171,10 @@ static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
u32 id = 0;
while (id < DVB_MAX_IDS) {
- struct list_head *entry;
- list_for_each (entry, &adap->device_list) {
- struct dvb_device *dev;
- dev = list_entry (entry, struct dvb_device, list_head);
+ struct dvb_device *dev;
+ list_for_each_entry(dev, &adap->device_list, list_head)
if (dev->type == type && dev->id == id)
goto skip;
- }
return id;
skip:
id++;
@@ -200,7 +188,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
{
struct dvb_device *dvbdev;
struct file_operations *dvbdevfops;
- struct class_device *clsdev;
+ struct device *clsdev;
int id;
mutex_lock(&dvbdev_register_lock);
@@ -208,7 +196,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
if ((id = dvbdev_get_free_id (adap, type)) < 0){
mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
- printk ("%s: could get find free device id...\n", __FUNCTION__);
+ printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
return -ENFILE;
}
@@ -242,17 +230,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR,
- nums2minor(adap->num, type, id)),
- adap->device, "dvb%d.%s%d", adap->num,
- dnames[type], id);
+ clsdev = device_create(dvb_class, adap->device,
+ MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
__FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
return PTR_ERR(clsdev);
}
- dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+ dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
nums2minor(adap->num, type, id));
@@ -266,8 +253,8 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
if (!dvbdev)
return;
- class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
- dvbdev->type, dvbdev->id)));
+ device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
+ dvbdev->type, dvbdev->id)));
list_del (&dvbdev->list_head);
kfree (dvbdev->fops);
@@ -281,13 +268,10 @@ static int dvbdev_get_free_adapter_num (void)
int num = 0;
while (num < DVB_MAX_ADAPTERS) {
- struct list_head *entry;
- list_for_each (entry, &dvb_adapter_list) {
- struct dvb_adapter *adap;
- adap = list_entry (entry, struct dvb_adapter, list_head);
+ struct dvb_adapter *adap;
+ list_for_each_entry(adap, &dvb_adapter_list, list_head)
if (adap->num == num)
goto skip;
- }
return num;
skip:
num++;
@@ -311,7 +295,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
memset (adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list);
- printk ("DVB: registering new adapter (%s).\n", name);
+ printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
adap->num = num;
adap->name = name;
@@ -407,13 +391,13 @@ static int __init init_dvbdev(void)
dev_t dev = MKDEV(DVB_MAJOR, 0);
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
- printk("dvb-core: unable to get major %d\n", DVB_MAJOR);
+ printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
return retval;
}
cdev_init(&dvb_device_cdev, &dvb_device_fops);
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
- printk("dvb-core: unable to get major %d\n", DVB_MAJOR);
+ printk(KERN_ERR "dvb-core: unable register character device\n");
goto error;
}
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 54488737a08f..d73934dd4c57 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -2,7 +2,6 @@ config DVB_USB
tristate "Support for various USB DVB devices"
depends on DVB_CORE && USB && I2C
select FW_LOADER
- select DVB_PLL
help
By enabling this you will be able to choose the various supported
USB1.1 and USB2.0 DVB devices.
@@ -27,13 +26,14 @@ config DVB_USB_A800
depends on DVB_USB
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
help
Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
config DVB_USB_DIBUSB_MB
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
depends on DVB_USB
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MB
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
@@ -74,6 +74,8 @@ config DVB_USB_DIB0700
select DVB_DIB7000M
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_DIB0070
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
USB bridge is also present in devices having the DiB7700 DVB-T-USB
@@ -89,7 +91,7 @@ config DVB_USB_DIB0700
config DVB_USB_UMT_010
tristate "HanfTek UMT-010 DVB-T USB2.0 support"
depends on DVB_USB
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
@@ -98,7 +100,7 @@ config DVB_USB_UMT_010
config DVB_USB_CXUSB
tristate "Conexant USB2.0 hybrid reference design support"
depends on DVB_USB
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_CX22702 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
@@ -142,7 +144,7 @@ config DVB_USB_AU6610
config DVB_USB_DIGITV
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
depends on DVB_USB
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
help
@@ -188,6 +190,7 @@ config DVB_USB_NOVA_T_USB2
depends on DVB_USB
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
help
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
@@ -216,5 +219,23 @@ config DVB_USB_OPERA1
tristate "Opera1 DVB-S USB2.0 receiver"
depends on DVB_USB
select DVB_STV0299 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
help
Say Y here to support the Opera DVB-S USB2.0 receiver.
+
+config DVB_USB_AF9005
+ tristate "Afatech AF9005 DVB-T USB1.1 support"
+ depends on DVB_USB && EXPERIMENTAL
+ select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
+ and the TerraTec Cinergy T USB XE (Rev.1)
+
+config DVB_USB_AF9005_REMOTE
+ tristate "Afatech AF9005 default remote control support"
+ depends on DVB_USB_AF9005
+ help
+ Say Y here to support the default remote control decoding for the
+ Afatech AF9005 based receiver.
+
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 976f840cc904..73ac0a93fdeb 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -55,4 +55,10 @@ dvb-usb-opera-objs = opera1.o
obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+dvb-usb-af9005-objs = af9005.o af9005-fe.o
+obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
+
+dvb-usb-af9005-remote-objs = af9005-remote.o
+obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
new file mode 100644
index 000000000000..b1a9c4cdec93
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9005-fe.c
@@ -0,0 +1,1488 @@
+/* Frontend part of the Linux driver for the Afatech 9005
+ * USB1.1 DVB-T receiver.
+ *
+ * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "af9005.h"
+#include "af9005-script.h"
+#include "mt2060.h"
+#include "qt1010.h"
+#include <asm/div64.h>
+
+struct af9005_fe_state {
+ struct dvb_usb_device *d;
+ fe_status_t stat;
+
+ /* retraining parameters */
+ u32 original_fcw;
+ u16 original_rf_top;
+ u16 original_if_top;
+ u16 original_if_min;
+ u16 original_aci0_if_top;
+ u16 original_aci1_if_top;
+ u16 original_aci0_if_min;
+ u8 original_if_unplug_th;
+ u8 original_rf_unplug_th;
+ u8 original_dtop_if_unplug_th;
+ u8 original_dtop_rf_unplug_th;
+
+ /* statistics */
+ u32 pre_vit_error_count;
+ u32 pre_vit_bit_count;
+ u32 ber;
+ u32 post_vit_error_count;
+ u32 post_vit_bit_count;
+ u32 unc;
+ u16 abort_count;
+
+ int opened;
+ int strong;
+ unsigned long next_status_check;
+ struct dvb_frontend frontend;
+};
+
+static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,
+ u16 reglo, u8 pos, u8 len, u16 value)
+{
+ int ret;
+ u8 temp;
+
+ if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
+ return ret;
+ temp = (u8) ((value & 0x0300) >> 8);
+ return af9005_write_register_bits(d, reghi, pos, len,
+ (u8) ((value & 0x300) >> 8));
+}
+
+static int af9005_read_word_agc(struct dvb_usb_device *d, u16 reghi,
+ u16 reglo, u8 pos, u8 len, u16 * value)
+{
+ int ret;
+ u8 temp0, temp1;
+
+ if ((ret = af9005_read_ofdm_register(d, reglo, &temp0)))
+ return ret;
+ if ((ret = af9005_read_ofdm_register(d, reghi, &temp1)))
+ return ret;
+ switch (pos) {
+ case 0:
+ *value = ((u16) (temp1 & 0x03) << 8) + (u16) temp0;
+ break;
+ case 2:
+ *value = ((u16) (temp1 & 0x0C) << 6) + (u16) temp0;
+ break;
+ case 4:
+ *value = ((u16) (temp1 & 0x30) << 4) + (u16) temp0;
+ break;
+ case 6:
+ *value = ((u16) (temp1 & 0xC0) << 2) + (u16) temp0;
+ break;
+ default:
+ err("invalid pos in read word agc");
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
+static int af9005_is_fecmon_available(struct dvb_frontend *fe, int *available)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 temp;
+
+ *available = false;
+
+ ret = af9005_read_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en,
+ fec_vtb_rsd_mon_en_pos,
+ fec_vtb_rsd_mon_en_len, &temp);
+ if (ret)
+ return ret;
+ if (temp & 1) {
+ ret =
+ af9005_read_register_bits(state->d,
+ xd_p_reg_ofsm_read_rbc_en,
+ reg_ofsm_read_rbc_en_pos,
+ reg_ofsm_read_rbc_en_len, &temp);
+ if (ret)
+ return ret;
+ if ((temp & 1) == 0)
+ *available = true;
+
+ }
+ return 0;
+}
+
+static int af9005_get_post_vit_err_cw_count(struct dvb_frontend *fe,
+ u32 * post_err_count,
+ u32 * post_cw_count,
+ u16 * abort_count)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u32 err_count;
+ u32 cw_count;
+ u8 temp, temp0, temp1, temp2;
+ u16 loc_abort_count;
+
+ *post_err_count = 0;
+ *post_cw_count = 0;
+
+ /* check if error bit count is ready */
+ ret =
+ af9005_read_register_bits(state->d, xd_r_fec_rsd_ber_rdy,
+ fec_rsd_ber_rdy_pos, fec_rsd_ber_rdy_len,
+ &temp);
+ if (ret)
+ return ret;
+ if (!temp) {
+ deb_info("rsd counter not ready\n");
+ return 100;
+ }
+ /* get abort count */
+ ret =
+ af9005_read_ofdm_register(state->d,
+ xd_r_fec_rsd_abort_packet_cnt_7_0,
+ &temp0);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d,
+ xd_r_fec_rsd_abort_packet_cnt_15_8,
+ &temp1);
+ if (ret)
+ return ret;
+ loc_abort_count = ((u16) temp1 << 8) + temp0;
+
+ /* get error count */
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_7_0,
+ &temp0);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_15_8,
+ &temp1);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_23_16,
+ &temp2);
+ if (ret)
+ return ret;
+ err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;
+ *post_err_count = err_count - (u32) loc_abort_count *8 * 8;
+
+ /* get RSD packet number */
+ ret =
+ af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,
+ &temp0);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,
+ &temp1);
+ if (ret)
+ return ret;
+ cw_count = ((u32) temp1 << 8) + temp0;
+ if (cw_count == 0) {
+ err("wrong RSD packet count");
+ return -EIO;
+ }
+ deb_info("POST abort count %d err count %d rsd packets %d\n",
+ loc_abort_count, err_count, cw_count);
+ *post_cw_count = cw_count - (u32) loc_abort_count;
+ *abort_count = loc_abort_count;
+ return 0;
+
+}
+
+static int af9005_get_post_vit_ber(struct dvb_frontend *fe,
+ u32 * post_err_count, u32 * post_cw_count,
+ u16 * abort_count)
+{
+ u32 loc_cw_count = 0, loc_err_count;
+ u16 loc_abort_count;
+ int ret;
+
+ ret =
+ af9005_get_post_vit_err_cw_count(fe, &loc_err_count, &loc_cw_count,
+ &loc_abort_count);
+ if (ret)
+ return ret;
+ *post_err_count = loc_err_count;
+ *post_cw_count = loc_cw_count * 204 * 8;
+ *abort_count = loc_abort_count;
+
+ return 0;
+}
+
+static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
+ u32 * pre_err_count,
+ u32 * pre_bit_count)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ u8 temp, temp0, temp1, temp2;
+ u32 super_frame_count, x, bits;
+ int ret;
+
+ ret =
+ af9005_read_register_bits(state->d, xd_r_fec_vtb_ber_rdy,
+ fec_vtb_ber_rdy_pos, fec_vtb_ber_rdy_len,
+ &temp);
+ if (ret)
+ return ret;
+ if (!temp) {
+ deb_info("viterbi counter not ready\n");
+ return 101; /* ERR_APO_VTB_COUNTER_NOT_READY; */
+ }
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_7_0,
+ &temp0);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_15_8,
+ &temp1);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_23_16,
+ &temp2);
+ if (ret)
+ return ret;
+ *pre_err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;
+
+ ret =
+ af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,
+ &temp0);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,
+ &temp1);
+ if (ret)
+ return ret;
+ super_frame_count = ((u32) temp1 << 8) + temp0;
+ if (super_frame_count == 0) {
+ deb_info("super frame count 0\n");
+ return 102;
+ }
+
+ /* read fft mode */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod,
+ reg_tpsd_txmod_pos, reg_tpsd_txmod_len,
+ &temp);
+ if (ret)
+ return ret;
+ if (temp == 0) {
+ /* 2K */
+ x = 1512;
+ } else if (temp == 1) {
+ /* 8k */
+ x = 6048;
+ } else {
+ err("Invalid fft mode");
+ return -EINVAL;
+ }
+
+ /* read constellation mode */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
+ reg_tpsd_const_pos, reg_tpsd_const_len,
+ &temp);
+ if (ret)
+ return ret;
+ switch (temp) {
+ case 0: /* QPSK */
+ bits = 2;
+ break;
+ case 1: /* QAM_16 */
+ bits = 4;
+ break;
+ case 2: /* QAM_64 */
+ bits = 6;
+ break;
+ default:
+ err("invalid constellation mode");
+ return -EINVAL;
+ }
+ *pre_bit_count = super_frame_count * 68 * 4 * x * bits;
+ deb_info("PRE err count %d frame count %d bit count %d\n",
+ *pre_err_count, super_frame_count, *pre_bit_count);
+ return 0;
+}
+
+static int af9005_reset_pre_viterbi(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+
+ /* set super frame count to 1 */
+ ret =
+ af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,
+ 1 & 0xff);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,
+ 1 >> 8);
+ if (ret)
+ return ret;
+ /* reset pre viterbi error count */
+ ret =
+ af9005_write_register_bits(state->d, xd_p_fec_vtb_ber_rst,
+ fec_vtb_ber_rst_pos, fec_vtb_ber_rst_len,
+ 1);
+
+ return ret;
+}
+
+static int af9005_reset_post_viterbi(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+
+ /* set packet unit */
+ ret =
+ af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,
+ 10000 & 0xff);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,
+ 10000 >> 8);
+ if (ret)
+ return ret;
+ /* reset post viterbi error count */
+ ret =
+ af9005_write_register_bits(state->d, xd_p_fec_rsd_ber_rst,
+ fec_rsd_ber_rst_pos, fec_rsd_ber_rst_len,
+ 1);
+
+ return ret;
+}
+
+static int af9005_get_statistic(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret, fecavailable;
+ u64 numerator, denominator;
+
+ deb_info("GET STATISTIC\n");
+ ret = af9005_is_fecmon_available(fe, &fecavailable);
+ if (ret)
+ return ret;
+ if (!fecavailable) {
+ deb_info("fecmon not available\n");
+ return 0;
+ }
+
+ ret = af9005_get_pre_vit_err_bit_count(fe, &state->pre_vit_error_count,
+ &state->pre_vit_bit_count);
+ if (ret == 0) {
+ af9005_reset_pre_viterbi(fe);
+ if (state->pre_vit_bit_count > 0) {
+ /* according to v 0.0.4 of the dvb api ber should be a multiple
+ of 10E-9 so we have to multiply the error count by
+ 10E9=1000000000 */
+ numerator =
+ (u64) state->pre_vit_error_count * (u64) 1000000000;
+ denominator = (u64) state->pre_vit_bit_count;
+ state->ber = do_div(numerator, denominator);
+ } else {
+ state->ber = 0xffffffff;
+ }
+ }
+
+ ret = af9005_get_post_vit_ber(fe, &state->post_vit_error_count,
+ &state->post_vit_bit_count,
+ &state->abort_count);
+ if (ret == 0) {
+ ret = af9005_reset_post_viterbi(fe);
+ state->unc += state->abort_count;
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int af9005_fe_refresh_state(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ if (time_after(jiffies, state->next_status_check)) {
+ deb_info("REFRESH STATE\n");
+
+ /* statistics */
+ if (af9005_get_statistic(fe))
+ err("get_statistic_failed");
+ state->next_status_check = jiffies + 250 * HZ / 1000;
+ }
+ return 0;
+}
+
+static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ u8 temp;
+ int ret;
+
+ if (fe->ops.tuner_ops.release == NULL)
+ return -ENODEV;
+
+ *stat = 0;
+ ret = af9005_read_register_bits(state->d, xd_p_agc_lock,
+ agc_lock_pos, agc_lock_len, &temp);
+ if (ret)
+ return ret;
+ if (temp)
+ *stat |= FE_HAS_SIGNAL;
+
+ ret = af9005_read_register_bits(state->d, xd_p_fd_tpsd_lock,
+ fd_tpsd_lock_pos, fd_tpsd_lock_len,
+ &temp);
+ if (ret)
+ return ret;
+ if (temp)
+ *stat |= FE_HAS_CARRIER;
+
+ ret = af9005_read_register_bits(state->d,
+ xd_r_mp2if_sync_byte_locked,
+ mp2if_sync_byte_locked_pos,
+ mp2if_sync_byte_locked_pos, &temp);
+ if (ret)
+ return ret;
+ if (temp)
+ *stat |= FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK;
+ if (state->opened)
+ af9005_led_control(state->d, *stat & FE_HAS_LOCK);
+
+ ret =
+ af9005_read_register_bits(state->d, xd_p_reg_strong_sginal_detected,
+ reg_strong_sginal_detected_pos,
+ reg_strong_sginal_detected_len, &temp);
+ if (ret)
+ return ret;
+ if (temp != state->strong) {
+ deb_info("adjust for strong signal %d\n", temp);
+ state->strong = temp;
+ }
+ return 0;
+}
+
+static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ if (fe->ops.tuner_ops.release == NULL)
+ return -ENODEV;
+ af9005_fe_refresh_state(fe);
+ *ber = state->ber;
+ return 0;
+}
+
+static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ if (fe->ops.tuner_ops.release == NULL)
+ return -ENODEV;
+ af9005_fe_refresh_state(fe);
+ *unc = state->unc;
+ return 0;
+}
+
+static int af9005_fe_read_signal_strength(struct dvb_frontend *fe,
+ u16 * strength)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 if_gain, rf_gain;
+
+ if (fe->ops.tuner_ops.release == NULL)
+ return -ENODEV;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain,
+ &rf_gain);
+ if (ret)
+ return ret;
+ ret =
+ af9005_read_ofdm_register(state->d, xd_r_reg_aagc_if_gain,
+ &if_gain);
+ if (ret)
+ return ret;
+ /* this value has no real meaning, but i don't have the tables that relate
+ the rf and if gain with the dbm, so I just scale the value */
+ *strength = (512 - rf_gain - if_gain) << 7;
+ return 0;
+}
+
+static int af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+ /* the snr can be derived from the ber and the constellation
+ but I don't think this kind of complex calculations belong
+ in the driver. I may be wrong.... */
+ return -ENOSYS;
+}
+
+static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
+{
+ u8 temp0, temp1, temp2, temp3, buf[4];
+ int ret;
+ u32 NS_coeff1_2048Nu;
+ u32 NS_coeff1_8191Nu;
+ u32 NS_coeff1_8192Nu;
+ u32 NS_coeff1_8193Nu;
+ u32 NS_coeff2_2k;
+ u32 NS_coeff2_8k;
+
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ NS_coeff1_2048Nu = 0x2ADB6DC;
+ NS_coeff1_8191Nu = 0xAB7313;
+ NS_coeff1_8192Nu = 0xAB6DB7;
+ NS_coeff1_8193Nu = 0xAB685C;
+ NS_coeff2_2k = 0x156DB6E;
+ NS_coeff2_8k = 0x55B6DC;
+ break;
+
+ case BANDWIDTH_7_MHZ:
+ NS_coeff1_2048Nu = 0x3200001;
+ NS_coeff1_8191Nu = 0xC80640;
+ NS_coeff1_8192Nu = 0xC80000;
+ NS_coeff1_8193Nu = 0xC7F9C0;
+ NS_coeff2_2k = 0x1900000;
+ NS_coeff2_8k = 0x640000;
+ break;
+
+ case BANDWIDTH_8_MHZ:
+ NS_coeff1_2048Nu = 0x3924926;
+ NS_coeff1_8191Nu = 0xE4996E;
+ NS_coeff1_8192Nu = 0xE49249;
+ NS_coeff1_8193Nu = 0xE48B25;
+ NS_coeff2_2k = 0x1C92493;
+ NS_coeff2_8k = 0x724925;
+ break;
+ default:
+ err("Invalid bandwith %d.", bw);
+ return -EINVAL;
+ }
+
+ /*
+ * write NS_coeff1_2048Nu
+ */
+
+ temp0 = (u8) (NS_coeff1_2048Nu & 0x000000FF);
+ temp1 = (u8) ((NS_coeff1_2048Nu & 0x0000FF00) >> 8);
+ temp2 = (u8) ((NS_coeff1_2048Nu & 0x00FF0000) >> 16);
+ temp3 = (u8) ((NS_coeff1_2048Nu & 0x03000000) >> 24);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ /* cfoe_NS_2k_coeff1_25_24 */
+ ret = af9005_write_ofdm_register(d, 0xAE00, buf[0]);
+ if (ret)
+ return ret;
+
+ /* cfoe_NS_2k_coeff1_23_16 */
+ ret = af9005_write_ofdm_register(d, 0xAE01, buf[1]);
+ if (ret)
+ return ret;
+
+ /* cfoe_NS_2k_coeff1_15_8 */
+ ret = af9005_write_ofdm_register(d, 0xAE02, buf[2]);
+ if (ret)
+ return ret;
+
+ /* cfoe_NS_2k_coeff1_7_0 */
+ ret = af9005_write_ofdm_register(d, 0xAE03, buf[3]);
+ if (ret)
+ return ret;
+
+ /*
+ * write NS_coeff2_2k
+ */
+
+ temp0 = (u8) ((NS_coeff2_2k & 0x0000003F));
+ temp1 = (u8) ((NS_coeff2_2k & 0x00003FC0) >> 6);
+ temp2 = (u8) ((NS_coeff2_2k & 0x003FC000) >> 14);
+ temp3 = (u8) ((NS_coeff2_2k & 0x01C00000) >> 22);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ ret = af9005_write_ofdm_register(d, 0xAE04, buf[0]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE05, buf[1]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE06, buf[2]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE07, buf[3]);
+ if (ret)
+ return ret;
+
+ /*
+ * write NS_coeff1_8191Nu
+ */
+
+ temp0 = (u8) ((NS_coeff1_8191Nu & 0x000000FF));
+ temp1 = (u8) ((NS_coeff1_8191Nu & 0x0000FF00) >> 8);
+ temp2 = (u8) ((NS_coeff1_8191Nu & 0x00FFC000) >> 16);
+ temp3 = (u8) ((NS_coeff1_8191Nu & 0x03000000) >> 24);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ ret = af9005_write_ofdm_register(d, 0xAE08, buf[0]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE09, buf[1]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0A, buf[2]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0B, buf[3]);
+ if (ret)
+ return ret;
+
+ /*
+ * write NS_coeff1_8192Nu
+ */
+
+ temp0 = (u8) (NS_coeff1_8192Nu & 0x000000FF);
+ temp1 = (u8) ((NS_coeff1_8192Nu & 0x0000FF00) >> 8);
+ temp2 = (u8) ((NS_coeff1_8192Nu & 0x00FFC000) >> 16);
+ temp3 = (u8) ((NS_coeff1_8192Nu & 0x03000000) >> 24);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0C, buf[0]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0D, buf[1]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0E, buf[2]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE0F, buf[3]);
+ if (ret)
+ return ret;
+
+ /*
+ * write NS_coeff1_8193Nu
+ */
+
+ temp0 = (u8) ((NS_coeff1_8193Nu & 0x000000FF));
+ temp1 = (u8) ((NS_coeff1_8193Nu & 0x0000FF00) >> 8);
+ temp2 = (u8) ((NS_coeff1_8193Nu & 0x00FFC000) >> 16);
+ temp3 = (u8) ((NS_coeff1_8193Nu & 0x03000000) >> 24);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ ret = af9005_write_ofdm_register(d, 0xAE10, buf[0]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE11, buf[1]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE12, buf[2]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE13, buf[3]);
+ if (ret)
+ return ret;
+
+ /*
+ * write NS_coeff2_8k
+ */
+
+ temp0 = (u8) ((NS_coeff2_8k & 0x0000003F));
+ temp1 = (u8) ((NS_coeff2_8k & 0x00003FC0) >> 6);
+ temp2 = (u8) ((NS_coeff2_8k & 0x003FC000) >> 14);
+ temp3 = (u8) ((NS_coeff2_8k & 0x01C00000) >> 22);
+
+ /* big endian to make 8051 happy */
+ buf[0] = temp3;
+ buf[1] = temp2;
+ buf[2] = temp1;
+ buf[3] = temp0;
+
+ ret = af9005_write_ofdm_register(d, 0xAE14, buf[0]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE15, buf[1]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE16, buf[2]);
+ if (ret)
+ return ret;
+
+ ret = af9005_write_ofdm_register(d, 0xAE17, buf[3]);
+ return ret;
+
+}
+
+static int af9005_fe_select_bw(struct dvb_usb_device *d, fe_bandwidth_t bw)
+{
+ u8 temp;
+ switch (bw) {
+ case BANDWIDTH_6_MHZ:
+ temp = 0;
+ break;
+ case BANDWIDTH_7_MHZ:
+ temp = 1;
+ break;
+ case BANDWIDTH_8_MHZ:
+ temp = 2;
+ break;
+ default:
+ err("Invalid bandwith %d.", bw);
+ return -EINVAL;
+ }
+ return af9005_write_register_bits(d, xd_g_reg_bw, reg_bw_pos,
+ reg_bw_len, temp);
+}
+
+static int af9005_fe_power(struct dvb_frontend *fe, int on)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ u8 temp = on;
+ int ret;
+ deb_info("power %s tuner\n", on ? "on" : "off");
+ ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0);
+ return ret;
+}
+
+static struct mt2060_config af9005_mt2060_config = {
+ 0xC0
+};
+
+static struct qt1010_config af9005_qt1010_config = {
+ 0xC4
+};
+
+static int af9005_fe_init(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ int ret, i, scriptlen;
+ u8 temp, temp0 = 0, temp1 = 0, temp2 = 0;
+ u8 buf[2];
+ u16 if1;
+
+ deb_info("in af9005_fe_init\n");
+
+ /* reset */
+ deb_info("reset\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst_en,
+ 4, 1, 0x01)))
+ return ret;
+ if ((ret = af9005_write_ofdm_register(state->d, APO_REG_RESET, 0)))
+ return ret;
+ /* clear ofdm reset */
+ deb_info("clear ofdm reset\n");
+ for (i = 0; i < 150; i++) {
+ if ((ret =
+ af9005_read_ofdm_register(state->d,
+ xd_I2C_reg_ofdm_rst, &temp)))
+ return ret;
+ if (temp & (regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos))
+ break;
+ msleep(10);
+ }
+ if (i == 150)
+ return -ETIMEDOUT;
+
+ /*FIXME in the dump
+ write B200 A9
+ write xd_g_reg_ofsm_clk 7
+ read eepr c6 (2)
+ read eepr c7 (2)
+ misc ctrl 3 -> 1
+ read eepr ca (6)
+ write xd_g_reg_ofsm_clk 0
+ write B200 a1
+ */
+ ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa9);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x07);
+ if (ret)
+ return ret;
+ temp = 0x01;
+ ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x00);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa1);
+ if (ret)
+ return ret;
+
+ temp = regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos;
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst,
+ reg_ofdm_rst_pos, reg_ofdm_rst_len, 1)))
+ return ret;
+ ret = af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst,
+ reg_ofdm_rst_pos, reg_ofdm_rst_len, 0);
+
+ if (ret)
+ return ret;
+ /* don't know what register aefc is, but this is what the windows driver does */
+ ret = af9005_write_ofdm_register(state->d, 0xaefc, 0);
+ if (ret)
+ return ret;
+
+ /* set stand alone chip */
+ deb_info("set stand alone chip\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_dca_stand_alone,
+ reg_dca_stand_alone_pos,
+ reg_dca_stand_alone_len, 1)))
+ return ret;
+
+ /* set dca upper & lower chip */
+ deb_info("set dca upper & lower chip\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_dca_upper_chip,
+ reg_dca_upper_chip_pos,
+ reg_dca_upper_chip_len, 0)))
+ return ret;
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_dca_lower_chip,
+ reg_dca_lower_chip_pos,
+ reg_dca_lower_chip_len, 0)))
+ return ret;
+
+ /* set 2wire master clock to 0x14 (for 60KHz) */
+ deb_info("set 2wire master clock to 0x14 (for 60KHz)\n");
+ if ((ret =
+ af9005_write_ofdm_register(state->d, xd_I2C_i2c_m_period, 0x14)))
+ return ret;
+
+ /* clear dca enable chip */
+ deb_info("clear dca enable chip\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_dca_en,
+ reg_dca_en_pos, reg_dca_en_len, 0)))
+ return ret;
+ /* FIXME these are register bits, but I don't know which ones */
+ ret = af9005_write_ofdm_register(state->d, 0xa16c, 1);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, 0xa3c1, 0);
+ if (ret)
+ return ret;
+
+ /* init other parameters: program cfoe and select bandwith */
+ deb_info("program cfoe\n");
+ if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ)))
+ return ret;
+ /* set read-update bit for constellation */
+ deb_info("set read-update bit for constellation\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_feq_read_update,
+ reg_feq_read_update_pos,
+ reg_feq_read_update_len, 1)))
+ return ret;
+
+ /* sample code has a set MPEG TS code here
+ but sniffing reveals that it doesn't do it */
+
+ /* set read-update bit to 1 for DCA constellation */
+ deb_info("set read-update bit 1 for DCA constellation\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_reg_dca_read_update,
+ reg_dca_read_update_pos,
+ reg_dca_read_update_len, 1)))
+ return ret;
+
+ /* enable fec monitor */
+ deb_info("enable fec monitor\n");
+ if ((ret =
+ af9005_write_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en,
+ fec_vtb_rsd_mon_en_pos,
+ fec_vtb_rsd_mon_en_len, 1)))
+ return ret;
+
+ /* FIXME should be register bits, I don't know which ones */
+ ret = af9005_write_ofdm_register(state->d, 0xa601, 0);
+
+ /* set api_retrain_never_freeze */
+ deb_info("set api_retrain_never_freeze\n");
+ if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01)))
+ return ret;
+
+ /* load init script */
+ deb_info("load init script\n");
+ scriptlen = sizeof(script) / sizeof(RegDesc);
+ for (i = 0; i < scriptlen; i++) {
+ if ((ret =
+ af9005_write_register_bits(state->d, script[i].reg,
+ script[i].pos,
+ script[i].len, script[i].val)))
+ return ret;
+ /* save 3 bytes of original fcw */
+ if (script[i].reg == 0xae18)
+ temp2 = script[i].val;
+ if (script[i].reg == 0xae19)
+ temp1 = script[i].val;
+ if (script[i].reg == 0xae1a)
+ temp0 = script[i].val;
+
+ /* save original unplug threshold */
+ if (script[i].reg == xd_p_reg_unplug_th)
+ state->original_if_unplug_th = script[i].val;
+ if (script[i].reg == xd_p_reg_unplug_rf_gain_th)
+ state->original_rf_unplug_th = script[i].val;
+ if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th)
+ state->original_dtop_if_unplug_th = script[i].val;
+ if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th)
+ state->original_dtop_rf_unplug_th = script[i].val;
+
+ }
+ state->original_fcw =
+ ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0;
+
+
+ /* save original TOPs */
+ deb_info("save original TOPs\n");
+
+ /* RF TOP */
+ ret =
+ af9005_read_word_agc(state->d,
+ xd_p_reg_aagc_rf_top_numerator_9_8,
+ xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
+ &state->original_rf_top);
+ if (ret)
+ return ret;
+
+ /* IF TOP */
+ ret =
+ af9005_read_word_agc(state->d,
+ xd_p_reg_aagc_if_top_numerator_9_8,
+ xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
+ &state->original_if_top);
+ if (ret)
+ return ret;
+
+ /* ACI 0 IF TOP */
+ ret =
+ af9005_read_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
+ &state->original_aci0_if_top);
+ if (ret)
+ return ret;
+
+ /* ACI 1 IF TOP */
+ ret =
+ af9005_read_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
+ &state->original_aci1_if_top);
+ if (ret)
+ return ret;
+
+ /* attach tuner and init */
+ if (fe->ops.tuner_ops.release == NULL) {
+ /* read tuner and board id from eeprom */
+ ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2);
+ if (ret) {
+ err("Impossible to read EEPROM\n");
+ return ret;
+ }
+ deb_info("Tuner id %d, board id %d\n", buf[0], buf[1]);
+ switch (buf[0]) {
+ case 2: /* MT2060 */
+ /* read if1 from eeprom */
+ ret = af9005_read_eeprom(adap->dev, 0xc8, buf, 2);
+ if (ret) {
+ err("Impossible to read EEPROM\n");
+ return ret;
+ }
+ if1 = (u16) (buf[0] << 8) + buf[1];
+ if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap,
+ &af9005_mt2060_config, if1) == NULL) {
+ deb_info("MT2060 attach failed\n");
+ return -ENODEV;
+ }
+ break;
+ case 3: /* QT1010 */
+ case 9: /* QT1010B */
+ if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap,
+ &af9005_qt1010_config) ==NULL) {
+ deb_info("QT1010 attach failed\n");
+ return -ENODEV;
+ }
+ break;
+ default:
+ err("Unsupported tuner type %d", buf[0]);
+ return -ENODEV;
+ }
+ ret = fe->ops.tuner_ops.init(fe);
+ if (ret)
+ return ret;
+ }
+
+ deb_info("profit!\n");
+ return 0;
+}
+
+static int af9005_fe_sleep(struct dvb_frontend *fe)
+{
+ return af9005_fe_power(fe, 0);
+}
+
+static int af9005_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+
+ if (acquire) {
+ state->opened++;
+ } else {
+
+ state->opened--;
+ if (!state->opened)
+ af9005_led_control(state->d, 0);
+ }
+ return 0;
+}
+
+static int af9005_fe_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 temp, temp0, temp1, temp2;
+
+ deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency,
+ fep->u.ofdm.bandwidth);
+ if (fe->ops.tuner_ops.release == NULL) {
+ err("Tuner not attached");
+ return -ENODEV;
+ }
+
+ deb_info("turn off led\n");
+ /* not in the log */
+ ret = af9005_led_control(state->d, 0);
+ if (ret)
+ return ret;
+ /* not sure about the bits */
+ ret = af9005_write_register_bits(state->d, XD_MP2IF_MISC, 2, 1, 0);
+ if (ret)
+ return ret;
+
+ /* set FCW to default value */
+ deb_info("set FCW to default value\n");
+ temp0 = (u8) (state->original_fcw & 0x000000ff);
+ temp1 = (u8) ((state->original_fcw & 0x0000ff00) >> 8);
+ temp2 = (u8) ((state->original_fcw & 0x00ff0000) >> 16);
+ ret = af9005_write_ofdm_register(state->d, 0xae1a, temp0);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, 0xae19, temp1);
+ if (ret)
+ return ret;
+ ret = af9005_write_ofdm_register(state->d, 0xae18, temp2);
+ if (ret)
+ return ret;
+
+ /* restore original TOPs */
+ deb_info("restore original TOPs\n");
+ ret =
+ af9005_write_word_agc(state->d,
+ xd_p_reg_aagc_rf_top_numerator_9_8,
+ xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
+ state->original_rf_top);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_word_agc(state->d,
+ xd_p_reg_aagc_if_top_numerator_9_8,
+ xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
+ state->original_if_top);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
+ state->original_aci0_if_top);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
+ state->original_aci1_if_top);
+ if (ret)
+ return ret;
+
+ /* select bandwith */
+ deb_info("select bandwidth");
+ ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth);
+ if (ret)
+ return ret;
+ ret = af9005_fe_program_cfoe(state->d, fep->u.ofdm.bandwidth);
+ if (ret)
+ return ret;
+
+ /* clear easy mode flag */
+ deb_info("clear easy mode flag\n");
+ ret = af9005_write_ofdm_register(state->d, 0xaefd, 0);
+ if (ret)
+ return ret;
+
+ /* set unplug threshold to original value */
+ deb_info("set unplug threshold to original value\n");
+ ret =
+ af9005_write_ofdm_register(state->d, xd_p_reg_unplug_th,
+ state->original_if_unplug_th);
+ if (ret)
+ return ret;
+ /* set tuner */
+ deb_info("set tuner\n");
+ ret = fe->ops.tuner_ops.set_params(fe, fep);
+ if (ret)
+ return ret;
+
+ /* trigger ofsm */
+ deb_info("trigger ofsm\n");
+ temp = 0;
+ ret = af9005_write_tuner_registers(state->d, 0xffff, &temp, 1);
+ if (ret)
+ return ret;
+
+ /* clear retrain and freeze flag */
+ deb_info("clear retrain and freeze flag\n");
+ ret =
+ af9005_write_register_bits(state->d,
+ xd_p_reg_api_retrain_request,
+ reg_api_retrain_request_pos, 2, 0);
+ if (ret)
+ return ret;
+
+ /* reset pre viterbi and post viterbi registers and statistics */
+ af9005_reset_pre_viterbi(fe);
+ af9005_reset_post_viterbi(fe);
+ state->pre_vit_error_count = 0;
+ state->pre_vit_bit_count = 0;
+ state->ber = 0;
+ state->post_vit_error_count = 0;
+ /* state->unc = 0; commented out since it should be ever increasing */
+ state->abort_count = 0;
+
+ state->next_status_check = jiffies;
+ state->strong = -1;
+
+ return 0;
+}
+
+static int af9005_fe_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 temp;
+
+ /* mode */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
+ reg_tpsd_const_pos, reg_tpsd_const_len,
+ &temp);
+ if (ret)
+ return ret;
+ deb_info("===== fe_get_frontend ==============\n");
+ deb_info("CONSTELLATION ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.constellation = QPSK;
+ deb_info("QPSK\n");
+ break;
+ case 1:
+ fep->u.ofdm.constellation = QAM_16;
+ deb_info("QAM_16\n");
+ break;
+ case 2:
+ fep->u.ofdm.constellation = QAM_64;
+ deb_info("QAM_64\n");
+ break;
+ }
+
+ /* tps hierarchy and alpha value */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_hier,
+ reg_tpsd_hier_pos, reg_tpsd_hier_len,
+ &temp);
+ if (ret)
+ return ret;
+ deb_info("HIERARCHY ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ deb_info("NONE\n");
+ break;
+ case 1:
+ fep->u.ofdm.hierarchy_information = HIERARCHY_1;
+ deb_info("1\n");
+ break;
+ case 2:
+ fep->u.ofdm.hierarchy_information = HIERARCHY_2;
+ deb_info("2\n");
+ break;
+ case 3:
+ fep->u.ofdm.hierarchy_information = HIERARCHY_4;
+ deb_info("4\n");
+ break;
+ }
+
+ /* high/low priority */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_dec_pri,
+ reg_dec_pri_pos, reg_dec_pri_len, &temp);
+ if (ret)
+ return ret;
+ /* if temp is set = high priority */
+ deb_info("PRIORITY %s\n", temp ? "high" : "low");
+
+ /* high coderate */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_hpcr,
+ reg_tpsd_hpcr_pos, reg_tpsd_hpcr_len,
+ &temp);
+ if (ret)
+ return ret;
+ deb_info("CODERATE HP ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.code_rate_HP = FEC_1_2;
+ deb_info("FEC_1_2\n");
+ break;
+ case 1:
+ fep->u.ofdm.code_rate_HP = FEC_2_3;
+ deb_info("FEC_2_3\n");
+ break;
+ case 2:
+ fep->u.ofdm.code_rate_HP = FEC_3_4;
+ deb_info("FEC_3_4\n");
+ break;
+ case 3:
+ fep->u.ofdm.code_rate_HP = FEC_5_6;
+ deb_info("FEC_5_6\n");
+ break;
+ case 4:
+ fep->u.ofdm.code_rate_HP = FEC_7_8;
+ deb_info("FEC_7_8\n");
+ break;
+ }
+
+ /* low coderate */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_lpcr,
+ reg_tpsd_lpcr_pos, reg_tpsd_lpcr_len,
+ &temp);
+ if (ret)
+ return ret;
+ deb_info("CODERATE LP ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.code_rate_LP = FEC_1_2;
+ deb_info("FEC_1_2\n");
+ break;
+ case 1:
+ fep->u.ofdm.code_rate_LP = FEC_2_3;
+ deb_info("FEC_2_3\n");
+ break;
+ case 2:
+ fep->u.ofdm.code_rate_LP = FEC_3_4;
+ deb_info("FEC_3_4\n");
+ break;
+ case 3:
+ fep->u.ofdm.code_rate_LP = FEC_5_6;
+ deb_info("FEC_5_6\n");
+ break;
+ case 4:
+ fep->u.ofdm.code_rate_LP = FEC_7_8;
+ deb_info("FEC_7_8\n");
+ break;
+ }
+
+ /* guard interval */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_gi,
+ reg_tpsd_gi_pos, reg_tpsd_gi_len, &temp);
+ if (ret)
+ return ret;
+ deb_info("GUARD INTERVAL ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ deb_info("1_32\n");
+ break;
+ case 1:
+ fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ deb_info("1_16\n");
+ break;
+ case 2:
+ fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ deb_info("1_8\n");
+ break;
+ case 3:
+ fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ deb_info("1_4\n");
+ break;
+ }
+
+ /* fft */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod,
+ reg_tpsd_txmod_pos, reg_tpsd_txmod_len,
+ &temp);
+ if (ret)
+ return ret;
+ deb_info("TRANSMISSION MODE ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ deb_info("2K\n");
+ break;
+ case 1:
+ fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ deb_info("8K\n");
+ break;
+ }
+
+ /* bandwidth */
+ ret =
+ af9005_read_register_bits(state->d, xd_g_reg_bw, reg_bw_pos,
+ reg_bw_len, &temp);
+ deb_info("BANDWIDTH ");
+ switch (temp) {
+ case 0:
+ fep->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ deb_info("6\n");
+ break;
+ case 1:
+ fep->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ deb_info("7\n");
+ break;
+ case 2:
+ fep->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ deb_info("8\n");
+ break;
+ }
+ return 0;
+}
+
+static void af9005_fe_release(struct dvb_frontend *fe)
+{
+ struct af9005_fe_state *state =
+ (struct af9005_fe_state *)fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops af9005_fe_ops;
+
+struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d)
+{
+ struct af9005_fe_state *state = NULL;
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct af9005_fe_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ deb_info("attaching frontend af9005\n");
+
+ state->d = d;
+ state->opened = 0;
+
+ memcpy(&state->frontend.ops, &af9005_fe_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ return &state->frontend;
+ error:
+ return NULL;
+}
+
+static struct dvb_frontend_ops af9005_fe_ops = {
+ .info = {
+ .name = "AF9005 USB DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 250000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = af9005_fe_release,
+
+ .init = af9005_fe_init,
+ .sleep = af9005_fe_sleep,
+ .ts_bus_ctrl = af9005_ts_bus_ctrl,
+
+ .set_frontend = af9005_fe_set_frontend,
+ .get_frontend = af9005_fe_get_frontend,
+
+ .read_status = af9005_fe_read_status,
+ .read_ber = af9005_fe_read_ber,
+ .read_signal_strength = af9005_fe_read_signal_strength,
+ .read_snr = af9005_fe_read_snr,
+ .read_ucblocks = af9005_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
new file mode 100644
index 000000000000..ff00c0e8f4a1
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9005-remote.c
@@ -0,0 +1,157 @@
+/* DVB USB compliant Linux driver for the Afatech 9005
+ * USB1.1 DVB-T receiver.
+ *
+ * Standard remote decode function
+ *
+ * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * see Documentation/dvb/REDME.dvb-usb for more information
+ */
+#include "af9005.h"
+/* debug */
+int dvb_usb_af9005_remote_debug;
+module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+ "enable (1) or disable (0) debug messages."
+ DVB_USB_DEBUG_STATUS);
+
+#define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args)
+
+struct dvb_usb_rc_key af9005_rc_keys[] = {
+
+ {0x01, 0xb7, KEY_POWER},
+ {0x01, 0xa7, KEY_VOLUMEUP},
+ {0x01, 0x87, KEY_CHANNELUP},
+ {0x01, 0x7f, KEY_MUTE},
+ {0x01, 0xbf, KEY_VOLUMEDOWN},
+ {0x01, 0x3f, KEY_CHANNELDOWN},
+ {0x01, 0xdf, KEY_1},
+ {0x01, 0x5f, KEY_2},
+ {0x01, 0x9f, KEY_3},
+ {0x01, 0x1f, KEY_4},
+ {0x01, 0xef, KEY_5},
+ {0x01, 0x6f, KEY_6},
+ {0x01, 0xaf, KEY_7},
+ {0x01, 0x27, KEY_8},
+ {0x01, 0x07, KEY_9},
+ {0x01, 0xcf, KEY_ZOOM},
+ {0x01, 0x4f, KEY_0},
+ {0x01, 0x8f, KEY_GOTO}, /* marked jump on the remote */
+
+ {0x00, 0xbd, KEY_POWER},
+ {0x00, 0x7d, KEY_VOLUMEUP},
+ {0x00, 0xfd, KEY_CHANNELUP},
+ {0x00, 0x9d, KEY_MUTE},
+ {0x00, 0x5d, KEY_VOLUMEDOWN},
+ {0x00, 0xdd, KEY_CHANNELDOWN},
+ {0x00, 0xad, KEY_1},
+ {0x00, 0x6d, KEY_2},
+ {0x00, 0xed, KEY_3},
+ {0x00, 0x8d, KEY_4},
+ {0x00, 0x4d, KEY_5},
+ {0x00, 0xcd, KEY_6},
+ {0x00, 0xb5, KEY_7},
+ {0x00, 0x75, KEY_8},
+ {0x00, 0xf5, KEY_9},
+ {0x00, 0x95, KEY_ZOOM},
+ {0x00, 0x55, KEY_0},
+ {0x00, 0xd5, KEY_GOTO}, /* marked jump on the remote */
+};
+
+int af9005_rc_keys_size = ARRAY_SIZE(af9005_rc_keys);
+
+static int repeatable_keys[] = {
+ KEY_VOLUMEUP,
+ KEY_VOLUMEDOWN,
+ KEY_CHANNELUP,
+ KEY_CHANNELDOWN
+};
+
+int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
+ int *state)
+{
+ u16 mark, space;
+ u32 result;
+ u8 cust, dat, invdat;
+ int i;
+
+ if (len >= 6) {
+ mark = (u16) (data[0] << 8) + data[1];
+ space = (u16) (data[2] << 8) + data[3];
+ if (space * 3 < mark) {
+ for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
+ if (d->last_event == repeatable_keys[i]) {
+ *state = REMOTE_KEY_REPEAT;
+ *event = d->last_event;
+ deb_decode("repeat key, event %x\n",
+ *event);
+ return 0;
+ }
+ }
+ deb_decode("repeated key ignored (non repeatable)\n");
+ return 0;
+ } else if (len >= 33 * 4) { /*32 bits + start code */
+ result = 0;
+ for (i = 4; i < 4 + 32 * 4; i += 4) {
+ result <<= 1;
+ mark = (u16) (data[i] << 8) + data[i + 1];
+ mark >>= 1;
+ space = (u16) (data[i + 2] << 8) + data[i + 3];
+ space >>= 1;
+ if (mark * 2 > space)
+ result += 1;
+ }
+ deb_decode("key pressed, raw value %x\n", result);
+ if ((result & 0xff000000) != 0xfe000000) {
+ deb_decode
+ ("doesn't start with 0xfe, ignored\n");
+ return 0;
+ }
+ cust = (result >> 16) & 0xff;
+ dat = (result >> 8) & 0xff;
+ invdat = (~result) & 0xff;
+ if (dat != invdat) {
+ deb_decode("code != inverted code\n");
+ return 0;
+ }
+ for (i = 0; i < af9005_rc_keys_size; i++) {
+ if (af9005_rc_keys[i].custom == cust
+ && af9005_rc_keys[i].data == dat) {
+ *event = af9005_rc_keys[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ deb_decode
+ ("key pressed, event %x\n", *event);
+ return 0;
+ }
+ }
+ deb_decode("not found in table\n");
+ }
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(af9005_rc_keys);
+EXPORT_SYMBOL(af9005_rc_keys_size);
+EXPORT_SYMBOL(af9005_rc_decode);
+
+MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
+MODULE_DESCRIPTION
+ ("Standard remote control decoder for Afatech 9005 DVB-T USB1.1 stick");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h
new file mode 100644
index 000000000000..6eeaae51b1ca
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9005-script.h
@@ -0,0 +1,203 @@
+/*
+File automatically generated by createinit.py using data
+extracted from AF05BDA.sys (windows driver):
+
+dd if=AF05BDA.sys of=initsequence bs=1 skip=88316 count=1110
+python createinit.py > af9005-script.h
+
+*/
+
+typedef struct {
+ u16 reg;
+ u8 pos;
+ u8 len;
+ u8 val;
+} RegDesc;
+
+RegDesc script[] = {
+ {0xa180, 0x0, 0x8, 0xa},
+ {0xa181, 0x0, 0x8, 0xd7},
+ {0xa182, 0x0, 0x8, 0xa3},
+ {0xa0a0, 0x0, 0x8, 0x0},
+ {0xa0a1, 0x0, 0x5, 0x0},
+ {0xa0a1, 0x5, 0x1, 0x1},
+ {0xa0c0, 0x0, 0x4, 0x1},
+ {0xa20e, 0x4, 0x4, 0xa},
+ {0xa20f, 0x0, 0x8, 0x40},
+ {0xa210, 0x0, 0x8, 0x8},
+ {0xa32a, 0x0, 0x4, 0xa},
+ {0xa32c, 0x0, 0x8, 0x20},
+ {0xa32b, 0x0, 0x8, 0x15},
+ {0xa1a0, 0x1, 0x1, 0x1},
+ {0xa000, 0x0, 0x1, 0x1},
+ {0xa000, 0x1, 0x1, 0x0},
+ {0xa001, 0x1, 0x1, 0x1},
+ {0xa001, 0x0, 0x1, 0x0},
+ {0xa001, 0x5, 0x1, 0x0},
+ {0xa00e, 0x0, 0x5, 0x10},
+ {0xa00f, 0x0, 0x3, 0x4},
+ {0xa00f, 0x3, 0x3, 0x5},
+ {0xa010, 0x0, 0x3, 0x4},
+ {0xa010, 0x3, 0x3, 0x5},
+ {0xa016, 0x4, 0x4, 0x3},
+ {0xa01f, 0x0, 0x6, 0xa},
+ {0xa020, 0x0, 0x6, 0xa},
+ {0xa2bc, 0x0, 0x1, 0x1},
+ {0xa2bc, 0x5, 0x1, 0x1},
+ {0xa015, 0x0, 0x8, 0x50},
+ {0xa016, 0x0, 0x1, 0x0},
+ {0xa02a, 0x0, 0x8, 0x50},
+ {0xa029, 0x0, 0x8, 0x4b},
+ {0xa614, 0x0, 0x8, 0x46},
+ {0xa002, 0x0, 0x5, 0x19},
+ {0xa003, 0x0, 0x5, 0x1a},
+ {0xa004, 0x0, 0x5, 0x19},
+ {0xa005, 0x0, 0x5, 0x1a},
+ {0xa008, 0x0, 0x8, 0x69},
+ {0xa009, 0x0, 0x2, 0x2},
+ {0xae1b, 0x0, 0x8, 0x69},
+ {0xae1c, 0x0, 0x8, 0x2},
+ {0xae1d, 0x0, 0x8, 0x2a},
+ {0xa022, 0x0, 0x8, 0xaa},
+ {0xa006, 0x0, 0x8, 0xc8},
+ {0xa007, 0x0, 0x2, 0x0},
+ {0xa00c, 0x0, 0x8, 0xba},
+ {0xa00d, 0x0, 0x2, 0x2},
+ {0xa608, 0x0, 0x8, 0xba},
+ {0xa60e, 0x0, 0x2, 0x2},
+ {0xa609, 0x0, 0x8, 0x80},
+ {0xa60e, 0x2, 0x2, 0x3},
+ {0xa00a, 0x0, 0x8, 0xb6},
+ {0xa00b, 0x0, 0x2, 0x0},
+ {0xa011, 0x0, 0x8, 0xb9},
+ {0xa012, 0x0, 0x2, 0x0},
+ {0xa013, 0x0, 0x8, 0xbd},
+ {0xa014, 0x0, 0x2, 0x2},
+ {0xa366, 0x0, 0x1, 0x1},
+ {0xa2bc, 0x3, 0x1, 0x0},
+ {0xa2bd, 0x0, 0x8, 0xa},
+ {0xa2be, 0x0, 0x8, 0x14},
+ {0xa2bf, 0x0, 0x8, 0x8},
+ {0xa60a, 0x0, 0x8, 0xbd},
+ {0xa60e, 0x4, 0x2, 0x2},
+ {0xa60b, 0x0, 0x8, 0x86},
+ {0xa60e, 0x6, 0x2, 0x3},
+ {0xa001, 0x2, 0x2, 0x1},
+ {0xa1c7, 0x0, 0x8, 0xf5},
+ {0xa03d, 0x0, 0x8, 0xb1},
+ {0xa616, 0x0, 0x8, 0xff},
+ {0xa617, 0x0, 0x8, 0xad},
+ {0xa618, 0x0, 0x8, 0xad},
+ {0xa61e, 0x3, 0x1, 0x1},
+ {0xae1a, 0x0, 0x8, 0x0},
+ {0xae19, 0x0, 0x8, 0xc8},
+ {0xae18, 0x0, 0x8, 0x61},
+ {0xa140, 0x0, 0x8, 0x0},
+ {0xa141, 0x0, 0x8, 0xc8},
+ {0xa142, 0x0, 0x7, 0x61},
+ {0xa023, 0x0, 0x8, 0xff},
+ {0xa021, 0x0, 0x8, 0xad},
+ {0xa026, 0x0, 0x1, 0x0},
+ {0xa024, 0x0, 0x8, 0xff},
+ {0xa025, 0x0, 0x8, 0xff},
+ {0xa1c8, 0x0, 0x8, 0xf},
+ {0xa2bc, 0x1, 0x1, 0x0},
+ {0xa60c, 0x0, 0x4, 0x5},
+ {0xa60c, 0x4, 0x4, 0x6},
+ {0xa60d, 0x0, 0x8, 0xa},
+ {0xa371, 0x0, 0x1, 0x1},
+ {0xa366, 0x1, 0x3, 0x7},
+ {0xa338, 0x0, 0x8, 0x10},
+ {0xa339, 0x0, 0x6, 0x7},
+ {0xa33a, 0x0, 0x6, 0x1f},
+ {0xa33b, 0x0, 0x8, 0xf6},
+ {0xa33c, 0x3, 0x5, 0x4},
+ {0xa33d, 0x4, 0x4, 0x0},
+ {0xa33d, 0x1, 0x1, 0x1},
+ {0xa33d, 0x2, 0x1, 0x1},
+ {0xa33d, 0x3, 0x1, 0x1},
+ {0xa16d, 0x0, 0x4, 0xf},
+ {0xa161, 0x0, 0x5, 0x5},
+ {0xa162, 0x0, 0x4, 0x5},
+ {0xa165, 0x0, 0x8, 0xff},
+ {0xa166, 0x0, 0x8, 0x9c},
+ {0xa2c3, 0x0, 0x4, 0x5},
+ {0xa61a, 0x0, 0x6, 0xf},
+ {0xb200, 0x0, 0x8, 0xa1},
+ {0xb201, 0x0, 0x8, 0x7},
+ {0xa093, 0x0, 0x1, 0x0},
+ {0xa093, 0x1, 0x5, 0xf},
+ {0xa094, 0x0, 0x8, 0xff},
+ {0xa095, 0x0, 0x8, 0xf},
+ {0xa080, 0x2, 0x5, 0x3},
+ {0xa081, 0x0, 0x4, 0x0},
+ {0xa081, 0x4, 0x4, 0x9},
+ {0xa082, 0x0, 0x5, 0x1f},
+ {0xa08d, 0x0, 0x8, 0x1},
+ {0xa083, 0x0, 0x8, 0x32},
+ {0xa084, 0x0, 0x1, 0x0},
+ {0xa08e, 0x0, 0x8, 0x3},
+ {0xa085, 0x0, 0x8, 0x32},
+ {0xa086, 0x0, 0x3, 0x0},
+ {0xa087, 0x0, 0x8, 0x6e},
+ {0xa088, 0x0, 0x5, 0x15},
+ {0xa089, 0x0, 0x8, 0x0},
+ {0xa08a, 0x0, 0x5, 0x19},
+ {0xa08b, 0x0, 0x8, 0x92},
+ {0xa08c, 0x0, 0x5, 0x1c},
+ {0xa120, 0x0, 0x8, 0x0},
+ {0xa121, 0x0, 0x5, 0x10},
+ {0xa122, 0x0, 0x8, 0x0},
+ {0xa123, 0x0, 0x7, 0x40},
+ {0xa123, 0x7, 0x1, 0x0},
+ {0xa124, 0x0, 0x8, 0x13},
+ {0xa125, 0x0, 0x7, 0x10},
+ {0xa1c0, 0x0, 0x8, 0x0},
+ {0xa1c1, 0x0, 0x5, 0x4},
+ {0xa1c2, 0x0, 0x8, 0x0},
+ {0xa1c3, 0x0, 0x5, 0x10},
+ {0xa1c3, 0x5, 0x3, 0x0},
+ {0xa1c4, 0x0, 0x6, 0x0},
+ {0xa1c5, 0x0, 0x7, 0x10},
+ {0xa100, 0x0, 0x8, 0x0},
+ {0xa101, 0x0, 0x5, 0x10},
+ {0xa102, 0x0, 0x8, 0x0},
+ {0xa103, 0x0, 0x7, 0x40},
+ {0xa103, 0x7, 0x1, 0x0},
+ {0xa104, 0x0, 0x8, 0x18},
+ {0xa105, 0x0, 0x7, 0xa},
+ {0xa106, 0x0, 0x8, 0x20},
+ {0xa107, 0x0, 0x8, 0x40},
+ {0xa108, 0x0, 0x4, 0x0},
+ {0xa38c, 0x0, 0x8, 0xfc},
+ {0xa38d, 0x0, 0x8, 0x0},
+ {0xa38e, 0x0, 0x8, 0x7e},
+ {0xa38f, 0x0, 0x8, 0x0},
+ {0xa390, 0x0, 0x8, 0x2f},
+ {0xa60f, 0x5, 0x1, 0x1},
+ {0xa170, 0x0, 0x8, 0xdc},
+ {0xa171, 0x0, 0x2, 0x0},
+ {0xa2ae, 0x0, 0x1, 0x1},
+ {0xa2ae, 0x1, 0x1, 0x1},
+ {0xa392, 0x0, 0x1, 0x1},
+ {0xa391, 0x2, 0x1, 0x0},
+ {0xabc1, 0x0, 0x8, 0xff},
+ {0xabc2, 0x0, 0x8, 0x0},
+ {0xabc8, 0x0, 0x8, 0x8},
+ {0xabca, 0x0, 0x8, 0x10},
+ {0xabcb, 0x0, 0x1, 0x0},
+ {0xabc3, 0x5, 0x3, 0x7},
+ {0xabc0, 0x6, 0x1, 0x0},
+ {0xabc0, 0x4, 0x2, 0x0},
+ {0xa344, 0x4, 0x4, 0x1},
+ {0xabc0, 0x7, 0x1, 0x1},
+ {0xabc0, 0x2, 0x1, 0x1},
+ {0xa345, 0x0, 0x8, 0x66},
+ {0xa346, 0x0, 0x8, 0x66},
+ {0xa347, 0x0, 0x4, 0x0},
+ {0xa343, 0x0, 0x4, 0xa},
+ {0xa347, 0x4, 0x4, 0x2},
+ {0xa348, 0x0, 0x4, 0xc},
+ {0xa348, 0x4, 0x4, 0x7},
+ {0xa349, 0x0, 0x6, 0x2},
+};
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
new file mode 100644
index 000000000000..7db6eee50e39
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -0,0 +1,1141 @@
+/* DVB USB compliant Linux driver for the Afatech 9005
+ * USB1.1 DVB-T receiver.
+ *
+ * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * see Documentation/dvb/REDME.dvb-usb for more information
+ */
+#include "af9005.h"
+
+/* debug */
+int dvb_usb_af9005_debug;
+module_param_named(debug, dvb_usb_af9005_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+ "set debugging level (1=info,xfer=2,rc=4,reg=8,i2c=16,fw=32 (or-able))."
+ DVB_USB_DEBUG_STATUS);
+/* enable obnoxious led */
+int dvb_usb_af9005_led = 1;
+module_param_named(led, dvb_usb_af9005_led, bool, 0644);
+MODULE_PARM_DESC(led, "enable led (default: 1).");
+
+/* eeprom dump */
+int dvb_usb_af9005_dump_eeprom = 0;
+module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
+MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
+
+/* remote control decoder */
+int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
+ int *state);
+void *rc_keys;
+int *rc_keys_size;
+
+u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+
+struct af9005_device_state {
+ u8 sequence;
+ int led_state;
+};
+
+int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen,
+ u8 * rbuf, u16 rlen, int delay_ms)
+{
+ int actlen, ret = -ENOMEM;
+
+ if (wbuf == NULL || wlen == 0)
+ return -EINVAL;
+
+ if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+ return ret;
+
+ deb_xfer(">>> ");
+ debug_dump(wbuf, wlen, deb_xfer);
+
+ ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
+ 2), wbuf, wlen,
+ &actlen, 2000);
+
+ if (ret)
+ err("bulk message failed: %d (%d/%d)", ret, wlen, actlen);
+ else
+ ret = actlen != wlen ? -1 : 0;
+
+ /* an answer is expected, and no error before */
+ if (!ret && rbuf && rlen) {
+ if (delay_ms)
+ msleep(delay_ms);
+
+ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
+ 0x01), rbuf,
+ rlen, &actlen, 2000);
+
+ if (ret)
+ err("recv bulk message failed: %d", ret);
+ else {
+ deb_xfer("<<< ");
+ debug_dump(rbuf, actlen, deb_xfer);
+ }
+ }
+
+ mutex_unlock(&d->usb_mutex);
+ return ret;
+}
+
+int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len)
+{
+ return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0);
+}
+
+int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
+ int readwrite, int type, u8 * values, int len)
+{
+ struct af9005_device_state *st = d->priv;
+ u8 obuf[16] = { 0 };
+ u8 ibuf[17] = { 0 };
+ u8 command;
+ int i;
+ int ret;
+
+ if (len < 1) {
+ err("generic read/write, less than 1 byte. Makes no sense.");
+ return -EINVAL;
+ }
+ if (len > 8) {
+ err("generic read/write, more than 8 bytes. Not supported.");
+ return -EINVAL;
+ }
+
+ obuf[0] = 14; /* rest of buffer length low */
+ obuf[1] = 0; /* rest of buffer length high */
+
+ obuf[2] = AF9005_REGISTER_RW; /* register operation */
+ obuf[3] = 12; /* rest of buffer length */
+
+ obuf[4] = st->sequence++; /* sequence number */
+
+ obuf[5] = (u8) (reg >> 8); /* register address */
+ obuf[6] = (u8) (reg & 0xff);
+
+ if (type == AF9005_OFDM_REG) {
+ command = AF9005_CMD_OFDM_REG;
+ } else {
+ command = AF9005_CMD_TUNER;
+ }
+
+ if (len > 1)
+ command |=
+ AF9005_CMD_BURST | AF9005_CMD_AUTOINC | (len - 1) << 3;
+ command |= readwrite;
+ if (readwrite == AF9005_CMD_WRITE)
+ for (i = 0; i < len; i++)
+ obuf[8 + i] = values[i];
+ else if (type == AF9005_TUNER_REG)
+ /* read command for tuner, the first byte contains the i2c address */
+ obuf[8] = values[0];
+ obuf[7] = command;
+
+ ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
+ if (ret)
+ return ret;
+
+ /* sanity check */
+ if (ibuf[2] != AF9005_REGISTER_RW_ACK) {
+ err("generic read/write, wrong reply code.");
+ return -EIO;
+ }
+ if (ibuf[3] != 0x0d) {
+ err("generic read/write, wrong length in reply.");
+ return -EIO;
+ }
+ if (ibuf[4] != obuf[4]) {
+ err("generic read/write, wrong sequence in reply.");
+ return -EIO;
+ }
+ /*
+ Windows driver doesn't check these fields, in fact sometimes
+ the register in the reply is different that what has been sent
+
+ if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) {
+ err("generic read/write, wrong register in reply.");
+ return -EIO;
+ }
+ if (ibuf[7] != command) {
+ err("generic read/write wrong command in reply.");
+ return -EIO;
+ }
+ */
+ if (ibuf[16] != 0x01) {
+ err("generic read/write wrong status code in reply.");
+ return -EIO;
+ }
+ if (readwrite == AF9005_CMD_READ)
+ for (i = 0; i < len; i++)
+ values[i] = ibuf[8 + i];
+
+ return 0;
+
+}
+
+int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 * value)
+{
+ int ret;
+ deb_reg("read register %x ", reg);
+ ret = af9005_generic_read_write(d, reg,
+ AF9005_CMD_READ, AF9005_OFDM_REG,
+ value, 1);
+ if (ret)
+ deb_reg("failed\n");
+ else
+ deb_reg("value %x\n", *value);
+ return ret;
+}
+
+int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len)
+{
+ int ret;
+ deb_reg("read %d registers %x ", len, reg);
+ ret = af9005_generic_read_write(d, reg,
+ AF9005_CMD_READ, AF9005_OFDM_REG,
+ values, len);
+ if (ret)
+ deb_reg("failed\n");
+ else
+ debug_dump(values, len, deb_reg);
+ return ret;
+}
+
+int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 value)
+{
+ int ret;
+ u8 temp = value;
+ deb_reg("write register %x value %x ", reg, value);
+ ret = af9005_generic_read_write(d, reg,
+ AF9005_CMD_WRITE, AF9005_OFDM_REG,
+ &temp, 1);
+ if (ret)
+ deb_reg("failed\n");
+ else
+ deb_reg("ok\n");
+ return ret;
+}
+
+int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len)
+{
+ int ret;
+ deb_reg("write %d registers %x values ", len, reg);
+ debug_dump(values, len, deb_reg);
+
+ ret = af9005_generic_read_write(d, reg,
+ AF9005_CMD_WRITE, AF9005_OFDM_REG,
+ values, len);
+ if (ret)
+ deb_reg("failed\n");
+ else
+ deb_reg("ok\n");
+ return ret;
+}
+
+int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos,
+ u8 len, u8 * value)
+{
+ u8 temp;
+ int ret;
+ deb_reg("read bits %x %x %x", reg, pos, len);
+ ret = af9005_read_ofdm_register(d, reg, &temp);
+ if (ret) {
+ deb_reg(" failed\n");
+ return ret;
+ }
+ *value = (temp >> pos) & regmask[len - 1];
+ deb_reg(" value %x\n", *value);
+ return 0;
+
+}
+
+int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos,
+ u8 len, u8 value)
+{
+ u8 temp, mask;
+ int ret;
+ deb_reg("write bits %x %x %x value %x\n", reg, pos, len, value);
+ if (pos == 0 && len == 8)
+ return af9005_write_ofdm_register(d, reg, value);
+ ret = af9005_read_ofdm_register(d, reg, &temp);
+ if (ret)
+ return ret;
+ mask = regmask[len - 1] << pos;
+ temp = (temp & ~mask) | ((value << pos) & mask);
+ return af9005_write_ofdm_register(d, reg, temp);
+
+}
+
+static int af9005_usb_read_tuner_registers(struct dvb_usb_device *d,
+ u16 reg, u8 * values, int len)
+{
+ return af9005_generic_read_write(d, reg,
+ AF9005_CMD_READ, AF9005_TUNER_REG,
+ values, len);
+}
+
+static int af9005_usb_write_tuner_registers(struct dvb_usb_device *d,
+ u16 reg, u8 * values, int len)
+{
+ return af9005_generic_read_write(d, reg,
+ AF9005_CMD_WRITE,
+ AF9005_TUNER_REG, values, len);
+}
+
+int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len)
+{
+ /* don't let the name of this function mislead you: it's just used
+ as an interface from the firmware to the i2c bus. The actual
+ i2c addresses are contained in the data */
+ int ret, i, done = 0, fail = 0;
+ u8 temp;
+ ret = af9005_usb_write_tuner_registers(d, reg, values, len);
+ if (ret)
+ return ret;
+ if (reg != 0xffff) {
+ /* check if write done (0xa40d bit 1) or fail (0xa40d bit 2) */
+ for (i = 0; i < 200; i++) {
+ ret =
+ af9005_read_ofdm_register(d,
+ xd_I2C_i2c_m_status_wdat_done,
+ &temp);
+ if (ret)
+ return ret;
+ done = temp & (regmask[i2c_m_status_wdat_done_len - 1]
+ << i2c_m_status_wdat_done_pos);
+ if (done)
+ break;
+ fail = temp & (regmask[i2c_m_status_wdat_fail_len - 1]
+ << i2c_m_status_wdat_fail_pos);
+ if (fail)
+ break;
+ msleep(50);
+ }
+ if (i == 200)
+ return -ETIMEDOUT;
+ if (fail) {
+ /* clear write fail bit */
+ af9005_write_register_bits(d,
+ xd_I2C_i2c_m_status_wdat_fail,
+ i2c_m_status_wdat_fail_pos,
+ i2c_m_status_wdat_fail_len,
+ 1);
+ return -EIO;
+ }
+ /* clear write done bit */
+ ret =
+ af9005_write_register_bits(d,
+ xd_I2C_i2c_m_status_wdat_fail,
+ i2c_m_status_wdat_done_pos,
+ i2c_m_status_wdat_done_len, 1);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg, u8 addr,
+ u8 * values, int len)
+{
+ /* don't let the name of this function mislead you: it's just used
+ as an interface from the firmware to the i2c bus. The actual
+ i2c addresses are contained in the data */
+ int ret, i;
+ u8 temp, buf[2];
+
+ buf[0] = addr; /* tuner i2c address */
+ buf[1] = values[0]; /* tuner register */
+
+ values[0] = addr + 0x01; /* i2c read address */
+
+ if (reg == APO_REG_I2C_RW_SILICON_TUNER) {
+ /* write tuner i2c address to tuner, 0c00c0 undocumented, found by sniffing */
+ ret = af9005_write_tuner_registers(d, 0x00c0, buf, 2);
+ if (ret)
+ return ret;
+ }
+
+ /* send read command to ofsm */
+ ret = af9005_usb_read_tuner_registers(d, reg, values, 1);
+ if (ret)
+ return ret;
+
+ /* check if read done */
+ for (i = 0; i < 200; i++) {
+ ret = af9005_read_ofdm_register(d, 0xa408, &temp);
+ if (ret)
+ return ret;
+ if (temp & 0x01)
+ break;
+ msleep(50);
+ }
+ if (i == 200)
+ return -ETIMEDOUT;
+
+ /* clear read done bit (by writing 1) */
+ ret = af9005_write_ofdm_register(d, xd_I2C_i2c_m_data8, 1);
+ if (ret)
+ return ret;
+
+ /* get read data (available from 0xa400) */
+ for (i = 0; i < len; i++) {
+ ret = af9005_read_ofdm_register(d, 0xa400 + i, &temp);
+ if (ret)
+ return ret;
+ values[i] = temp;
+ }
+ return 0;
+}
+
+static int af9005_i2c_write(struct dvb_usb_device *d, u8 i2caddr, u8 reg,
+ u8 * data, int len)
+{
+ int ret, i;
+ u8 buf[3];
+ deb_i2c("i2c_write i2caddr %x, reg %x, len %d data ", i2caddr,
+ reg, len);
+ debug_dump(data, len, deb_i2c);
+
+ for (i = 0; i < len; i++) {
+ buf[0] = i2caddr;
+ buf[1] = reg + (u8) i;
+ buf[2] = data[i];
+ ret =
+ af9005_write_tuner_registers(d,
+ APO_REG_I2C_RW_SILICON_TUNER,
+ buf, 3);
+ if (ret) {
+ deb_i2c("i2c_write failed\n");
+ return ret;
+ }
+ }
+ deb_i2c("i2c_write ok\n");
+ return 0;
+}
+
+static int af9005_i2c_read(struct dvb_usb_device *d, u8 i2caddr, u8 reg,
+ u8 * data, int len)
+{
+ int ret, i;
+ u8 temp;
+ deb_i2c("i2c_read i2caddr %x, reg %x, len %d\n ", i2caddr, reg, len);
+ for (i = 0; i < len; i++) {
+ temp = reg + i;
+ ret =
+ af9005_read_tuner_registers(d,
+ APO_REG_I2C_RW_SILICON_TUNER,
+ i2caddr, &temp, 1);
+ if (ret) {
+ deb_i2c("i2c_read failed\n");
+ return ret;
+ }
+ data[i] = temp;
+ }
+ deb_i2c("i2c data read: ");
+ debug_dump(data, len, deb_i2c);
+ return 0;
+}
+
+static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ /* only implements what the mt2060 module does, don't know how
+ to make it really generic */
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret;
+ u8 reg, addr;
+ u8 *value;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ if (num > 2)
+ warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+ if (num == 2) {
+ /* reads a single register */
+ reg = *msg[0].buf;
+ addr = msg[0].addr;
+ value = msg[1].buf;
+ ret = af9005_i2c_read(d, addr, reg, value, 1);
+ if (ret == 0)
+ ret = 2;
+ } else {
+ /* write one or more registers */
+ reg = msg[0].buf[0];
+ addr = msg[0].addr;
+ value = &msg[0].buf[1];
+ ret = af9005_i2c_write(d, addr, reg, value, msg[0].len - 1);
+ if (ret == 0)
+ ret = 1;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return ret;
+}
+
+static u32 af9005_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm af9005_i2c_algo = {
+ .master_xfer = af9005_i2c_xfer,
+ .functionality = af9005_i2c_func,
+};
+
+int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
+ int wlen, u8 * rbuf, int rlen)
+{
+ struct af9005_device_state *st = d->priv;
+
+ int ret, i, packet_len;
+ u8 buf[64];
+ u8 ibuf[64];
+
+ if (wlen < 0) {
+ err("send command, wlen less than 0 bytes. Makes no sense.");
+ return -EINVAL;
+ }
+ if (wlen > 54) {
+ err("send command, wlen more than 54 bytes. Not supported.");
+ return -EINVAL;
+ }
+ if (rlen > 54) {
+ err("send command, rlen more than 54 bytes. Not supported.");
+ return -EINVAL;
+ }
+ packet_len = wlen + 5;
+ buf[0] = (u8) (packet_len & 0xff);
+ buf[1] = (u8) ((packet_len & 0xff00) >> 8);
+
+ buf[2] = 0x26; /* packet type */
+ buf[3] = wlen + 3;
+ buf[4] = st->sequence++;
+ buf[5] = command;
+ buf[6] = wlen;
+ for (i = 0; i < wlen; i++)
+ buf[7 + i] = wbuf[i];
+ ret = af9005_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
+ if (ret)
+ return ret;
+ if (ibuf[2] != 0x27) {
+ err("send command, wrong reply code.");
+ return -EIO;
+ }
+ if (ibuf[4] != buf[4]) {
+ err("send command, wrong sequence in reply.");
+ return -EIO;
+ }
+ if (ibuf[5] != 0x01) {
+ err("send command, wrong status code in reply.");
+ return -EIO;
+ }
+ if (ibuf[6] != rlen) {
+ err("send command, invalid data length in reply.");
+ return -EIO;
+ }
+ for (i = 0; i < rlen; i++)
+ rbuf[i] = ibuf[i + 7];
+ return 0;
+}
+
+int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
+ int len)
+{
+ struct af9005_device_state *st = d->priv;
+ u8 obuf[16], ibuf[14];
+ int ret, i;
+
+ memset(obuf, 0, sizeof(obuf));
+ memset(ibuf, 0, sizeof(ibuf));
+
+ obuf[0] = 14; /* length of rest of packet low */
+ obuf[1] = 0; /* length of rest of packer high */
+
+ obuf[2] = 0x2a; /* read/write eeprom */
+
+ obuf[3] = 12; /* size */
+
+ obuf[4] = st->sequence++;
+
+ obuf[5] = 0; /* read */
+
+ obuf[6] = len;
+ obuf[7] = address;
+ ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
+ if (ret)
+ return ret;
+ if (ibuf[2] != 0x2b) {
+ err("Read eeprom, invalid reply code");
+ return -EIO;
+ }
+ if (ibuf[3] != 10) {
+ err("Read eeprom, invalid reply length");
+ return -EIO;
+ }
+ if (ibuf[4] != obuf[4]) {
+ err("Read eeprom, wrong sequence in reply ");
+ return -EIO;
+ }
+ if (ibuf[5] != 1) {
+ err("Read eeprom, wrong status in reply ");
+ return -EIO;
+ }
+ for (i = 0; i < len; i++) {
+ values[i] = ibuf[6 + i];
+ }
+ return 0;
+}
+
+static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
+{
+ u8 buf[FW_BULKOUT_SIZE + 2];
+ u16 checksum;
+ int act_len, i, ret;
+ memset(buf, 0, sizeof(buf));
+ buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
+ buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
+ switch (type) {
+ case FW_CONFIG:
+ buf[2] = 0x11;
+ buf[3] = 0x04;
+ buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */
+ buf[5] = 0x03;
+ checksum = buf[4] + buf[5];
+ buf[6] = (u8) ((checksum >> 8) & 0xff);
+ buf[7] = (u8) (checksum & 0xff);
+ break;
+ case FW_CONFIRM:
+ buf[2] = 0x11;
+ buf[3] = 0x04;
+ buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */
+ buf[5] = 0x01;
+ checksum = buf[4] + buf[5];
+ buf[6] = (u8) ((checksum >> 8) & 0xff);
+ buf[7] = (u8) (checksum & 0xff);
+ break;
+ case FW_BOOT:
+ buf[2] = 0x10;
+ buf[3] = 0x08;
+ buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */
+ buf[5] = 0x97;
+ buf[6] = 0xaa;
+ buf[7] = 0x55;
+ buf[8] = 0xa5;
+ buf[9] = 0x5a;
+ checksum = 0;
+ for (i = 4; i <= 9; i++)
+ checksum += buf[i];
+ buf[10] = (u8) ((checksum >> 8) & 0xff);
+ buf[11] = (u8) (checksum & 0xff);
+ break;
+ default:
+ err("boot packet invalid boot packet type");
+ return -EINVAL;
+ }
+ deb_fw(">>> ");
+ debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);
+
+ ret = usb_bulk_msg(udev,
+ usb_sndbulkpipe(udev, 0x02),
+ buf, FW_BULKOUT_SIZE + 2, &act_len, 2000);
+ if (ret)
+ err("boot packet bulk message failed: %d (%d/%d)", ret,
+ FW_BULKOUT_SIZE + 2, act_len);
+ else
+ ret = act_len != FW_BULKOUT_SIZE + 2 ? -1 : 0;
+ if (ret)
+ return ret;
+ memset(buf, 0, 9);
+ ret = usb_bulk_msg(udev,
+ usb_rcvbulkpipe(udev, 0x01), buf, 9, &act_len, 2000);
+ if (ret) {
+ err("boot packet recv bulk message failed: %d", ret);
+ return ret;
+ }
+ deb_fw("<<< ");
+ debug_dump(buf, act_len, deb_fw);
+ checksum = 0;
+ switch (type) {
+ case FW_CONFIG:
+ if (buf[2] != 0x11) {
+ err("boot bad config header.");
+ return -EIO;
+ }
+ if (buf[3] != 0x05) {
+ err("boot bad config size.");
+ return -EIO;
+ }
+ if (buf[4] != 0x00) {
+ err("boot bad config sequence.");
+ return -EIO;
+ }
+ if (buf[5] != 0x04) {
+ err("boot bad config subtype.");
+ return -EIO;
+ }
+ for (i = 4; i <= 6; i++)
+ checksum += buf[i];
+ if (buf[7] * 256 + buf[8] != checksum) {
+ err("boot bad config checksum.");
+ return -EIO;
+ }
+ *reply = buf[6];
+ break;
+ case FW_CONFIRM:
+ if (buf[2] != 0x11) {
+ err("boot bad confirm header.");
+ return -EIO;
+ }
+ if (buf[3] != 0x05) {
+ err("boot bad confirm size.");
+ return -EIO;
+ }
+ if (buf[4] != 0x00) {
+ err("boot bad confirm sequence.");
+ return -EIO;
+ }
+ if (buf[5] != 0x02) {
+ err("boot bad confirm subtype.");
+ return -EIO;
+ }
+ for (i = 4; i <= 6; i++)
+ checksum += buf[i];
+ if (buf[7] * 256 + buf[8] != checksum) {
+ err("boot bad confirm checksum.");
+ return -EIO;
+ }
+ *reply = buf[6];
+ break;
+ case FW_BOOT:
+ if (buf[2] != 0x10) {
+ err("boot bad boot header.");
+ return -EIO;
+ }
+ if (buf[3] != 0x05) {
+ err("boot bad boot size.");
+ return -EIO;
+ }
+ if (buf[4] != 0x00) {
+ err("boot bad boot sequence.");
+ return -EIO;
+ }
+ if (buf[5] != 0x01) {
+ err("boot bad boot pattern 01.");
+ return -EIO;
+ }
+ if (buf[6] != 0x10) {
+ err("boot bad boot pattern 10.");
+ return -EIO;
+ }
+ for (i = 4; i <= 6; i++)
+ checksum += buf[i];
+ if (buf[7] * 256 + buf[8] != checksum) {
+ err("boot bad boot checksum.");
+ return -EIO;
+ }
+ break;
+
+ }
+
+ return 0;
+}
+
+int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
+{
+ int i, packets, ret, act_len;
+
+ u8 buf[FW_BULKOUT_SIZE + 2];
+ u8 reply;
+
+ ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+ if (ret)
+ return ret;
+ if (reply != 0x01) {
+ err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
+ return -EIO;
+ }
+ packets = fw->size / FW_BULKOUT_SIZE;
+ buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
+ buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
+ for (i = 0; i < packets; i++) {
+ memcpy(&buf[2], fw->data + i * FW_BULKOUT_SIZE,
+ FW_BULKOUT_SIZE);
+ deb_fw(">>> ");
+ debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);
+ ret = usb_bulk_msg(udev,
+ usb_sndbulkpipe(udev, 0x02),
+ buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
+ if (ret) {
+ err("firmware download failed at packet %d with code %d", i, ret);
+ return ret;
+ }
+ }
+ ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);
+ if (ret)
+ return ret;
+ if (reply != (u8) (packets & 0xff)) {
+ err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
+ return -EIO;
+ }
+ ret = af9005_boot_packet(udev, FW_BOOT, &reply);
+ if (ret)
+ return ret;
+ ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+ if (ret)
+ return ret;
+ if (reply != 0x02) {
+ err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);
+ return -EIO;
+ }
+
+ return 0;
+
+}
+
+int af9005_led_control(struct dvb_usb_device *d, int onoff)
+{
+ struct af9005_device_state *st = d->priv;
+ int temp, ret;
+
+ if (onoff && dvb_usb_af9005_led)
+ temp = 1;
+ else
+ temp = 0;
+ if (st->led_state != temp) {
+ ret =
+ af9005_write_register_bits(d, xd_p_reg_top_locken1,
+ reg_top_locken1_pos,
+ reg_top_locken1_len, temp);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_register_bits(d, xd_p_reg_top_lock1,
+ reg_top_lock1_pos,
+ reg_top_lock1_len, temp);
+ if (ret)
+ return ret;
+ st->led_state = temp;
+ }
+ return 0;
+}
+
+static int af9005_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ u8 buf[8];
+ int i;
+
+ /* without these calls the first commands after downloading
+ the firmware fail. I put these calls here to simulate
+ what it is done in dvb-usb-init.c.
+ */
+ struct usb_device *udev = adap->dev->udev;
+ usb_clear_halt(udev, usb_sndbulkpipe(udev, 2));
+ usb_clear_halt(udev, usb_rcvbulkpipe(udev, 1));
+ if (dvb_usb_af9005_dump_eeprom) {
+ printk("EEPROM DUMP\n");
+ for (i = 0; i < 255; i += 8) {
+ af9005_read_eeprom(adap->dev, i, buf, 8);
+ printk("ADDR %x ", i);
+ debug_dump(buf, 8, printk);
+ }
+ }
+ adap->fe = af9005_fe_attach(adap->dev);
+ return 0;
+}
+
+static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
+{
+ struct af9005_device_state *st = d->priv;
+ int ret, len;
+
+ u8 obuf[5];
+ u8 ibuf[256];
+
+ *state = REMOTE_NO_KEY_PRESSED;
+ if (rc_decode == NULL) {
+ /* it shouldn't never come here */
+ return 0;
+ }
+ /* deb_info("rc_query\n"); */
+ obuf[0] = 3; /* rest of packet length low */
+ obuf[1] = 0; /* rest of packet lentgh high */
+ obuf[2] = 0x40; /* read remote */
+ obuf[3] = 1; /* rest of packet length */
+ obuf[4] = st->sequence++; /* sequence number */
+ ret = af9005_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
+ if (ret) {
+ err("rc query failed");
+ return ret;
+ }
+ if (ibuf[2] != 0x41) {
+ err("rc query bad header.");
+ return -EIO;
+ }
+ if (ibuf[4] != obuf[4]) {
+ err("rc query bad sequence.");
+ return -EIO;
+ }
+ len = ibuf[5];
+ if (len > 246) {
+ err("rc query invalid length");
+ return -EIO;
+ }
+ if (len > 0) {
+ deb_rc("rc data (%d) ", len);
+ debug_dump((ibuf + 6), len, deb_rc);
+ ret = rc_decode(d, &ibuf[6], len, event, state);
+ if (ret) {
+ err("rc_decode failed");
+ return ret;
+ } else {
+ deb_rc("rc_decode state %x event %x\n", *state, *event);
+ if (*state == REMOTE_KEY_REPEAT)
+ *event = d->last_event;
+ }
+ }
+ return 0;
+}
+
+static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+
+ return 0;
+}
+
+static int af9005_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret;
+ deb_info("pid filter control onoff %d\n", onoff);
+ if (onoff) {
+ ret =
+ af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_register_bits(adap->dev,
+ XD_MP2IF_DMX_CTRL, 1, 1, 1);
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);
+ } else
+ ret =
+ af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 0);
+ if (ret)
+ return ret;
+ deb_info("pid filter control ok\n");
+ return 0;
+}
+
+static int af9005_pid_filter(struct dvb_usb_adapter *adap, int index,
+ u16 pid, int onoff)
+{
+ u8 cmd = index & 0x1f;
+ int ret;
+ deb_info("set pid filter, index %d, pid %x, onoff %d\n", index,
+ pid, onoff);
+ if (onoff) {
+ /* cannot use it as pid_filter_ctrl since it has to be done
+ before setting the first pid */
+ if (adap->feedcount == 1) {
+ deb_info("first pid set, enable pid table\n");
+ ret = af9005_pid_filter_control(adap, onoff);
+ if (ret)
+ return ret;
+ }
+ ret =
+ af9005_write_ofdm_register(adap->dev,
+ XD_MP2IF_PID_DATA_L,
+ (u8) (pid & 0xff));
+ if (ret)
+ return ret;
+ ret =
+ af9005_write_ofdm_register(adap->dev,
+ XD_MP2IF_PID_DATA_H,
+ (u8) (pid >> 8));
+ if (ret)
+ return ret;
+ cmd |= 0x20 | 0x40;
+ } else {
+ if (adap->feedcount == 0) {
+ deb_info("last pid unset, disable pid table\n");
+ ret = af9005_pid_filter_control(adap, onoff);
+ if (ret)
+ return ret;
+ }
+ }
+ ret = af9005_write_ofdm_register(adap->dev, XD_MP2IF_PID_IDX, cmd);
+ if (ret)
+ return ret;
+ deb_info("set pid ok\n");
+ return 0;
+}
+
+static int af9005_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ int ret;
+ u8 reply;
+ ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+ if (ret)
+ return ret;
+ deb_info("result of FW_CONFIG in identify state %d\n", reply);
+ if (reply == 0x01)
+ *cold = 1;
+ else if (reply == 0x02)
+ *cold = 0;
+ else
+ return -EIO;
+ deb_info("Identify state cold = %d\n", *cold);
+ return 0;
+}
+
+static struct dvb_usb_device_properties af9005_properties;
+
+static int af9005_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
+}
+
+static struct usb_device_id af9005_usb_table[] = {
+ {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},
+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},
+ {0},
+};
+
+MODULE_DEVICE_TABLE(usb, af9005_usb_table);
+
+static struct dvb_usb_device_properties af9005_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "af9005.fw",
+ .download_firmware = af9005_download_firmware,
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct af9005_device_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .caps =
+ DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+ .pid_filter_count = 32,
+ .pid_filter = af9005_pid_filter,
+ /* .pid_filter_ctrl = af9005_pid_filter_control, */
+ .frontend_attach = af9005_frontend_attach,
+ /* .tuner_attach = af9005_tuner_attach, */
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 10,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 4096, /* actual size seen is 3948 */
+ }
+ }
+ },
+ }
+ },
+ .power_ctrl = af9005_power_ctrl,
+ .identify_state = af9005_identify_state,
+
+ .i2c_algo = &af9005_i2c_algo,
+
+ .rc_interval = 200,
+ .rc_key_map = NULL,
+ .rc_key_map_size = 0,
+ .rc_query = af9005_rc_query,
+
+ .num_device_descs = 2,
+ .devices = {
+ {.name = "Afatech DVB-T USB1.1 stick",
+ .cold_ids = {&af9005_usb_table[0], NULL},
+ .warm_ids = {NULL},
+ },
+ {.name = "TerraTec Cinergy T USB XE",
+ .cold_ids = {&af9005_usb_table[1], NULL},
+ .warm_ids = {NULL},
+ },
+ {NULL},
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver af9005_usb_driver = {
+ .name = "dvb_usb_af9005",
+ .probe = af9005_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = af9005_usb_table,
+};
+
+/* module stuff */
+static int __init af9005_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&af9005_usb_driver))) {
+ err("usb_register failed. (%d)", result);
+ return result;
+ }
+ rc_decode = symbol_request(af9005_rc_decode);
+ rc_keys = symbol_request(af9005_rc_keys);
+ rc_keys_size = symbol_request(af9005_rc_keys_size);
+ if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
+ err("af9005_rc_decode function not found, disabling remote");
+ af9005_properties.rc_query = NULL;
+ } else {
+ af9005_properties.rc_key_map = rc_keys;
+ af9005_properties.rc_key_map_size = *rc_keys_size;
+ }
+
+ return 0;
+}
+
+static void __exit af9005_usb_module_exit(void)
+{
+ /* release rc decode symbols */
+ if (rc_decode != NULL)
+ symbol_put(af9005_rc_decode);
+ if (rc_keys != NULL)
+ symbol_put(af9005_rc_keys);
+ if (rc_keys_size != NULL)
+ symbol_put(af9005_rc_keys_size);
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&af9005_usb_driver);
+}
+
+module_init(af9005_usb_module_init);
+module_exit(af9005_usb_module_exit);
+
+MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
+MODULE_DESCRIPTION("Driver for Afatech 9005 DVB-T USB1.1 stick");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h
new file mode 100644
index 000000000000..0bc48a012187
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9005.h
@@ -0,0 +1,3496 @@
+/* Common header-file of the Linux driver for the Afatech 9005
+ * USB1.1 DVB-T receiver.
+ *
+ * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_AF9005_H_
+#define _DVB_USB_AF9005_H_
+
+#define DVB_USB_LOG_PREFIX "af9005"
+#include "dvb-usb.h"
+
+extern int dvb_usb_af9005_debug;
+#define deb_info(args...) dprintk(dvb_usb_af9005_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_af9005_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_af9005_debug,0x04,args)
+#define deb_reg(args...) dprintk(dvb_usb_af9005_debug,0x08,args)
+#define deb_i2c(args...) dprintk(dvb_usb_af9005_debug,0x10,args)
+#define deb_fw(args...) dprintk(dvb_usb_af9005_debug,0x20,args)
+
+extern int dvb_usb_af9005_led;
+
+/* firmware */
+#define FW_BULKOUT_SIZE 250
+enum {
+ FW_CONFIG,
+ FW_CONFIRM,
+ FW_BOOT
+};
+
+/* af9005 commands */
+#define AF9005_OFDM_REG 0
+#define AF9005_TUNER_REG 1
+
+#define AF9005_REGISTER_RW 0x20
+#define AF9005_REGISTER_RW_ACK 0x21
+
+#define AF9005_CMD_OFDM_REG 0x00
+#define AF9005_CMD_TUNER 0x80
+#define AF9005_CMD_BURST 0x02
+#define AF9005_CMD_AUTOINC 0x04
+#define AF9005_CMD_READ 0x00
+#define AF9005_CMD_WRITE 0x01
+
+/* af9005 registers */
+#define APO_REG_RESET 0xAEFF
+
+#define APO_REG_I2C_RW_CAN_TUNER 0xF000
+#define APO_REG_I2C_RW_SILICON_TUNER 0xF001
+#define APO_REG_GPIO_RW_SILICON_TUNER 0xFFFE /* also for OFSM */
+#define APO_REG_TRIGGER_OFSM 0xFFFF /* also for OFSM */
+
+/***********************************************************************
+ * Apollo Registers from VLSI *
+ ***********************************************************************/
+#define xd_p_reg_aagc_inverted_agc 0xA000
+#define reg_aagc_inverted_agc_pos 0
+#define reg_aagc_inverted_agc_len 1
+#define reg_aagc_inverted_agc_lsb 0
+#define xd_p_reg_aagc_sign_only 0xA000
+#define reg_aagc_sign_only_pos 1
+#define reg_aagc_sign_only_len 1
+#define reg_aagc_sign_only_lsb 0
+#define xd_p_reg_aagc_slow_adc_en 0xA000
+#define reg_aagc_slow_adc_en_pos 2
+#define reg_aagc_slow_adc_en_len 1
+#define reg_aagc_slow_adc_en_lsb 0
+#define xd_p_reg_aagc_slow_adc_scale 0xA000
+#define reg_aagc_slow_adc_scale_pos 3
+#define reg_aagc_slow_adc_scale_len 5
+#define reg_aagc_slow_adc_scale_lsb 0
+#define xd_p_reg_aagc_check_slow_adc_lock 0xA001
+#define reg_aagc_check_slow_adc_lock_pos 0
+#define reg_aagc_check_slow_adc_lock_len 1
+#define reg_aagc_check_slow_adc_lock_lsb 0
+#define xd_p_reg_aagc_init_control 0xA001
+#define reg_aagc_init_control_pos 1
+#define reg_aagc_init_control_len 1
+#define reg_aagc_init_control_lsb 0
+#define xd_p_reg_aagc_total_gain_sel 0xA001
+#define reg_aagc_total_gain_sel_pos 2
+#define reg_aagc_total_gain_sel_len 2
+#define reg_aagc_total_gain_sel_lsb 0
+#define xd_p_reg_aagc_out_inv 0xA001
+#define reg_aagc_out_inv_pos 5
+#define reg_aagc_out_inv_len 1
+#define reg_aagc_out_inv_lsb 0
+#define xd_p_reg_aagc_int_en 0xA001
+#define reg_aagc_int_en_pos 6
+#define reg_aagc_int_en_len 1
+#define reg_aagc_int_en_lsb 0
+#define xd_p_reg_aagc_lock_change_flag 0xA001
+#define reg_aagc_lock_change_flag_pos 7
+#define reg_aagc_lock_change_flag_len 1
+#define reg_aagc_lock_change_flag_lsb 0
+#define xd_p_reg_aagc_rf_loop_bw_scale_acquire 0xA002
+#define reg_aagc_rf_loop_bw_scale_acquire_pos 0
+#define reg_aagc_rf_loop_bw_scale_acquire_len 5
+#define reg_aagc_rf_loop_bw_scale_acquire_lsb 0
+#define xd_p_reg_aagc_rf_loop_bw_scale_track 0xA003
+#define reg_aagc_rf_loop_bw_scale_track_pos 0
+#define reg_aagc_rf_loop_bw_scale_track_len 5
+#define reg_aagc_rf_loop_bw_scale_track_lsb 0
+#define xd_p_reg_aagc_if_loop_bw_scale_acquire 0xA004
+#define reg_aagc_if_loop_bw_scale_acquire_pos 0
+#define reg_aagc_if_loop_bw_scale_acquire_len 5
+#define reg_aagc_if_loop_bw_scale_acquire_lsb 0
+#define xd_p_reg_aagc_if_loop_bw_scale_track 0xA005
+#define reg_aagc_if_loop_bw_scale_track_pos 0
+#define reg_aagc_if_loop_bw_scale_track_len 5
+#define reg_aagc_if_loop_bw_scale_track_lsb 0
+#define xd_p_reg_aagc_max_rf_agc_7_0 0xA006
+#define reg_aagc_max_rf_agc_7_0_pos 0
+#define reg_aagc_max_rf_agc_7_0_len 8
+#define reg_aagc_max_rf_agc_7_0_lsb 0
+#define xd_p_reg_aagc_max_rf_agc_9_8 0xA007
+#define reg_aagc_max_rf_agc_9_8_pos 0
+#define reg_aagc_max_rf_agc_9_8_len 2
+#define reg_aagc_max_rf_agc_9_8_lsb 8
+#define xd_p_reg_aagc_min_rf_agc_7_0 0xA008
+#define reg_aagc_min_rf_agc_7_0_pos 0
+#define reg_aagc_min_rf_agc_7_0_len 8
+#define reg_aagc_min_rf_agc_7_0_lsb 0
+#define xd_p_reg_aagc_min_rf_agc_9_8 0xA009
+#define reg_aagc_min_rf_agc_9_8_pos 0
+#define reg_aagc_min_rf_agc_9_8_len 2
+#define reg_aagc_min_rf_agc_9_8_lsb 8
+#define xd_p_reg_aagc_max_if_agc_7_0 0xA00A
+#define reg_aagc_max_if_agc_7_0_pos 0
+#define reg_aagc_max_if_agc_7_0_len 8
+#define reg_aagc_max_if_agc_7_0_lsb 0
+#define xd_p_reg_aagc_max_if_agc_9_8 0xA00B
+#define reg_aagc_max_if_agc_9_8_pos 0
+#define reg_aagc_max_if_agc_9_8_len 2
+#define reg_aagc_max_if_agc_9_8_lsb 8
+#define xd_p_reg_aagc_min_if_agc_7_0 0xA00C
+#define reg_aagc_min_if_agc_7_0_pos 0
+#define reg_aagc_min_if_agc_7_0_len 8
+#define reg_aagc_min_if_agc_7_0_lsb 0
+#define xd_p_reg_aagc_min_if_agc_9_8 0xA00D
+#define reg_aagc_min_if_agc_9_8_pos 0
+#define reg_aagc_min_if_agc_9_8_len 2
+#define reg_aagc_min_if_agc_9_8_lsb 8
+#define xd_p_reg_aagc_lock_sample_scale 0xA00E
+#define reg_aagc_lock_sample_scale_pos 0
+#define reg_aagc_lock_sample_scale_len 5
+#define reg_aagc_lock_sample_scale_lsb 0
+#define xd_p_reg_aagc_rf_agc_lock_scale_acquire 0xA00F
+#define reg_aagc_rf_agc_lock_scale_acquire_pos 0
+#define reg_aagc_rf_agc_lock_scale_acquire_len 3
+#define reg_aagc_rf_agc_lock_scale_acquire_lsb 0
+#define xd_p_reg_aagc_rf_agc_lock_scale_track 0xA00F
+#define reg_aagc_rf_agc_lock_scale_track_pos 3
+#define reg_aagc_rf_agc_lock_scale_track_len 3
+#define reg_aagc_rf_agc_lock_scale_track_lsb 0
+#define xd_p_reg_aagc_if_agc_lock_scale_acquire 0xA010
+#define reg_aagc_if_agc_lock_scale_acquire_pos 0
+#define reg_aagc_if_agc_lock_scale_acquire_len 3
+#define reg_aagc_if_agc_lock_scale_acquire_lsb 0
+#define xd_p_reg_aagc_if_agc_lock_scale_track 0xA010
+#define reg_aagc_if_agc_lock_scale_track_pos 3
+#define reg_aagc_if_agc_lock_scale_track_len 3
+#define reg_aagc_if_agc_lock_scale_track_lsb 0
+#define xd_p_reg_aagc_rf_top_numerator_7_0 0xA011
+#define reg_aagc_rf_top_numerator_7_0_pos 0
+#define reg_aagc_rf_top_numerator_7_0_len 8
+#define reg_aagc_rf_top_numerator_7_0_lsb 0
+#define xd_p_reg_aagc_rf_top_numerator_9_8 0xA012
+#define reg_aagc_rf_top_numerator_9_8_pos 0
+#define reg_aagc_rf_top_numerator_9_8_len 2
+#define reg_aagc_rf_top_numerator_9_8_lsb 8
+#define xd_p_reg_aagc_if_top_numerator_7_0 0xA013
+#define reg_aagc_if_top_numerator_7_0_pos 0
+#define reg_aagc_if_top_numerator_7_0_len 8
+#define reg_aagc_if_top_numerator_7_0_lsb 0
+#define xd_p_reg_aagc_if_top_numerator_9_8 0xA014
+#define reg_aagc_if_top_numerator_9_8_pos 0
+#define reg_aagc_if_top_numerator_9_8_len 2
+#define reg_aagc_if_top_numerator_9_8_lsb 8
+#define xd_p_reg_aagc_adc_out_desired_7_0 0xA015
+#define reg_aagc_adc_out_desired_7_0_pos 0
+#define reg_aagc_adc_out_desired_7_0_len 8
+#define reg_aagc_adc_out_desired_7_0_lsb 0
+#define xd_p_reg_aagc_adc_out_desired_8 0xA016
+#define reg_aagc_adc_out_desired_8_pos 0
+#define reg_aagc_adc_out_desired_8_len 1
+#define reg_aagc_adc_out_desired_8_lsb 0
+#define xd_p_reg_aagc_fixed_gain 0xA016
+#define reg_aagc_fixed_gain_pos 3
+#define reg_aagc_fixed_gain_len 1
+#define reg_aagc_fixed_gain_lsb 0
+#define xd_p_reg_aagc_lock_count_th 0xA016
+#define reg_aagc_lock_count_th_pos 4
+#define reg_aagc_lock_count_th_len 4
+#define reg_aagc_lock_count_th_lsb 0
+#define xd_p_reg_aagc_fixed_rf_agc_control_7_0 0xA017
+#define reg_aagc_fixed_rf_agc_control_7_0_pos 0
+#define reg_aagc_fixed_rf_agc_control_7_0_len 8
+#define reg_aagc_fixed_rf_agc_control_7_0_lsb 0
+#define xd_p_reg_aagc_fixed_rf_agc_control_15_8 0xA018
+#define reg_aagc_fixed_rf_agc_control_15_8_pos 0
+#define reg_aagc_fixed_rf_agc_control_15_8_len 8
+#define reg_aagc_fixed_rf_agc_control_15_8_lsb 8
+#define xd_p_reg_aagc_fixed_rf_agc_control_23_16 0xA019
+#define reg_aagc_fixed_rf_agc_control_23_16_pos 0
+#define reg_aagc_fixed_rf_agc_control_23_16_len 8
+#define reg_aagc_fixed_rf_agc_control_23_16_lsb 16
+#define xd_p_reg_aagc_fixed_rf_agc_control_30_24 0xA01A
+#define reg_aagc_fixed_rf_agc_control_30_24_pos 0
+#define reg_aagc_fixed_rf_agc_control_30_24_len 7
+#define reg_aagc_fixed_rf_agc_control_30_24_lsb 24
+#define xd_p_reg_aagc_fixed_if_agc_control_7_0 0xA01B
+#define reg_aagc_fixed_if_agc_control_7_0_pos 0
+#define reg_aagc_fixed_if_agc_control_7_0_len 8
+#define reg_aagc_fixed_if_agc_control_7_0_lsb 0
+#define xd_p_reg_aagc_fixed_if_agc_control_15_8 0xA01C
+#define reg_aagc_fixed_if_agc_control_15_8_pos 0
+#define reg_aagc_fixed_if_agc_control_15_8_len 8
+#define reg_aagc_fixed_if_agc_control_15_8_lsb 8
+#define xd_p_reg_aagc_fixed_if_agc_control_23_16 0xA01D
+#define reg_aagc_fixed_if_agc_control_23_16_pos 0
+#define reg_aagc_fixed_if_agc_control_23_16_len 8
+#define reg_aagc_fixed_if_agc_control_23_16_lsb 16
+#define xd_p_reg_aagc_fixed_if_agc_control_30_24 0xA01E
+#define reg_aagc_fixed_if_agc_control_30_24_pos 0
+#define reg_aagc_fixed_if_agc_control_30_24_len 7
+#define reg_aagc_fixed_if_agc_control_30_24_lsb 24
+#define xd_p_reg_aagc_rf_agc_unlock_numerator 0xA01F
+#define reg_aagc_rf_agc_unlock_numerator_pos 0
+#define reg_aagc_rf_agc_unlock_numerator_len 6
+#define reg_aagc_rf_agc_unlock_numerator_lsb 0
+#define xd_p_reg_aagc_if_agc_unlock_numerator 0xA020
+#define reg_aagc_if_agc_unlock_numerator_pos 0
+#define reg_aagc_if_agc_unlock_numerator_len 6
+#define reg_aagc_if_agc_unlock_numerator_lsb 0
+#define xd_p_reg_unplug_th 0xA021
+#define reg_unplug_th_pos 0
+#define reg_unplug_th_len 8
+#define reg_aagc_rf_x0_lsb 0
+#define xd_p_reg_weak_signal_rfagc_thr 0xA022
+#define reg_weak_signal_rfagc_thr_pos 0
+#define reg_weak_signal_rfagc_thr_len 8
+#define reg_weak_signal_rfagc_thr_lsb 0
+#define xd_p_reg_unplug_rf_gain_th 0xA023
+#define reg_unplug_rf_gain_th_pos 0
+#define reg_unplug_rf_gain_th_len 8
+#define reg_unplug_rf_gain_th_lsb 0
+#define xd_p_reg_unplug_dtop_rf_gain_th 0xA024
+#define reg_unplug_dtop_rf_gain_th_pos 0
+#define reg_unplug_dtop_rf_gain_th_len 8
+#define reg_unplug_dtop_rf_gain_th_lsb 0
+#define xd_p_reg_unplug_dtop_if_gain_th 0xA025
+#define reg_unplug_dtop_if_gain_th_pos 0
+#define reg_unplug_dtop_if_gain_th_len 8
+#define reg_unplug_dtop_if_gain_th_lsb 0
+#define xd_p_reg_top_recover_at_unplug_en 0xA026
+#define reg_top_recover_at_unplug_en_pos 0
+#define reg_top_recover_at_unplug_en_len 1
+#define reg_top_recover_at_unplug_en_lsb 0
+#define xd_p_reg_aagc_rf_x6 0xA027
+#define reg_aagc_rf_x6_pos 0
+#define reg_aagc_rf_x6_len 8
+#define reg_aagc_rf_x6_lsb 0
+#define xd_p_reg_aagc_rf_x7 0xA028
+#define reg_aagc_rf_x7_pos 0
+#define reg_aagc_rf_x7_len 8
+#define reg_aagc_rf_x7_lsb 0
+#define xd_p_reg_aagc_rf_x8 0xA029
+#define reg_aagc_rf_x8_pos 0
+#define reg_aagc_rf_x8_len 8
+#define reg_aagc_rf_x8_lsb 0
+#define xd_p_reg_aagc_rf_x9 0xA02A
+#define reg_aagc_rf_x9_pos 0
+#define reg_aagc_rf_x9_len 8
+#define reg_aagc_rf_x9_lsb 0
+#define xd_p_reg_aagc_rf_x10 0xA02B
+#define reg_aagc_rf_x10_pos 0
+#define reg_aagc_rf_x10_len 8
+#define reg_aagc_rf_x10_lsb 0
+#define xd_p_reg_aagc_rf_x11 0xA02C
+#define reg_aagc_rf_x11_pos 0
+#define reg_aagc_rf_x11_len 8
+#define reg_aagc_rf_x11_lsb 0
+#define xd_p_reg_aagc_rf_x12 0xA02D
+#define reg_aagc_rf_x12_pos 0
+#define reg_aagc_rf_x12_len 8
+#define reg_aagc_rf_x12_lsb 0
+#define xd_p_reg_aagc_rf_x13 0xA02E
+#define reg_aagc_rf_x13_pos 0
+#define reg_aagc_rf_x13_len 8
+#define reg_aagc_rf_x13_lsb 0
+#define xd_p_reg_aagc_if_x0 0xA02F
+#define reg_aagc_if_x0_pos 0
+#define reg_aagc_if_x0_len 8
+#define reg_aagc_if_x0_lsb 0
+#define xd_p_reg_aagc_if_x1 0xA030
+#define reg_aagc_if_x1_pos 0
+#define reg_aagc_if_x1_len 8
+#define reg_aagc_if_x1_lsb 0
+#define xd_p_reg_aagc_if_x2 0xA031
+#define reg_aagc_if_x2_pos 0
+#define reg_aagc_if_x2_len 8
+#define reg_aagc_if_x2_lsb 0
+#define xd_p_reg_aagc_if_x3 0xA032
+#define reg_aagc_if_x3_pos 0
+#define reg_aagc_if_x3_len 8
+#define reg_aagc_if_x3_lsb 0
+#define xd_p_reg_aagc_if_x4 0xA033
+#define reg_aagc_if_x4_pos 0
+#define reg_aagc_if_x4_len 8
+#define reg_aagc_if_x4_lsb 0
+#define xd_p_reg_aagc_if_x5 0xA034
+#define reg_aagc_if_x5_pos 0
+#define reg_aagc_if_x5_len 8
+#define reg_aagc_if_x5_lsb 0
+#define xd_p_reg_aagc_if_x6 0xA035
+#define reg_aagc_if_x6_pos 0
+#define reg_aagc_if_x6_len 8
+#define reg_aagc_if_x6_lsb 0
+#define xd_p_reg_aagc_if_x7 0xA036
+#define reg_aagc_if_x7_pos 0
+#define reg_aagc_if_x7_len 8
+#define reg_aagc_if_x7_lsb 0
+#define xd_p_reg_aagc_if_x8 0xA037
+#define reg_aagc_if_x8_pos 0
+#define reg_aagc_if_x8_len 8
+#define reg_aagc_if_x8_lsb 0
+#define xd_p_reg_aagc_if_x9 0xA038
+#define reg_aagc_if_x9_pos 0
+#define reg_aagc_if_x9_len 8
+#define reg_aagc_if_x9_lsb 0
+#define xd_p_reg_aagc_if_x10 0xA039
+#define reg_aagc_if_x10_pos 0
+#define reg_aagc_if_x10_len 8
+#define reg_aagc_if_x10_lsb 0
+#define xd_p_reg_aagc_if_x11 0xA03A
+#define reg_aagc_if_x11_pos 0
+#define reg_aagc_if_x11_len 8
+#define reg_aagc_if_x11_lsb 0
+#define xd_p_reg_aagc_if_x12 0xA03B
+#define reg_aagc_if_x12_pos 0
+#define reg_aagc_if_x12_len 8
+#define reg_aagc_if_x12_lsb 0
+#define xd_p_reg_aagc_if_x13 0xA03C
+#define reg_aagc_if_x13_pos 0
+#define reg_aagc_if_x13_len 8
+#define reg_aagc_if_x13_lsb 0
+#define xd_p_reg_aagc_min_rf_ctl_8bit_for_dca 0xA03D
+#define reg_aagc_min_rf_ctl_8bit_for_dca_pos 0
+#define reg_aagc_min_rf_ctl_8bit_for_dca_len 8
+#define reg_aagc_min_rf_ctl_8bit_for_dca_lsb 0
+#define xd_p_reg_aagc_min_if_ctl_8bit_for_dca 0xA03E
+#define reg_aagc_min_if_ctl_8bit_for_dca_pos 0
+#define reg_aagc_min_if_ctl_8bit_for_dca_len 8
+#define reg_aagc_min_if_ctl_8bit_for_dca_lsb 0
+#define xd_r_reg_aagc_total_gain_7_0 0xA070
+#define reg_aagc_total_gain_7_0_pos 0
+#define reg_aagc_total_gain_7_0_len 8
+#define reg_aagc_total_gain_7_0_lsb 0
+#define xd_r_reg_aagc_total_gain_15_8 0xA071
+#define reg_aagc_total_gain_15_8_pos 0
+#define reg_aagc_total_gain_15_8_len 8
+#define reg_aagc_total_gain_15_8_lsb 8
+#define xd_p_reg_aagc_in_sat_cnt_7_0 0xA074
+#define reg_aagc_in_sat_cnt_7_0_pos 0
+#define reg_aagc_in_sat_cnt_7_0_len 8
+#define reg_aagc_in_sat_cnt_7_0_lsb 0
+#define xd_p_reg_aagc_in_sat_cnt_15_8 0xA075
+#define reg_aagc_in_sat_cnt_15_8_pos 0
+#define reg_aagc_in_sat_cnt_15_8_len 8
+#define reg_aagc_in_sat_cnt_15_8_lsb 8
+#define xd_p_reg_aagc_in_sat_cnt_23_16 0xA076
+#define reg_aagc_in_sat_cnt_23_16_pos 0
+#define reg_aagc_in_sat_cnt_23_16_len 8
+#define reg_aagc_in_sat_cnt_23_16_lsb 16
+#define xd_p_reg_aagc_in_sat_cnt_31_24 0xA077
+#define reg_aagc_in_sat_cnt_31_24_pos 0
+#define reg_aagc_in_sat_cnt_31_24_len 8
+#define reg_aagc_in_sat_cnt_31_24_lsb 24
+#define xd_r_reg_aagc_digital_rf_volt_7_0 0xA078
+#define reg_aagc_digital_rf_volt_7_0_pos 0
+#define reg_aagc_digital_rf_volt_7_0_len 8
+#define reg_aagc_digital_rf_volt_7_0_lsb 0
+#define xd_r_reg_aagc_digital_rf_volt_9_8 0xA079
+#define reg_aagc_digital_rf_volt_9_8_pos 0
+#define reg_aagc_digital_rf_volt_9_8_len 2
+#define reg_aagc_digital_rf_volt_9_8_lsb 8
+#define xd_r_reg_aagc_digital_if_volt_7_0 0xA07A
+#define reg_aagc_digital_if_volt_7_0_pos 0
+#define reg_aagc_digital_if_volt_7_0_len 8
+#define reg_aagc_digital_if_volt_7_0_lsb 0
+#define xd_r_reg_aagc_digital_if_volt_9_8 0xA07B
+#define reg_aagc_digital_if_volt_9_8_pos 0
+#define reg_aagc_digital_if_volt_9_8_len 2
+#define reg_aagc_digital_if_volt_9_8_lsb 8
+#define xd_r_reg_aagc_rf_gain 0xA07C
+#define reg_aagc_rf_gain_pos 0
+#define reg_aagc_rf_gain_len 8
+#define reg_aagc_rf_gain_lsb 0
+#define xd_r_reg_aagc_if_gain 0xA07D
+#define reg_aagc_if_gain_pos 0
+#define reg_aagc_if_gain_len 8
+#define reg_aagc_if_gain_lsb 0
+#define xd_p_tinr_imp_indicator 0xA080
+#define tinr_imp_indicator_pos 0
+#define tinr_imp_indicator_len 2
+#define tinr_imp_indicator_lsb 0
+#define xd_p_reg_tinr_fifo_size 0xA080
+#define reg_tinr_fifo_size_pos 2
+#define reg_tinr_fifo_size_len 5
+#define reg_tinr_fifo_size_lsb 0
+#define xd_p_reg_tinr_saturation_cnt_th 0xA081
+#define reg_tinr_saturation_cnt_th_pos 0
+#define reg_tinr_saturation_cnt_th_len 4
+#define reg_tinr_saturation_cnt_th_lsb 0
+#define xd_p_reg_tinr_saturation_th_3_0 0xA081
+#define reg_tinr_saturation_th_3_0_pos 4
+#define reg_tinr_saturation_th_3_0_len 4
+#define reg_tinr_saturation_th_3_0_lsb 0
+#define xd_p_reg_tinr_saturation_th_8_4 0xA082
+#define reg_tinr_saturation_th_8_4_pos 0
+#define reg_tinr_saturation_th_8_4_len 5
+#define reg_tinr_saturation_th_8_4_lsb 4
+#define xd_p_reg_tinr_imp_duration_th_2k_7_0 0xA083
+#define reg_tinr_imp_duration_th_2k_7_0_pos 0
+#define reg_tinr_imp_duration_th_2k_7_0_len 8
+#define reg_tinr_imp_duration_th_2k_7_0_lsb 0
+#define xd_p_reg_tinr_imp_duration_th_2k_8 0xA084
+#define reg_tinr_imp_duration_th_2k_8_pos 0
+#define reg_tinr_imp_duration_th_2k_8_len 1
+#define reg_tinr_imp_duration_th_2k_8_lsb 0
+#define xd_p_reg_tinr_imp_duration_th_8k_7_0 0xA085
+#define reg_tinr_imp_duration_th_8k_7_0_pos 0
+#define reg_tinr_imp_duration_th_8k_7_0_len 8
+#define reg_tinr_imp_duration_th_8k_7_0_lsb 0
+#define xd_p_reg_tinr_imp_duration_th_8k_10_8 0xA086
+#define reg_tinr_imp_duration_th_8k_10_8_pos 0
+#define reg_tinr_imp_duration_th_8k_10_8_len 3
+#define reg_tinr_imp_duration_th_8k_10_8_lsb 8
+#define xd_p_reg_tinr_freq_ratio_6m_7_0 0xA087
+#define reg_tinr_freq_ratio_6m_7_0_pos 0
+#define reg_tinr_freq_ratio_6m_7_0_len 8
+#define reg_tinr_freq_ratio_6m_7_0_lsb 0
+#define xd_p_reg_tinr_freq_ratio_6m_12_8 0xA088
+#define reg_tinr_freq_ratio_6m_12_8_pos 0
+#define reg_tinr_freq_ratio_6m_12_8_len 5
+#define reg_tinr_freq_ratio_6m_12_8_lsb 8
+#define xd_p_reg_tinr_freq_ratio_7m_7_0 0xA089
+#define reg_tinr_freq_ratio_7m_7_0_pos 0
+#define reg_tinr_freq_ratio_7m_7_0_len 8
+#define reg_tinr_freq_ratio_7m_7_0_lsb 0
+#define xd_p_reg_tinr_freq_ratio_7m_12_8 0xA08A
+#define reg_tinr_freq_ratio_7m_12_8_pos 0
+#define reg_tinr_freq_ratio_7m_12_8_len 5
+#define reg_tinr_freq_ratio_7m_12_8_lsb 8
+#define xd_p_reg_tinr_freq_ratio_8m_7_0 0xA08B
+#define reg_tinr_freq_ratio_8m_7_0_pos 0
+#define reg_tinr_freq_ratio_8m_7_0_len 8
+#define reg_tinr_freq_ratio_8m_7_0_lsb 0
+#define xd_p_reg_tinr_freq_ratio_8m_12_8 0xA08C
+#define reg_tinr_freq_ratio_8m_12_8_pos 0
+#define reg_tinr_freq_ratio_8m_12_8_len 5
+#define reg_tinr_freq_ratio_8m_12_8_lsb 8
+#define xd_p_reg_tinr_imp_duration_th_low_2k 0xA08D
+#define reg_tinr_imp_duration_th_low_2k_pos 0
+#define reg_tinr_imp_duration_th_low_2k_len 8
+#define reg_tinr_imp_duration_th_low_2k_lsb 0
+#define xd_p_reg_tinr_imp_duration_th_low_8k 0xA08E
+#define reg_tinr_imp_duration_th_low_8k_pos 0
+#define reg_tinr_imp_duration_th_low_8k_len 8
+#define reg_tinr_imp_duration_th_low_8k_lsb 0
+#define xd_r_reg_tinr_counter_7_0 0xA090
+#define reg_tinr_counter_7_0_pos 0
+#define reg_tinr_counter_7_0_len 8
+#define reg_tinr_counter_7_0_lsb 0
+#define xd_r_reg_tinr_counter_15_8 0xA091
+#define reg_tinr_counter_15_8_pos 0
+#define reg_tinr_counter_15_8_len 8
+#define reg_tinr_counter_15_8_lsb 8
+#define xd_p_reg_tinr_adative_tinr_en 0xA093
+#define reg_tinr_adative_tinr_en_pos 0
+#define reg_tinr_adative_tinr_en_len 1
+#define reg_tinr_adative_tinr_en_lsb 0
+#define xd_p_reg_tinr_peak_fifo_size 0xA093
+#define reg_tinr_peak_fifo_size_pos 1
+#define reg_tinr_peak_fifo_size_len 5
+#define reg_tinr_peak_fifo_size_lsb 0
+#define xd_p_reg_tinr_counter_rst 0xA093
+#define reg_tinr_counter_rst_pos 6
+#define reg_tinr_counter_rst_len 1
+#define reg_tinr_counter_rst_lsb 0
+#define xd_p_reg_tinr_search_period_7_0 0xA094
+#define reg_tinr_search_period_7_0_pos 0
+#define reg_tinr_search_period_7_0_len 8
+#define reg_tinr_search_period_7_0_lsb 0
+#define xd_p_reg_tinr_search_period_15_8 0xA095
+#define reg_tinr_search_period_15_8_pos 0
+#define reg_tinr_search_period_15_8_len 8
+#define reg_tinr_search_period_15_8_lsb 8
+#define xd_p_reg_ccifs_fcw_7_0 0xA0A0
+#define reg_ccifs_fcw_7_0_pos 0
+#define reg_ccifs_fcw_7_0_len 8
+#define reg_ccifs_fcw_7_0_lsb 0
+#define xd_p_reg_ccifs_fcw_12_8 0xA0A1
+#define reg_ccifs_fcw_12_8_pos 0
+#define reg_ccifs_fcw_12_8_len 5
+#define reg_ccifs_fcw_12_8_lsb 8
+#define xd_p_reg_ccifs_spec_inv 0xA0A1
+#define reg_ccifs_spec_inv_pos 5
+#define reg_ccifs_spec_inv_len 1
+#define reg_ccifs_spec_inv_lsb 0
+#define xd_p_reg_gp_trigger 0xA0A2
+#define reg_gp_trigger_pos 0
+#define reg_gp_trigger_len 1
+#define reg_gp_trigger_lsb 0
+#define xd_p_reg_trigger_sel 0xA0A2
+#define reg_trigger_sel_pos 1
+#define reg_trigger_sel_len 2
+#define reg_trigger_sel_lsb 0
+#define xd_p_reg_debug_ofdm 0xA0A2
+#define reg_debug_ofdm_pos 3
+#define reg_debug_ofdm_len 2
+#define reg_debug_ofdm_lsb 0
+#define xd_p_reg_trigger_module_sel 0xA0A3
+#define reg_trigger_module_sel_pos 0
+#define reg_trigger_module_sel_len 6
+#define reg_trigger_module_sel_lsb 0
+#define xd_p_reg_trigger_set_sel 0xA0A4
+#define reg_trigger_set_sel_pos 0
+#define reg_trigger_set_sel_len 6
+#define reg_trigger_set_sel_lsb 0
+#define xd_p_reg_fw_int_mask_n 0xA0A4
+#define reg_fw_int_mask_n_pos 6
+#define reg_fw_int_mask_n_len 1
+#define reg_fw_int_mask_n_lsb 0
+#define xd_p_reg_debug_group 0xA0A5
+#define reg_debug_group_pos 0
+#define reg_debug_group_len 4
+#define reg_debug_group_lsb 0
+#define xd_p_reg_odbg_clk_sel 0xA0A5
+#define reg_odbg_clk_sel_pos 4
+#define reg_odbg_clk_sel_len 2
+#define reg_odbg_clk_sel_lsb 0
+#define xd_p_reg_ccif_sc 0xA0C0
+#define reg_ccif_sc_pos 0
+#define reg_ccif_sc_len 4
+#define reg_ccif_sc_lsb 0
+#define xd_r_reg_ccif_saturate 0xA0C1
+#define reg_ccif_saturate_pos 0
+#define reg_ccif_saturate_len 2
+#define reg_ccif_saturate_lsb 0
+#define xd_r_reg_antif_saturate 0xA0C1
+#define reg_antif_saturate_pos 2
+#define reg_antif_saturate_len 4
+#define reg_antif_saturate_lsb 0
+#define xd_r_reg_acif_saturate 0xA0C2
+#define reg_acif_saturate_pos 0
+#define reg_acif_saturate_len 8
+#define reg_acif_saturate_lsb 0
+#define xd_p_reg_tmr_timer0_threshold_7_0 0xA0C8
+#define reg_tmr_timer0_threshold_7_0_pos 0
+#define reg_tmr_timer0_threshold_7_0_len 8
+#define reg_tmr_timer0_threshold_7_0_lsb 0
+#define xd_p_reg_tmr_timer0_threshold_15_8 0xA0C9
+#define reg_tmr_timer0_threshold_15_8_pos 0
+#define reg_tmr_timer0_threshold_15_8_len 8
+#define reg_tmr_timer0_threshold_15_8_lsb 8
+#define xd_p_reg_tmr_timer0_enable 0xA0CA
+#define reg_tmr_timer0_enable_pos 0
+#define reg_tmr_timer0_enable_len 1
+#define reg_tmr_timer0_enable_lsb 0
+#define xd_p_reg_tmr_timer0_clk_sel 0xA0CA
+#define reg_tmr_timer0_clk_sel_pos 1
+#define reg_tmr_timer0_clk_sel_len 1
+#define reg_tmr_timer0_clk_sel_lsb 0
+#define xd_p_reg_tmr_timer0_int 0xA0CA
+#define reg_tmr_timer0_int_pos 2
+#define reg_tmr_timer0_int_len 1
+#define reg_tmr_timer0_int_lsb 0
+#define xd_p_reg_tmr_timer0_rst 0xA0CA
+#define reg_tmr_timer0_rst_pos 3
+#define reg_tmr_timer0_rst_len 1
+#define reg_tmr_timer0_rst_lsb 0
+#define xd_r_reg_tmr_timer0_count_7_0 0xA0CB
+#define reg_tmr_timer0_count_7_0_pos 0
+#define reg_tmr_timer0_count_7_0_len 8
+#define reg_tmr_timer0_count_7_0_lsb 0
+#define xd_r_reg_tmr_timer0_count_15_8 0xA0CC
+#define reg_tmr_timer0_count_15_8_pos 0
+#define reg_tmr_timer0_count_15_8_len 8
+#define reg_tmr_timer0_count_15_8_lsb 8
+#define xd_p_reg_suspend 0xA0CD
+#define reg_suspend_pos 0
+#define reg_suspend_len 1
+#define reg_suspend_lsb 0
+#define xd_p_reg_suspend_rdy 0xA0CD
+#define reg_suspend_rdy_pos 1
+#define reg_suspend_rdy_len 1
+#define reg_suspend_rdy_lsb 0
+#define xd_p_reg_resume 0xA0CD
+#define reg_resume_pos 2
+#define reg_resume_len 1
+#define reg_resume_lsb 0
+#define xd_p_reg_resume_rdy 0xA0CD
+#define reg_resume_rdy_pos 3
+#define reg_resume_rdy_len 1
+#define reg_resume_rdy_lsb 0
+#define xd_p_reg_fmf 0xA0CE
+#define reg_fmf_pos 0
+#define reg_fmf_len 8
+#define reg_fmf_lsb 0
+#define xd_p_ccid_accumulate_num_2k_7_0 0xA100
+#define ccid_accumulate_num_2k_7_0_pos 0
+#define ccid_accumulate_num_2k_7_0_len 8
+#define ccid_accumulate_num_2k_7_0_lsb 0
+#define xd_p_ccid_accumulate_num_2k_12_8 0xA101
+#define ccid_accumulate_num_2k_12_8_pos 0
+#define ccid_accumulate_num_2k_12_8_len 5
+#define ccid_accumulate_num_2k_12_8_lsb 8
+#define xd_p_ccid_accumulate_num_8k_7_0 0xA102
+#define ccid_accumulate_num_8k_7_0_pos 0
+#define ccid_accumulate_num_8k_7_0_len 8
+#define ccid_accumulate_num_8k_7_0_lsb 0
+#define xd_p_ccid_accumulate_num_8k_14_8 0xA103
+#define ccid_accumulate_num_8k_14_8_pos 0
+#define ccid_accumulate_num_8k_14_8_len 7
+#define ccid_accumulate_num_8k_14_8_lsb 8
+#define xd_p_ccid_desired_level_0 0xA103
+#define ccid_desired_level_0_pos 7
+#define ccid_desired_level_0_len 1
+#define ccid_desired_level_0_lsb 0
+#define xd_p_ccid_desired_level_8_1 0xA104
+#define ccid_desired_level_8_1_pos 0
+#define ccid_desired_level_8_1_len 8
+#define ccid_desired_level_8_1_lsb 1
+#define xd_p_ccid_apply_delay 0xA105
+#define ccid_apply_delay_pos 0
+#define ccid_apply_delay_len 7
+#define ccid_apply_delay_lsb 0
+#define xd_p_ccid_CCID_Threshold1 0xA106
+#define ccid_CCID_Threshold1_pos 0
+#define ccid_CCID_Threshold1_len 8
+#define ccid_CCID_Threshold1_lsb 0
+#define xd_p_ccid_CCID_Threshold2 0xA107
+#define ccid_CCID_Threshold2_pos 0
+#define ccid_CCID_Threshold2_len 8
+#define ccid_CCID_Threshold2_lsb 0
+#define xd_p_reg_ccid_gain_scale 0xA108
+#define reg_ccid_gain_scale_pos 0
+#define reg_ccid_gain_scale_len 4
+#define reg_ccid_gain_scale_lsb 0
+#define xd_p_reg_ccid2_passband_gain_set 0xA108
+#define reg_ccid2_passband_gain_set_pos 4
+#define reg_ccid2_passband_gain_set_len 4
+#define reg_ccid2_passband_gain_set_lsb 0
+#define xd_r_ccid_multiplier_7_0 0xA109
+#define ccid_multiplier_7_0_pos 0
+#define ccid_multiplier_7_0_len 8
+#define ccid_multiplier_7_0_lsb 0
+#define xd_r_ccid_multiplier_15_8 0xA10A
+#define ccid_multiplier_15_8_pos 0
+#define ccid_multiplier_15_8_len 8
+#define ccid_multiplier_15_8_lsb 8
+#define xd_r_ccid_right_shift_bits 0xA10B
+#define ccid_right_shift_bits_pos 0
+#define ccid_right_shift_bits_len 4
+#define ccid_right_shift_bits_lsb 0
+#define xd_r_reg_ccid_sx_7_0 0xA10C
+#define reg_ccid_sx_7_0_pos 0
+#define reg_ccid_sx_7_0_len 8
+#define reg_ccid_sx_7_0_lsb 0
+#define xd_r_reg_ccid_sx_15_8 0xA10D
+#define reg_ccid_sx_15_8_pos 0
+#define reg_ccid_sx_15_8_len 8
+#define reg_ccid_sx_15_8_lsb 8
+#define xd_r_reg_ccid_sx_21_16 0xA10E
+#define reg_ccid_sx_21_16_pos 0
+#define reg_ccid_sx_21_16_len 6
+#define reg_ccid_sx_21_16_lsb 16
+#define xd_r_reg_ccid_sy_7_0 0xA110
+#define reg_ccid_sy_7_0_pos 0
+#define reg_ccid_sy_7_0_len 8
+#define reg_ccid_sy_7_0_lsb 0
+#define xd_r_reg_ccid_sy_15_8 0xA111
+#define reg_ccid_sy_15_8_pos 0
+#define reg_ccid_sy_15_8_len 8
+#define reg_ccid_sy_15_8_lsb 8
+#define xd_r_reg_ccid_sy_23_16 0xA112
+#define reg_ccid_sy_23_16_pos 0
+#define reg_ccid_sy_23_16_len 8
+#define reg_ccid_sy_23_16_lsb 16
+#define xd_r_reg_ccid2_sz_7_0 0xA114
+#define reg_ccid2_sz_7_0_pos 0
+#define reg_ccid2_sz_7_0_len 8
+#define reg_ccid2_sz_7_0_lsb 0
+#define xd_r_reg_ccid2_sz_15_8 0xA115
+#define reg_ccid2_sz_15_8_pos 0
+#define reg_ccid2_sz_15_8_len 8
+#define reg_ccid2_sz_15_8_lsb 8
+#define xd_r_reg_ccid2_sz_23_16 0xA116
+#define reg_ccid2_sz_23_16_pos 0
+#define reg_ccid2_sz_23_16_len 8
+#define reg_ccid2_sz_23_16_lsb 16
+#define xd_r_reg_ccid2_sz_25_24 0xA117
+#define reg_ccid2_sz_25_24_pos 0
+#define reg_ccid2_sz_25_24_len 2
+#define reg_ccid2_sz_25_24_lsb 24
+#define xd_r_reg_ccid2_sy_7_0 0xA118
+#define reg_ccid2_sy_7_0_pos 0
+#define reg_ccid2_sy_7_0_len 8
+#define reg_ccid2_sy_7_0_lsb 0
+#define xd_r_reg_ccid2_sy_15_8 0xA119
+#define reg_ccid2_sy_15_8_pos 0
+#define reg_ccid2_sy_15_8_len 8
+#define reg_ccid2_sy_15_8_lsb 8
+#define xd_r_reg_ccid2_sy_23_16 0xA11A
+#define reg_ccid2_sy_23_16_pos 0
+#define reg_ccid2_sy_23_16_len 8
+#define reg_ccid2_sy_23_16_lsb 16
+#define xd_r_reg_ccid2_sy_25_24 0xA11B
+#define reg_ccid2_sy_25_24_pos 0
+#define reg_ccid2_sy_25_24_len 2
+#define reg_ccid2_sy_25_24_lsb 24
+#define xd_p_dagc1_accumulate_num_2k_7_0 0xA120
+#define dagc1_accumulate_num_2k_7_0_pos 0
+#define dagc1_accumulate_num_2k_7_0_len 8
+#define dagc1_accumulate_num_2k_7_0_lsb 0
+#define xd_p_dagc1_accumulate_num_2k_12_8 0xA121
+#define dagc1_accumulate_num_2k_12_8_pos 0
+#define dagc1_accumulate_num_2k_12_8_len 5
+#define dagc1_accumulate_num_2k_12_8_lsb 8
+#define xd_p_dagc1_accumulate_num_8k_7_0 0xA122
+#define dagc1_accumulate_num_8k_7_0_pos 0
+#define dagc1_accumulate_num_8k_7_0_len 8
+#define dagc1_accumulate_num_8k_7_0_lsb 0
+#define xd_p_dagc1_accumulate_num_8k_14_8 0xA123
+#define dagc1_accumulate_num_8k_14_8_pos 0
+#define dagc1_accumulate_num_8k_14_8_len 7
+#define dagc1_accumulate_num_8k_14_8_lsb 8
+#define xd_p_dagc1_desired_level_0 0xA123
+#define dagc1_desired_level_0_pos 7
+#define dagc1_desired_level_0_len 1
+#define dagc1_desired_level_0_lsb 0
+#define xd_p_dagc1_desired_level_8_1 0xA124
+#define dagc1_desired_level_8_1_pos 0
+#define dagc1_desired_level_8_1_len 8
+#define dagc1_desired_level_8_1_lsb 1
+#define xd_p_dagc1_apply_delay 0xA125
+#define dagc1_apply_delay_pos 0
+#define dagc1_apply_delay_len 7
+#define dagc1_apply_delay_lsb 0
+#define xd_p_dagc1_bypass_scale_ctl 0xA126
+#define dagc1_bypass_scale_ctl_pos 0
+#define dagc1_bypass_scale_ctl_len 2
+#define dagc1_bypass_scale_ctl_lsb 0
+#define xd_p_reg_dagc1_in_sat_cnt_7_0 0xA127
+#define reg_dagc1_in_sat_cnt_7_0_pos 0
+#define reg_dagc1_in_sat_cnt_7_0_len 8
+#define reg_dagc1_in_sat_cnt_7_0_lsb 0
+#define xd_p_reg_dagc1_in_sat_cnt_15_8 0xA128
+#define reg_dagc1_in_sat_cnt_15_8_pos 0
+#define reg_dagc1_in_sat_cnt_15_8_len 8
+#define reg_dagc1_in_sat_cnt_15_8_lsb 8
+#define xd_p_reg_dagc1_in_sat_cnt_23_16 0xA129
+#define reg_dagc1_in_sat_cnt_23_16_pos 0
+#define reg_dagc1_in_sat_cnt_23_16_len 8
+#define reg_dagc1_in_sat_cnt_23_16_lsb 16
+#define xd_p_reg_dagc1_in_sat_cnt_31_24 0xA12A
+#define reg_dagc1_in_sat_cnt_31_24_pos 0
+#define reg_dagc1_in_sat_cnt_31_24_len 8
+#define reg_dagc1_in_sat_cnt_31_24_lsb 24
+#define xd_p_reg_dagc1_out_sat_cnt_7_0 0xA12B
+#define reg_dagc1_out_sat_cnt_7_0_pos 0
+#define reg_dagc1_out_sat_cnt_7_0_len 8
+#define reg_dagc1_out_sat_cnt_7_0_lsb 0
+#define xd_p_reg_dagc1_out_sat_cnt_15_8 0xA12C
+#define reg_dagc1_out_sat_cnt_15_8_pos 0
+#define reg_dagc1_out_sat_cnt_15_8_len 8
+#define reg_dagc1_out_sat_cnt_15_8_lsb 8
+#define xd_p_reg_dagc1_out_sat_cnt_23_16 0xA12D
+#define reg_dagc1_out_sat_cnt_23_16_pos 0
+#define reg_dagc1_out_sat_cnt_23_16_len 8
+#define reg_dagc1_out_sat_cnt_23_16_lsb 16
+#define xd_p_reg_dagc1_out_sat_cnt_31_24 0xA12E
+#define reg_dagc1_out_sat_cnt_31_24_pos 0
+#define reg_dagc1_out_sat_cnt_31_24_len 8
+#define reg_dagc1_out_sat_cnt_31_24_lsb 24
+#define xd_r_dagc1_multiplier_7_0 0xA136
+#define dagc1_multiplier_7_0_pos 0
+#define dagc1_multiplier_7_0_len 8
+#define dagc1_multiplier_7_0_lsb 0
+#define xd_r_dagc1_multiplier_15_8 0xA137
+#define dagc1_multiplier_15_8_pos 0
+#define dagc1_multiplier_15_8_len 8
+#define dagc1_multiplier_15_8_lsb 8
+#define xd_r_dagc1_right_shift_bits 0xA138
+#define dagc1_right_shift_bits_pos 0
+#define dagc1_right_shift_bits_len 4
+#define dagc1_right_shift_bits_lsb 0
+#define xd_p_reg_bfs_fcw_7_0 0xA140
+#define reg_bfs_fcw_7_0_pos 0
+#define reg_bfs_fcw_7_0_len 8
+#define reg_bfs_fcw_7_0_lsb 0
+#define xd_p_reg_bfs_fcw_15_8 0xA141
+#define reg_bfs_fcw_15_8_pos 0
+#define reg_bfs_fcw_15_8_len 8
+#define reg_bfs_fcw_15_8_lsb 8
+#define xd_p_reg_bfs_fcw_22_16 0xA142
+#define reg_bfs_fcw_22_16_pos 0
+#define reg_bfs_fcw_22_16_len 7
+#define reg_bfs_fcw_22_16_lsb 16
+#define xd_p_reg_antif_sf_7_0 0xA144
+#define reg_antif_sf_7_0_pos 0
+#define reg_antif_sf_7_0_len 8
+#define reg_antif_sf_7_0_lsb 0
+#define xd_p_reg_antif_sf_11_8 0xA145
+#define reg_antif_sf_11_8_pos 0
+#define reg_antif_sf_11_8_len 4
+#define reg_antif_sf_11_8_lsb 8
+#define xd_r_bfs_fcw_q_7_0 0xA150
+#define bfs_fcw_q_7_0_pos 0
+#define bfs_fcw_q_7_0_len 8
+#define bfs_fcw_q_7_0_lsb 0
+#define xd_r_bfs_fcw_q_15_8 0xA151
+#define bfs_fcw_q_15_8_pos 0
+#define bfs_fcw_q_15_8_len 8
+#define bfs_fcw_q_15_8_lsb 8
+#define xd_r_bfs_fcw_q_22_16 0xA152
+#define bfs_fcw_q_22_16_pos 0
+#define bfs_fcw_q_22_16_len 7
+#define bfs_fcw_q_22_16_lsb 16
+#define xd_p_reg_dca_enu 0xA160
+#define reg_dca_enu_pos 0
+#define reg_dca_enu_len 1
+#define reg_dca_enu_lsb 0
+#define xd_p_reg_dca_enl 0xA160
+#define reg_dca_enl_pos 1
+#define reg_dca_enl_len 1
+#define reg_dca_enl_lsb 0
+#define xd_p_reg_dca_lower_chip 0xA160
+#define reg_dca_lower_chip_pos 2
+#define reg_dca_lower_chip_len 1
+#define reg_dca_lower_chip_lsb 0
+#define xd_p_reg_dca_upper_chip 0xA160
+#define reg_dca_upper_chip_pos 3
+#define reg_dca_upper_chip_len 1
+#define reg_dca_upper_chip_lsb 0
+#define xd_p_reg_dca_platch 0xA160
+#define reg_dca_platch_pos 4
+#define reg_dca_platch_len 1
+#define reg_dca_platch_lsb 0
+#define xd_p_reg_dca_th 0xA161
+#define reg_dca_th_pos 0
+#define reg_dca_th_len 5
+#define reg_dca_th_lsb 0
+#define xd_p_reg_dca_scale 0xA162
+#define reg_dca_scale_pos 0
+#define reg_dca_scale_len 4
+#define reg_dca_scale_lsb 0
+#define xd_p_reg_dca_tone_7_0 0xA163
+#define reg_dca_tone_7_0_pos 0
+#define reg_dca_tone_7_0_len 8
+#define reg_dca_tone_7_0_lsb 0
+#define xd_p_reg_dca_tone_12_8 0xA164
+#define reg_dca_tone_12_8_pos 0
+#define reg_dca_tone_12_8_len 5
+#define reg_dca_tone_12_8_lsb 8
+#define xd_p_reg_dca_time_7_0 0xA165
+#define reg_dca_time_7_0_pos 0
+#define reg_dca_time_7_0_len 8
+#define reg_dca_time_7_0_lsb 0
+#define xd_p_reg_dca_time_15_8 0xA166
+#define reg_dca_time_15_8_pos 0
+#define reg_dca_time_15_8_len 8
+#define reg_dca_time_15_8_lsb 8
+#define xd_r_dcasm 0xA167
+#define dcasm_pos 0
+#define dcasm_len 3
+#define dcasm_lsb 0
+#define xd_p_reg_qnt_valuew_7_0 0xA168
+#define reg_qnt_valuew_7_0_pos 0
+#define reg_qnt_valuew_7_0_len 8
+#define reg_qnt_valuew_7_0_lsb 0
+#define xd_p_reg_qnt_valuew_10_8 0xA169
+#define reg_qnt_valuew_10_8_pos 0
+#define reg_qnt_valuew_10_8_len 3
+#define reg_qnt_valuew_10_8_lsb 8
+#define xd_p_dca_sbx_gain_diff_7_0 0xA16A
+#define dca_sbx_gain_diff_7_0_pos 0
+#define dca_sbx_gain_diff_7_0_len 8
+#define dca_sbx_gain_diff_7_0_lsb 0
+#define xd_p_dca_sbx_gain_diff_9_8 0xA16B
+#define dca_sbx_gain_diff_9_8_pos 0
+#define dca_sbx_gain_diff_9_8_len 2
+#define dca_sbx_gain_diff_9_8_lsb 8
+#define xd_p_reg_dca_stand_alone 0xA16C
+#define reg_dca_stand_alone_pos 0
+#define reg_dca_stand_alone_len 1
+#define reg_dca_stand_alone_lsb 0
+#define xd_p_reg_dca_upper_out_en 0xA16C
+#define reg_dca_upper_out_en_pos 1
+#define reg_dca_upper_out_en_len 1
+#define reg_dca_upper_out_en_lsb 0
+#define xd_p_reg_dca_rc_en 0xA16C
+#define reg_dca_rc_en_pos 2
+#define reg_dca_rc_en_len 1
+#define reg_dca_rc_en_lsb 0
+#define xd_p_reg_dca_retrain_send 0xA16C
+#define reg_dca_retrain_send_pos 3
+#define reg_dca_retrain_send_len 1
+#define reg_dca_retrain_send_lsb 0
+#define xd_p_reg_dca_retrain_rec 0xA16C
+#define reg_dca_retrain_rec_pos 4
+#define reg_dca_retrain_rec_len 1
+#define reg_dca_retrain_rec_lsb 0
+#define xd_p_reg_dca_api_tpsrdy 0xA16C
+#define reg_dca_api_tpsrdy_pos 5
+#define reg_dca_api_tpsrdy_len 1
+#define reg_dca_api_tpsrdy_lsb 0
+#define xd_p_reg_dca_symbol_gap 0xA16D
+#define reg_dca_symbol_gap_pos 0
+#define reg_dca_symbol_gap_len 4
+#define reg_dca_symbol_gap_lsb 0
+#define xd_p_reg_qnt_nfvaluew_7_0 0xA16E
+#define reg_qnt_nfvaluew_7_0_pos 0
+#define reg_qnt_nfvaluew_7_0_len 8
+#define reg_qnt_nfvaluew_7_0_lsb 0
+#define xd_p_reg_qnt_nfvaluew_10_8 0xA16F
+#define reg_qnt_nfvaluew_10_8_pos 0
+#define reg_qnt_nfvaluew_10_8_len 3
+#define reg_qnt_nfvaluew_10_8_lsb 8
+#define xd_p_reg_qnt_flatness_thr_7_0 0xA170
+#define reg_qnt_flatness_thr_7_0_pos 0
+#define reg_qnt_flatness_thr_7_0_len 8
+#define reg_qnt_flatness_thr_7_0_lsb 0
+#define xd_p_reg_qnt_flatness_thr_9_8 0xA171
+#define reg_qnt_flatness_thr_9_8_pos 0
+#define reg_qnt_flatness_thr_9_8_len 2
+#define reg_qnt_flatness_thr_9_8_lsb 8
+#define xd_p_reg_dca_tone_idx_5_0 0xA171
+#define reg_dca_tone_idx_5_0_pos 2
+#define reg_dca_tone_idx_5_0_len 6
+#define reg_dca_tone_idx_5_0_lsb 0
+#define xd_p_reg_dca_tone_idx_12_6 0xA172
+#define reg_dca_tone_idx_12_6_pos 0
+#define reg_dca_tone_idx_12_6_len 7
+#define reg_dca_tone_idx_12_6_lsb 6
+#define xd_p_reg_dca_data_vld 0xA173
+#define reg_dca_data_vld_pos 0
+#define reg_dca_data_vld_len 1
+#define reg_dca_data_vld_lsb 0
+#define xd_p_reg_dca_read_update 0xA173
+#define reg_dca_read_update_pos 1
+#define reg_dca_read_update_len 1
+#define reg_dca_read_update_lsb 0
+#define xd_r_reg_dca_data_re_5_0 0xA173
+#define reg_dca_data_re_5_0_pos 2
+#define reg_dca_data_re_5_0_len 6
+#define reg_dca_data_re_5_0_lsb 0
+#define xd_r_reg_dca_data_re_10_6 0xA174
+#define reg_dca_data_re_10_6_pos 0
+#define reg_dca_data_re_10_6_len 5
+#define reg_dca_data_re_10_6_lsb 6
+#define xd_r_reg_dca_data_im_7_0 0xA175
+#define reg_dca_data_im_7_0_pos 0
+#define reg_dca_data_im_7_0_len 8
+#define reg_dca_data_im_7_0_lsb 0
+#define xd_r_reg_dca_data_im_10_8 0xA176
+#define reg_dca_data_im_10_8_pos 0
+#define reg_dca_data_im_10_8_len 3
+#define reg_dca_data_im_10_8_lsb 8
+#define xd_r_reg_dca_data_h2_7_0 0xA178
+#define reg_dca_data_h2_7_0_pos 0
+#define reg_dca_data_h2_7_0_len 8
+#define reg_dca_data_h2_7_0_lsb 0
+#define xd_r_reg_dca_data_h2_9_8 0xA179
+#define reg_dca_data_h2_9_8_pos 0
+#define reg_dca_data_h2_9_8_len 2
+#define reg_dca_data_h2_9_8_lsb 8
+#define xd_p_reg_f_adc_7_0 0xA180
+#define reg_f_adc_7_0_pos 0
+#define reg_f_adc_7_0_len 8
+#define reg_f_adc_7_0_lsb 0
+#define xd_p_reg_f_adc_15_8 0xA181
+#define reg_f_adc_15_8_pos 0
+#define reg_f_adc_15_8_len 8
+#define reg_f_adc_15_8_lsb 8
+#define xd_p_reg_f_adc_23_16 0xA182
+#define reg_f_adc_23_16_pos 0
+#define reg_f_adc_23_16_len 8
+#define reg_f_adc_23_16_lsb 16
+#define xd_r_intp_mu_7_0 0xA190
+#define intp_mu_7_0_pos 0
+#define intp_mu_7_0_len 8
+#define intp_mu_7_0_lsb 0
+#define xd_r_intp_mu_15_8 0xA191
+#define intp_mu_15_8_pos 0
+#define intp_mu_15_8_len 8
+#define intp_mu_15_8_lsb 8
+#define xd_r_intp_mu_19_16 0xA192
+#define intp_mu_19_16_pos 0
+#define intp_mu_19_16_len 4
+#define intp_mu_19_16_lsb 16
+#define xd_p_reg_agc_rst 0xA1A0
+#define reg_agc_rst_pos 0
+#define reg_agc_rst_len 1
+#define reg_agc_rst_lsb 0
+#define xd_p_rf_agc_en 0xA1A0
+#define rf_agc_en_pos 1
+#define rf_agc_en_len 1
+#define rf_agc_en_lsb 0
+#define xd_p_rf_agc_dis 0xA1A0
+#define rf_agc_dis_pos 2
+#define rf_agc_dis_len 1
+#define rf_agc_dis_lsb 0
+#define xd_p_if_agc_rst 0xA1A0
+#define if_agc_rst_pos 3
+#define if_agc_rst_len 1
+#define if_agc_rst_lsb 0
+#define xd_p_if_agc_en 0xA1A0
+#define if_agc_en_pos 4
+#define if_agc_en_len 1
+#define if_agc_en_lsb 0
+#define xd_p_if_agc_dis 0xA1A0
+#define if_agc_dis_pos 5
+#define if_agc_dis_len 1
+#define if_agc_dis_lsb 0
+#define xd_p_agc_lock 0xA1A0
+#define agc_lock_pos 6
+#define agc_lock_len 1
+#define agc_lock_lsb 0
+#define xd_p_reg_tinr_rst 0xA1A1
+#define reg_tinr_rst_pos 0
+#define reg_tinr_rst_len 1
+#define reg_tinr_rst_lsb 0
+#define xd_p_reg_tinr_en 0xA1A1
+#define reg_tinr_en_pos 1
+#define reg_tinr_en_len 1
+#define reg_tinr_en_lsb 0
+#define xd_p_reg_ccifs_en 0xA1A2
+#define reg_ccifs_en_pos 0
+#define reg_ccifs_en_len 1
+#define reg_ccifs_en_lsb 0
+#define xd_p_reg_ccifs_dis 0xA1A2
+#define reg_ccifs_dis_pos 1
+#define reg_ccifs_dis_len 1
+#define reg_ccifs_dis_lsb 0
+#define xd_p_reg_ccifs_rst 0xA1A2
+#define reg_ccifs_rst_pos 2
+#define reg_ccifs_rst_len 1
+#define reg_ccifs_rst_lsb 0
+#define xd_p_reg_ccifs_byp 0xA1A2
+#define reg_ccifs_byp_pos 3
+#define reg_ccifs_byp_len 1
+#define reg_ccifs_byp_lsb 0
+#define xd_p_reg_ccif_en 0xA1A3
+#define reg_ccif_en_pos 0
+#define reg_ccif_en_len 1
+#define reg_ccif_en_lsb 0
+#define xd_p_reg_ccif_dis 0xA1A3
+#define reg_ccif_dis_pos 1
+#define reg_ccif_dis_len 1
+#define reg_ccif_dis_lsb 0
+#define xd_p_reg_ccif_rst 0xA1A3
+#define reg_ccif_rst_pos 2
+#define reg_ccif_rst_len 1
+#define reg_ccif_rst_lsb 0
+#define xd_p_reg_ccif_byp 0xA1A3
+#define reg_ccif_byp_pos 3
+#define reg_ccif_byp_len 1
+#define reg_ccif_byp_lsb 0
+#define xd_p_dagc1_rst 0xA1A4
+#define dagc1_rst_pos 0
+#define dagc1_rst_len 1
+#define dagc1_rst_lsb 0
+#define xd_p_dagc1_en 0xA1A4
+#define dagc1_en_pos 1
+#define dagc1_en_len 1
+#define dagc1_en_lsb 0
+#define xd_p_dagc1_mode 0xA1A4
+#define dagc1_mode_pos 2
+#define dagc1_mode_len 2
+#define dagc1_mode_lsb 0
+#define xd_p_dagc1_done 0xA1A4
+#define dagc1_done_pos 4
+#define dagc1_done_len 1
+#define dagc1_done_lsb 0
+#define xd_p_ccid_rst 0xA1A5
+#define ccid_rst_pos 0
+#define ccid_rst_len 1
+#define ccid_rst_lsb 0
+#define xd_p_ccid_en 0xA1A5
+#define ccid_en_pos 1
+#define ccid_en_len 1
+#define ccid_en_lsb 0
+#define xd_p_ccid_mode 0xA1A5
+#define ccid_mode_pos 2
+#define ccid_mode_len 2
+#define ccid_mode_lsb 0
+#define xd_p_ccid_done 0xA1A5
+#define ccid_done_pos 4
+#define ccid_done_len 1
+#define ccid_done_lsb 0
+#define xd_r_ccid_deted 0xA1A5
+#define ccid_deted_pos 5
+#define ccid_deted_len 1
+#define ccid_deted_lsb 0
+#define xd_p_ccid2_en 0xA1A5
+#define ccid2_en_pos 6
+#define ccid2_en_len 1
+#define ccid2_en_lsb 0
+#define xd_p_ccid2_done 0xA1A5
+#define ccid2_done_pos 7
+#define ccid2_done_len 1
+#define ccid2_done_lsb 0
+#define xd_p_reg_bfs_en 0xA1A6
+#define reg_bfs_en_pos 0
+#define reg_bfs_en_len 1
+#define reg_bfs_en_lsb 0
+#define xd_p_reg_bfs_dis 0xA1A6
+#define reg_bfs_dis_pos 1
+#define reg_bfs_dis_len 1
+#define reg_bfs_dis_lsb 0
+#define xd_p_reg_bfs_rst 0xA1A6
+#define reg_bfs_rst_pos 2
+#define reg_bfs_rst_len 1
+#define reg_bfs_rst_lsb 0
+#define xd_p_reg_bfs_byp 0xA1A6
+#define reg_bfs_byp_pos 3
+#define reg_bfs_byp_len 1
+#define reg_bfs_byp_lsb 0
+#define xd_p_reg_antif_en 0xA1A7
+#define reg_antif_en_pos 0
+#define reg_antif_en_len 1
+#define reg_antif_en_lsb 0
+#define xd_p_reg_antif_dis 0xA1A7
+#define reg_antif_dis_pos 1
+#define reg_antif_dis_len 1
+#define reg_antif_dis_lsb 0
+#define xd_p_reg_antif_rst 0xA1A7
+#define reg_antif_rst_pos 2
+#define reg_antif_rst_len 1
+#define reg_antif_rst_lsb 0
+#define xd_p_reg_antif_byp 0xA1A7
+#define reg_antif_byp_pos 3
+#define reg_antif_byp_len 1
+#define reg_antif_byp_lsb 0
+#define xd_p_intp_en 0xA1A8
+#define intp_en_pos 0
+#define intp_en_len 1
+#define intp_en_lsb 0
+#define xd_p_intp_dis 0xA1A8
+#define intp_dis_pos 1
+#define intp_dis_len 1
+#define intp_dis_lsb 0
+#define xd_p_intp_rst 0xA1A8
+#define intp_rst_pos 2
+#define intp_rst_len 1
+#define intp_rst_lsb 0
+#define xd_p_intp_byp 0xA1A8
+#define intp_byp_pos 3
+#define intp_byp_len 1
+#define intp_byp_lsb 0
+#define xd_p_reg_acif_en 0xA1A9
+#define reg_acif_en_pos 0
+#define reg_acif_en_len 1
+#define reg_acif_en_lsb 0
+#define xd_p_reg_acif_dis 0xA1A9
+#define reg_acif_dis_pos 1
+#define reg_acif_dis_len 1
+#define reg_acif_dis_lsb 0
+#define xd_p_reg_acif_rst 0xA1A9
+#define reg_acif_rst_pos 2
+#define reg_acif_rst_len 1
+#define reg_acif_rst_lsb 0
+#define xd_p_reg_acif_byp 0xA1A9
+#define reg_acif_byp_pos 3
+#define reg_acif_byp_len 1
+#define reg_acif_byp_lsb 0
+#define xd_p_reg_acif_sync_mode 0xA1A9
+#define reg_acif_sync_mode_pos 4
+#define reg_acif_sync_mode_len 1
+#define reg_acif_sync_mode_lsb 0
+#define xd_p_dagc2_rst 0xA1AA
+#define dagc2_rst_pos 0
+#define dagc2_rst_len 1
+#define dagc2_rst_lsb 0
+#define xd_p_dagc2_en 0xA1AA
+#define dagc2_en_pos 1
+#define dagc2_en_len 1
+#define dagc2_en_lsb 0
+#define xd_p_dagc2_mode 0xA1AA
+#define dagc2_mode_pos 2
+#define dagc2_mode_len 2
+#define dagc2_mode_lsb 0
+#define xd_p_dagc2_done 0xA1AA
+#define dagc2_done_pos 4
+#define dagc2_done_len 1
+#define dagc2_done_lsb 0
+#define xd_p_reg_dca_en 0xA1AB
+#define reg_dca_en_pos 0
+#define reg_dca_en_len 1
+#define reg_dca_en_lsb 0
+#define xd_p_dagc2_accumulate_num_2k_7_0 0xA1C0
+#define dagc2_accumulate_num_2k_7_0_pos 0
+#define dagc2_accumulate_num_2k_7_0_len 8
+#define dagc2_accumulate_num_2k_7_0_lsb 0
+#define xd_p_dagc2_accumulate_num_2k_12_8 0xA1C1
+#define dagc2_accumulate_num_2k_12_8_pos 0
+#define dagc2_accumulate_num_2k_12_8_len 5
+#define dagc2_accumulate_num_2k_12_8_lsb 8
+#define xd_p_dagc2_accumulate_num_8k_7_0 0xA1C2
+#define dagc2_accumulate_num_8k_7_0_pos 0
+#define dagc2_accumulate_num_8k_7_0_len 8
+#define dagc2_accumulate_num_8k_7_0_lsb 0
+#define xd_p_dagc2_accumulate_num_8k_12_8 0xA1C3
+#define dagc2_accumulate_num_8k_12_8_pos 0
+#define dagc2_accumulate_num_8k_12_8_len 5
+#define dagc2_accumulate_num_8k_12_8_lsb 8
+#define xd_p_dagc2_desired_level_2_0 0xA1C3
+#define dagc2_desired_level_2_0_pos 5
+#define dagc2_desired_level_2_0_len 3
+#define dagc2_desired_level_2_0_lsb 0
+#define xd_p_dagc2_desired_level_8_3 0xA1C4
+#define dagc2_desired_level_8_3_pos 0
+#define dagc2_desired_level_8_3_len 6
+#define dagc2_desired_level_8_3_lsb 3
+#define xd_p_dagc2_apply_delay 0xA1C5
+#define dagc2_apply_delay_pos 0
+#define dagc2_apply_delay_len 7
+#define dagc2_apply_delay_lsb 0
+#define xd_p_dagc2_bypass_scale_ctl 0xA1C6
+#define dagc2_bypass_scale_ctl_pos 0
+#define dagc2_bypass_scale_ctl_len 3
+#define dagc2_bypass_scale_ctl_lsb 0
+#define xd_p_dagc2_programmable_shift1 0xA1C7
+#define dagc2_programmable_shift1_pos 0
+#define dagc2_programmable_shift1_len 8
+#define dagc2_programmable_shift1_lsb 0
+#define xd_p_dagc2_programmable_shift2 0xA1C8
+#define dagc2_programmable_shift2_pos 0
+#define dagc2_programmable_shift2_len 8
+#define dagc2_programmable_shift2_lsb 0
+#define xd_p_reg_dagc2_in_sat_cnt_7_0 0xA1C9
+#define reg_dagc2_in_sat_cnt_7_0_pos 0
+#define reg_dagc2_in_sat_cnt_7_0_len 8
+#define reg_dagc2_in_sat_cnt_7_0_lsb 0
+#define xd_p_reg_dagc2_in_sat_cnt_15_8 0xA1CA
+#define reg_dagc2_in_sat_cnt_15_8_pos 0
+#define reg_dagc2_in_sat_cnt_15_8_len 8
+#define reg_dagc2_in_sat_cnt_15_8_lsb 8
+#define xd_p_reg_dagc2_in_sat_cnt_23_16 0xA1CB
+#define reg_dagc2_in_sat_cnt_23_16_pos 0
+#define reg_dagc2_in_sat_cnt_23_16_len 8
+#define reg_dagc2_in_sat_cnt_23_16_lsb 16
+#define xd_p_reg_dagc2_in_sat_cnt_31_24 0xA1CC
+#define reg_dagc2_in_sat_cnt_31_24_pos 0
+#define reg_dagc2_in_sat_cnt_31_24_len 8
+#define reg_dagc2_in_sat_cnt_31_24_lsb 24
+#define xd_p_reg_dagc2_out_sat_cnt_7_0 0xA1CD
+#define reg_dagc2_out_sat_cnt_7_0_pos 0
+#define reg_dagc2_out_sat_cnt_7_0_len 8
+#define reg_dagc2_out_sat_cnt_7_0_lsb 0
+#define xd_p_reg_dagc2_out_sat_cnt_15_8 0xA1CE
+#define reg_dagc2_out_sat_cnt_15_8_pos 0
+#define reg_dagc2_out_sat_cnt_15_8_len 8
+#define reg_dagc2_out_sat_cnt_15_8_lsb 8
+#define xd_p_reg_dagc2_out_sat_cnt_23_16 0xA1CF
+#define reg_dagc2_out_sat_cnt_23_16_pos 0
+#define reg_dagc2_out_sat_cnt_23_16_len 8
+#define reg_dagc2_out_sat_cnt_23_16_lsb 16
+#define xd_p_reg_dagc2_out_sat_cnt_31_24 0xA1D0
+#define reg_dagc2_out_sat_cnt_31_24_pos 0
+#define reg_dagc2_out_sat_cnt_31_24_len 8
+#define reg_dagc2_out_sat_cnt_31_24_lsb 24
+#define xd_r_dagc2_multiplier_7_0 0xA1D6
+#define dagc2_multiplier_7_0_pos 0
+#define dagc2_multiplier_7_0_len 8
+#define dagc2_multiplier_7_0_lsb 0
+#define xd_r_dagc2_multiplier_15_8 0xA1D7
+#define dagc2_multiplier_15_8_pos 0
+#define dagc2_multiplier_15_8_len 8
+#define dagc2_multiplier_15_8_lsb 8
+#define xd_r_dagc2_right_shift_bits 0xA1D8
+#define dagc2_right_shift_bits_pos 0
+#define dagc2_right_shift_bits_len 4
+#define dagc2_right_shift_bits_lsb 0
+#define xd_p_cfoe_NS_coeff1_7_0 0xA200
+#define cfoe_NS_coeff1_7_0_pos 0
+#define cfoe_NS_coeff1_7_0_len 8
+#define cfoe_NS_coeff1_7_0_lsb 0
+#define xd_p_cfoe_NS_coeff1_15_8 0xA201
+#define cfoe_NS_coeff1_15_8_pos 0
+#define cfoe_NS_coeff1_15_8_len 8
+#define cfoe_NS_coeff1_15_8_lsb 8
+#define xd_p_cfoe_NS_coeff1_23_16 0xA202
+#define cfoe_NS_coeff1_23_16_pos 0
+#define cfoe_NS_coeff1_23_16_len 8
+#define cfoe_NS_coeff1_23_16_lsb 16
+#define xd_p_cfoe_NS_coeff1_25_24 0xA203
+#define cfoe_NS_coeff1_25_24_pos 0
+#define cfoe_NS_coeff1_25_24_len 2
+#define cfoe_NS_coeff1_25_24_lsb 24
+#define xd_p_cfoe_NS_coeff2_5_0 0xA203
+#define cfoe_NS_coeff2_5_0_pos 2
+#define cfoe_NS_coeff2_5_0_len 6
+#define cfoe_NS_coeff2_5_0_lsb 0
+#define xd_p_cfoe_NS_coeff2_13_6 0xA204
+#define cfoe_NS_coeff2_13_6_pos 0
+#define cfoe_NS_coeff2_13_6_len 8
+#define cfoe_NS_coeff2_13_6_lsb 6
+#define xd_p_cfoe_NS_coeff2_21_14 0xA205
+#define cfoe_NS_coeff2_21_14_pos 0
+#define cfoe_NS_coeff2_21_14_len 8
+#define cfoe_NS_coeff2_21_14_lsb 14
+#define xd_p_cfoe_NS_coeff2_24_22 0xA206
+#define cfoe_NS_coeff2_24_22_pos 0
+#define cfoe_NS_coeff2_24_22_len 3
+#define cfoe_NS_coeff2_24_22_lsb 22
+#define xd_p_cfoe_lf_c1_4_0 0xA206
+#define cfoe_lf_c1_4_0_pos 3
+#define cfoe_lf_c1_4_0_len 5
+#define cfoe_lf_c1_4_0_lsb 0
+#define xd_p_cfoe_lf_c1_12_5 0xA207
+#define cfoe_lf_c1_12_5_pos 0
+#define cfoe_lf_c1_12_5_len 8
+#define cfoe_lf_c1_12_5_lsb 5
+#define xd_p_cfoe_lf_c1_20_13 0xA208
+#define cfoe_lf_c1_20_13_pos 0
+#define cfoe_lf_c1_20_13_len 8
+#define cfoe_lf_c1_20_13_lsb 13
+#define xd_p_cfoe_lf_c1_25_21 0xA209
+#define cfoe_lf_c1_25_21_pos 0
+#define cfoe_lf_c1_25_21_len 5
+#define cfoe_lf_c1_25_21_lsb 21
+#define xd_p_cfoe_lf_c2_2_0 0xA209
+#define cfoe_lf_c2_2_0_pos 5
+#define cfoe_lf_c2_2_0_len 3
+#define cfoe_lf_c2_2_0_lsb 0
+#define xd_p_cfoe_lf_c2_10_3 0xA20A
+#define cfoe_lf_c2_10_3_pos 0
+#define cfoe_lf_c2_10_3_len 8
+#define cfoe_lf_c2_10_3_lsb 3
+#define xd_p_cfoe_lf_c2_18_11 0xA20B
+#define cfoe_lf_c2_18_11_pos 0
+#define cfoe_lf_c2_18_11_len 8
+#define cfoe_lf_c2_18_11_lsb 11
+#define xd_p_cfoe_lf_c2_25_19 0xA20C
+#define cfoe_lf_c2_25_19_pos 0
+#define cfoe_lf_c2_25_19_len 7
+#define cfoe_lf_c2_25_19_lsb 19
+#define xd_p_cfoe_ifod_7_0 0xA20D
+#define cfoe_ifod_7_0_pos 0
+#define cfoe_ifod_7_0_len 8
+#define cfoe_ifod_7_0_lsb 0
+#define xd_p_cfoe_ifod_10_8 0xA20E
+#define cfoe_ifod_10_8_pos 0
+#define cfoe_ifod_10_8_len 3
+#define cfoe_ifod_10_8_lsb 8
+#define xd_p_cfoe_Divg_ctr_th 0xA20E
+#define cfoe_Divg_ctr_th_pos 4
+#define cfoe_Divg_ctr_th_len 4
+#define cfoe_Divg_ctr_th_lsb 0
+#define xd_p_cfoe_FOT_divg_th 0xA20F
+#define cfoe_FOT_divg_th_pos 0
+#define cfoe_FOT_divg_th_len 8
+#define cfoe_FOT_divg_th_lsb 0
+#define xd_p_cfoe_FOT_cnvg_th 0xA210
+#define cfoe_FOT_cnvg_th_pos 0
+#define cfoe_FOT_cnvg_th_len 8
+#define cfoe_FOT_cnvg_th_lsb 0
+#define xd_p_reg_cfoe_offset_7_0 0xA211
+#define reg_cfoe_offset_7_0_pos 0
+#define reg_cfoe_offset_7_0_len 8
+#define reg_cfoe_offset_7_0_lsb 0
+#define xd_p_reg_cfoe_offset_9_8 0xA212
+#define reg_cfoe_offset_9_8_pos 0
+#define reg_cfoe_offset_9_8_len 2
+#define reg_cfoe_offset_9_8_lsb 8
+#define xd_p_reg_cfoe_ifoe_sign_corr 0xA212
+#define reg_cfoe_ifoe_sign_corr_pos 2
+#define reg_cfoe_ifoe_sign_corr_len 1
+#define reg_cfoe_ifoe_sign_corr_lsb 0
+#define xd_r_cfoe_fot_LF_output_7_0 0xA218
+#define cfoe_fot_LF_output_7_0_pos 0
+#define cfoe_fot_LF_output_7_0_len 8
+#define cfoe_fot_LF_output_7_0_lsb 0
+#define xd_r_cfoe_fot_LF_output_15_8 0xA219
+#define cfoe_fot_LF_output_15_8_pos 0
+#define cfoe_fot_LF_output_15_8_len 8
+#define cfoe_fot_LF_output_15_8_lsb 8
+#define xd_r_cfoe_ifo_metric_7_0 0xA21A
+#define cfoe_ifo_metric_7_0_pos 0
+#define cfoe_ifo_metric_7_0_len 8
+#define cfoe_ifo_metric_7_0_lsb 0
+#define xd_r_cfoe_ifo_metric_15_8 0xA21B
+#define cfoe_ifo_metric_15_8_pos 0
+#define cfoe_ifo_metric_15_8_len 8
+#define cfoe_ifo_metric_15_8_lsb 8
+#define xd_r_cfoe_ifo_metric_23_16 0xA21C
+#define cfoe_ifo_metric_23_16_pos 0
+#define cfoe_ifo_metric_23_16_len 8
+#define cfoe_ifo_metric_23_16_lsb 16
+#define xd_p_ste_Nu 0xA220
+#define ste_Nu_pos 0
+#define ste_Nu_len 2
+#define ste_Nu_lsb 0
+#define xd_p_ste_GI 0xA220
+#define ste_GI_pos 2
+#define ste_GI_len 3
+#define ste_GI_lsb 0
+#define xd_p_ste_symbol_num 0xA221
+#define ste_symbol_num_pos 0
+#define ste_symbol_num_len 2
+#define ste_symbol_num_lsb 0
+#define xd_p_ste_sample_num 0xA221
+#define ste_sample_num_pos 2
+#define ste_sample_num_len 2
+#define ste_sample_num_lsb 0
+#define xd_p_reg_ste_buf_en 0xA221
+#define reg_ste_buf_en_pos 7
+#define reg_ste_buf_en_len 1
+#define reg_ste_buf_en_lsb 0
+#define xd_p_ste_FFT_offset_7_0 0xA222
+#define ste_FFT_offset_7_0_pos 0
+#define ste_FFT_offset_7_0_len 8
+#define ste_FFT_offset_7_0_lsb 0
+#define xd_p_ste_FFT_offset_11_8 0xA223
+#define ste_FFT_offset_11_8_pos 0
+#define ste_FFT_offset_11_8_len 4
+#define ste_FFT_offset_11_8_lsb 8
+#define xd_p_reg_ste_tstmod 0xA223
+#define reg_ste_tstmod_pos 5
+#define reg_ste_tstmod_len 1
+#define reg_ste_tstmod_lsb 0
+#define xd_p_ste_adv_start_7_0 0xA224
+#define ste_adv_start_7_0_pos 0
+#define ste_adv_start_7_0_len 8
+#define ste_adv_start_7_0_lsb 0
+#define xd_p_ste_adv_start_10_8 0xA225
+#define ste_adv_start_10_8_pos 0
+#define ste_adv_start_10_8_len 3
+#define ste_adv_start_10_8_lsb 8
+#define xd_p_ste_adv_stop 0xA226
+#define ste_adv_stop_pos 0
+#define ste_adv_stop_len 8
+#define ste_adv_stop_lsb 0
+#define xd_r_ste_P_value_7_0 0xA228
+#define ste_P_value_7_0_pos 0
+#define ste_P_value_7_0_len 8
+#define ste_P_value_7_0_lsb 0
+#define xd_r_ste_P_value_10_8 0xA229
+#define ste_P_value_10_8_pos 0
+#define ste_P_value_10_8_len 3
+#define ste_P_value_10_8_lsb 8
+#define xd_r_ste_M_value_7_0 0xA22A
+#define ste_M_value_7_0_pos 0
+#define ste_M_value_7_0_len 8
+#define ste_M_value_7_0_lsb 0
+#define xd_r_ste_M_value_10_8 0xA22B
+#define ste_M_value_10_8_pos 0
+#define ste_M_value_10_8_len 3
+#define ste_M_value_10_8_lsb 8
+#define xd_r_ste_H1 0xA22C
+#define ste_H1_pos 0
+#define ste_H1_len 7
+#define ste_H1_lsb 0
+#define xd_r_ste_H2 0xA22D
+#define ste_H2_pos 0
+#define ste_H2_len 7
+#define ste_H2_lsb 0
+#define xd_r_ste_H3 0xA22E
+#define ste_H3_pos 0
+#define ste_H3_len 7
+#define ste_H3_lsb 0
+#define xd_r_ste_H4 0xA22F
+#define ste_H4_pos 0
+#define ste_H4_len 7
+#define ste_H4_lsb 0
+#define xd_r_ste_Corr_value_I_7_0 0xA230
+#define ste_Corr_value_I_7_0_pos 0
+#define ste_Corr_value_I_7_0_len 8
+#define ste_Corr_value_I_7_0_lsb 0
+#define xd_r_ste_Corr_value_I_15_8 0xA231
+#define ste_Corr_value_I_15_8_pos 0
+#define ste_Corr_value_I_15_8_len 8
+#define ste_Corr_value_I_15_8_lsb 8
+#define xd_r_ste_Corr_value_I_23_16 0xA232
+#define ste_Corr_value_I_23_16_pos 0
+#define ste_Corr_value_I_23_16_len 8
+#define ste_Corr_value_I_23_16_lsb 16
+#define xd_r_ste_Corr_value_I_27_24 0xA233
+#define ste_Corr_value_I_27_24_pos 0
+#define ste_Corr_value_I_27_24_len 4
+#define ste_Corr_value_I_27_24_lsb 24
+#define xd_r_ste_Corr_value_Q_7_0 0xA234
+#define ste_Corr_value_Q_7_0_pos 0
+#define ste_Corr_value_Q_7_0_len 8
+#define ste_Corr_value_Q_7_0_lsb 0
+#define xd_r_ste_Corr_value_Q_15_8 0xA235
+#define ste_Corr_value_Q_15_8_pos 0
+#define ste_Corr_value_Q_15_8_len 8
+#define ste_Corr_value_Q_15_8_lsb 8
+#define xd_r_ste_Corr_value_Q_23_16 0xA236
+#define ste_Corr_value_Q_23_16_pos 0
+#define ste_Corr_value_Q_23_16_len 8
+#define ste_Corr_value_Q_23_16_lsb 16
+#define xd_r_ste_Corr_value_Q_27_24 0xA237
+#define ste_Corr_value_Q_27_24_pos 0
+#define ste_Corr_value_Q_27_24_len 4
+#define ste_Corr_value_Q_27_24_lsb 24
+#define xd_r_ste_J_num_7_0 0xA238
+#define ste_J_num_7_0_pos 0
+#define ste_J_num_7_0_len 8
+#define ste_J_num_7_0_lsb 0
+#define xd_r_ste_J_num_15_8 0xA239
+#define ste_J_num_15_8_pos 0
+#define ste_J_num_15_8_len 8
+#define ste_J_num_15_8_lsb 8
+#define xd_r_ste_J_num_23_16 0xA23A
+#define ste_J_num_23_16_pos 0
+#define ste_J_num_23_16_len 8
+#define ste_J_num_23_16_lsb 16
+#define xd_r_ste_J_num_31_24 0xA23B
+#define ste_J_num_31_24_pos 0
+#define ste_J_num_31_24_len 8
+#define ste_J_num_31_24_lsb 24
+#define xd_r_ste_J_den_7_0 0xA23C
+#define ste_J_den_7_0_pos 0
+#define ste_J_den_7_0_len 8
+#define ste_J_den_7_0_lsb 0
+#define xd_r_ste_J_den_15_8 0xA23D
+#define ste_J_den_15_8_pos 0
+#define ste_J_den_15_8_len 8
+#define ste_J_den_15_8_lsb 8
+#define xd_r_ste_J_den_18_16 0xA23E
+#define ste_J_den_18_16_pos 0
+#define ste_J_den_18_16_len 3
+#define ste_J_den_18_16_lsb 16
+#define xd_r_ste_Beacon_Indicator 0xA23E
+#define ste_Beacon_Indicator_pos 4
+#define ste_Beacon_Indicator_len 1
+#define ste_Beacon_Indicator_lsb 0
+#define xd_r_tpsd_Frame_Num 0xA250
+#define tpsd_Frame_Num_pos 0
+#define tpsd_Frame_Num_len 2
+#define tpsd_Frame_Num_lsb 0
+#define xd_r_tpsd_Constel 0xA250
+#define tpsd_Constel_pos 2
+#define tpsd_Constel_len 2
+#define tpsd_Constel_lsb 0
+#define xd_r_tpsd_GI 0xA250
+#define tpsd_GI_pos 4
+#define tpsd_GI_len 2
+#define tpsd_GI_lsb 0
+#define xd_r_tpsd_Mode 0xA250
+#define tpsd_Mode_pos 6
+#define tpsd_Mode_len 2
+#define tpsd_Mode_lsb 0
+#define xd_r_tpsd_CR_HP 0xA251
+#define tpsd_CR_HP_pos 0
+#define tpsd_CR_HP_len 3
+#define tpsd_CR_HP_lsb 0
+#define xd_r_tpsd_CR_LP 0xA251
+#define tpsd_CR_LP_pos 3
+#define tpsd_CR_LP_len 3
+#define tpsd_CR_LP_lsb 0
+#define xd_r_tpsd_Hie 0xA252
+#define tpsd_Hie_pos 0
+#define tpsd_Hie_len 3
+#define tpsd_Hie_lsb 0
+#define xd_r_tpsd_Res_Bits 0xA252
+#define tpsd_Res_Bits_pos 3
+#define tpsd_Res_Bits_len 5
+#define tpsd_Res_Bits_lsb 0
+#define xd_r_tpsd_Res_Bits_0 0xA253
+#define tpsd_Res_Bits_0_pos 0
+#define tpsd_Res_Bits_0_len 1
+#define tpsd_Res_Bits_0_lsb 0
+#define xd_r_tpsd_LengthInd 0xA253
+#define tpsd_LengthInd_pos 1
+#define tpsd_LengthInd_len 6
+#define tpsd_LengthInd_lsb 0
+#define xd_r_tpsd_Cell_Id_7_0 0xA254
+#define tpsd_Cell_Id_7_0_pos 0
+#define tpsd_Cell_Id_7_0_len 8
+#define tpsd_Cell_Id_7_0_lsb 0
+#define xd_r_tpsd_Cell_Id_15_8 0xA255
+#define tpsd_Cell_Id_15_8_pos 0
+#define tpsd_Cell_Id_15_8_len 8
+#define tpsd_Cell_Id_15_8_lsb 0
+#define xd_p_reg_fft_mask_tone0_7_0 0xA260
+#define reg_fft_mask_tone0_7_0_pos 0
+#define reg_fft_mask_tone0_7_0_len 8
+#define reg_fft_mask_tone0_7_0_lsb 0
+#define xd_p_reg_fft_mask_tone0_12_8 0xA261
+#define reg_fft_mask_tone0_12_8_pos 0
+#define reg_fft_mask_tone0_12_8_len 5
+#define reg_fft_mask_tone0_12_8_lsb 8
+#define xd_p_reg_fft_mask_tone1_7_0 0xA262
+#define reg_fft_mask_tone1_7_0_pos 0
+#define reg_fft_mask_tone1_7_0_len 8
+#define reg_fft_mask_tone1_7_0_lsb 0
+#define xd_p_reg_fft_mask_tone1_12_8 0xA263
+#define reg_fft_mask_tone1_12_8_pos 0
+#define reg_fft_mask_tone1_12_8_len 5
+#define reg_fft_mask_tone1_12_8_lsb 8
+#define xd_p_reg_fft_mask_tone2_7_0 0xA264
+#define reg_fft_mask_tone2_7_0_pos 0
+#define reg_fft_mask_tone2_7_0_len 8
+#define reg_fft_mask_tone2_7_0_lsb 0
+#define xd_p_reg_fft_mask_tone2_12_8 0xA265
+#define reg_fft_mask_tone2_12_8_pos 0
+#define reg_fft_mask_tone2_12_8_len 5
+#define reg_fft_mask_tone2_12_8_lsb 8
+#define xd_p_reg_fft_mask_tone3_7_0 0xA266
+#define reg_fft_mask_tone3_7_0_pos 0
+#define reg_fft_mask_tone3_7_0_len 8
+#define reg_fft_mask_tone3_7_0_lsb 0
+#define xd_p_reg_fft_mask_tone3_12_8 0xA267
+#define reg_fft_mask_tone3_12_8_pos 0
+#define reg_fft_mask_tone3_12_8_len 5
+#define reg_fft_mask_tone3_12_8_lsb 8
+#define xd_p_reg_fft_mask_from0_7_0 0xA268
+#define reg_fft_mask_from0_7_0_pos 0
+#define reg_fft_mask_from0_7_0_len 8
+#define reg_fft_mask_from0_7_0_lsb 0
+#define xd_p_reg_fft_mask_from0_12_8 0xA269
+#define reg_fft_mask_from0_12_8_pos 0
+#define reg_fft_mask_from0_12_8_len 5
+#define reg_fft_mask_from0_12_8_lsb 8
+#define xd_p_reg_fft_mask_to0_7_0 0xA26A
+#define reg_fft_mask_to0_7_0_pos 0
+#define reg_fft_mask_to0_7_0_len 8
+#define reg_fft_mask_to0_7_0_lsb 0
+#define xd_p_reg_fft_mask_to0_12_8 0xA26B
+#define reg_fft_mask_to0_12_8_pos 0
+#define reg_fft_mask_to0_12_8_len 5
+#define reg_fft_mask_to0_12_8_lsb 8
+#define xd_p_reg_fft_mask_from1_7_0 0xA26C
+#define reg_fft_mask_from1_7_0_pos 0
+#define reg_fft_mask_from1_7_0_len 8
+#define reg_fft_mask_from1_7_0_lsb 0
+#define xd_p_reg_fft_mask_from1_12_8 0xA26D
+#define reg_fft_mask_from1_12_8_pos 0
+#define reg_fft_mask_from1_12_8_len 5
+#define reg_fft_mask_from1_12_8_lsb 8
+#define xd_p_reg_fft_mask_to1_7_0 0xA26E
+#define reg_fft_mask_to1_7_0_pos 0
+#define reg_fft_mask_to1_7_0_len 8
+#define reg_fft_mask_to1_7_0_lsb 0
+#define xd_p_reg_fft_mask_to1_12_8 0xA26F
+#define reg_fft_mask_to1_12_8_pos 0
+#define reg_fft_mask_to1_12_8_len 5
+#define reg_fft_mask_to1_12_8_lsb 8
+#define xd_p_reg_cge_idx0_7_0 0xA280
+#define reg_cge_idx0_7_0_pos 0
+#define reg_cge_idx0_7_0_len 8
+#define reg_cge_idx0_7_0_lsb 0
+#define xd_p_reg_cge_idx0_12_8 0xA281
+#define reg_cge_idx0_12_8_pos 0
+#define reg_cge_idx0_12_8_len 5
+#define reg_cge_idx0_12_8_lsb 8
+#define xd_p_reg_cge_idx1_7_0 0xA282
+#define reg_cge_idx1_7_0_pos 0
+#define reg_cge_idx1_7_0_len 8
+#define reg_cge_idx1_7_0_lsb 0
+#define xd_p_reg_cge_idx1_12_8 0xA283
+#define reg_cge_idx1_12_8_pos 0
+#define reg_cge_idx1_12_8_len 5
+#define reg_cge_idx1_12_8_lsb 8
+#define xd_p_reg_cge_idx2_7_0 0xA284
+#define reg_cge_idx2_7_0_pos 0
+#define reg_cge_idx2_7_0_len 8
+#define reg_cge_idx2_7_0_lsb 0
+#define xd_p_reg_cge_idx2_12_8 0xA285
+#define reg_cge_idx2_12_8_pos 0
+#define reg_cge_idx2_12_8_len 5
+#define reg_cge_idx2_12_8_lsb 8
+#define xd_p_reg_cge_idx3_7_0 0xA286
+#define reg_cge_idx3_7_0_pos 0
+#define reg_cge_idx3_7_0_len 8
+#define reg_cge_idx3_7_0_lsb 0
+#define xd_p_reg_cge_idx3_12_8 0xA287
+#define reg_cge_idx3_12_8_pos 0
+#define reg_cge_idx3_12_8_len 5
+#define reg_cge_idx3_12_8_lsb 8
+#define xd_p_reg_cge_idx4_7_0 0xA288
+#define reg_cge_idx4_7_0_pos 0
+#define reg_cge_idx4_7_0_len 8
+#define reg_cge_idx4_7_0_lsb 0
+#define xd_p_reg_cge_idx4_12_8 0xA289
+#define reg_cge_idx4_12_8_pos 0
+#define reg_cge_idx4_12_8_len 5
+#define reg_cge_idx4_12_8_lsb 8
+#define xd_p_reg_cge_idx5_7_0 0xA28A
+#define reg_cge_idx5_7_0_pos 0
+#define reg_cge_idx5_7_0_len 8
+#define reg_cge_idx5_7_0_lsb 0
+#define xd_p_reg_cge_idx5_12_8 0xA28B
+#define reg_cge_idx5_12_8_pos 0
+#define reg_cge_idx5_12_8_len 5
+#define reg_cge_idx5_12_8_lsb 8
+#define xd_p_reg_cge_idx6_7_0 0xA28C
+#define reg_cge_idx6_7_0_pos 0
+#define reg_cge_idx6_7_0_len 8
+#define reg_cge_idx6_7_0_lsb 0
+#define xd_p_reg_cge_idx6_12_8 0xA28D
+#define reg_cge_idx6_12_8_pos 0
+#define reg_cge_idx6_12_8_len 5
+#define reg_cge_idx6_12_8_lsb 8
+#define xd_p_reg_cge_idx7_7_0 0xA28E
+#define reg_cge_idx7_7_0_pos 0
+#define reg_cge_idx7_7_0_len 8
+#define reg_cge_idx7_7_0_lsb 0
+#define xd_p_reg_cge_idx7_12_8 0xA28F
+#define reg_cge_idx7_12_8_pos 0
+#define reg_cge_idx7_12_8_len 5
+#define reg_cge_idx7_12_8_lsb 8
+#define xd_p_reg_cge_idx8_7_0 0xA290
+#define reg_cge_idx8_7_0_pos 0
+#define reg_cge_idx8_7_0_len 8
+#define reg_cge_idx8_7_0_lsb 0
+#define xd_p_reg_cge_idx8_12_8 0xA291
+#define reg_cge_idx8_12_8_pos 0
+#define reg_cge_idx8_12_8_len 5
+#define reg_cge_idx8_12_8_lsb 8
+#define xd_p_reg_cge_idx9_7_0 0xA292
+#define reg_cge_idx9_7_0_pos 0
+#define reg_cge_idx9_7_0_len 8
+#define reg_cge_idx9_7_0_lsb 0
+#define xd_p_reg_cge_idx9_12_8 0xA293
+#define reg_cge_idx9_12_8_pos 0
+#define reg_cge_idx9_12_8_len 5
+#define reg_cge_idx9_12_8_lsb 8
+#define xd_p_reg_cge_idx10_7_0 0xA294
+#define reg_cge_idx10_7_0_pos 0
+#define reg_cge_idx10_7_0_len 8
+#define reg_cge_idx10_7_0_lsb 0
+#define xd_p_reg_cge_idx10_12_8 0xA295
+#define reg_cge_idx10_12_8_pos 0
+#define reg_cge_idx10_12_8_len 5
+#define reg_cge_idx10_12_8_lsb 8
+#define xd_p_reg_cge_idx11_7_0 0xA296
+#define reg_cge_idx11_7_0_pos 0
+#define reg_cge_idx11_7_0_len 8
+#define reg_cge_idx11_7_0_lsb 0
+#define xd_p_reg_cge_idx11_12_8 0xA297
+#define reg_cge_idx11_12_8_pos 0
+#define reg_cge_idx11_12_8_len 5
+#define reg_cge_idx11_12_8_lsb 8
+#define xd_p_reg_cge_idx12_7_0 0xA298
+#define reg_cge_idx12_7_0_pos 0
+#define reg_cge_idx12_7_0_len 8
+#define reg_cge_idx12_7_0_lsb 0
+#define xd_p_reg_cge_idx12_12_8 0xA299
+#define reg_cge_idx12_12_8_pos 0
+#define reg_cge_idx12_12_8_len 5
+#define reg_cge_idx12_12_8_lsb 8
+#define xd_p_reg_cge_idx13_7_0 0xA29A
+#define reg_cge_idx13_7_0_pos 0
+#define reg_cge_idx13_7_0_len 8
+#define reg_cge_idx13_7_0_lsb 0
+#define xd_p_reg_cge_idx13_12_8 0xA29B
+#define reg_cge_idx13_12_8_pos 0
+#define reg_cge_idx13_12_8_len 5
+#define reg_cge_idx13_12_8_lsb 8
+#define xd_p_reg_cge_idx14_7_0 0xA29C
+#define reg_cge_idx14_7_0_pos 0
+#define reg_cge_idx14_7_0_len 8
+#define reg_cge_idx14_7_0_lsb 0
+#define xd_p_reg_cge_idx14_12_8 0xA29D
+#define reg_cge_idx14_12_8_pos 0
+#define reg_cge_idx14_12_8_len 5
+#define reg_cge_idx14_12_8_lsb 8
+#define xd_p_reg_cge_idx15_7_0 0xA29E
+#define reg_cge_idx15_7_0_pos 0
+#define reg_cge_idx15_7_0_len 8
+#define reg_cge_idx15_7_0_lsb 0
+#define xd_p_reg_cge_idx15_12_8 0xA29F
+#define reg_cge_idx15_12_8_pos 0
+#define reg_cge_idx15_12_8_len 5
+#define reg_cge_idx15_12_8_lsb 8
+#define xd_r_reg_fft_crc 0xA2A8
+#define reg_fft_crc_pos 0
+#define reg_fft_crc_len 8
+#define reg_fft_crc_lsb 0
+#define xd_p_fd_fft_shift_max 0xA2A9
+#define fd_fft_shift_max_pos 0
+#define fd_fft_shift_max_len 4
+#define fd_fft_shift_max_lsb 0
+#define xd_r_fd_fft_shift 0xA2A9
+#define fd_fft_shift_pos 4
+#define fd_fft_shift_len 4
+#define fd_fft_shift_lsb 0
+#define xd_r_fd_fft_frame_num 0xA2AA
+#define fd_fft_frame_num_pos 0
+#define fd_fft_frame_num_len 2
+#define fd_fft_frame_num_lsb 0
+#define xd_r_fd_fft_symbol_count 0xA2AB
+#define fd_fft_symbol_count_pos 0
+#define fd_fft_symbol_count_len 7
+#define fd_fft_symbol_count_lsb 0
+#define xd_r_reg_fft_idx_max_7_0 0xA2AC
+#define reg_fft_idx_max_7_0_pos 0
+#define reg_fft_idx_max_7_0_len 8
+#define reg_fft_idx_max_7_0_lsb 0
+#define xd_r_reg_fft_idx_max_12_8 0xA2AD
+#define reg_fft_idx_max_12_8_pos 0
+#define reg_fft_idx_max_12_8_len 5
+#define reg_fft_idx_max_12_8_lsb 8
+#define xd_p_reg_cge_program 0xA2AE
+#define reg_cge_program_pos 0
+#define reg_cge_program_len 1
+#define reg_cge_program_lsb 0
+#define xd_p_reg_cge_fixed 0xA2AE
+#define reg_cge_fixed_pos 1
+#define reg_cge_fixed_len 1
+#define reg_cge_fixed_lsb 0
+#define xd_p_reg_fft_rotate_en 0xA2AE
+#define reg_fft_rotate_en_pos 2
+#define reg_fft_rotate_en_len 1
+#define reg_fft_rotate_en_lsb 0
+#define xd_p_reg_fft_rotate_base_4_0 0xA2AE
+#define reg_fft_rotate_base_4_0_pos 3
+#define reg_fft_rotate_base_4_0_len 5
+#define reg_fft_rotate_base_4_0_lsb 0
+#define xd_p_reg_fft_rotate_base_12_5 0xA2AF
+#define reg_fft_rotate_base_12_5_pos 0
+#define reg_fft_rotate_base_12_5_len 8
+#define reg_fft_rotate_base_12_5_lsb 5
+#define xd_p_reg_gp_trigger_fd 0xA2B8
+#define reg_gp_trigger_fd_pos 0
+#define reg_gp_trigger_fd_len 1
+#define reg_gp_trigger_fd_lsb 0
+#define xd_p_reg_trigger_sel_fd 0xA2B8
+#define reg_trigger_sel_fd_pos 1
+#define reg_trigger_sel_fd_len 2
+#define reg_trigger_sel_fd_lsb 0
+#define xd_p_reg_trigger_module_sel_fd 0xA2B9
+#define reg_trigger_module_sel_fd_pos 0
+#define reg_trigger_module_sel_fd_len 6
+#define reg_trigger_module_sel_fd_lsb 0
+#define xd_p_reg_trigger_set_sel_fd 0xA2BA
+#define reg_trigger_set_sel_fd_pos 0
+#define reg_trigger_set_sel_fd_len 6
+#define reg_trigger_set_sel_fd_lsb 0
+#define xd_p_reg_fd_noname_7_0 0xA2BC
+#define reg_fd_noname_7_0_pos 0
+#define reg_fd_noname_7_0_len 8
+#define reg_fd_noname_7_0_lsb 0
+#define xd_p_reg_fd_noname_15_8 0xA2BD
+#define reg_fd_noname_15_8_pos 0
+#define reg_fd_noname_15_8_len 8
+#define reg_fd_noname_15_8_lsb 8
+#define xd_p_reg_fd_noname_23_16 0xA2BE
+#define reg_fd_noname_23_16_pos 0
+#define reg_fd_noname_23_16_len 8
+#define reg_fd_noname_23_16_lsb 16
+#define xd_p_reg_fd_noname_31_24 0xA2BF
+#define reg_fd_noname_31_24_pos 0
+#define reg_fd_noname_31_24_len 8
+#define reg_fd_noname_31_24_lsb 24
+#define xd_r_fd_fpcc_cp_corr_signn 0xA2C0
+#define fd_fpcc_cp_corr_signn_pos 0
+#define fd_fpcc_cp_corr_signn_len 8
+#define fd_fpcc_cp_corr_signn_lsb 0
+#define xd_p_reg_feq_s1 0xA2C1
+#define reg_feq_s1_pos 0
+#define reg_feq_s1_len 5
+#define reg_feq_s1_lsb 0
+#define xd_p_fd_fpcc_cp_corr_tone_th 0xA2C2
+#define fd_fpcc_cp_corr_tone_th_pos 0
+#define fd_fpcc_cp_corr_tone_th_len 6
+#define fd_fpcc_cp_corr_tone_th_lsb 0
+#define xd_p_fd_fpcc_cp_corr_symbol_log_th 0xA2C3
+#define fd_fpcc_cp_corr_symbol_log_th_pos 0
+#define fd_fpcc_cp_corr_symbol_log_th_len 4
+#define fd_fpcc_cp_corr_symbol_log_th_lsb 0
+#define xd_p_fd_fpcc_cp_corr_int 0xA2C4
+#define fd_fpcc_cp_corr_int_pos 0
+#define fd_fpcc_cp_corr_int_len 1
+#define fd_fpcc_cp_corr_int_lsb 0
+#define xd_p_reg_sfoe_ns_7_0 0xA320
+#define reg_sfoe_ns_7_0_pos 0
+#define reg_sfoe_ns_7_0_len 8
+#define reg_sfoe_ns_7_0_lsb 0
+#define xd_p_reg_sfoe_ns_14_8 0xA321
+#define reg_sfoe_ns_14_8_pos 0
+#define reg_sfoe_ns_14_8_len 7
+#define reg_sfoe_ns_14_8_lsb 8
+#define xd_p_reg_sfoe_c1_7_0 0xA322
+#define reg_sfoe_c1_7_0_pos 0
+#define reg_sfoe_c1_7_0_len 8
+#define reg_sfoe_c1_7_0_lsb 0
+#define xd_p_reg_sfoe_c1_15_8 0xA323
+#define reg_sfoe_c1_15_8_pos 0
+#define reg_sfoe_c1_15_8_len 8
+#define reg_sfoe_c1_15_8_lsb 8
+#define xd_p_reg_sfoe_c1_17_16 0xA324
+#define reg_sfoe_c1_17_16_pos 0
+#define reg_sfoe_c1_17_16_len 2
+#define reg_sfoe_c1_17_16_lsb 16
+#define xd_p_reg_sfoe_c2_7_0 0xA325
+#define reg_sfoe_c2_7_0_pos 0
+#define reg_sfoe_c2_7_0_len 8
+#define reg_sfoe_c2_7_0_lsb 0
+#define xd_p_reg_sfoe_c2_15_8 0xA326
+#define reg_sfoe_c2_15_8_pos 0
+#define reg_sfoe_c2_15_8_len 8
+#define reg_sfoe_c2_15_8_lsb 8
+#define xd_p_reg_sfoe_c2_17_16 0xA327
+#define reg_sfoe_c2_17_16_pos 0
+#define reg_sfoe_c2_17_16_len 2
+#define reg_sfoe_c2_17_16_lsb 16
+#define xd_r_reg_sfoe_out_9_2 0xA328
+#define reg_sfoe_out_9_2_pos 0
+#define reg_sfoe_out_9_2_len 8
+#define reg_sfoe_out_9_2_lsb 0
+#define xd_r_reg_sfoe_out_1_0 0xA329
+#define reg_sfoe_out_1_0_pos 0
+#define reg_sfoe_out_1_0_len 2
+#define reg_sfoe_out_1_0_lsb 0
+#define xd_p_reg_sfoe_lm_counter_th 0xA32A
+#define reg_sfoe_lm_counter_th_pos 0
+#define reg_sfoe_lm_counter_th_len 4
+#define reg_sfoe_lm_counter_th_lsb 0
+#define xd_p_reg_sfoe_convg_th 0xA32B
+#define reg_sfoe_convg_th_pos 0
+#define reg_sfoe_convg_th_len 8
+#define reg_sfoe_convg_th_lsb 0
+#define xd_p_reg_sfoe_divg_th 0xA32C
+#define reg_sfoe_divg_th_pos 0
+#define reg_sfoe_divg_th_len 8
+#define reg_sfoe_divg_th_lsb 0
+#define xd_p_fd_tpsd_en 0xA330
+#define fd_tpsd_en_pos 0
+#define fd_tpsd_en_len 1
+#define fd_tpsd_en_lsb 0
+#define xd_p_fd_tpsd_dis 0xA330
+#define fd_tpsd_dis_pos 1
+#define fd_tpsd_dis_len 1
+#define fd_tpsd_dis_lsb 0
+#define xd_p_fd_tpsd_rst 0xA330
+#define fd_tpsd_rst_pos 2
+#define fd_tpsd_rst_len 1
+#define fd_tpsd_rst_lsb 0
+#define xd_p_fd_tpsd_lock 0xA330
+#define fd_tpsd_lock_pos 3
+#define fd_tpsd_lock_len 1
+#define fd_tpsd_lock_lsb 0
+#define xd_r_fd_tpsd_s19 0xA330
+#define fd_tpsd_s19_pos 4
+#define fd_tpsd_s19_len 1
+#define fd_tpsd_s19_lsb 0
+#define xd_r_fd_tpsd_s17 0xA330
+#define fd_tpsd_s17_pos 5
+#define fd_tpsd_s17_len 1
+#define fd_tpsd_s17_lsb 0
+#define xd_p_fd_sfr_ste_en 0xA331
+#define fd_sfr_ste_en_pos 0
+#define fd_sfr_ste_en_len 1
+#define fd_sfr_ste_en_lsb 0
+#define xd_p_fd_sfr_ste_dis 0xA331
+#define fd_sfr_ste_dis_pos 1
+#define fd_sfr_ste_dis_len 1
+#define fd_sfr_ste_dis_lsb 0
+#define xd_p_fd_sfr_ste_rst 0xA331
+#define fd_sfr_ste_rst_pos 2
+#define fd_sfr_ste_rst_len 1
+#define fd_sfr_ste_rst_lsb 0
+#define xd_p_fd_sfr_ste_mode 0xA331
+#define fd_sfr_ste_mode_pos 3
+#define fd_sfr_ste_mode_len 1
+#define fd_sfr_ste_mode_lsb 0
+#define xd_p_fd_sfr_ste_done 0xA331
+#define fd_sfr_ste_done_pos 4
+#define fd_sfr_ste_done_len 1
+#define fd_sfr_ste_done_lsb 0
+#define xd_p_reg_cfoe_ffoe_en 0xA332
+#define reg_cfoe_ffoe_en_pos 0
+#define reg_cfoe_ffoe_en_len 1
+#define reg_cfoe_ffoe_en_lsb 0
+#define xd_p_reg_cfoe_ffoe_dis 0xA332
+#define reg_cfoe_ffoe_dis_pos 1
+#define reg_cfoe_ffoe_dis_len 1
+#define reg_cfoe_ffoe_dis_lsb 0
+#define xd_p_reg_cfoe_ffoe_rst 0xA332
+#define reg_cfoe_ffoe_rst_pos 2
+#define reg_cfoe_ffoe_rst_len 1
+#define reg_cfoe_ffoe_rst_lsb 0
+#define xd_p_reg_cfoe_ifoe_en 0xA332
+#define reg_cfoe_ifoe_en_pos 3
+#define reg_cfoe_ifoe_en_len 1
+#define reg_cfoe_ifoe_en_lsb 0
+#define xd_p_reg_cfoe_ifoe_dis 0xA332
+#define reg_cfoe_ifoe_dis_pos 4
+#define reg_cfoe_ifoe_dis_len 1
+#define reg_cfoe_ifoe_dis_lsb 0
+#define xd_p_reg_cfoe_ifoe_rst 0xA332
+#define reg_cfoe_ifoe_rst_pos 5
+#define reg_cfoe_ifoe_rst_len 1
+#define reg_cfoe_ifoe_rst_lsb 0
+#define xd_p_reg_cfoe_fot_en 0xA332
+#define reg_cfoe_fot_en_pos 6
+#define reg_cfoe_fot_en_len 1
+#define reg_cfoe_fot_en_lsb 0
+#define xd_p_reg_cfoe_fot_lm_en 0xA332
+#define reg_cfoe_fot_lm_en_pos 7
+#define reg_cfoe_fot_lm_en_len 1
+#define reg_cfoe_fot_lm_en_lsb 0
+#define xd_p_reg_cfoe_fot_rst 0xA333
+#define reg_cfoe_fot_rst_pos 0
+#define reg_cfoe_fot_rst_len 1
+#define reg_cfoe_fot_rst_lsb 0
+#define xd_r_fd_cfoe_ffoe_done 0xA333
+#define fd_cfoe_ffoe_done_pos 1
+#define fd_cfoe_ffoe_done_len 1
+#define fd_cfoe_ffoe_done_lsb 0
+#define xd_p_fd_cfoe_metric_vld 0xA333
+#define fd_cfoe_metric_vld_pos 2
+#define fd_cfoe_metric_vld_len 1
+#define fd_cfoe_metric_vld_lsb 0
+#define xd_p_reg_cfoe_ifod_vld 0xA333
+#define reg_cfoe_ifod_vld_pos 3
+#define reg_cfoe_ifod_vld_len 1
+#define reg_cfoe_ifod_vld_lsb 0
+#define xd_r_fd_cfoe_ifoe_done 0xA333
+#define fd_cfoe_ifoe_done_pos 4
+#define fd_cfoe_ifoe_done_len 1
+#define fd_cfoe_ifoe_done_lsb 0
+#define xd_r_fd_cfoe_fot_valid 0xA333
+#define fd_cfoe_fot_valid_pos 5
+#define fd_cfoe_fot_valid_len 1
+#define fd_cfoe_fot_valid_lsb 0
+#define xd_p_reg_cfoe_divg_int 0xA333
+#define reg_cfoe_divg_int_pos 6
+#define reg_cfoe_divg_int_len 1
+#define reg_cfoe_divg_int_lsb 0
+#define xd_r_reg_cfoe_divg_flag 0xA333
+#define reg_cfoe_divg_flag_pos 7
+#define reg_cfoe_divg_flag_len 1
+#define reg_cfoe_divg_flag_lsb 0
+#define xd_p_reg_sfoe_en 0xA334
+#define reg_sfoe_en_pos 0
+#define reg_sfoe_en_len 1
+#define reg_sfoe_en_lsb 0
+#define xd_p_reg_sfoe_dis 0xA334
+#define reg_sfoe_dis_pos 1
+#define reg_sfoe_dis_len 1
+#define reg_sfoe_dis_lsb 0
+#define xd_p_reg_sfoe_rst 0xA334
+#define reg_sfoe_rst_pos 2
+#define reg_sfoe_rst_len 1
+#define reg_sfoe_rst_lsb 0
+#define xd_p_reg_sfoe_vld_int 0xA334
+#define reg_sfoe_vld_int_pos 3
+#define reg_sfoe_vld_int_len 1
+#define reg_sfoe_vld_int_lsb 0
+#define xd_p_reg_sfoe_lm_en 0xA334
+#define reg_sfoe_lm_en_pos 4
+#define reg_sfoe_lm_en_len 1
+#define reg_sfoe_lm_en_lsb 0
+#define xd_p_reg_sfoe_divg_int 0xA334
+#define reg_sfoe_divg_int_pos 5
+#define reg_sfoe_divg_int_len 1
+#define reg_sfoe_divg_int_lsb 0
+#define xd_r_reg_sfoe_divg_flag 0xA334
+#define reg_sfoe_divg_flag_pos 6
+#define reg_sfoe_divg_flag_len 1
+#define reg_sfoe_divg_flag_lsb 0
+#define xd_p_reg_fft_rst 0xA335
+#define reg_fft_rst_pos 0
+#define reg_fft_rst_len 1
+#define reg_fft_rst_lsb 0
+#define xd_p_reg_fft_fast_beacon 0xA335
+#define reg_fft_fast_beacon_pos 1
+#define reg_fft_fast_beacon_len 1
+#define reg_fft_fast_beacon_lsb 0
+#define xd_p_reg_fft_fast_valid 0xA335
+#define reg_fft_fast_valid_pos 2
+#define reg_fft_fast_valid_len 1
+#define reg_fft_fast_valid_lsb 0
+#define xd_p_reg_fft_mask_en 0xA335
+#define reg_fft_mask_en_pos 3
+#define reg_fft_mask_en_len 1
+#define reg_fft_mask_en_lsb 0
+#define xd_p_reg_fft_crc_en 0xA335
+#define reg_fft_crc_en_pos 4
+#define reg_fft_crc_en_len 1
+#define reg_fft_crc_en_lsb 0
+#define xd_p_reg_finr_en 0xA336
+#define reg_finr_en_pos 0
+#define reg_finr_en_len 1
+#define reg_finr_en_lsb 0
+#define xd_p_fd_fste_en 0xA337
+#define fd_fste_en_pos 1
+#define fd_fste_en_len 1
+#define fd_fste_en_lsb 0
+#define xd_p_fd_sqi_tps_level_shift 0xA338
+#define fd_sqi_tps_level_shift_pos 0
+#define fd_sqi_tps_level_shift_len 8
+#define fd_sqi_tps_level_shift_lsb 0
+#define xd_p_fd_pilot_ma_len 0xA339
+#define fd_pilot_ma_len_pos 0
+#define fd_pilot_ma_len_len 6
+#define fd_pilot_ma_len_lsb 0
+#define xd_p_fd_tps_ma_len 0xA33A
+#define fd_tps_ma_len_pos 0
+#define fd_tps_ma_len_len 6
+#define fd_tps_ma_len_lsb 0
+#define xd_p_fd_sqi_s3 0xA33B
+#define fd_sqi_s3_pos 0
+#define fd_sqi_s3_len 8
+#define fd_sqi_s3_lsb 0
+#define xd_p_fd_sqi_dummy_reg_0 0xA33C
+#define fd_sqi_dummy_reg_0_pos 0
+#define fd_sqi_dummy_reg_0_len 1
+#define fd_sqi_dummy_reg_0_lsb 0
+#define xd_p_fd_sqi_debug_sel 0xA33C
+#define fd_sqi_debug_sel_pos 1
+#define fd_sqi_debug_sel_len 2
+#define fd_sqi_debug_sel_lsb 0
+#define xd_p_fd_sqi_s2 0xA33C
+#define fd_sqi_s2_pos 3
+#define fd_sqi_s2_len 5
+#define fd_sqi_s2_lsb 0
+#define xd_p_fd_sqi_dummy_reg_1 0xA33D
+#define fd_sqi_dummy_reg_1_pos 0
+#define fd_sqi_dummy_reg_1_len 1
+#define fd_sqi_dummy_reg_1_lsb 0
+#define xd_p_fd_inr_ignore 0xA33D
+#define fd_inr_ignore_pos 1
+#define fd_inr_ignore_len 1
+#define fd_inr_ignore_lsb 0
+#define xd_p_fd_pilot_ignore 0xA33D
+#define fd_pilot_ignore_pos 2
+#define fd_pilot_ignore_len 1
+#define fd_pilot_ignore_lsb 0
+#define xd_p_fd_etps_ignore 0xA33D
+#define fd_etps_ignore_pos 3
+#define fd_etps_ignore_len 1
+#define fd_etps_ignore_lsb 0
+#define xd_p_fd_sqi_s1 0xA33D
+#define fd_sqi_s1_pos 4
+#define fd_sqi_s1_len 4
+#define fd_sqi_s1_lsb 0
+#define xd_p_reg_fste_ehw_7_0 0xA33E
+#define reg_fste_ehw_7_0_pos 0
+#define reg_fste_ehw_7_0_len 8
+#define reg_fste_ehw_7_0_lsb 0
+#define xd_p_reg_fste_ehw_9_8 0xA33F
+#define reg_fste_ehw_9_8_pos 0
+#define reg_fste_ehw_9_8_len 2
+#define reg_fste_ehw_9_8_lsb 8
+#define xd_p_reg_fste_i_adj_vld 0xA33F
+#define reg_fste_i_adj_vld_pos 2
+#define reg_fste_i_adj_vld_len 1
+#define reg_fste_i_adj_vld_lsb 0
+#define xd_p_reg_fste_phase_ini_7_0 0xA340
+#define reg_fste_phase_ini_7_0_pos 0
+#define reg_fste_phase_ini_7_0_len 8
+#define reg_fste_phase_ini_7_0_lsb 0
+#define xd_p_reg_fste_phase_ini_11_8 0xA341
+#define reg_fste_phase_ini_11_8_pos 0
+#define reg_fste_phase_ini_11_8_len 4
+#define reg_fste_phase_ini_11_8_lsb 8
+#define xd_p_reg_fste_phase_inc_3_0 0xA341
+#define reg_fste_phase_inc_3_0_pos 4
+#define reg_fste_phase_inc_3_0_len 4
+#define reg_fste_phase_inc_3_0_lsb 0
+#define xd_p_reg_fste_phase_inc_11_4 0xA342
+#define reg_fste_phase_inc_11_4_pos 0
+#define reg_fste_phase_inc_11_4_len 8
+#define reg_fste_phase_inc_11_4_lsb 4
+#define xd_p_reg_fste_acum_cost_cnt_max 0xA343
+#define reg_fste_acum_cost_cnt_max_pos 0
+#define reg_fste_acum_cost_cnt_max_len 4
+#define reg_fste_acum_cost_cnt_max_lsb 0
+#define xd_p_reg_fste_step_size_std 0xA343
+#define reg_fste_step_size_std_pos 4
+#define reg_fste_step_size_std_len 4
+#define reg_fste_step_size_std_lsb 0
+#define xd_p_reg_fste_step_size_max 0xA344
+#define reg_fste_step_size_max_pos 0
+#define reg_fste_step_size_max_len 4
+#define reg_fste_step_size_max_lsb 0
+#define xd_p_reg_fste_step_size_min 0xA344
+#define reg_fste_step_size_min_pos 4
+#define reg_fste_step_size_min_len 4
+#define reg_fste_step_size_min_lsb 0
+#define xd_p_reg_fste_frac_step_size_7_0 0xA345
+#define reg_fste_frac_step_size_7_0_pos 0
+#define reg_fste_frac_step_size_7_0_len 8
+#define reg_fste_frac_step_size_7_0_lsb 0
+#define xd_p_reg_fste_frac_step_size_15_8 0xA346
+#define reg_fste_frac_step_size_15_8_pos 0
+#define reg_fste_frac_step_size_15_8_len 8
+#define reg_fste_frac_step_size_15_8_lsb 8
+#define xd_p_reg_fste_frac_step_size_19_16 0xA347
+#define reg_fste_frac_step_size_19_16_pos 0
+#define reg_fste_frac_step_size_19_16_len 4
+#define reg_fste_frac_step_size_19_16_lsb 16
+#define xd_p_reg_fste_rpd_dir_cnt_max 0xA347
+#define reg_fste_rpd_dir_cnt_max_pos 4
+#define reg_fste_rpd_dir_cnt_max_len 4
+#define reg_fste_rpd_dir_cnt_max_lsb 0
+#define xd_p_reg_fste_ehs 0xA348
+#define reg_fste_ehs_pos 0
+#define reg_fste_ehs_len 4
+#define reg_fste_ehs_lsb 0
+#define xd_p_reg_fste_frac_cost_cnt_max_3_0 0xA348
+#define reg_fste_frac_cost_cnt_max_3_0_pos 4
+#define reg_fste_frac_cost_cnt_max_3_0_len 4
+#define reg_fste_frac_cost_cnt_max_3_0_lsb 0
+#define xd_p_reg_fste_frac_cost_cnt_max_9_4 0xA349
+#define reg_fste_frac_cost_cnt_max_9_4_pos 0
+#define reg_fste_frac_cost_cnt_max_9_4_len 6
+#define reg_fste_frac_cost_cnt_max_9_4_lsb 4
+#define xd_p_reg_fste_w0_7_0 0xA34A
+#define reg_fste_w0_7_0_pos 0
+#define reg_fste_w0_7_0_len 8
+#define reg_fste_w0_7_0_lsb 0
+#define xd_p_reg_fste_w0_11_8 0xA34B
+#define reg_fste_w0_11_8_pos 0
+#define reg_fste_w0_11_8_len 4
+#define reg_fste_w0_11_8_lsb 8
+#define xd_p_reg_fste_w1_3_0 0xA34B
+#define reg_fste_w1_3_0_pos 4
+#define reg_fste_w1_3_0_len 4
+#define reg_fste_w1_3_0_lsb 0
+#define xd_p_reg_fste_w1_11_4 0xA34C
+#define reg_fste_w1_11_4_pos 0
+#define reg_fste_w1_11_4_len 8
+#define reg_fste_w1_11_4_lsb 4
+#define xd_p_reg_fste_w2_7_0 0xA34D
+#define reg_fste_w2_7_0_pos 0
+#define reg_fste_w2_7_0_len 8
+#define reg_fste_w2_7_0_lsb 0
+#define xd_p_reg_fste_w2_11_8 0xA34E
+#define reg_fste_w2_11_8_pos 0
+#define reg_fste_w2_11_8_len 4
+#define reg_fste_w2_11_8_lsb 8
+#define xd_p_reg_fste_w3_3_0 0xA34E
+#define reg_fste_w3_3_0_pos 4
+#define reg_fste_w3_3_0_len 4
+#define reg_fste_w3_3_0_lsb 0
+#define xd_p_reg_fste_w3_11_4 0xA34F
+#define reg_fste_w3_11_4_pos 0
+#define reg_fste_w3_11_4_len 8
+#define reg_fste_w3_11_4_lsb 4
+#define xd_p_reg_fste_w4_7_0 0xA350
+#define reg_fste_w4_7_0_pos 0
+#define reg_fste_w4_7_0_len 8
+#define reg_fste_w4_7_0_lsb 0
+#define xd_p_reg_fste_w4_11_8 0xA351
+#define reg_fste_w4_11_8_pos 0
+#define reg_fste_w4_11_8_len 4
+#define reg_fste_w4_11_8_lsb 8
+#define xd_p_reg_fste_w5_3_0 0xA351
+#define reg_fste_w5_3_0_pos 4
+#define reg_fste_w5_3_0_len 4
+#define reg_fste_w5_3_0_lsb 0
+#define xd_p_reg_fste_w5_11_4 0xA352
+#define reg_fste_w5_11_4_pos 0
+#define reg_fste_w5_11_4_len 8
+#define reg_fste_w5_11_4_lsb 4
+#define xd_p_reg_fste_w6_7_0 0xA353
+#define reg_fste_w6_7_0_pos 0
+#define reg_fste_w6_7_0_len 8
+#define reg_fste_w6_7_0_lsb 0
+#define xd_p_reg_fste_w6_11_8 0xA354
+#define reg_fste_w6_11_8_pos 0
+#define reg_fste_w6_11_8_len 4
+#define reg_fste_w6_11_8_lsb 8
+#define xd_p_reg_fste_w7_3_0 0xA354
+#define reg_fste_w7_3_0_pos 4
+#define reg_fste_w7_3_0_len 4
+#define reg_fste_w7_3_0_lsb 0
+#define xd_p_reg_fste_w7_11_4 0xA355
+#define reg_fste_w7_11_4_pos 0
+#define reg_fste_w7_11_4_len 8
+#define reg_fste_w7_11_4_lsb 4
+#define xd_p_reg_fste_w8_7_0 0xA356
+#define reg_fste_w8_7_0_pos 0
+#define reg_fste_w8_7_0_len 8
+#define reg_fste_w8_7_0_lsb 0
+#define xd_p_reg_fste_w8_11_8 0xA357
+#define reg_fste_w8_11_8_pos 0
+#define reg_fste_w8_11_8_len 4
+#define reg_fste_w8_11_8_lsb 8
+#define xd_p_reg_fste_w9_3_0 0xA357
+#define reg_fste_w9_3_0_pos 4
+#define reg_fste_w9_3_0_len 4
+#define reg_fste_w9_3_0_lsb 0
+#define xd_p_reg_fste_w9_11_4 0xA358
+#define reg_fste_w9_11_4_pos 0
+#define reg_fste_w9_11_4_len 8
+#define reg_fste_w9_11_4_lsb 4
+#define xd_p_reg_fste_wa_7_0 0xA359
+#define reg_fste_wa_7_0_pos 0
+#define reg_fste_wa_7_0_len 8
+#define reg_fste_wa_7_0_lsb 0
+#define xd_p_reg_fste_wa_11_8 0xA35A
+#define reg_fste_wa_11_8_pos 0
+#define reg_fste_wa_11_8_len 4
+#define reg_fste_wa_11_8_lsb 8
+#define xd_p_reg_fste_wb_3_0 0xA35A
+#define reg_fste_wb_3_0_pos 4
+#define reg_fste_wb_3_0_len 4
+#define reg_fste_wb_3_0_lsb 0
+#define xd_p_reg_fste_wb_11_4 0xA35B
+#define reg_fste_wb_11_4_pos 0
+#define reg_fste_wb_11_4_len 8
+#define reg_fste_wb_11_4_lsb 4
+#define xd_r_fd_fste_i_adj 0xA35C
+#define fd_fste_i_adj_pos 0
+#define fd_fste_i_adj_len 5
+#define fd_fste_i_adj_lsb 0
+#define xd_r_fd_fste_f_adj_7_0 0xA35D
+#define fd_fste_f_adj_7_0_pos 0
+#define fd_fste_f_adj_7_0_len 8
+#define fd_fste_f_adj_7_0_lsb 0
+#define xd_r_fd_fste_f_adj_15_8 0xA35E
+#define fd_fste_f_adj_15_8_pos 0
+#define fd_fste_f_adj_15_8_len 8
+#define fd_fste_f_adj_15_8_lsb 8
+#define xd_r_fd_fste_f_adj_19_16 0xA35F
+#define fd_fste_f_adj_19_16_pos 0
+#define fd_fste_f_adj_19_16_len 4
+#define fd_fste_f_adj_19_16_lsb 16
+#define xd_p_reg_feq_Leak_Bypass 0xA366
+#define reg_feq_Leak_Bypass_pos 0
+#define reg_feq_Leak_Bypass_len 1
+#define reg_feq_Leak_Bypass_lsb 0
+#define xd_p_reg_feq_Leak_Mneg1 0xA366
+#define reg_feq_Leak_Mneg1_pos 1
+#define reg_feq_Leak_Mneg1_len 3
+#define reg_feq_Leak_Mneg1_lsb 0
+#define xd_p_reg_feq_Leak_B_ShiftQ 0xA366
+#define reg_feq_Leak_B_ShiftQ_pos 4
+#define reg_feq_Leak_B_ShiftQ_len 4
+#define reg_feq_Leak_B_ShiftQ_lsb 0
+#define xd_p_reg_feq_Leak_B_Float0 0xA367
+#define reg_feq_Leak_B_Float0_pos 0
+#define reg_feq_Leak_B_Float0_len 8
+#define reg_feq_Leak_B_Float0_lsb 0
+#define xd_p_reg_feq_Leak_B_Float1 0xA368
+#define reg_feq_Leak_B_Float1_pos 0
+#define reg_feq_Leak_B_Float1_len 8
+#define reg_feq_Leak_B_Float1_lsb 0
+#define xd_p_reg_feq_Leak_B_Float2 0xA369
+#define reg_feq_Leak_B_Float2_pos 0
+#define reg_feq_Leak_B_Float2_len 8
+#define reg_feq_Leak_B_Float2_lsb 0
+#define xd_p_reg_feq_Leak_B_Float3 0xA36A
+#define reg_feq_Leak_B_Float3_pos 0
+#define reg_feq_Leak_B_Float3_len 8
+#define reg_feq_Leak_B_Float3_lsb 0
+#define xd_p_reg_feq_Leak_B_Float4 0xA36B
+#define reg_feq_Leak_B_Float4_pos 0
+#define reg_feq_Leak_B_Float4_len 8
+#define reg_feq_Leak_B_Float4_lsb 0
+#define xd_p_reg_feq_Leak_B_Float5 0xA36C
+#define reg_feq_Leak_B_Float5_pos 0
+#define reg_feq_Leak_B_Float5_len 8
+#define reg_feq_Leak_B_Float5_lsb 0
+#define xd_p_reg_feq_Leak_B_Float6 0xA36D
+#define reg_feq_Leak_B_Float6_pos 0
+#define reg_feq_Leak_B_Float6_len 8
+#define reg_feq_Leak_B_Float6_lsb 0
+#define xd_p_reg_feq_Leak_B_Float7 0xA36E
+#define reg_feq_Leak_B_Float7_pos 0
+#define reg_feq_Leak_B_Float7_len 8
+#define reg_feq_Leak_B_Float7_lsb 0
+#define xd_r_reg_feq_data_h2_7_0 0xA36F
+#define reg_feq_data_h2_7_0_pos 0
+#define reg_feq_data_h2_7_0_len 8
+#define reg_feq_data_h2_7_0_lsb 0
+#define xd_r_reg_feq_data_h2_9_8 0xA370
+#define reg_feq_data_h2_9_8_pos 0
+#define reg_feq_data_h2_9_8_len 2
+#define reg_feq_data_h2_9_8_lsb 8
+#define xd_p_reg_feq_leak_use_slice_tps 0xA371
+#define reg_feq_leak_use_slice_tps_pos 0
+#define reg_feq_leak_use_slice_tps_len 1
+#define reg_feq_leak_use_slice_tps_lsb 0
+#define xd_p_reg_feq_read_update 0xA371
+#define reg_feq_read_update_pos 1
+#define reg_feq_read_update_len 1
+#define reg_feq_read_update_lsb 0
+#define xd_p_reg_feq_data_vld 0xA371
+#define reg_feq_data_vld_pos 2
+#define reg_feq_data_vld_len 1
+#define reg_feq_data_vld_lsb 0
+#define xd_p_reg_feq_tone_idx_4_0 0xA371
+#define reg_feq_tone_idx_4_0_pos 3
+#define reg_feq_tone_idx_4_0_len 5
+#define reg_feq_tone_idx_4_0_lsb 0
+#define xd_p_reg_feq_tone_idx_12_5 0xA372
+#define reg_feq_tone_idx_12_5_pos 0
+#define reg_feq_tone_idx_12_5_len 8
+#define reg_feq_tone_idx_12_5_lsb 5
+#define xd_r_reg_feq_data_re_7_0 0xA373
+#define reg_feq_data_re_7_0_pos 0
+#define reg_feq_data_re_7_0_len 8
+#define reg_feq_data_re_7_0_lsb 0
+#define xd_r_reg_feq_data_re_10_8 0xA374
+#define reg_feq_data_re_10_8_pos 0
+#define reg_feq_data_re_10_8_len 3
+#define reg_feq_data_re_10_8_lsb 8
+#define xd_r_reg_feq_data_im_7_0 0xA375
+#define reg_feq_data_im_7_0_pos 0
+#define reg_feq_data_im_7_0_len 8
+#define reg_feq_data_im_7_0_lsb 0
+#define xd_r_reg_feq_data_im_10_8 0xA376
+#define reg_feq_data_im_10_8_pos 0
+#define reg_feq_data_im_10_8_len 3
+#define reg_feq_data_im_10_8_lsb 8
+#define xd_r_reg_feq_y_re 0xA377
+#define reg_feq_y_re_pos 0
+#define reg_feq_y_re_len 8
+#define reg_feq_y_re_lsb 0
+#define xd_r_reg_feq_y_im 0xA378
+#define reg_feq_y_im_pos 0
+#define reg_feq_y_im_len 8
+#define reg_feq_y_im_lsb 0
+#define xd_r_reg_feq_h_re_7_0 0xA379
+#define reg_feq_h_re_7_0_pos 0
+#define reg_feq_h_re_7_0_len 8
+#define reg_feq_h_re_7_0_lsb 0
+#define xd_r_reg_feq_h_re_8 0xA37A
+#define reg_feq_h_re_8_pos 0
+#define reg_feq_h_re_8_len 1
+#define reg_feq_h_re_8_lsb 0
+#define xd_r_reg_feq_h_im_7_0 0xA37B
+#define reg_feq_h_im_7_0_pos 0
+#define reg_feq_h_im_7_0_len 8
+#define reg_feq_h_im_7_0_lsb 0
+#define xd_r_reg_feq_h_im_8 0xA37C
+#define reg_feq_h_im_8_pos 0
+#define reg_feq_h_im_8_len 1
+#define reg_feq_h_im_8_lsb 0
+#define xd_p_fec_super_frm_unit_7_0 0xA380
+#define fec_super_frm_unit_7_0_pos 0
+#define fec_super_frm_unit_7_0_len 8
+#define fec_super_frm_unit_7_0_lsb 0
+#define xd_p_fec_super_frm_unit_15_8 0xA381
+#define fec_super_frm_unit_15_8_pos 0
+#define fec_super_frm_unit_15_8_len 8
+#define fec_super_frm_unit_15_8_lsb 8
+#define xd_r_fec_vtb_err_bit_cnt_7_0 0xA382
+#define fec_vtb_err_bit_cnt_7_0_pos 0
+#define fec_vtb_err_bit_cnt_7_0_len 8
+#define fec_vtb_err_bit_cnt_7_0_lsb 0
+#define xd_r_fec_vtb_err_bit_cnt_15_8 0xA383
+#define fec_vtb_err_bit_cnt_15_8_pos 0
+#define fec_vtb_err_bit_cnt_15_8_len 8
+#define fec_vtb_err_bit_cnt_15_8_lsb 8
+#define xd_r_fec_vtb_err_bit_cnt_23_16 0xA384
+#define fec_vtb_err_bit_cnt_23_16_pos 0
+#define fec_vtb_err_bit_cnt_23_16_len 8
+#define fec_vtb_err_bit_cnt_23_16_lsb 16
+#define xd_p_fec_rsd_packet_unit_7_0 0xA385
+#define fec_rsd_packet_unit_7_0_pos 0
+#define fec_rsd_packet_unit_7_0_len 8
+#define fec_rsd_packet_unit_7_0_lsb 0
+#define xd_p_fec_rsd_packet_unit_15_8 0xA386
+#define fec_rsd_packet_unit_15_8_pos 0
+#define fec_rsd_packet_unit_15_8_len 8
+#define fec_rsd_packet_unit_15_8_lsb 8
+#define xd_r_fec_rsd_bit_err_cnt_7_0 0xA387
+#define fec_rsd_bit_err_cnt_7_0_pos 0
+#define fec_rsd_bit_err_cnt_7_0_len 8
+#define fec_rsd_bit_err_cnt_7_0_lsb 0
+#define xd_r_fec_rsd_bit_err_cnt_15_8 0xA388
+#define fec_rsd_bit_err_cnt_15_8_pos 0
+#define fec_rsd_bit_err_cnt_15_8_len 8
+#define fec_rsd_bit_err_cnt_15_8_lsb 8
+#define xd_r_fec_rsd_bit_err_cnt_23_16 0xA389
+#define fec_rsd_bit_err_cnt_23_16_pos 0
+#define fec_rsd_bit_err_cnt_23_16_len 8
+#define fec_rsd_bit_err_cnt_23_16_lsb 16
+#define xd_r_fec_rsd_abort_packet_cnt_7_0 0xA38A
+#define fec_rsd_abort_packet_cnt_7_0_pos 0
+#define fec_rsd_abort_packet_cnt_7_0_len 8
+#define fec_rsd_abort_packet_cnt_7_0_lsb 0
+#define xd_r_fec_rsd_abort_packet_cnt_15_8 0xA38B
+#define fec_rsd_abort_packet_cnt_15_8_pos 0
+#define fec_rsd_abort_packet_cnt_15_8_len 8
+#define fec_rsd_abort_packet_cnt_15_8_lsb 8
+#define xd_p_fec_RSD_PKT_NUM_PER_UNIT_7_0 0xA38C
+#define fec_RSD_PKT_NUM_PER_UNIT_7_0_pos 0
+#define fec_RSD_PKT_NUM_PER_UNIT_7_0_len 8
+#define fec_RSD_PKT_NUM_PER_UNIT_7_0_lsb 0
+#define xd_p_fec_RSD_PKT_NUM_PER_UNIT_15_8 0xA38D
+#define fec_RSD_PKT_NUM_PER_UNIT_15_8_pos 0
+#define fec_RSD_PKT_NUM_PER_UNIT_15_8_len 8
+#define fec_RSD_PKT_NUM_PER_UNIT_15_8_lsb 8
+#define xd_p_fec_RS_TH_1_7_0 0xA38E
+#define fec_RS_TH_1_7_0_pos 0
+#define fec_RS_TH_1_7_0_len 8
+#define fec_RS_TH_1_7_0_lsb 0
+#define xd_p_fec_RS_TH_1_15_8 0xA38F
+#define fec_RS_TH_1_15_8_pos 0
+#define fec_RS_TH_1_15_8_len 8
+#define fec_RS_TH_1_15_8_lsb 8
+#define xd_p_fec_RS_TH_2 0xA390
+#define fec_RS_TH_2_pos 0
+#define fec_RS_TH_2_len 8
+#define fec_RS_TH_2_lsb 0
+#define xd_p_fec_mon_en 0xA391
+#define fec_mon_en_pos 0
+#define fec_mon_en_len 1
+#define fec_mon_en_lsb 0
+#define xd_p_reg_b8to47 0xA391
+#define reg_b8to47_pos 1
+#define reg_b8to47_len 1
+#define reg_b8to47_lsb 0
+#define xd_p_reg_rsd_sync_rep 0xA391
+#define reg_rsd_sync_rep_pos 2
+#define reg_rsd_sync_rep_len 1
+#define reg_rsd_sync_rep_lsb 0
+#define xd_p_fec_rsd_retrain_rst 0xA391
+#define fec_rsd_retrain_rst_pos 3
+#define fec_rsd_retrain_rst_len 1
+#define fec_rsd_retrain_rst_lsb 0
+#define xd_r_fec_rsd_ber_rdy 0xA391
+#define fec_rsd_ber_rdy_pos 4
+#define fec_rsd_ber_rdy_len 1
+#define fec_rsd_ber_rdy_lsb 0
+#define xd_p_fec_rsd_ber_rst 0xA391
+#define fec_rsd_ber_rst_pos 5
+#define fec_rsd_ber_rst_len 1
+#define fec_rsd_ber_rst_lsb 0
+#define xd_r_fec_vtb_ber_rdy 0xA391
+#define fec_vtb_ber_rdy_pos 6
+#define fec_vtb_ber_rdy_len 1
+#define fec_vtb_ber_rdy_lsb 0
+#define xd_p_fec_vtb_ber_rst 0xA391
+#define fec_vtb_ber_rst_pos 7
+#define fec_vtb_ber_rst_len 1
+#define fec_vtb_ber_rst_lsb 0
+#define xd_p_reg_vtb_clk40en 0xA392
+#define reg_vtb_clk40en_pos 0
+#define reg_vtb_clk40en_len 1
+#define reg_vtb_clk40en_lsb 0
+#define xd_p_fec_vtb_rsd_mon_en 0xA392
+#define fec_vtb_rsd_mon_en_pos 1
+#define fec_vtb_rsd_mon_en_len 1
+#define fec_vtb_rsd_mon_en_lsb 0
+#define xd_p_reg_fec_data_en 0xA392
+#define reg_fec_data_en_pos 2
+#define reg_fec_data_en_len 1
+#define reg_fec_data_en_lsb 0
+#define xd_p_fec_dummy_reg_2 0xA392
+#define fec_dummy_reg_2_pos 3
+#define fec_dummy_reg_2_len 3
+#define fec_dummy_reg_2_lsb 0
+#define xd_p_reg_sync_chk 0xA392
+#define reg_sync_chk_pos 6
+#define reg_sync_chk_len 1
+#define reg_sync_chk_lsb 0
+#define xd_p_fec_rsd_bypass 0xA392
+#define fec_rsd_bypass_pos 7
+#define fec_rsd_bypass_len 1
+#define fec_rsd_bypass_lsb 0
+#define xd_p_fec_sw_rst 0xA393
+#define fec_sw_rst_pos 0
+#define fec_sw_rst_len 1
+#define fec_sw_rst_lsb 0
+#define xd_r_fec_vtb_pm_crc 0xA394
+#define fec_vtb_pm_crc_pos 0
+#define fec_vtb_pm_crc_len 8
+#define fec_vtb_pm_crc_lsb 0
+#define xd_r_fec_vtb_tb_7_crc 0xA395
+#define fec_vtb_tb_7_crc_pos 0
+#define fec_vtb_tb_7_crc_len 8
+#define fec_vtb_tb_7_crc_lsb 0
+#define xd_r_fec_vtb_tb_6_crc 0xA396
+#define fec_vtb_tb_6_crc_pos 0
+#define fec_vtb_tb_6_crc_len 8
+#define fec_vtb_tb_6_crc_lsb 0
+#define xd_r_fec_vtb_tb_5_crc 0xA397
+#define fec_vtb_tb_5_crc_pos 0
+#define fec_vtb_tb_5_crc_len 8
+#define fec_vtb_tb_5_crc_lsb 0
+#define xd_r_fec_vtb_tb_4_crc 0xA398
+#define fec_vtb_tb_4_crc_pos 0
+#define fec_vtb_tb_4_crc_len 8
+#define fec_vtb_tb_4_crc_lsb 0
+#define xd_r_fec_vtb_tb_3_crc 0xA399
+#define fec_vtb_tb_3_crc_pos 0
+#define fec_vtb_tb_3_crc_len 8
+#define fec_vtb_tb_3_crc_lsb 0
+#define xd_r_fec_vtb_tb_2_crc 0xA39A
+#define fec_vtb_tb_2_crc_pos 0
+#define fec_vtb_tb_2_crc_len 8
+#define fec_vtb_tb_2_crc_lsb 0
+#define xd_r_fec_vtb_tb_1_crc 0xA39B
+#define fec_vtb_tb_1_crc_pos 0
+#define fec_vtb_tb_1_crc_len 8
+#define fec_vtb_tb_1_crc_lsb 0
+#define xd_r_fec_vtb_tb_0_crc 0xA39C
+#define fec_vtb_tb_0_crc_pos 0
+#define fec_vtb_tb_0_crc_len 8
+#define fec_vtb_tb_0_crc_lsb 0
+#define xd_r_fec_rsd_bank0_crc 0xA39D
+#define fec_rsd_bank0_crc_pos 0
+#define fec_rsd_bank0_crc_len 8
+#define fec_rsd_bank0_crc_lsb 0
+#define xd_r_fec_rsd_bank1_crc 0xA39E
+#define fec_rsd_bank1_crc_pos 0
+#define fec_rsd_bank1_crc_len 8
+#define fec_rsd_bank1_crc_lsb 0
+#define xd_r_fec_idi_vtb_crc 0xA39F
+#define fec_idi_vtb_crc_pos 0
+#define fec_idi_vtb_crc_len 8
+#define fec_idi_vtb_crc_lsb 0
+#define xd_g_reg_tpsd_txmod 0xA3C0
+#define reg_tpsd_txmod_pos 0
+#define reg_tpsd_txmod_len 2
+#define reg_tpsd_txmod_lsb 0
+#define xd_g_reg_tpsd_gi 0xA3C0
+#define reg_tpsd_gi_pos 2
+#define reg_tpsd_gi_len 2
+#define reg_tpsd_gi_lsb 0
+#define xd_g_reg_tpsd_hier 0xA3C0
+#define reg_tpsd_hier_pos 4
+#define reg_tpsd_hier_len 3
+#define reg_tpsd_hier_lsb 0
+#define xd_g_reg_bw 0xA3C1
+#define reg_bw_pos 2
+#define reg_bw_len 2
+#define reg_bw_lsb 0
+#define xd_g_reg_dec_pri 0xA3C1
+#define reg_dec_pri_pos 4
+#define reg_dec_pri_len 1
+#define reg_dec_pri_lsb 0
+#define xd_g_reg_tpsd_const 0xA3C1
+#define reg_tpsd_const_pos 6
+#define reg_tpsd_const_len 2
+#define reg_tpsd_const_lsb 0
+#define xd_g_reg_tpsd_hpcr 0xA3C2
+#define reg_tpsd_hpcr_pos 0
+#define reg_tpsd_hpcr_len 3
+#define reg_tpsd_hpcr_lsb 0
+#define xd_g_reg_tpsd_lpcr 0xA3C2
+#define reg_tpsd_lpcr_pos 3
+#define reg_tpsd_lpcr_len 3
+#define reg_tpsd_lpcr_lsb 0
+#define xd_g_reg_ofsm_clk 0xA3D0
+#define reg_ofsm_clk_pos 0
+#define reg_ofsm_clk_len 3
+#define reg_ofsm_clk_lsb 0
+#define xd_g_reg_fclk_cfg 0xA3D1
+#define reg_fclk_cfg_pos 0
+#define reg_fclk_cfg_len 1
+#define reg_fclk_cfg_lsb 0
+#define xd_g_reg_fclk_idi 0xA3D1
+#define reg_fclk_idi_pos 1
+#define reg_fclk_idi_len 1
+#define reg_fclk_idi_lsb 0
+#define xd_g_reg_fclk_odi 0xA3D1
+#define reg_fclk_odi_pos 2
+#define reg_fclk_odi_len 1
+#define reg_fclk_odi_lsb 0
+#define xd_g_reg_fclk_rsd 0xA3D1
+#define reg_fclk_rsd_pos 3
+#define reg_fclk_rsd_len 1
+#define reg_fclk_rsd_lsb 0
+#define xd_g_reg_fclk_vtb 0xA3D1
+#define reg_fclk_vtb_pos 4
+#define reg_fclk_vtb_len 1
+#define reg_fclk_vtb_lsb 0
+#define xd_g_reg_fclk_cste 0xA3D1
+#define reg_fclk_cste_pos 5
+#define reg_fclk_cste_len 1
+#define reg_fclk_cste_lsb 0
+#define xd_g_reg_fclk_mp2if 0xA3D1
+#define reg_fclk_mp2if_pos 6
+#define reg_fclk_mp2if_len 1
+#define reg_fclk_mp2if_lsb 0
+#define xd_I2C_i2c_m_slave_addr 0xA400
+#define i2c_m_slave_addr_pos 0
+#define i2c_m_slave_addr_len 8
+#define i2c_m_slave_addr_lsb 0
+#define xd_I2C_i2c_m_data1 0xA401
+#define i2c_m_data1_pos 0
+#define i2c_m_data1_len 8
+#define i2c_m_data1_lsb 0
+#define xd_I2C_i2c_m_data2 0xA402
+#define i2c_m_data2_pos 0
+#define i2c_m_data2_len 8
+#define i2c_m_data2_lsb 0
+#define xd_I2C_i2c_m_data3 0xA403
+#define i2c_m_data3_pos 0
+#define i2c_m_data3_len 8
+#define i2c_m_data3_lsb 0
+#define xd_I2C_i2c_m_data4 0xA404
+#define i2c_m_data4_pos 0
+#define i2c_m_data4_len 8
+#define i2c_m_data4_lsb 0
+#define xd_I2C_i2c_m_data5 0xA405
+#define i2c_m_data5_pos 0
+#define i2c_m_data5_len 8
+#define i2c_m_data5_lsb 0
+#define xd_I2C_i2c_m_data6 0xA406
+#define i2c_m_data6_pos 0
+#define i2c_m_data6_len 8
+#define i2c_m_data6_lsb 0
+#define xd_I2C_i2c_m_data7 0xA407
+#define i2c_m_data7_pos 0
+#define i2c_m_data7_len 8
+#define i2c_m_data7_lsb 0
+#define xd_I2C_i2c_m_data8 0xA408
+#define i2c_m_data8_pos 0
+#define i2c_m_data8_len 8
+#define i2c_m_data8_lsb 0
+#define xd_I2C_i2c_m_data9 0xA409
+#define i2c_m_data9_pos 0
+#define i2c_m_data9_len 8
+#define i2c_m_data9_lsb 0
+#define xd_I2C_i2c_m_data10 0xA40A
+#define i2c_m_data10_pos 0
+#define i2c_m_data10_len 8
+#define i2c_m_data10_lsb 0
+#define xd_I2C_i2c_m_data11 0xA40B
+#define i2c_m_data11_pos 0
+#define i2c_m_data11_len 8
+#define i2c_m_data11_lsb 0
+#define xd_I2C_i2c_m_cmd_rw 0xA40C
+#define i2c_m_cmd_rw_pos 0
+#define i2c_m_cmd_rw_len 1
+#define i2c_m_cmd_rw_lsb 0
+#define xd_I2C_i2c_m_cmd_rwlen 0xA40C
+#define i2c_m_cmd_rwlen_pos 3
+#define i2c_m_cmd_rwlen_len 4
+#define i2c_m_cmd_rwlen_lsb 0
+#define xd_I2C_i2c_m_status_cmd_exe 0xA40D
+#define i2c_m_status_cmd_exe_pos 0
+#define i2c_m_status_cmd_exe_len 1
+#define i2c_m_status_cmd_exe_lsb 0
+#define xd_I2C_i2c_m_status_wdat_done 0xA40D
+#define i2c_m_status_wdat_done_pos 1
+#define i2c_m_status_wdat_done_len 1
+#define i2c_m_status_wdat_done_lsb 0
+#define xd_I2C_i2c_m_status_wdat_fail 0xA40D
+#define i2c_m_status_wdat_fail_pos 2
+#define i2c_m_status_wdat_fail_len 1
+#define i2c_m_status_wdat_fail_lsb 0
+#define xd_I2C_i2c_m_period 0xA40E
+#define i2c_m_period_pos 0
+#define i2c_m_period_len 8
+#define i2c_m_period_lsb 0
+#define xd_I2C_i2c_m_reg_msb_lsb 0xA40F
+#define i2c_m_reg_msb_lsb_pos 0
+#define i2c_m_reg_msb_lsb_len 1
+#define i2c_m_reg_msb_lsb_lsb 0
+#define xd_I2C_reg_ofdm_rst 0xA40F
+#define reg_ofdm_rst_pos 1
+#define reg_ofdm_rst_len 1
+#define reg_ofdm_rst_lsb 0
+#define xd_I2C_reg_sample_period_on_tuner 0xA40F
+#define reg_sample_period_on_tuner_pos 2
+#define reg_sample_period_on_tuner_len 1
+#define reg_sample_period_on_tuner_lsb 0
+#define xd_I2C_reg_rst_i2c 0xA40F
+#define reg_rst_i2c_pos 3
+#define reg_rst_i2c_len 1
+#define reg_rst_i2c_lsb 0
+#define xd_I2C_reg_ofdm_rst_en 0xA40F
+#define reg_ofdm_rst_en_pos 4
+#define reg_ofdm_rst_en_len 1
+#define reg_ofdm_rst_en_lsb 0
+#define xd_I2C_reg_tuner_sda_sync_on 0xA40F
+#define reg_tuner_sda_sync_on_pos 5
+#define reg_tuner_sda_sync_on_len 1
+#define reg_tuner_sda_sync_on_lsb 0
+#define xd_p_mp2if_data_access_disable_ofsm 0xA500
+#define mp2if_data_access_disable_ofsm_pos 0
+#define mp2if_data_access_disable_ofsm_len 1
+#define mp2if_data_access_disable_ofsm_lsb 0
+#define xd_p_reg_mp2_sw_rst_ofsm 0xA500
+#define reg_mp2_sw_rst_ofsm_pos 1
+#define reg_mp2_sw_rst_ofsm_len 1
+#define reg_mp2_sw_rst_ofsm_lsb 0
+#define xd_p_reg_mp2if_clk_en_ofsm 0xA500
+#define reg_mp2if_clk_en_ofsm_pos 2
+#define reg_mp2if_clk_en_ofsm_len 1
+#define reg_mp2if_clk_en_ofsm_lsb 0
+#define xd_r_mp2if_sync_byte_locked 0xA500
+#define mp2if_sync_byte_locked_pos 3
+#define mp2if_sync_byte_locked_len 1
+#define mp2if_sync_byte_locked_lsb 0
+#define xd_r_mp2if_ts_not_188 0xA500
+#define mp2if_ts_not_188_pos 4
+#define mp2if_ts_not_188_len 1
+#define mp2if_ts_not_188_lsb 0
+#define xd_r_mp2if_psb_empty 0xA500
+#define mp2if_psb_empty_pos 5
+#define mp2if_psb_empty_len 1
+#define mp2if_psb_empty_lsb 0
+#define xd_r_mp2if_psb_overflow 0xA500
+#define mp2if_psb_overflow_pos 6
+#define mp2if_psb_overflow_len 1
+#define mp2if_psb_overflow_lsb 0
+#define xd_p_mp2if_keep_sf_sync_byte_ofsm 0xA500
+#define mp2if_keep_sf_sync_byte_ofsm_pos 7
+#define mp2if_keep_sf_sync_byte_ofsm_len 1
+#define mp2if_keep_sf_sync_byte_ofsm_lsb 0
+#define xd_r_mp2if_psb_mp2if_num_pkt 0xA501
+#define mp2if_psb_mp2if_num_pkt_pos 0
+#define mp2if_psb_mp2if_num_pkt_len 6
+#define mp2if_psb_mp2if_num_pkt_lsb 0
+#define xd_p_reg_mpeg_full_speed_ofsm 0xA501
+#define reg_mpeg_full_speed_ofsm_pos 6
+#define reg_mpeg_full_speed_ofsm_len 1
+#define reg_mpeg_full_speed_ofsm_lsb 0
+#define xd_p_mp2if_mpeg_ser_mode_ofsm 0xA501
+#define mp2if_mpeg_ser_mode_ofsm_pos 7
+#define mp2if_mpeg_ser_mode_ofsm_len 1
+#define mp2if_mpeg_ser_mode_ofsm_lsb 0
+#define xd_p_reg_sw_mon51 0xA600
+#define reg_sw_mon51_pos 0
+#define reg_sw_mon51_len 8
+#define reg_sw_mon51_lsb 0
+#define xd_p_reg_top_pcsel 0xA601
+#define reg_top_pcsel_pos 0
+#define reg_top_pcsel_len 1
+#define reg_top_pcsel_lsb 0
+#define xd_p_reg_top_rs232 0xA601
+#define reg_top_rs232_pos 1
+#define reg_top_rs232_len 1
+#define reg_top_rs232_lsb 0
+#define xd_p_reg_top_pcout 0xA601
+#define reg_top_pcout_pos 2
+#define reg_top_pcout_len 1
+#define reg_top_pcout_lsb 0
+#define xd_p_reg_top_debug 0xA601
+#define reg_top_debug_pos 3
+#define reg_top_debug_len 1
+#define reg_top_debug_lsb 0
+#define xd_p_reg_top_adcdly 0xA601
+#define reg_top_adcdly_pos 4
+#define reg_top_adcdly_len 2
+#define reg_top_adcdly_lsb 0
+#define xd_p_reg_top_pwrdw 0xA601
+#define reg_top_pwrdw_pos 6
+#define reg_top_pwrdw_len 1
+#define reg_top_pwrdw_lsb 0
+#define xd_p_reg_top_pwrdw_inv 0xA601
+#define reg_top_pwrdw_inv_pos 7
+#define reg_top_pwrdw_inv_len 1
+#define reg_top_pwrdw_inv_lsb 0
+#define xd_p_reg_top_int_inv 0xA602
+#define reg_top_int_inv_pos 0
+#define reg_top_int_inv_len 1
+#define reg_top_int_inv_lsb 0
+#define xd_p_reg_top_dio_sel 0xA602
+#define reg_top_dio_sel_pos 1
+#define reg_top_dio_sel_len 1
+#define reg_top_dio_sel_lsb 0
+#define xd_p_reg_top_gpioon0 0xA603
+#define reg_top_gpioon0_pos 0
+#define reg_top_gpioon0_len 1
+#define reg_top_gpioon0_lsb 0
+#define xd_p_reg_top_gpioon1 0xA603
+#define reg_top_gpioon1_pos 1
+#define reg_top_gpioon1_len 1
+#define reg_top_gpioon1_lsb 0
+#define xd_p_reg_top_gpioon2 0xA603
+#define reg_top_gpioon2_pos 2
+#define reg_top_gpioon2_len 1
+#define reg_top_gpioon2_lsb 0
+#define xd_p_reg_top_gpioon3 0xA603
+#define reg_top_gpioon3_pos 3
+#define reg_top_gpioon3_len 1
+#define reg_top_gpioon3_lsb 0
+#define xd_p_reg_top_lockon1 0xA603
+#define reg_top_lockon1_pos 4
+#define reg_top_lockon1_len 1
+#define reg_top_lockon1_lsb 0
+#define xd_p_reg_top_lockon2 0xA603
+#define reg_top_lockon2_pos 5
+#define reg_top_lockon2_len 1
+#define reg_top_lockon2_lsb 0
+#define xd_p_reg_top_gpioo0 0xA604
+#define reg_top_gpioo0_pos 0
+#define reg_top_gpioo0_len 1
+#define reg_top_gpioo0_lsb 0
+#define xd_p_reg_top_gpioo1 0xA604
+#define reg_top_gpioo1_pos 1
+#define reg_top_gpioo1_len 1
+#define reg_top_gpioo1_lsb 0
+#define xd_p_reg_top_gpioo2 0xA604
+#define reg_top_gpioo2_pos 2
+#define reg_top_gpioo2_len 1
+#define reg_top_gpioo2_lsb 0
+#define xd_p_reg_top_gpioo3 0xA604
+#define reg_top_gpioo3_pos 3
+#define reg_top_gpioo3_len 1
+#define reg_top_gpioo3_lsb 0
+#define xd_p_reg_top_lock1 0xA604
+#define reg_top_lock1_pos 4
+#define reg_top_lock1_len 1
+#define reg_top_lock1_lsb 0
+#define xd_p_reg_top_lock2 0xA604
+#define reg_top_lock2_pos 5
+#define reg_top_lock2_len 1
+#define reg_top_lock2_lsb 0
+#define xd_p_reg_top_gpioen0 0xA605
+#define reg_top_gpioen0_pos 0
+#define reg_top_gpioen0_len 1
+#define reg_top_gpioen0_lsb 0
+#define xd_p_reg_top_gpioen1 0xA605
+#define reg_top_gpioen1_pos 1
+#define reg_top_gpioen1_len 1
+#define reg_top_gpioen1_lsb 0
+#define xd_p_reg_top_gpioen2 0xA605
+#define reg_top_gpioen2_pos 2
+#define reg_top_gpioen2_len 1
+#define reg_top_gpioen2_lsb 0
+#define xd_p_reg_top_gpioen3 0xA605
+#define reg_top_gpioen3_pos 3
+#define reg_top_gpioen3_len 1
+#define reg_top_gpioen3_lsb 0
+#define xd_p_reg_top_locken1 0xA605
+#define reg_top_locken1_pos 4
+#define reg_top_locken1_len 1
+#define reg_top_locken1_lsb 0
+#define xd_p_reg_top_locken2 0xA605
+#define reg_top_locken2_pos 5
+#define reg_top_locken2_len 1
+#define reg_top_locken2_lsb 0
+#define xd_r_reg_top_gpioi0 0xA606
+#define reg_top_gpioi0_pos 0
+#define reg_top_gpioi0_len 1
+#define reg_top_gpioi0_lsb 0
+#define xd_r_reg_top_gpioi1 0xA606
+#define reg_top_gpioi1_pos 1
+#define reg_top_gpioi1_len 1
+#define reg_top_gpioi1_lsb 0
+#define xd_r_reg_top_gpioi2 0xA606
+#define reg_top_gpioi2_pos 2
+#define reg_top_gpioi2_len 1
+#define reg_top_gpioi2_lsb 0
+#define xd_r_reg_top_gpioi3 0xA606
+#define reg_top_gpioi3_pos 3
+#define reg_top_gpioi3_len 1
+#define reg_top_gpioi3_lsb 0
+#define xd_r_reg_top_locki1 0xA606
+#define reg_top_locki1_pos 4
+#define reg_top_locki1_len 1
+#define reg_top_locki1_lsb 0
+#define xd_r_reg_top_locki2 0xA606
+#define reg_top_locki2_pos 5
+#define reg_top_locki2_len 1
+#define reg_top_locki2_lsb 0
+#define xd_p_reg_dummy_7_0 0xA608
+#define reg_dummy_7_0_pos 0
+#define reg_dummy_7_0_len 8
+#define reg_dummy_7_0_lsb 0
+#define xd_p_reg_dummy_15_8 0xA609
+#define reg_dummy_15_8_pos 0
+#define reg_dummy_15_8_len 8
+#define reg_dummy_15_8_lsb 8
+#define xd_p_reg_dummy_23_16 0xA60A
+#define reg_dummy_23_16_pos 0
+#define reg_dummy_23_16_len 8
+#define reg_dummy_23_16_lsb 16
+#define xd_p_reg_dummy_31_24 0xA60B
+#define reg_dummy_31_24_pos 0
+#define reg_dummy_31_24_len 8
+#define reg_dummy_31_24_lsb 24
+#define xd_p_reg_dummy_39_32 0xA60C
+#define reg_dummy_39_32_pos 0
+#define reg_dummy_39_32_len 8
+#define reg_dummy_39_32_lsb 32
+#define xd_p_reg_dummy_47_40 0xA60D
+#define reg_dummy_47_40_pos 0
+#define reg_dummy_47_40_len 8
+#define reg_dummy_47_40_lsb 40
+#define xd_p_reg_dummy_55_48 0xA60E
+#define reg_dummy_55_48_pos 0
+#define reg_dummy_55_48_len 8
+#define reg_dummy_55_48_lsb 48
+#define xd_p_reg_dummy_63_56 0xA60F
+#define reg_dummy_63_56_pos 0
+#define reg_dummy_63_56_len 8
+#define reg_dummy_63_56_lsb 56
+#define xd_p_reg_dummy_71_64 0xA610
+#define reg_dummy_71_64_pos 0
+#define reg_dummy_71_64_len 8
+#define reg_dummy_71_64_lsb 64
+#define xd_p_reg_dummy_79_72 0xA611
+#define reg_dummy_79_72_pos 0
+#define reg_dummy_79_72_len 8
+#define reg_dummy_79_72_lsb 72
+#define xd_p_reg_dummy_87_80 0xA612
+#define reg_dummy_87_80_pos 0
+#define reg_dummy_87_80_len 8
+#define reg_dummy_87_80_lsb 80
+#define xd_p_reg_dummy_95_88 0xA613
+#define reg_dummy_95_88_pos 0
+#define reg_dummy_95_88_len 8
+#define reg_dummy_95_88_lsb 88
+#define xd_p_reg_dummy_103_96 0xA614
+#define reg_dummy_103_96_pos 0
+#define reg_dummy_103_96_len 8
+#define reg_dummy_103_96_lsb 96
+
+#define xd_p_reg_unplug_flag 0xA615
+#define reg_unplug_flag_pos 0
+#define reg_unplug_flag_len 1
+#define reg_unplug_flag_lsb 104
+
+#define xd_p_reg_api_dca_stes_request 0xA615
+#define reg_api_dca_stes_request_pos 1
+#define reg_api_dca_stes_request_len 1
+#define reg_api_dca_stes_request_lsb 0
+
+#define xd_p_reg_back_to_dca_flag 0xA615
+#define reg_back_to_dca_flag_pos 2
+#define reg_back_to_dca_flag_len 1
+#define reg_back_to_dca_flag_lsb 106
+
+#define xd_p_reg_api_retrain_request 0xA615
+#define reg_api_retrain_request_pos 3
+#define reg_api_retrain_request_len 1
+#define reg_api_retrain_request_lsb 0
+
+#define xd_p_reg_Dyn_Top_Try_flag 0xA615
+#define reg_Dyn_Top_Try_flag_pos 3
+#define reg_Dyn_Top_Try_flag_len 1
+#define reg_Dyn_Top_Try_flag_lsb 107
+
+#define xd_p_reg_API_retrain_freeze_flag 0xA615
+#define reg_API_retrain_freeze_flag_pos 4
+#define reg_API_retrain_freeze_flag_len 1
+#define reg_API_retrain_freeze_flag_lsb 108
+
+#define xd_p_reg_dummy_111_104 0xA615
+#define reg_dummy_111_104_pos 0
+#define reg_dummy_111_104_len 8
+#define reg_dummy_111_104_lsb 104
+#define xd_p_reg_dummy_119_112 0xA616
+#define reg_dummy_119_112_pos 0
+#define reg_dummy_119_112_len 8
+#define reg_dummy_119_112_lsb 112
+#define xd_p_reg_dummy_127_120 0xA617
+#define reg_dummy_127_120_pos 0
+#define reg_dummy_127_120_len 8
+#define reg_dummy_127_120_lsb 120
+#define xd_p_reg_dummy_135_128 0xA618
+#define reg_dummy_135_128_pos 0
+#define reg_dummy_135_128_len 8
+#define reg_dummy_135_128_lsb 128
+
+#define xd_p_reg_dummy_143_136 0xA619
+#define reg_dummy_143_136_pos 0
+#define reg_dummy_143_136_len 8
+#define reg_dummy_143_136_lsb 136
+
+#define xd_p_reg_CCIR_dis 0xA619
+#define reg_CCIR_dis_pos 0
+#define reg_CCIR_dis_len 1
+#define reg_CCIR_dis_lsb 0
+
+#define xd_p_reg_dummy_151_144 0xA61A
+#define reg_dummy_151_144_pos 0
+#define reg_dummy_151_144_len 8
+#define reg_dummy_151_144_lsb 144
+
+#define xd_p_reg_dummy_159_152 0xA61B
+#define reg_dummy_159_152_pos 0
+#define reg_dummy_159_152_len 8
+#define reg_dummy_159_152_lsb 152
+
+#define xd_p_reg_dummy_167_160 0xA61C
+#define reg_dummy_167_160_pos 0
+#define reg_dummy_167_160_len 8
+#define reg_dummy_167_160_lsb 160
+
+#define xd_p_reg_dummy_175_168 0xA61D
+#define reg_dummy_175_168_pos 0
+#define reg_dummy_175_168_len 8
+#define reg_dummy_175_168_lsb 168
+
+#define xd_p_reg_dummy_183_176 0xA61E
+#define reg_dummy_183_176_pos 0
+#define reg_dummy_183_176_len 8
+#define reg_dummy_183_176_lsb 176
+
+#define xd_p_reg_ofsm_read_rbc_en 0xA61E
+#define reg_ofsm_read_rbc_en_pos 2
+#define reg_ofsm_read_rbc_en_len 1
+#define reg_ofsm_read_rbc_en_lsb 0
+
+#define xd_p_reg_ce_filter_selection_dis 0xA61E
+#define reg_ce_filter_selection_dis_pos 1
+#define reg_ce_filter_selection_dis_len 1
+#define reg_ce_filter_selection_dis_lsb 0
+
+#define xd_p_reg_OFSM_version_control_7_0 0xA611
+#define reg_OFSM_version_control_7_0_pos 0
+#define reg_OFSM_version_control_7_0_len 8
+#define reg_OFSM_version_control_7_0_lsb 0
+
+#define xd_p_reg_OFSM_version_control_15_8 0xA61F
+#define reg_OFSM_version_control_15_8_pos 0
+#define reg_OFSM_version_control_15_8_len 8
+#define reg_OFSM_version_control_15_8_lsb 0
+
+#define xd_p_reg_OFSM_version_control_23_16 0xA620
+#define reg_OFSM_version_control_23_16_pos 0
+#define reg_OFSM_version_control_23_16_len 8
+#define reg_OFSM_version_control_23_16_lsb 0
+
+#define xd_p_reg_dummy_191_184 0xA61F
+#define reg_dummy_191_184_pos 0
+#define reg_dummy_191_184_len 8
+#define reg_dummy_191_184_lsb 184
+
+#define xd_p_reg_dummy_199_192 0xA620
+#define reg_dummy_199_192_pos 0
+#define reg_dummy_199_192_len 8
+#define reg_dummy_199_192_lsb 192
+
+#define xd_p_reg_ce_en 0xABC0
+#define reg_ce_en_pos 0
+#define reg_ce_en_len 1
+#define reg_ce_en_lsb 0
+#define xd_p_reg_ce_fctrl_en 0xABC0
+#define reg_ce_fctrl_en_pos 1
+#define reg_ce_fctrl_en_len 1
+#define reg_ce_fctrl_en_lsb 0
+#define xd_p_reg_ce_fste_tdi 0xABC0
+#define reg_ce_fste_tdi_pos 2
+#define reg_ce_fste_tdi_len 1
+#define reg_ce_fste_tdi_lsb 0
+#define xd_p_reg_ce_dynamic 0xABC0
+#define reg_ce_dynamic_pos 3
+#define reg_ce_dynamic_len 1
+#define reg_ce_dynamic_lsb 0
+#define xd_p_reg_ce_conf 0xABC0
+#define reg_ce_conf_pos 4
+#define reg_ce_conf_len 2
+#define reg_ce_conf_lsb 0
+#define xd_p_reg_ce_dyn12 0xABC0
+#define reg_ce_dyn12_pos 6
+#define reg_ce_dyn12_len 1
+#define reg_ce_dyn12_lsb 0
+#define xd_p_reg_ce_derot_en 0xABC0
+#define reg_ce_derot_en_pos 7
+#define reg_ce_derot_en_len 1
+#define reg_ce_derot_en_lsb 0
+#define xd_p_reg_ce_dynamic_th_7_0 0xABC1
+#define reg_ce_dynamic_th_7_0_pos 0
+#define reg_ce_dynamic_th_7_0_len 8
+#define reg_ce_dynamic_th_7_0_lsb 0
+#define xd_p_reg_ce_dynamic_th_15_8 0xABC2
+#define reg_ce_dynamic_th_15_8_pos 0
+#define reg_ce_dynamic_th_15_8_len 8
+#define reg_ce_dynamic_th_15_8_lsb 8
+#define xd_p_reg_ce_s1 0xABC3
+#define reg_ce_s1_pos 0
+#define reg_ce_s1_len 5
+#define reg_ce_s1_lsb 0
+#define xd_p_reg_ce_var_forced_value 0xABC3
+#define reg_ce_var_forced_value_pos 5
+#define reg_ce_var_forced_value_len 3
+#define reg_ce_var_forced_value_lsb 0
+#define xd_p_reg_ce_data_im_7_0 0xABC4
+#define reg_ce_data_im_7_0_pos 0
+#define reg_ce_data_im_7_0_len 8
+#define reg_ce_data_im_7_0_lsb 0
+#define xd_p_reg_ce_data_im_8 0xABC5
+#define reg_ce_data_im_8_pos 0
+#define reg_ce_data_im_8_len 1
+#define reg_ce_data_im_8_lsb 0
+#define xd_p_reg_ce_data_re_6_0 0xABC5
+#define reg_ce_data_re_6_0_pos 1
+#define reg_ce_data_re_6_0_len 7
+#define reg_ce_data_re_6_0_lsb 0
+#define xd_p_reg_ce_data_re_8_7 0xABC6
+#define reg_ce_data_re_8_7_pos 0
+#define reg_ce_data_re_8_7_len 2
+#define reg_ce_data_re_8_7_lsb 7
+#define xd_p_reg_ce_tone_5_0 0xABC6
+#define reg_ce_tone_5_0_pos 2
+#define reg_ce_tone_5_0_len 6
+#define reg_ce_tone_5_0_lsb 0
+#define xd_p_reg_ce_tone_12_6 0xABC7
+#define reg_ce_tone_12_6_pos 0
+#define reg_ce_tone_12_6_len 7
+#define reg_ce_tone_12_6_lsb 6
+#define xd_p_reg_ce_centroid_drift_th 0xABC8
+#define reg_ce_centroid_drift_th_pos 0
+#define reg_ce_centroid_drift_th_len 8
+#define reg_ce_centroid_drift_th_lsb 0
+#define xd_p_reg_ce_centroid_count_max 0xABC9
+#define reg_ce_centroid_count_max_pos 0
+#define reg_ce_centroid_count_max_len 4
+#define reg_ce_centroid_count_max_lsb 0
+#define xd_p_reg_ce_centroid_bias_inc_7_0 0xABCA
+#define reg_ce_centroid_bias_inc_7_0_pos 0
+#define reg_ce_centroid_bias_inc_7_0_len 8
+#define reg_ce_centroid_bias_inc_7_0_lsb 0
+#define xd_p_reg_ce_centroid_bias_inc_8 0xABCB
+#define reg_ce_centroid_bias_inc_8_pos 0
+#define reg_ce_centroid_bias_inc_8_len 1
+#define reg_ce_centroid_bias_inc_8_lsb 0
+#define xd_p_reg_ce_var_th0_7_0 0xABCC
+#define reg_ce_var_th0_7_0_pos 0
+#define reg_ce_var_th0_7_0_len 8
+#define reg_ce_var_th0_7_0_lsb 0
+#define xd_p_reg_ce_var_th0_15_8 0xABCD
+#define reg_ce_var_th0_15_8_pos 0
+#define reg_ce_var_th0_15_8_len 8
+#define reg_ce_var_th0_15_8_lsb 8
+#define xd_p_reg_ce_var_th1_7_0 0xABCE
+#define reg_ce_var_th1_7_0_pos 0
+#define reg_ce_var_th1_7_0_len 8
+#define reg_ce_var_th1_7_0_lsb 0
+#define xd_p_reg_ce_var_th1_15_8 0xABCF
+#define reg_ce_var_th1_15_8_pos 0
+#define reg_ce_var_th1_15_8_len 8
+#define reg_ce_var_th1_15_8_lsb 8
+#define xd_p_reg_ce_var_th2_7_0 0xABD0
+#define reg_ce_var_th2_7_0_pos 0
+#define reg_ce_var_th2_7_0_len 8
+#define reg_ce_var_th2_7_0_lsb 0
+#define xd_p_reg_ce_var_th2_15_8 0xABD1
+#define reg_ce_var_th2_15_8_pos 0
+#define reg_ce_var_th2_15_8_len 8
+#define reg_ce_var_th2_15_8_lsb 8
+#define xd_p_reg_ce_var_th3_7_0 0xABD2
+#define reg_ce_var_th3_7_0_pos 0
+#define reg_ce_var_th3_7_0_len 8
+#define reg_ce_var_th3_7_0_lsb 0
+#define xd_p_reg_ce_var_th3_15_8 0xABD3
+#define reg_ce_var_th3_15_8_pos 0
+#define reg_ce_var_th3_15_8_len 8
+#define reg_ce_var_th3_15_8_lsb 8
+#define xd_p_reg_ce_var_th4_7_0 0xABD4
+#define reg_ce_var_th4_7_0_pos 0
+#define reg_ce_var_th4_7_0_len 8
+#define reg_ce_var_th4_7_0_lsb 0
+#define xd_p_reg_ce_var_th4_15_8 0xABD5
+#define reg_ce_var_th4_15_8_pos 0
+#define reg_ce_var_th4_15_8_len 8
+#define reg_ce_var_th4_15_8_lsb 8
+#define xd_p_reg_ce_var_th5_7_0 0xABD6
+#define reg_ce_var_th5_7_0_pos 0
+#define reg_ce_var_th5_7_0_len 8
+#define reg_ce_var_th5_7_0_lsb 0
+#define xd_p_reg_ce_var_th5_15_8 0xABD7
+#define reg_ce_var_th5_15_8_pos 0
+#define reg_ce_var_th5_15_8_len 8
+#define reg_ce_var_th5_15_8_lsb 8
+#define xd_p_reg_ce_var_th6_7_0 0xABD8
+#define reg_ce_var_th6_7_0_pos 0
+#define reg_ce_var_th6_7_0_len 8
+#define reg_ce_var_th6_7_0_lsb 0
+#define xd_p_reg_ce_var_th6_15_8 0xABD9
+#define reg_ce_var_th6_15_8_pos 0
+#define reg_ce_var_th6_15_8_len 8
+#define reg_ce_var_th6_15_8_lsb 8
+#define xd_p_reg_ce_fctrl_reset 0xABDA
+#define reg_ce_fctrl_reset_pos 0
+#define reg_ce_fctrl_reset_len 1
+#define reg_ce_fctrl_reset_lsb 0
+#define xd_p_reg_ce_cent_auto_clr_en 0xABDA
+#define reg_ce_cent_auto_clr_en_pos 1
+#define reg_ce_cent_auto_clr_en_len 1
+#define reg_ce_cent_auto_clr_en_lsb 0
+#define xd_p_reg_ce_fctrl_auto_reset_en 0xABDA
+#define reg_ce_fctrl_auto_reset_en_pos 2
+#define reg_ce_fctrl_auto_reset_en_len 1
+#define reg_ce_fctrl_auto_reset_en_lsb 0
+#define xd_p_reg_ce_var_forced_en 0xABDA
+#define reg_ce_var_forced_en_pos 3
+#define reg_ce_var_forced_en_len 1
+#define reg_ce_var_forced_en_lsb 0
+#define xd_p_reg_ce_cent_forced_en 0xABDA
+#define reg_ce_cent_forced_en_pos 4
+#define reg_ce_cent_forced_en_len 1
+#define reg_ce_cent_forced_en_lsb 0
+#define xd_p_reg_ce_var_max 0xABDA
+#define reg_ce_var_max_pos 5
+#define reg_ce_var_max_len 3
+#define reg_ce_var_max_lsb 0
+#define xd_p_reg_ce_cent_forced_value_7_0 0xABDB
+#define reg_ce_cent_forced_value_7_0_pos 0
+#define reg_ce_cent_forced_value_7_0_len 8
+#define reg_ce_cent_forced_value_7_0_lsb 0
+#define xd_p_reg_ce_cent_forced_value_11_8 0xABDC
+#define reg_ce_cent_forced_value_11_8_pos 0
+#define reg_ce_cent_forced_value_11_8_len 4
+#define reg_ce_cent_forced_value_11_8_lsb 8
+#define xd_p_reg_ce_fctrl_rd 0xABDD
+#define reg_ce_fctrl_rd_pos 0
+#define reg_ce_fctrl_rd_len 1
+#define reg_ce_fctrl_rd_lsb 0
+#define xd_p_reg_ce_centroid_max_6_0 0xABDD
+#define reg_ce_centroid_max_6_0_pos 1
+#define reg_ce_centroid_max_6_0_len 7
+#define reg_ce_centroid_max_6_0_lsb 0
+#define xd_p_reg_ce_centroid_max_11_7 0xABDE
+#define reg_ce_centroid_max_11_7_pos 0
+#define reg_ce_centroid_max_11_7_len 5
+#define reg_ce_centroid_max_11_7_lsb 7
+#define xd_p_reg_ce_var 0xABDF
+#define reg_ce_var_pos 0
+#define reg_ce_var_len 3
+#define reg_ce_var_lsb 0
+#define xd_p_reg_ce_fctrl_rdy 0xABDF
+#define reg_ce_fctrl_rdy_pos 3
+#define reg_ce_fctrl_rdy_len 1
+#define reg_ce_fctrl_rdy_lsb 0
+#define xd_p_reg_ce_centroid_out_3_0 0xABDF
+#define reg_ce_centroid_out_3_0_pos 4
+#define reg_ce_centroid_out_3_0_len 4
+#define reg_ce_centroid_out_3_0_lsb 0
+#define xd_p_reg_ce_centroid_out_11_4 0xABE0
+#define reg_ce_centroid_out_11_4_pos 0
+#define reg_ce_centroid_out_11_4_len 8
+#define reg_ce_centroid_out_11_4_lsb 4
+#define xd_p_reg_ce_bias_7_0 0xABE1
+#define reg_ce_bias_7_0_pos 0
+#define reg_ce_bias_7_0_len 8
+#define reg_ce_bias_7_0_lsb 0
+#define xd_p_reg_ce_bias_11_8 0xABE2
+#define reg_ce_bias_11_8_pos 0
+#define reg_ce_bias_11_8_len 4
+#define reg_ce_bias_11_8_lsb 8
+#define xd_p_reg_ce_m1_3_0 0xABE2
+#define reg_ce_m1_3_0_pos 4
+#define reg_ce_m1_3_0_len 4
+#define reg_ce_m1_3_0_lsb 0
+#define xd_p_reg_ce_m1_11_4 0xABE3
+#define reg_ce_m1_11_4_pos 0
+#define reg_ce_m1_11_4_len 8
+#define reg_ce_m1_11_4_lsb 4
+#define xd_p_reg_ce_rh0_7_0 0xABE4
+#define reg_ce_rh0_7_0_pos 0
+#define reg_ce_rh0_7_0_len 8
+#define reg_ce_rh0_7_0_lsb 0
+#define xd_p_reg_ce_rh0_15_8 0xABE5
+#define reg_ce_rh0_15_8_pos 0
+#define reg_ce_rh0_15_8_len 8
+#define reg_ce_rh0_15_8_lsb 8
+#define xd_p_reg_ce_rh0_23_16 0xABE6
+#define reg_ce_rh0_23_16_pos 0
+#define reg_ce_rh0_23_16_len 8
+#define reg_ce_rh0_23_16_lsb 16
+#define xd_p_reg_ce_rh0_31_24 0xABE7
+#define reg_ce_rh0_31_24_pos 0
+#define reg_ce_rh0_31_24_len 8
+#define reg_ce_rh0_31_24_lsb 24
+#define xd_p_reg_ce_rh3_real_7_0 0xABE8
+#define reg_ce_rh3_real_7_0_pos 0
+#define reg_ce_rh3_real_7_0_len 8
+#define reg_ce_rh3_real_7_0_lsb 0
+#define xd_p_reg_ce_rh3_real_15_8 0xABE9
+#define reg_ce_rh3_real_15_8_pos 0
+#define reg_ce_rh3_real_15_8_len 8
+#define reg_ce_rh3_real_15_8_lsb 8
+#define xd_p_reg_ce_rh3_real_23_16 0xABEA
+#define reg_ce_rh3_real_23_16_pos 0
+#define reg_ce_rh3_real_23_16_len 8
+#define reg_ce_rh3_real_23_16_lsb 16
+#define xd_p_reg_ce_rh3_real_31_24 0xABEB
+#define reg_ce_rh3_real_31_24_pos 0
+#define reg_ce_rh3_real_31_24_len 8
+#define reg_ce_rh3_real_31_24_lsb 24
+#define xd_p_reg_ce_rh3_imag_7_0 0xABEC
+#define reg_ce_rh3_imag_7_0_pos 0
+#define reg_ce_rh3_imag_7_0_len 8
+#define reg_ce_rh3_imag_7_0_lsb 0
+#define xd_p_reg_ce_rh3_imag_15_8 0xABED
+#define reg_ce_rh3_imag_15_8_pos 0
+#define reg_ce_rh3_imag_15_8_len 8
+#define reg_ce_rh3_imag_15_8_lsb 8
+#define xd_p_reg_ce_rh3_imag_23_16 0xABEE
+#define reg_ce_rh3_imag_23_16_pos 0
+#define reg_ce_rh3_imag_23_16_len 8
+#define reg_ce_rh3_imag_23_16_lsb 16
+#define xd_p_reg_ce_rh3_imag_31_24 0xABEF
+#define reg_ce_rh3_imag_31_24_pos 0
+#define reg_ce_rh3_imag_31_24_len 8
+#define reg_ce_rh3_imag_31_24_lsb 24
+#define xd_p_reg_feq_fix_eh2_7_0 0xABF0
+#define reg_feq_fix_eh2_7_0_pos 0
+#define reg_feq_fix_eh2_7_0_len 8
+#define reg_feq_fix_eh2_7_0_lsb 0
+#define xd_p_reg_feq_fix_eh2_15_8 0xABF1
+#define reg_feq_fix_eh2_15_8_pos 0
+#define reg_feq_fix_eh2_15_8_len 8
+#define reg_feq_fix_eh2_15_8_lsb 8
+#define xd_p_reg_feq_fix_eh2_23_16 0xABF2
+#define reg_feq_fix_eh2_23_16_pos 0
+#define reg_feq_fix_eh2_23_16_len 8
+#define reg_feq_fix_eh2_23_16_lsb 16
+#define xd_p_reg_feq_fix_eh2_31_24 0xABF3
+#define reg_feq_fix_eh2_31_24_pos 0
+#define reg_feq_fix_eh2_31_24_len 8
+#define reg_feq_fix_eh2_31_24_lsb 24
+#define xd_p_reg_ce_m2_central_7_0 0xABF4
+#define reg_ce_m2_central_7_0_pos 0
+#define reg_ce_m2_central_7_0_len 8
+#define reg_ce_m2_central_7_0_lsb 0
+#define xd_p_reg_ce_m2_central_15_8 0xABF5
+#define reg_ce_m2_central_15_8_pos 0
+#define reg_ce_m2_central_15_8_len 8
+#define reg_ce_m2_central_15_8_lsb 8
+#define xd_p_reg_ce_fftshift 0xABF6
+#define reg_ce_fftshift_pos 0
+#define reg_ce_fftshift_len 4
+#define reg_ce_fftshift_lsb 0
+#define xd_p_reg_ce_fftshift1 0xABF6
+#define reg_ce_fftshift1_pos 4
+#define reg_ce_fftshift1_len 4
+#define reg_ce_fftshift1_lsb 0
+#define xd_p_reg_ce_fftshift2 0xABF7
+#define reg_ce_fftshift2_pos 0
+#define reg_ce_fftshift2_len 4
+#define reg_ce_fftshift2_lsb 0
+#define xd_p_reg_ce_top_mobile 0xABF7
+#define reg_ce_top_mobile_pos 4
+#define reg_ce_top_mobile_len 1
+#define reg_ce_top_mobile_lsb 0
+#define xd_p_reg_strong_sginal_detected 0xA2BC
+#define reg_strong_sginal_detected_pos 2
+#define reg_strong_sginal_detected_len 1
+#define reg_strong_sginal_detected_lsb 0
+
+#define XD_MP2IF_BASE 0xB000
+#define XD_MP2IF_CSR (0x00 + XD_MP2IF_BASE)
+#define XD_MP2IF_DMX_CTRL (0x03 + XD_MP2IF_BASE)
+#define XD_MP2IF_PID_IDX (0x04 + XD_MP2IF_BASE)
+#define XD_MP2IF_PID_DATA_L (0x05 + XD_MP2IF_BASE)
+#define XD_MP2IF_PID_DATA_H (0x06 + XD_MP2IF_BASE)
+#define XD_MP2IF_MISC (0x07 + XD_MP2IF_BASE)
+
+extern struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d);
+extern int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg,
+ u8 * value);
+extern int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len);
+extern int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg,
+ u8 value);
+extern int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len);
+extern int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg,
+ u8 addr, u8 * values, int len);
+extern int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg,
+ u8 * values, int len);
+extern int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg,
+ u8 pos, u8 len, u8 * value);
+extern int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg,
+ u8 pos, u8 len, u8 value);
+extern int af9005_send_command(struct dvb_usb_device *d, u8 command,
+ u8 * wbuf, int wlen, u8 * rbuf, int rlen);
+extern int af9005_read_eeprom(struct dvb_usb_device *d, u8 address,
+ u8 * values, int len);
+extern int af9005_tuner_attach(struct dvb_usb_adapter *adap);
+extern int af9005_led_control(struct dvb_usb_device *d, int onoff);
+
+extern u8 regmask[8];
+
+/* remote control decoder */
+extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
+ u32 * event, int *state);
+extern struct dvb_usb_rc_key af9005_rc_keys[];
+extern int af9005_rc_keys_size;
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index bac2ae3b4a1f..04e31cf7d530 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -354,41 +354,35 @@ static struct mt352_config cxusb_mt352_config = {
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
- u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
- adap->pll_addr = 0x61;
- memcpy(adap->pll_init, bpll, 4);
- adap->pll_desc = &dvb_pll_fmd1216me;
-
- adap->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
- adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
-
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+ DVB_PLL_FMD1216ME);
return 0;
}
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x61,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
{
- dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201);
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
return 0;
}
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
return 0;
}
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
- &dvb_pll_lg_tdvs_h06xf);
+ DVB_PLL_LG_TDVS_H06XF);
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index cda3adea24fb..4a903ea95896 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -30,17 +30,19 @@ extern int dvb_usb_dib0700_debug;
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
+#define REQUEST_SET_RC 0x11
#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
u8 channel_state;
u16 mt2060_if1[2];
-
+ u8 rc_toggle;
u8 is_dib7000pc;
};
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
+extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
extern struct i2c_algorithm dib0700_i2c_algo;
@@ -50,5 +52,4 @@ extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device
extern int dib0700_device_count;
extern struct dvb_usb_device_properties dib0700_devices[];
extern struct usb_device_id dib0700_usb_id_table[];
-
#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index dddf164f269a..3ea294eb96bd 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -13,6 +13,10 @@ int dvb_usb_dib0700_debug;
module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
+static int dvb_usb_dib0700_ir_proto = 1;
+module_param(dvb_usb_dib0700_ir_proto, int, 0644);
+MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
+
/* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{
@@ -32,7 +36,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
}
/* expecting tx buffer: request data[0] ... data[n] (n <= 4) */
-static int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
+int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
{
u16 index, value;
int status;
@@ -260,14 +264,29 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return dib0700_ctrl_wr(adap->dev, b, 4);
}
+static int dib0700_rc_setup(struct dvb_usb_device *d)
+{
+ u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
+ int i = dib0700_ctrl_wr(d, rc_setup, 3);
+ if (i<0) {
+ err("ir protocol setup failed");
+ return -1;
+ }
+ return 0;
+}
+
static int dib0700_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int i;
+ struct dvb_usb_device *dev;
for (i = 0; i < dib0700_device_count; i++)
- if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, NULL) == 0)
+ if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
+ {
+ dib0700_rc_setup(dev);
return 0;
+ }
return -ENODEV;
}
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 2208757d9017..e8c4a8694532 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -4,7 +4,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * Copyright (C) 2005-6 DiBcom, SA
+ * Copyright (C) 2005-7 DiBcom, SA
*/
#include "dib0700.h"
@@ -12,13 +12,19 @@
#include "dib7000m.h"
#include "dib7000p.h"
#include "mt2060.h"
+#include "mt2266.h"
+#include "dib0070.h"
static int force_lna_activation;
module_param(force_lna_activation, int, 0644);
MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
"if applicable for the device (default: 0=automatic/off).");
-/* Hauppauge Nova-T 500
+struct dib0700_adapter_state {
+ int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
+};
+
+/* Hauppauge Nova-T 500 (aka Bristol)
* has a LNA on GPIO0 which is enabled by setting 1 */
static struct mt2060_config bristol_mt2060_config[2] = {
{
@@ -96,6 +102,321 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
}
+/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
+
+/* MT226x */
+static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
+ {
+ BAND_UHF, // band_caps
+
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
+ * 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) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
+
+ 1130, // inv_gain
+ 21, // time_stabiliz
+
+ 0, // alpha_level
+ 118, // thlock
+
+ 0, // wbd_inv
+ 3530, // wbd_ref
+ 1, // wbd_sel
+ 0, // wbd_alpha
+
+ 65535, // agc1_max
+ 33770, // agc1_min
+ 65535, // agc2_max
+ 23592, // agc2_min
+
+ 0, // agc1_pt1
+ 62, // agc1_pt2
+ 255, // agc1_pt3
+ 64, // agc1_slope1
+ 64, // agc1_slope2
+ 132, // agc2_pt1
+ 192, // agc2_pt2
+ 80, // agc2_slope1
+ 80, // agc2_slope2
+
+ 17, // alpha_mant
+ 27, // alpha_exp
+ 23, // beta_mant
+ 51, // beta_exp
+
+ 1, // perform_agc_softsplit
+ }, {
+ BAND_VHF | BAND_LBAND, // band_caps
+
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
+ * 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) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+ 2372, // inv_gain
+ 21, // time_stabiliz
+
+ 0, // alpha_level
+ 118, // thlock
+
+ 0, // wbd_inv
+ 3530, // wbd_ref
+ 1, // wbd_sel
+ 0, // wbd_alpha
+
+ 65535, // agc1_max
+ 0, // agc1_min
+ 65535, // agc2_max
+ 23592, // agc2_min
+
+ 0, // agc1_pt1
+ 128, // agc1_pt2
+ 128, // agc1_pt3
+ 128, // agc1_slope1
+ 0, // agc1_slope2
+ 128, // agc2_pt1
+ 253, // agc2_pt2
+ 81, // agc2_slope1
+ 0, // agc2_slope2
+
+ 17, // alpha_mant
+ 27, // alpha_exp
+ 23, // beta_mant
+ 51, // beta_exp
+
+ 1, // perform_agc_softsplit
+ }
+};
+
+static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
+ 60000, 30000, // internal, sampling
+ 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
+ 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
+ (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
+ 0, // ifreq
+ 20452225, // timf
+};
+
+static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
+ { .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .tuner_is_baseband = 1,
+
+ .agc_config_count = 2,
+ .agc = stk7700d_7000p_mt2266_agc_config,
+ .bw = &stk7700d_mt2266_pll_config,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+ },
+ { .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .tuner_is_baseband = 1,
+
+ .agc_config_count = 2,
+ .agc = stk7700d_7000p_mt2266_agc_config,
+ .bw = &stk7700d_mt2266_pll_config,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+ }
+};
+
+static struct mt2266_config stk7700d_mt2266_config[2] = {
+ { .i2c_address = 0x60
+ },
+ { .i2c_address = 0x60
+ }
+};
+
+static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ if (adap->id == 0) {
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+ dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config);
+ }
+
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
+ &stk7700d_dib7000p_mt2266_config[adap->id]);
+
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct i2c_adapter *tun_i2c;
+ tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
+ &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
+}
+
+#define DEFAULT_RC_INTERVAL 150
+
+static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
+
+static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[4];
+ int i;
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ struct dib0700_state *st = d->priv;
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+ i=dib0700_ctrl_rd(d,rc_request,2,key,4);
+ if (i<=0) {
+ err("RC Query Failed");
+ return -1;
+ }
+ if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
+ if (key[3-1]!=st->rc_toggle) {
+ for (i=0;i<d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ st->rc_toggle=key[3-1];
+ return 0;
+ }
+ }
+ err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
+ }
+ return 0;
+}
+
+static struct dvb_usb_rc_key dib0700_rc_keys[] = {
+ /* Key codes for the tiny Pinnacle remote*/
+ { 0x07, 0x00, KEY_MUTE },
+ { 0x07, 0x01, KEY_MENU }, // Pinnacle logo
+ { 0x07, 0x39, KEY_POWER },
+ { 0x07, 0x03, KEY_VOLUMEUP },
+ { 0x07, 0x09, KEY_VOLUMEDOWN },
+ { 0x07, 0x06, KEY_CHANNELUP },
+ { 0x07, 0x0c, KEY_CHANNELDOWN },
+ { 0x07, 0x0f, KEY_1 },
+ { 0x07, 0x15, KEY_2 },
+ { 0x07, 0x10, KEY_3 },
+ { 0x07, 0x18, KEY_4 },
+ { 0x07, 0x1b, KEY_5 },
+ { 0x07, 0x1e, KEY_6 },
+ { 0x07, 0x11, KEY_7 },
+ { 0x07, 0x21, KEY_8 },
+ { 0x07, 0x12, KEY_9 },
+ { 0x07, 0x27, KEY_0 },
+ { 0x07, 0x24, KEY_SCREEN }, // 'Square' key
+ { 0x07, 0x2a, KEY_TEXT }, // 'T' key
+ { 0x07, 0x2d, KEY_REWIND },
+ { 0x07, 0x30, KEY_PLAY },
+ { 0x07, 0x33, KEY_FASTFORWARD },
+ { 0x07, 0x36, KEY_RECORD },
+ { 0x07, 0x3c, KEY_STOP },
+ { 0x07, 0x3f, KEY_CANCEL }, // '?' key
+ /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
+ { 0xeb, 0x01, KEY_POWER },
+ { 0xeb, 0x02, KEY_1 },
+ { 0xeb, 0x03, KEY_2 },
+ { 0xeb, 0x04, KEY_3 },
+ { 0xeb, 0x05, KEY_4 },
+ { 0xeb, 0x06, KEY_5 },
+ { 0xeb, 0x07, KEY_6 },
+ { 0xeb, 0x08, KEY_7 },
+ { 0xeb, 0x09, KEY_8 },
+ { 0xeb, 0x0a, KEY_9 },
+ { 0xeb, 0x0b, KEY_VIDEO },
+ { 0xeb, 0x0c, KEY_0 },
+ { 0xeb, 0x0d, KEY_REFRESH },
+ { 0xeb, 0x0f, KEY_EPG },
+ { 0xeb, 0x10, KEY_UP },
+ { 0xeb, 0x11, KEY_LEFT },
+ { 0xeb, 0x12, KEY_OK },
+ { 0xeb, 0x13, KEY_RIGHT },
+ { 0xeb, 0x14, KEY_DOWN },
+ { 0xeb, 0x16, KEY_INFO },
+ { 0xeb, 0x17, KEY_RED },
+ { 0xeb, 0x18, KEY_GREEN },
+ { 0xeb, 0x19, KEY_YELLOW },
+ { 0xeb, 0x1a, KEY_BLUE },
+ { 0xeb, 0x1b, KEY_CHANNELUP },
+ { 0xeb, 0x1c, KEY_VOLUMEUP },
+ { 0xeb, 0x1d, KEY_MUTE },
+ { 0xeb, 0x1e, KEY_VOLUMEDOWN },
+ { 0xeb, 0x1f, KEY_CHANNELDOWN },
+ { 0xeb, 0x40, KEY_PAUSE },
+ { 0xeb, 0x41, KEY_HOME },
+ { 0xeb, 0x42, KEY_MENU }, /* DVD Menu */
+ { 0xeb, 0x43, KEY_SUBTITLE },
+ { 0xeb, 0x44, KEY_TEXT }, /* Teletext */
+ { 0xeb, 0x45, KEY_DELETE },
+ { 0xeb, 0x46, KEY_TV },
+ { 0xeb, 0x47, KEY_DVD },
+ { 0xeb, 0x48, KEY_STOP },
+ { 0xeb, 0x49, KEY_VIDEO },
+ { 0xeb, 0x4a, KEY_AUDIO }, /* Music */
+ { 0xeb, 0x4b, KEY_SCREEN }, /* Pic */
+ { 0xeb, 0x4c, KEY_PLAY },
+ { 0xeb, 0x4d, KEY_BACK },
+ { 0xeb, 0x4e, KEY_REWIND },
+ { 0xeb, 0x4f, KEY_FASTFORWARD },
+ { 0xeb, 0x54, KEY_PREVIOUS },
+ { 0xeb, 0x58, KEY_RECORD },
+ { 0xeb, 0x5c, KEY_NEXT },
+
+ /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
+ { 0x1e, 0x00, KEY_0 },
+ { 0x1e, 0x01, KEY_1 },
+ { 0x1e, 0x02, KEY_2 },
+ { 0x1e, 0x03, KEY_3 },
+ { 0x1e, 0x04, KEY_4 },
+ { 0x1e, 0x05, KEY_5 },
+ { 0x1e, 0x06, KEY_6 },
+ { 0x1e, 0x07, KEY_7 },
+ { 0x1e, 0x08, KEY_8 },
+ { 0x1e, 0x09, KEY_9 },
+ { 0x1e, 0x0a, KEY_KPASTERISK },
+ { 0x1e, 0x0b, KEY_RED },
+ { 0x1e, 0x0c, KEY_RADIO },
+ { 0x1e, 0x0d, KEY_MENU },
+ { 0x1e, 0x0e, KEY_GRAVE }, /* # */
+ { 0x1e, 0x0f, KEY_MUTE },
+ { 0x1e, 0x10, KEY_VOLUMEUP },
+ { 0x1e, 0x11, KEY_VOLUMEDOWN },
+ { 0x1e, 0x12, KEY_CHANNEL },
+ { 0x1e, 0x14, KEY_UP },
+ { 0x1e, 0x15, KEY_DOWN },
+ { 0x1e, 0x16, KEY_LEFT },
+ { 0x1e, 0x17, KEY_RIGHT },
+ { 0x1e, 0x18, KEY_VIDEO },
+ { 0x1e, 0x19, KEY_AUDIO },
+ { 0x1e, 0x1a, KEY_MEDIA },
+ { 0x1e, 0x1b, KEY_EPG },
+ { 0x1e, 0x1c, KEY_TV },
+ { 0x1e, 0x1e, KEY_NEXT },
+ { 0x1e, 0x1f, KEY_BACK },
+ { 0x1e, 0x20, KEY_CHANNELUP },
+ { 0x1e, 0x21, KEY_CHANNELDOWN },
+ { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
+ { 0x1e, 0x25, KEY_OK },
+ { 0x1e, 0x29, KEY_BLUE},
+ { 0x1e, 0x2e, KEY_GREEN },
+ { 0x1e, 0x30, KEY_PAUSE },
+ { 0x1e, 0x32, KEY_REWIND },
+ { 0x1e, 0x34, KEY_FASTFORWARD },
+ { 0x1e, 0x35, KEY_PLAY },
+ { 0x1e, 0x36, KEY_STOP },
+ { 0x1e, 0x37, KEY_RECORD },
+ { 0x1e, 0x38, KEY_YELLOW },
+ { 0x1e, 0x3b, KEY_GOTO },
+ { 0x1e, 0x3d, KEY_POWER },
+};
+
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
BAND_UHF | BAND_VHF, // band_caps
@@ -194,6 +515,7 @@ static struct dibx000_bandwidth_config stk7700p_pll_config = {
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
60258167, // ifreq
20452225, // timf
+ 30000000, // xtal
};
static struct dib7000m_config stk7700p_dib7000m_config = {
@@ -213,6 +535,7 @@ static struct dib7000m_config stk7700p_dib7000m_config = {
static struct dib7000p_config stk7700p_dib7000p_config = {
.output_mpeg2_in_188_bytes = 1,
+ .agc_config_count = 1,
.agc = &stk7700p_7000p_mt2060_agc_config,
.bw = &stk7700p_pll_config,
@@ -267,27 +590,245 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
}
+/* DIB7070 generic */
+static struct dibx000_agc_config dib7070_agc_config = {
+ BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+ * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+ (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
+
+ 600, // inv_gain
+ 10, // time_stabiliz
+
+ 0, // alpha_level
+ 118, // thlock
+
+ 0, // wbd_inv
+ 3530, // wbd_ref
+ 1, // wbd_sel
+ 5, // wbd_alpha
+
+ 65535, // agc1_max
+ 0, // agc1_min
+
+ 65535, // agc2_max
+ 0, // agc2_min
+
+ 0, // agc1_pt1
+ 40, // agc1_pt2
+ 183, // agc1_pt3
+ 206, // agc1_slope1
+ 255, // agc1_slope2
+ 72, // agc2_pt1
+ 152, // agc2_pt2
+ 88, // agc2_slope1
+ 90, // agc2_slope2
+
+ 17, // alpha_mant
+ 27, // alpha_exp
+ 23, // beta_mant
+ 51, // beta_exp
+
+ 0, // perform_agc_softsplit
+};
+
+static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+ return dib7000p_set_gpio(fe, 8, 0, !onoff);
+}
+
+static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+ return dib7000p_set_gpio(fe, 9, 0, onoff);
+}
+
+static struct dib0070_config dib7070p_dib0070_config[2] = {
+ {
+ .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+ .reset = dib7070_tuner_reset,
+ .sleep = dib7070_tuner_sleep,
+ .clock_khz = 12000,
+ .clock_pad_drive = 4
+ }, {
+ .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+ .reset = dib7070_tuner_reset,
+ .sleep = dib7070_tuner_sleep,
+ .clock_khz = 12000,
+
+ }
+};
+
+static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ u16 offset;
+ u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ switch (band) {
+ case BAND_VHF: offset = 950; break;
+ case BAND_UHF:
+ default: offset = 550; break;
+ }
+ deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
+ dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ return state->set_param_save(fe, fep);
+}
+
+static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+
+ if (adap->id == 0) {
+ if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
+ return -ENODEV;
+ } else {
+ if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
+ return -ENODEV;
+ }
+
+ st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+ adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+ return 0;
+}
+
+static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
+ 60000, 15000, // internal, sampling
+ 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
+ 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
+ (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
+ (0 << 25) | 0, // ifreq = 0.000000 MHz
+ 20452225, // timf
+ 12000000, // xtal_hz
+};
+
+static struct dib7000p_config dib7070p_dib7000p_config = {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+};
+
+/* STK7070P */
+static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
+
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+/* STK7070PD */
+static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
+ {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+ }, {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+ }
+};
+
+static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+{
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config);
+
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
+{
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
+/* DVB-USB and USB stuff follows */
struct usb_device_id dib0700_usb_id_table[] = {
- { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
+/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
- { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+/* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
{ USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
- { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
- { } /* Terminating entry */
+/* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) },
+ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
+ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
+ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) },
+/* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
+ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
+ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
+/* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
+ { 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
.usb_ctrl = DEVICE_SPECIFIC, \
- .firmware = "dvb-usb-dib0700-01.fw", \
+ .firmware = "dvb-usb-dib0700-03-pre1.fw", \
.download_firmware = dib0700_download_firmware, \
.no_reconnect = 1, \
.size_of_priv = sizeof(struct dib0700_state), \
@@ -321,7 +862,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 6,
+ .num_device_descs = 7,
.devices = {
{ "DiBcom STK7700P reference design",
{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
@@ -336,7 +877,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ NULL },
},
{ "Compro Videomate U500",
- { &dib0700_usb_id_table[6], NULL },
+ { &dib0700_usb_id_table[6], &dib0700_usb_id_table[19] },
{ NULL },
},
{ "Uniwill STK7700P based (Hama and others)",
@@ -346,8 +887,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Leadtek Winfast DTV Dongle (STK7700P based)",
{ &dib0700_usb_id_table[8], NULL },
{ NULL },
+ },
+ { "AVerMedia AVerTV DVB-T Express",
+ { &dib0700_usb_id_table[20] },
+ { NULL },
}
- }
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
@@ -371,8 +921,112 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
{ NULL },
},
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .frontend_attach = stk7700d_frontend_attach,
+ .tuner_attach = stk7700d_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }, {
+ .frontend_attach = stk7700d_frontend_attach,
+ .tuner_attach = stk7700d_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }
+ },
+
+ .num_device_descs = 4,
+ .devices = {
+ { "Pinnacle PCTV 2000e",
+ { &dib0700_usb_id_table[11], NULL },
+ { NULL },
+ },
+ { "Terratec Cinergy DT XS Diversity",
+ { &dib0700_usb_id_table[12], NULL },
+ { NULL },
+ },
+ { "Hauppauge Nova-TD Stick/Elgato Eye-TV Diversity",
+ { &dib0700_usb_id_table[13], NULL },
+ { NULL },
+ },
+ { "DiBcom STK7700D reference design",
+ { &dib0700_usb_id_table[14], NULL },
+ { NULL },
+ },
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dib0700_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
+ .rc_query = dib0700_rc_query
+
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .frontend_attach = stk7070p_frontend_attach,
+ .tuner_attach = dib7070p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "DiBcom STK7070P reference design",
+ { &dib0700_usb_id_table[15], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV DVB-T Flash Stick",
+ { &dib0700_usb_id_table[16], NULL },
+ { NULL },
+ },
}
- }
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 2,
+ .adapter = {
+ {
+ .frontend_attach = stk7070pd_frontend_attach0,
+ .tuner_attach = dib7070p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ }, {
+ .frontend_attach = stk7070pd_frontend_attach1,
+ .tuner_attach = dib7070p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "DiBcom STK7070PD reference design",
+ { &dib0700_usb_id_table[17], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV Dual DVB-T Diversity Stick",
+ { &dib0700_usb_id_table[18], NULL },
+ { NULL },
+ },
+ }
+ },
};
int dib0700_device_count = ARRAY_SIZE(dib0700_devices);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 5143e426d283..9a184da01c47 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -295,7 +295,7 @@ int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
/* not found - use panasonic pll parameters */
- if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
+ if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
return -ENOMEM;
} else {
st->mt2060_present = 1;
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 7a6ae8f482e0..043cadae0859 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -14,6 +14,14 @@
*/
#include "dibusb.h"
+static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dibusb_state *st = adap->priv;
+
+ return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr);
+}
+
static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib3000_config demod_cfg;
@@ -21,21 +29,34 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
demod_cfg.demod_address = 0x8;
- if ((adap->fe = dib3000mb_attach(&demod_cfg,&adap->dev->i2c_adap,&st->ops)) == NULL)
+ if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
+ &adap->dev->i2c_adap, &st->ops)) == NULL)
return -ENODEV;
- adap->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
- adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
-
- adap->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+ adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
return 0;
}
static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x61;
- adap->pll_desc = &dvb_pll_tua6010xs;
+ struct dibusb_state *st = adap->priv;
+
+ st->tuner_addr = 0x61;
+
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+ DVB_PLL_TUA6010XS);
+ return 0;
+}
+
+static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dibusb_state *st = adap->priv;
+
+ st->tuner_addr = 0x60;
+
+ dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
+ DVB_PLL_TDA665X);
return 0;
}
@@ -50,30 +71,28 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
{ .flags = 0, .buf = b, .len = 2 },
{ .flags = I2C_M_RD, .buf = b2, .len = 1 },
};
+ struct dibusb_state *st = adap->priv;
/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
- msg[0].addr = msg[1].addr = 0x60;
+ msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(adap->fe,1,msg[0].addr);
+ if (adap->fe->ops.i2c_gate_ctrl)
+ adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
err("tuner i2c write failed.");
ret = -EREMOTEIO;
}
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(adap->fe,0,msg[0].addr);
+ if (adap->fe->ops.i2c_gate_ctrl)
+ adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
if (b2[0] == 0xfe) {
info("This device has the Thomson Cable onboard. Which is default.");
- dibusb_thomson_tuner_attach(adap);
+ ret = dibusb_thomson_tuner_attach(adap);
} else {
- u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
info("This device has the Panasonic ENV77H11D5 onboard.");
- adap->pll_addr = 0x60;
- memcpy(adap->pll_init,bpll,4);
- adap->pll_desc = &dvb_pll_tda665x;
+ ret = dibusb_panasonic_tuner_attach(adap);
}
return ret;
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
index b60781032742..8e847aa73ba1 100644
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -99,6 +99,7 @@
struct dibusb_state {
struct dib_fe_xfer_ops ops;
int mt2060_present;
+ u8 tuner_addr;
};
struct dibusb_device_state {
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index b5acb11c0bc9..bca1e0905739 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -118,7 +118,8 @@ static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
u8 b[5];
- dvb_usb_tuner_calc_regs(fe,fep,b, 5);
+
+ fe->ops.tuner_ops.calc_regs(fe, fep, b, sizeof(b));
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
@@ -130,12 +131,14 @@ static struct nxt6000_config digitv_nxt6000_config = {
static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct digitv_state *st = adap->dev->priv;
+
if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
- adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ st->is_nxt6000 = 0;
return 0;
}
if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
- adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+ st->is_nxt6000 = 1;
return 0;
}
return -EIO;
@@ -143,8 +146,14 @@ static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x60;
- adap->pll_desc = &dvb_pll_tded4;
+ struct digitv_state *st = adap->dev->priv;
+
+ if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
+ return -ENODEV;
+
+ if (st->is_nxt6000)
+ adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+
return 0;
}
@@ -273,6 +282,8 @@ static struct dvb_usb_device_properties digitv_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-digitv-02.fw",
+ .size_of_priv = sizeof(struct digitv_state),
+
.num_adapters = 1,
.adapter = {
{
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
index 477ee428a70e..8b43e3db8691 100644
--- a/drivers/media/dvb/dvb-usb/digitv.h
+++ b/drivers/media/dvb/dvb-usb/digitv.h
@@ -4,6 +4,10 @@
#define DVB_USB_LOG_PREFIX "digitv"
#include "dvb-usb.h"
+struct digitv_state {
+ int is_nxt6000;
+};
+
extern int dvb_usb_digitv_debug;
#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 7dbe14321019..d86cf9bee91c 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -1,5 +1,5 @@
/* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
- * Typhoon/ Yuan DVB-T USB2.0 receiver.
+ * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver.
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
*
@@ -96,6 +96,7 @@ static struct dvb_usb_device_properties dtt200u_properties;
static struct dvb_usb_device_properties wt220u_fc_properties;
static struct dvb_usb_device_properties wt220u_properties;
static struct dvb_usb_device_properties wt220u_zl0353_properties;
+static struct dvb_usb_device_properties wt220u_miglia_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -103,7 +104,8 @@ static int dtt200u_usb_probe(struct usb_interface *intf,
if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
+ dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
return 0;
return -ENODEV;
@@ -119,6 +121,7 @@ static struct usb_device_id dtt200u_usb_table [] = {
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) },
+ { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) },
{ 0 },
};
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -303,6 +306,25 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
}
};
+static struct dvb_usb_device_properties wt220u_miglia_properties = {
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-wt220u-miglia-01.fw",
+
+ .num_adapters = 1,
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "WideView WT-220U PenType Receiver (Miglia)",
+ .cold_ids = { &dtt200u_usb_table[9], NULL },
+ /* This device turns into WT220U_ZL0353_WARM when fw
+ has been uploaded */
+ .warm_ids = { NULL },
+ },
+ { NULL },
+ }
+};
+
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver dtt200u_usb_driver = {
.name = "dvb_usb_dtt200u",
@@ -333,6 +355,6 @@ module_init(dtt200u_usb_module_init);
module_exit(dtt200u_usb_module_exit);
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
+MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 088b6dee3a7f..23428cd30756 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -46,82 +46,3 @@ int dvb_usb_i2c_exit(struct dvb_usb_device *d)
d->state &= ~DVB_USB_STATE_I2C;
return 0;
}
-
-int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct i2c_msg msg = { .addr = adap->pll_addr, .flags = 0, .buf = adap->pll_init, .len = 4 };
- int ret = 0;
-
- /* if pll_desc is not used */
- if (adap->pll_desc == NULL)
- return 0;
-
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(fe, 1, adap->pll_addr);
-
- deb_pll("pll init: %x\n",adap->pll_addr);
- deb_pll("pll-buf: %x %x %x %x\n",adap->pll_init[0], adap->pll_init[1],
- adap->pll_init[2], adap->pll_init[3]);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&adap->dev->i2c_adap, &msg, 1) != 1) {
- err("tuner i2c write failed for pll_init.");
- ret = -EREMOTEIO;
- }
- msleep(1);
-
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(fe,0,adap->pll_addr);
- return ret;
-}
-EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
-
-int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
-
- if (buf_len != 5)
- return -EINVAL;
- if (adap->pll_desc == NULL)
- return 0;
-
- deb_pll("pll addr: %x, freq: %d %p\n",adap->pll_addr, fep->frequency, adap->pll_desc);
-
- b[0] = adap->pll_addr;
- dvb_pll_configure(adap->pll_desc, &b[1], fep->frequency, fep->u.ofdm.bandwidth);
-
- deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
-
- return 5;
-}
-EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
-
-int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- int ret = 0;
- u8 b[5];
- struct i2c_msg msg = { .addr = adap->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
-
- dvb_usb_tuner_calc_regs(fe,fep,b,5);
-
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(fe, 1, adap->pll_addr);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- if (i2c_transfer(&adap->dev->i2c_adap, &msg, 1) != 1) {
- err("tuner i2c write failed for pll_set.");
- ret = -EREMOTEIO;
- }
- msleep(1);
-
- if (adap->tuner_pass_ctrl)
- adap->tuner_pass_ctrl(fe, 0, adap->pll_addr);
-
- return ret;
-}
-EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 403081689de1..4fa3e895028a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -11,7 +11,9 @@
/* Vendor IDs */
#define USB_VID_ADSTECH 0x06e1
-#define USB_VID_ALCOR_MICRO 0x058f
+#define USB_VID_AFATECH 0x15a4
+#define USB_VID_ALCOR_MICRO 0x058f
+#define USB_VID_ALINK 0x05e3
#define USB_VID_ANCHOR 0x0547
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
#define USB_VID_AVERMEDIA 0x07ca
@@ -32,9 +34,11 @@
#define USB_VID_LEADTEK 0x0413
#define USB_VID_LITEON 0x04ca
#define USB_VID_MEDION 0x1660
+#define USB_VID_MIGLIA 0x18f3
#define USB_VID_MSI 0x0db0
#define USB_VID_OPERA1 0x695c
#define USB_VID_PINNACLE 0x2304
+#define USB_VID_TERRATEC 0x0ccd
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
@@ -44,6 +48,8 @@
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
#define USB_PID_ADSTECH_USB2_WARM 0xa334
+#define USB_PID_AFATECH_AF9005 0x9020
+#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -53,6 +59,7 @@
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
+#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
@@ -61,6 +68,9 @@
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
#define USB_PID_DIBCOM_STK7700P 0x1e14
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
+#define USB_PID_DIBCOM_STK7700D 0x1ef0
+#define USB_PID_DIBCOM_STK7070P 0x1ebc
+#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DPOSH_M9206_COLD 0x9206
#define USB_PID_DPOSH_M9206_WARM 0xa090
@@ -69,6 +79,7 @@
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
+#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
@@ -109,8 +120,17 @@
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
+#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
+#define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
+#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
+#define USB_PID_PINNACLE_PCTV2000E 0x022c
+#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
+#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
+#define USB_PID_PCTV_200E 0x020e
+#define USB_PID_PCTV_400E 0x020f
+#define USB_PID_PCTV_450E 0x0222
#define USB_PID_NEBULA_DIGITV 0x0201
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
@@ -130,9 +150,6 @@
#define USB_PID_MSI_MEGASKY580_55801 0x5581
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
-#define USB_PID_PCTV_200E 0x020e
-#define USB_PID_PCTV_400E 0x020f
-#define USB_PID_PCTV_450E 0x0222
#define USB_PID_LITEON_DVB_T_COLD 0xf000
#define USB_PID_LITEON_DVB_T_WARM 0xf001
#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360
@@ -142,8 +159,11 @@
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
-#define USB_PID_GENPIX_8PSK_COLD 0x0200
-#define USB_PID_GENPIX_8PSK_WARM 0x0201
+#define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
+#define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201
+#define USB_PID_GENPIX_8PSK_REV_2 0x0202
+#define USB_PID_GENPIX_SKYWALKER_1 0x0203
+#define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204
#define USB_PID_SIGMATEK_DVB_110 0x6610
#define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513
#define USB_PID_OPERA1_COLD 0x2830
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index ffdde83d1e77..cdd717c3fe45 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -24,7 +24,7 @@ MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0
static int dvb_usb_force_pid_filter_usage;
module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
-MODULE_PARM_DESC(disable_rc_polling, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
+MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
static int dvb_usb_adapter_init(struct dvb_usb_device *d)
{
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 9200a30dd1b9..7b9f35bfb4f0 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -110,7 +110,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
input_dev->name = "IR-receiver inside an USB DVB receiver";
input_dev->phys = d->rc_phys;
usb_to_input_id(d->udev, &input_dev->id);
- input_dev->cdev.dev = &d->udev->dev;
+ input_dev->dev.parent = &d->udev->dev;
/* set the bits for the keys */
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 6f824a569e14..d1b3c7b81fff 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -297,12 +297,6 @@ struct dvb_usb_adapter {
int feedcount;
int pid_filtering;
- /* tuner programming information */
- u8 pll_addr;
- u8 pll_init[4];
- struct dvb_pll_desc *pll_desc;
- int (*tuner_pass_ctrl) (struct dvb_frontend *, int, u8);
-
/* dvb */
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
@@ -388,11 +382,6 @@ extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
/* commonly used remote control parsing */
extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
-/* commonly used pll init and set functions */
-extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
-extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
-extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
-
/* commonly used firmware download types and function */
struct hexline {
u8 len;
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
index e0587e663591..f01d99c1c43c 100644
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -157,6 +157,7 @@ static int gl861_probe(struct usb_interface *intf,
static struct usb_device_id gl861_table [] = {
{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
+ { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, gl861_table);
@@ -187,12 +188,16 @@ static struct dvb_usb_device_properties gl861_properties = {
}},
.i2c_algo = &gl861_i2c_algo,
- .num_device_descs = 1,
+ .num_device_descs = 2,
.devices = {
{ "MSI Mega Sky 55801 DVB-T USB2.0",
{ &gl861_table[0], NULL },
{ NULL },
},
+ { "A-LINK DTU DVB-T USB2.0",
+ { &gl861_table[1], NULL },
+ { NULL },
+ },
}
};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index 6ccbdc9cd772..e37142d9271a 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -1,7 +1,8 @@
/* DVB USB compliant Linux driver for the
- * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
*
- * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
+ * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
*
* Thanks to GENPIX for the sample code used to implement this module.
*
@@ -17,27 +18,39 @@
struct gp8psk_fe_state {
struct dvb_frontend fe;
-
struct dvb_usb_device *d;
-
+ u8 lock;
u16 snr;
-
- unsigned long next_snr_check;
+ unsigned long next_status_check;
+ unsigned long status_check_interval;
};
+static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
+{
+ u8 buf[6];
+ if (time_after(jiffies,st->next_status_check)) {
+ gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1);
+ gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6);
+ st->snr = (buf[1]) << 8 | buf[0];
+ st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+ }
+ return 0;
+}
+
static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
{
struct gp8psk_fe_state *st = fe->demodulator_priv;
- u8 lock;
+ gp8psk_fe_update_status(st);
- if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
- return -EINVAL;
-
- if (lock)
+ if (st->lock)
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
else
*status = 0;
+ if (*status & FE_HAS_LOCK)
+ st->status_check_interval = 1000;
+ else
+ st->status_check_interval = 100;
return 0;
}
@@ -60,33 +73,29 @@ static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
{
struct gp8psk_fe_state *st = fe->demodulator_priv;
- u8 buf[2];
-
- if (time_after(jiffies,st->next_snr_check)) {
- gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
- *snr = (int)(buf[1]) << 8 | buf[0];
- /* snr is reported in dBu*256 */
- /* snr / 38.4 ~= 100% strength */
- /* snr * 17 returns 100% strength as 65535 */
- if (*snr <= 3855)
- *snr = (*snr<<4) + *snr; // snr * 17
- else
- *snr = 65535;
- st->next_snr_check = jiffies + (10*HZ)/1000;
- } else {
- *snr = st->snr;
- }
+ gp8psk_fe_update_status(st);
+ /* snr is reported in dBu*256 */
+ *snr = st->snr;
return 0;
}
static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
- return gp8psk_fe_read_snr(fe, strength);
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+ gp8psk_fe_update_status(st);
+ /* snr is reported in dBu*256 */
+ /* snr / 38.4 ~= 100% strength */
+ /* snr * 17 returns 100% strength as 65535 */
+ if (st->snr > 0xf00)
+ *strength = 0xffff;
+ else
+ *strength = (st->snr << 4) + st->snr; /* snr*17 */
+ return 0;
}
static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
{
- tune->min_delay_ms = 800;
+ tune->min_delay_ms = 200;
return 0;
}
@@ -124,7 +133,9 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
- state->next_snr_check = jiffies;
+ state->lock = 0;
+ state->next_status_check = jiffies;
+ state->status_check_interval = 200;
return 0;
}
@@ -190,6 +201,12 @@ static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t volt
return 0;
}
+static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff)
+{
+ struct gp8psk_fe_state* state = fe->demodulator_priv;
+ return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0);
+}
+
static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
{
struct gp8psk_fe_state* state = fe->demodulator_priv;
@@ -235,10 +252,10 @@ success:
static struct dvb_frontend_ops gp8psk_fe_ops = {
.info = {
- .name = "Genpix 8psk-USB DVB-S",
+ .name = "Genpix 8psk-to-USB2 DVB-S",
.type = FE_QPSK,
- .frequency_min = 950000,
- .frequency_max = 2150000,
+ .frequency_min = 800000,
+ .frequency_max = 2250000,
.frequency_stepsize = 100,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
@@ -269,4 +286,5 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
.set_tone = gp8psk_fe_set_tone,
.set_voltage = gp8psk_fe_set_voltage,
.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+ .enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage
};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 518d67fca5e8..92147ee3e14f 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -1,7 +1,8 @@
/* DVB USB compliant Linux driver for the
- * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
*
- * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
+ * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
*
* Thanks to GENPIX for the sample code used to implement this module.
*
@@ -40,7 +41,7 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
}
if (ret < 0 || ret != blen) {
- warn("usb in operation failed.");
+ warn("usb in %d operation failed.", req);
ret = -EIO;
} else
ret = 0;
@@ -97,10 +98,10 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
goto out_rel_fw;
- info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+ info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
ptr = fw->data;
- buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
while (ptr[0] != 0xff) {
u16 buflen = ptr[0] + 4;
@@ -129,25 +130,34 @@ out_rel_fw:
static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 status, buf;
+ int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
+
if (onoff) {
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
- if (! (status & 0x01)) /* started */
+ if (! (status & bm8pskStarted)) { /* started */
+ if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
+ gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
return -EINVAL;
+ }
- if (! (status & 0x02)) /* BCM4500 firmware loaded */
- if(gp8psk_load_bcm4500fw(d))
- return EINVAL;
+ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+ if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
+ if(gp8psk_load_bcm4500fw(d))
+ return EINVAL;
- if (! (status & 0x04)) /* LNB Power */
+ if (! (status & bmIntersilOn)) /* LNB Power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
&buf, 1))
return EINVAL;
- /* Set DVB mode */
- if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
- return -EINVAL;
- gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+ /* Set DVB mode to 1 */
+ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+ if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+ return EINVAL;
+ /* Abort possible TS (if previous tune crashed) */
+ if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
+ return EINVAL;
} else {
/* Turn off LNB power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
@@ -155,11 +165,28 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
/* Turn off 8psk power */
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
return -EINVAL;
-
+ if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
+ gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
}
return 0;
}
+int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
+{
+ u8 buf;
+ int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
+ /* Turn off 8psk power */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+ return -EINVAL;
+ /* Turn On 8psk power */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+ return -EINVAL;
+ /* load BCM4500 firmware */
+ if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+ if (gp8psk_load_bcm4500fw(d))
+ return EINVAL;
+ return 0;
+}
static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
@@ -177,12 +204,22 @@ static struct dvb_usb_device_properties gp8psk_properties;
static int gp8psk_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+ int ret;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+ if (ret == 0) {
+ info("found Genpix USB device pID = %x (hex)",
+ le16_to_cpu(udev->descriptor.idProduct));
+ }
+ return ret;
}
static struct usb_device_id gp8psk_usb_table [] = {
- { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
- { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) },
{ 0 },
};
MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
@@ -213,12 +250,24 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.generic_bulk_ctrl_endpoint = 0x01,
- .num_device_descs = 1,
+ .num_device_descs = 4,
.devices = {
- { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+ { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[0], NULL },
.warm_ids = { &gp8psk_usb_table[1], NULL },
},
+ { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
+ .cold_ids = { NULL },
+ .warm_ids = { &gp8psk_usb_table[2], NULL },
+ },
+ { .name = "Genpix SkyWalker-1 DVB-S receiver",
+ .cold_ids = { NULL },
+ .warm_ids = { &gp8psk_usb_table[3], NULL },
+ },
+ { .name = "Genpix SkyWalker-CW3K DVB-S receiver",
+ .cold_ids = { NULL },
+ .warm_ids = { &gp8psk_usb_table[4], NULL },
+ },
{ NULL },
}
};
@@ -253,6 +302,6 @@ module_init(gp8psk_usb_module_init);
module_exit(gp8psk_usb_module_exit);
MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
-MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
-MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S");
+MODULE_VERSION("1.1");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
index 3eba7061011c..e83a57506cfa 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.h
+++ b/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -1,7 +1,8 @@
/* DVB USB compliant Linux driver for the
- * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
*
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
*
* Thanks to GENPIX for the sample code used to implement this module.
*
@@ -30,21 +31,37 @@ extern int dvb_usb_gp8psk_debug;
#define TH_COMMAND_IN 0xC0
#define TH_COMMAND_OUT 0xC1
-/* command bytes */
-#define GET_8PSK_CONFIG 0x80
+/* gp8psk commands */
+
+#define GET_8PSK_CONFIG 0x80 /* in */
#define SET_8PSK_CONFIG 0x81
+#define I2C_WRITE 0x83
+#define I2C_READ 0x84
#define ARM_TRANSFER 0x85
#define TUNE_8PSK 0x86
-#define GET_SIGNAL_STRENGTH 0x87
+#define GET_SIGNAL_STRENGTH 0x87 /* in */
#define LOAD_BCM4500 0x88
-#define BOOT_8PSK 0x89
-#define START_INTERSIL 0x8A
+#define BOOT_8PSK 0x89 /* in */
+#define START_INTERSIL 0x8A /* in */
#define SET_LNB_VOLTAGE 0x8B
#define SET_22KHZ_TONE 0x8C
#define SEND_DISEQC_COMMAND 0x8D
#define SET_DVB_MODE 0x8E
#define SET_DN_SWITCH 0x8F
-#define GET_SIGNAL_LOCK 0x90
+#define GET_SIGNAL_LOCK 0x90 /* in */
+#define GET_SERIAL_NUMBER 0x93 /* in */
+#define USE_EXTRA_VOLT 0x94
+#define CW3K_INIT 0x9d
+
+/* PSK_configuration bits */
+#define bm8pskStarted 0x01
+#define bm8pskFW_Loaded 0x02
+#define bmIntersilOn 0x04
+#define bmDVBmode 0x08
+#define bm22kHz 0x10
+#define bmSEL18V 0x20
+#define bmDCtuned 0x40
+#define bmArmed 0x80
/* Satellite modulation modes */
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
@@ -75,5 +92,6 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen);
+extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
#endif
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index c546ddeda5d4..a956bc503a4c 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug;
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
+
static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
u16 index, void *data, int size)
{
@@ -57,7 +59,8 @@ static inline int m920x_write(struct usb_device *udev, u8 request,
static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
{
- int ret = 0;
+ int ret = 0, i, epi, flags = 0;
+ int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
/* Remote controller init. */
if (d->props.rc_query) {
@@ -76,9 +79,51 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
deb("Initialising remote control success\n");
}
+ for (i = 0; i < d->props.num_adapters; i++)
+ flags |= d->adapter[i].props.caps;
+
+ /* Some devices(Dposh) might crash if we attempt touch at all. */
+ if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
+ for (i = 0; i < d->props.num_adapters; i++) {
+ epi = d->adapter[i].props.stream.endpoint - 0x81;
+
+ if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
+ printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
+ return -EINVAL;
+ }
+
+ adap_enabled[epi] = 1;
+ }
+
+ for (i = 0; i < M9206_MAX_ADAPTERS; i++) {
+ if (adap_enabled[i])
+ continue;
+
+ if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0)
+ return ret;
+
+ if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0)
+ return ret;
+ }
+ }
+
return ret;
}
+static int m920x_init_ep(struct usb_interface *intf)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_host_interface *alt;
+
+ if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) {
+ deb("No alt found!\n");
+ return -ENODEV;
+ }
+
+ return usb_set_interface(udev, alt->desc.bInterfaceNumber,
+ alt->desc.bAlternateSetting);
+}
+
static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct m920x_state *m = d->priv;
@@ -211,8 +256,7 @@ static struct i2c_algorithm m920x_i2c_algo = {
};
/* pid filter */
-static int m920x_set_filter(struct dvb_usb_adapter *adap,
- int type, int idx, int pid)
+static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid)
{
int ret = 0;
@@ -221,10 +265,10 @@ static int m920x_set_filter(struct dvb_usb_adapter *adap,
pid |= 0x8000;
- if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
+ if ((ret = m920x_write(d->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
return ret;
- if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
+ if ((ret = m920x_write(d->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
return ret;
return ret;
@@ -233,40 +277,35 @@ static int m920x_set_filter(struct dvb_usb_adapter *adap,
static int m920x_update_filters(struct dvb_usb_adapter *adap)
{
struct m920x_state *m = adap->dev->priv;
- int enabled = m->filtering_enabled;
+ int enabled = m->filtering_enabled[adap->id];
int i, ret = 0, filter = 0;
+ int ep = adap->props.stream.endpoint;
for (i = 0; i < M9206_MAX_FILTERS; i++)
- if (m->filters[i] == 8192)
+ if (m->filters[adap->id][i] == 8192)
enabled = 0;
/* Disable all filters */
- if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0)
+ if ((ret = m920x_set_filter(adap->dev, ep, 1, enabled)) != 0)
return ret;
for (i = 0; i < M9206_MAX_FILTERS; i++)
- if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0)
+ if ((ret = m920x_set_filter(adap->dev, ep, i + 2, 0)) != 0)
return ret;
- if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0)
- return ret;
-
/* Set */
if (enabled) {
for (i = 0; i < M9206_MAX_FILTERS; i++) {
- if (m->filters[i] == 0)
+ if (m->filters[adap->id][i] == 0)
continue;
- if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
+ if ((ret = m920x_set_filter(adap->dev, ep, filter + 2, m->filters[adap->id][i])) != 0)
return ret;
filter++;
}
}
- if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
- return ret;
-
return ret;
}
@@ -274,7 +313,7 @@ static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct m920x_state *m = adap->dev->priv;
- m->filtering_enabled = onoff ? 1 : 0;
+ m->filtering_enabled[adap->id] = onoff ? 1 : 0;
return m920x_update_filters(adap);
}
@@ -283,7 +322,7 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in
{
struct m920x_state *m = adap->dev->priv;
- m->filters[index] = onoff ? pid : 0;
+ m->filters[adap->id][index] = onoff ? pid : 0;
return m920x_update_filters(adap);
}
@@ -368,6 +407,7 @@ static int m920x_identify_state(struct usb_device *udev,
/* demod configurations */
static int m920x_mt352_demod_init(struct dvb_frontend *fe)
{
+ int ret;
u8 config[] = { CONFIG, 0x3d };
u8 clock[] = { CLOCK_CTL, 0x30 };
u8 reset[] = { RESET, 0x80 };
@@ -377,17 +417,25 @@ static int m920x_mt352_demod_init(struct dvb_frontend *fe)
u8 unk1[] = { 0x93, 0x1a };
u8 unk2[] = { 0xb5, 0x7a };
- mt352_write(fe, config, ARRAY_SIZE(config));
- mt352_write(fe, clock, ARRAY_SIZE(clock));
- mt352_write(fe, reset, ARRAY_SIZE(reset));
- mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
- mt352_write(fe, agc, ARRAY_SIZE(agc));
- mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
- mt352_write(fe, unk1, ARRAY_SIZE(unk1));
- mt352_write(fe, unk2, ARRAY_SIZE(unk2));
-
deb("Demod init!\n");
+ if ((ret = mt352_write(fe, config, ARRAY_SIZE(config))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, clock, ARRAY_SIZE(clock))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, reset, ARRAY_SIZE(reset))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, agc, ARRAY_SIZE(agc))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, unk1, ARRAY_SIZE(unk1))) != 0)
+ return ret;
+ if ((ret = mt352_write(fe, unk2, ARRAY_SIZE(unk2))) != 0)
+ return ret;
+
return 0;
}
@@ -558,8 +606,7 @@ static struct dvb_usb_device_properties dposh_properties;
static int m920x_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct dvb_usb_device *d;
- struct usb_host_interface *alt;
+ struct dvb_usb_device *d = NULL;
int ret;
struct m920x_inits *rc_init_seq = NULL;
int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
@@ -604,23 +651,13 @@ static int m920x_probe(struct usb_interface *intf,
* tvwalkertwin_properties already configured both
* tuners, so there is nothing for us to do here
*/
-
- return -ENODEV;
}
found:
- alt = usb_altnum_to_altsetting(intf, 1);
- if (alt == NULL) {
- deb("No alt found!\n");
- return -ENODEV;
- }
-
- ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
- alt->desc.bAlternateSetting);
- if (ret < 0)
+ if ((ret = m920x_init_ep(intf)) < 0)
return ret;
- if ((ret = m920x_init(d, rc_init_seq)) != 0)
+ if (d && (ret = m920x_init(d, rc_init_seq)) != 0)
return ret;
return ret;
@@ -737,9 +774,9 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
*
* LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A
* TDA10046 #0 is located at i2c address 0x08
- * TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working)
+ * TDA10046 #1 is located at i2c address 0x0b
* TDA8275A #0 is located at i2c address 0x60
- * TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working)
+ * TDA8275A #1 is located at i2c address 0x61
*/
static struct dvb_usb_device_properties tvwalkertwin_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -756,7 +793,7 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
.size_of_priv = sizeof(struct m920x_state),
.identify_state = m920x_identify_state,
- .num_adapters = 1,
+ .num_adapters = 2,
.adapter = {{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
index 2c8942d04222..37532890accd 100644
--- a/drivers/media/dvb/dvb-usb/m920x.h
+++ b/drivers/media/dvb/dvb-usb/m920x.h
@@ -18,6 +18,7 @@
#define M9206_FW 0x30
#define M9206_MAX_FILTERS 8
+#define M9206_MAX_ADAPTERS 2
/*
sequences found in logs:
@@ -60,8 +61,8 @@ response to a write, is unknown.
*/
struct m920x_state {
- u16 filters[M9206_MAX_FILTERS];
- int filtering_enabled;
+ u16 filters[M9206_MAX_ADAPTERS][M9206_MAX_FILTERS];
+ int filtering_enabled[M9206_MAX_ADAPTERS];
int rep_count;
};
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 518d7ad217df..d7c04951ceab 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -263,7 +263,7 @@ static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(
dvb_pll_attach, adap->fe, 0xc0>>1,
- &adap->dev->i2c_adap, &dvb_pll_opera1
+ &adap->dev->i2c_adap, DVB_PLL_OPERA1
);
return 0;
}
@@ -435,9 +435,9 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
{
const struct firmware *fw = NULL;
u8 *b, *p;
- int ret = 0, i;
+ int ret = 0, i,fpgasize=40;
u8 testval;
- info("start downloading fpga firmware");
+ info("start downloading fpga firmware %s",filename);
if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
err("did not find the firmware file. (%s) "
@@ -454,17 +454,20 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
/* clear fpga ? */
opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1,
OPERA_WRITE_MSG);
- for (i = 0; p[i] != 0 && i < fw->size;) {
+ for (i = 0; i < fw->size;) {
+ if ( (fw->size - i) <fpgasize){
+ fpgasize=fw->size-i;
+ }
b = (u8 *) p + i;
if (opera1_xilinx_rw
- (dev, OPERA_WRITE_FX2, 0x0, b + 1, b[0],
- OPERA_WRITE_MSG) != b[0]
+ (dev, OPERA_WRITE_FX2, 0x0, b , fpgasize,
+ OPERA_WRITE_MSG) != fpgasize
) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
- i = i + 1 + b[0];
+ i = i + fpgasize;
}
/* restart the CPU */
if (ret || opera1_xilinx_rw
@@ -534,18 +537,16 @@ static struct dvb_usb_device_properties opera1_properties = {
static int opera1_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct dvb_usb_device *d;
struct usb_device *udev = interface_to_usbdev(intf);
if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM &&
udev->descriptor.idVendor == USB_VID_OPERA1 &&
- (d == NULL
- || opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga.fw") != 0)
- ) {
+ opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga-01.fw") != 0
+ ) {
return -EINVAL;
}
- if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, &d) != 0)
+ if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
return -EINVAL;
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index f77b48f76582..0dcab3d4e236 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -65,9 +65,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
static int umt_tuner_attach (struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x61;
- adap->pll_desc = &dvb_pll_tua6034;
- adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
return 0;
}
@@ -84,8 +82,8 @@ static int umt_probe(struct usb_interface *intf,
/* do not change the order of the ID table */
static struct usb_device_id umt_table [] = {
-/* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
-/* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
+/* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, umt_table);
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 69a46b3607a2..5bbd2d5192f0 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -159,7 +159,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
- for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
+ for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++)
if (vp7045_rc_keys[i].data == key) {
*state = REMOTE_KEY_PRESSED;
*event = vp7045_rc_keys[i].event;
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index ff448761dcef..59b9ed1f1aec 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -283,6 +283,14 @@ config DVB_LGDT330X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+config DVB_S5H1409
+ tristate "Samsung S5H1409 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
+
comment "Tuners/PLL support"
depends on DVB_CORE
@@ -291,7 +299,7 @@ config DVB_PLL
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
- This module driver a number of tuners based on PLL chips with a
+ This module drives a number of tuners based on PLL chips with a
common I2C interface. Say Y when you want to support these tuners.
config DVB_TDA826X
@@ -322,6 +330,29 @@ config DVB_TUNER_MT2060
help
A driver for the silicon IF tuner MT2060 from Microtune.
+config DVB_TUNER_MT2266
+ tristate "Microtune MT2266 silicon tuner"
+ depends on I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon baseband tuner MT2266 from Microtune.
+
+config DVB_TUNER_MT2131
+ tristate "Microtune MT2131 silicon tuner"
+ depends on I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon baseband tuner MT2131 from Microtune.
+
+config DVB_TUNER_DIB0070
+ tristate "DiBcom DiB0070 silicon base-band tuner"
+ depends on I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon baseband tuner DiB0070 from DiBcom.
+ This device is only used inside a SiP called togther with a
+ demodulator for now.
+
comment "Miscellaneous devices"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 27f386585d43..4b8ad1f132aa 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -2,7 +2,7 @@
# Makefile for the kernel DVB frontend device drivers.
#
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -40,5 +40,9 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TDA827X) += tda827x.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
+obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
+obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index baeb311de893..a913f49c062b 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -33,7 +33,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index 13ad1bfae663..11a4968f18cb 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -23,7 +23,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 335219ebce2d..1dc164d5488c 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -32,7 +32,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "cx22702.h"
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 10fc0c8316dd..b03d8283c37d 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 732e94aaa364..d74fdbd63361 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include "dvb_frontend.h"
@@ -917,7 +916,7 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
static int cx24123_tune(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
unsigned int mode_flags,
- int *delay,
+ unsigned int *delay,
fe_status_t *status)
{
int retval = 0;
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
new file mode 100644
index 000000000000..481eaa684157
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -0,0 +1,580 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; 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.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib0070.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0)
+
+#define DIB0070_P1D 0x00
+#define DIB0070_P1F 0x01
+#define DIB0070_P1G 0x03
+#define DIB0070S_P1A 0x02
+
+struct dib0070_state {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend *fe;
+ const struct dib0070_config *cfg;
+ u16 wbd_ff_offset;
+ u8 revision;
+};
+
+static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+{
+ u8 b[2];
+ struct i2c_msg msg[2] = {
+ { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
+ };
+ if (i2c_transfer(state->i2c, msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0070 I2C read failed\n");
+ return 0;
+ }
+ return (b[0] << 8) | b[1];
+}
+
+static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+{
+ u8 b[3] = { reg, val >> 8, val & 0xff };
+ struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0070 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+#define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0)
+
+static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+{
+ struct dib0070_state *st = fe->tuner_priv;
+ u16 tmp = 0;
+ tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
+
+ switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) {
+ case 8000:
+ tmp |= (0 << 14);
+ break;
+ case 7000:
+ tmp |= (1 << 14);
+ break;
+ case 6000:
+ tmp |= (2 << 14);
+ break;
+ case 5000:
+ default:
+ tmp |= (3 << 14);
+ break;
+ }
+ dib0070_write_reg(st, 0x02, tmp);
+ return 0;
+}
+
+static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
+{
+ int8_t captrim, fcaptrim, step_sign, step;
+ u16 adc, adc_diff = 3000;
+
+
+
+ dib0070_write_reg(st, 0x0f, 0xed10);
+ dib0070_write_reg(st, 0x17, 0x0034);
+
+ dib0070_write_reg(st, 0x18, 0x0032);
+ msleep(2);
+
+ step = captrim = fcaptrim = 64;
+
+ do {
+ step /= 2;
+ dib0070_write_reg(st, 0x14, LO4 | captrim);
+ msleep(1);
+ adc = dib0070_read_reg(st, 0x19);
+
+ dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024);
+
+ if (adc >= 400) {
+ adc -= 400;
+ step_sign = -1;
+ } else {
+ adc = 400 - adc;
+ step_sign = 1;
+ }
+
+ if (adc < adc_diff) {
+ dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff);
+ adc_diff = adc;
+ fcaptrim = captrim;
+
+
+
+ }
+ captrim += (step_sign * step);
+ } while (step >= 1);
+
+ dib0070_write_reg(st, 0x14, LO4 | fcaptrim);
+ dib0070_write_reg(st, 0x18, 0x07ff);
+}
+
+#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
+#define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7)
+#define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12)
+#define LO4_SET_CTRIM(l, c) l |= (c) << 10
+static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+{
+ struct dib0070_state *st = fe->tuner_priv;
+ u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf);
+
+ u8 band = BAND_OF_FREQUENCY(freq), c;
+
+ /*******************VCO***********************************/
+ u16 lo4 = 0;
+
+ u8 REFDIV, PRESC = 2;
+ u32 FBDiv, Rest, FREF, VCOF_kHz;
+ u16 Num, Den;
+ /*******************FrontEnd******************************/
+ u16 value = 0;
+
+ dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
+
+
+ dib0070_write_reg(st, 0x17, 0x30);
+
+ dib0070_set_bandwidth(fe, ch); /* c is used as HF */
+ switch (st->revision) {
+ case DIB0070S_P1A:
+ switch (band) {
+ case BAND_LBAND:
+ LO4_SET_VCO_HFDIV(lo4, 1, 1);
+ c = 2;
+ break;
+ case BAND_SBAND:
+ LO4_SET_VCO_HFDIV(lo4, 0, 0);
+ LO4_SET_CTRIM(lo4, 1);;
+ c = 1;
+ break;
+ case BAND_UHF:
+ default:
+ if (freq < 570000) {
+ LO4_SET_VCO_HFDIV(lo4, 1, 3);
+ PRESC = 6; c = 6;
+ } else if (freq < 680000) {
+ LO4_SET_VCO_HFDIV(lo4, 0, 2);
+ c = 4;
+ } else {
+ LO4_SET_VCO_HFDIV(lo4, 1, 2);
+ c = 4;
+ }
+ break;
+ } break;
+
+ case DIB0070_P1G:
+ case DIB0070_P1F:
+ default:
+ switch (band) {
+ case BAND_FM:
+ LO4_SET_VCO_HFDIV(lo4, 0, 7);
+ c = 24;
+ break;
+ case BAND_LBAND:
+ LO4_SET_VCO_HFDIV(lo4, 1, 0);
+ c = 2;
+ break;
+ case BAND_VHF:
+ if (freq < 180000) {
+ LO4_SET_VCO_HFDIV(lo4, 0, 3);
+ c = 16;
+ } else if (freq < 190000) {
+ LO4_SET_VCO_HFDIV(lo4, 1, 3);
+ c = 16;
+ } else {
+ LO4_SET_VCO_HFDIV(lo4, 0, 6);
+ c = 12;
+ }
+ break;
+
+ case BAND_UHF:
+ default:
+ if (freq < 570000) {
+ LO4_SET_VCO_HFDIV(lo4, 1, 5);
+ c = 6;
+ } else if (freq < 700000) {
+ LO4_SET_VCO_HFDIV(lo4, 0, 1);
+ c = 4;
+ } else {
+ LO4_SET_VCO_HFDIV(lo4, 1, 1);
+ c = 4;
+ }
+ break;
+ }
+ break;
+ }
+
+ dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf);
+ dprintk( "VCO = %hd", (lo4 >> 11) & 0x3);
+
+
+ VCOF_kHz = (c * freq) * 2;
+ dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq);
+
+ switch (band) {
+ case BAND_VHF:
+ REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
+ break;
+ case BAND_FM:
+ REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
+ break;
+ default:
+ REFDIV = (u8) ( st->cfg->clock_khz / 10000);
+ break;
+ }
+ FREF = st->cfg->clock_khz / REFDIV;
+
+ dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
+
+
+
+ switch (st->revision) {
+ case DIB0070S_P1A:
+ FBDiv = (VCOF_kHz / PRESC / FREF);
+ Rest = (VCOF_kHz / PRESC) - FBDiv * FREF;
+ break;
+
+ case DIB0070_P1G:
+ case DIB0070_P1F:
+ default:
+ FBDiv = (freq / (FREF / 2));
+ Rest = 2 * freq - FBDiv * FREF;
+ break;
+ }
+
+
+ if (Rest < LPF) Rest = 0;
+ else if (Rest < 2 * LPF) Rest = 2 * LPF;
+ else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
+ else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
+ Rest = (Rest * 6528) / (FREF / 10);
+ dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
+
+ Num = 0;
+ Den = 1;
+
+ if (Rest > 0) {
+ LO4_SET_SD(lo4, 1);
+ Den = 255;
+ Num = (u16)Rest;
+ }
+ dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
+
+
+
+ dib0070_write_reg(st, 0x11, (u16)FBDiv);
+
+
+ dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
+
+
+ dib0070_write_reg(st, 0x13, Num);
+
+
+ value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
+
+ switch (band) {
+ case BAND_UHF: value |= 0x4000 | 0x0800; break;
+ case BAND_LBAND: value |= 0x2000 | 0x0400; break;
+ default: value |= 0x8000 | 0x1000; break;
+ }
+ dib0070_write_reg(st, 0x20, value);
+
+ dib0070_captrim(st, lo4);
+ if (st->revision == DIB0070S_P1A) {
+ if (band == BAND_SBAND)
+ dib0070_write_reg(st, 0x15, 0x16e2);
+ else
+ dib0070_write_reg(st, 0x15, 0x56e5);
+ }
+
+
+
+ switch (band) {
+ case BAND_UHF: value = 0x7c82; break;
+ case BAND_LBAND: value = 0x7c84; break;
+ default: value = 0x7c81; break;
+ }
+ dib0070_write_reg(st, 0x0f, value);
+ dib0070_write_reg(st, 0x06, 0x3fff);
+
+ /* Front End */
+ /* c == TUNE, value = SWITCH */
+ c = 0;
+ value = 0;
+ switch (band) {
+ case BAND_FM:
+ c = 0; value = 1;
+ break;
+
+ case BAND_VHF:
+ if (freq <= 180000) c = 0;
+ else if (freq <= 188200) c = 1;
+ else if (freq <= 196400) c = 2;
+ else c = 3;
+ value = 1;
+ break;
+
+ case BAND_LBAND:
+ if (freq <= 1500000) c = 0;
+ else if (freq <= 1600000) c = 1;
+ else c = 3;
+ break;
+
+ case BAND_SBAND:
+ c = 7;
+ dib0070_write_reg(st, 0x1d,0xFFFF);
+ break;
+
+ case BAND_UHF:
+ default:
+ if (st->cfg->flip_chip) {
+ if (freq <= 550000) c = 0;
+ else if (freq <= 590000) c = 1;
+ else if (freq <= 666000) c = 3;
+ else c = 5;
+ } else {
+ if (freq <= 550000) c = 2;
+ else if (freq <= 650000) c = 3;
+ else if (freq <= 750000) c = 5;
+ else if (freq <= 850000) c = 6;
+ else c = 7;
+ }
+ value = 2;
+ break;
+ }
+
+ /* default: LNA_MATCH=7, BIAS=3 */
+ dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0));
+ dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127));
+ dib0070_write_reg(st, 0x0d, 0x0d80);
+
+
+ dib0070_write_reg(st, 0x18, 0x07ff);
+ dib0070_write_reg(st, 0x17, 0x0033);
+
+ return 0;
+}
+
+static int dib0070_wakeup(struct dvb_frontend *fe)
+{
+ struct dib0070_state *st = fe->tuner_priv;
+ if (st->cfg->sleep)
+ st->cfg->sleep(fe, 0);
+ return 0;
+}
+
+static int dib0070_sleep(struct dvb_frontend *fe)
+{
+ struct dib0070_state *st = fe->tuner_priv;
+ if (st->cfg->sleep)
+ st->cfg->sleep(fe, 1);
+ return 0;
+}
+
+static u16 dib0070_p1f_defaults[] =
+
+{
+ 7, 0x02,
+ 0x0008,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0002,
+ 0x0100,
+
+ 3, 0x0d,
+ 0x0d80,
+ 0x0001,
+ 0x0000,
+
+ 4, 0x11,
+ 0x0000,
+ 0x0103,
+ 0x0000,
+ 0x0000,
+
+ 3, 0x16,
+ 0x0004 | 0x0040,
+ 0x0030,
+ 0x07ff,
+
+ 6, 0x1b,
+ 0x4112,
+ 0xff00,
+ 0xc07f,
+ 0x0000,
+ 0x0180,
+ 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
+
+ 0,
+};
+
+static void dib0070_wbd_calibration(struct dib0070_state *state)
+{
+ u16 wbd_offs;
+ dib0070_write_reg(state, 0x0f, 0x6d81);
+ dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
+ msleep(9);
+ wbd_offs = dib0070_read_reg(state, 0x19);
+ dib0070_write_reg(state, 0x20, 0);
+ state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
+ dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
+}
+
+u16 dib0070_wbd_offset(struct dvb_frontend *fe)
+{
+ struct dib0070_state *st = fe->tuner_priv;
+ return st->wbd_ff_offset;
+}
+
+EXPORT_SYMBOL(dib0070_wbd_offset);
+static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
+{
+ struct dib0070_state *state = fe->tuner_priv;
+ u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+ dprintk( "CTRL_LO5: 0x%x", lo5);
+ return dib0070_write_reg(state, 0x15, lo5);
+}
+
+#define pgm_read_word(w) (*w)
+static int dib0070_reset(struct dib0070_state *state)
+{
+ u16 l, r, *n;
+
+ HARD_RESET(state);
+
+
+#ifndef FORCE_SBAND_TUNER
+ if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
+ state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
+ else
+#endif
+ state->revision = DIB0070S_P1A;
+
+ /* P1F or not */
+ dprintk( "Revision: %x", state->revision);
+
+ if (state->revision == DIB0070_P1D) {
+ dprintk( "Error: this driver is not to be used meant for P1D or earlier");
+ return -EINVAL;
+ }
+
+ n = (u16 *) dib0070_p1f_defaults;
+ l = pgm_read_word(n++);
+ while (l) {
+ r = pgm_read_word(n++);
+ do {
+ dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
+ r++;
+ } while (--l);
+ l = pgm_read_word(n++);
+ }
+
+ if (state->cfg->force_crystal_mode != 0)
+ r = state->cfg->force_crystal_mode;
+ else if (state->cfg->clock_khz >= 24000)
+ r = 1;
+ else
+ r = 2;
+
+ r |= state->cfg->osc_buffer_state << 3;
+
+ dib0070_write_reg(state, 0x10, r);
+ dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
+
+ if (state->cfg->invert_iq) {
+ r = dib0070_read_reg(state, 0x02) & 0xffdf;
+ dib0070_write_reg(state, 0x02, r | (1 << 5));
+ }
+
+
+ if (state->revision == DIB0070S_P1A)
+ dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1);
+ else
+ dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
+
+ dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
+ return 0;
+}
+
+
+static int dib0070_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static struct dvb_tuner_ops dib0070_ops = {
+ .info = {
+ .name = "DiBcom DiB0070",
+ .frequency_min = 45000000,
+ .frequency_max = 860000000,
+ .frequency_step = 1000,
+ },
+ .release = dib0070_release,
+
+ .init = dib0070_wakeup,
+ .sleep = dib0070_sleep,
+ .set_params = dib0070_tune_digital,
+// .get_frequency = dib0070_get_frequency,
+// .get_bandwidth = dib0070_get_bandwidth
+};
+
+struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
+{
+ struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
+ if (state == NULL)
+ return NULL;
+
+ state->cfg = cfg;
+ state->i2c = i2c;
+ state->fe = fe;
+ fe->tuner_priv = state;
+
+ if (dib0070_reset(state) != 0)
+ goto free_mem;
+
+ dib0070_wbd_calibration(state);
+
+ printk(KERN_INFO "DiB0070: successfully identified\n");
+ memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = state;
+ return fe;
+
+free_mem:
+ kfree(state);
+ fe->tuner_priv = NULL;
+ return NULL;
+}
+EXPORT_SYMBOL(dib0070_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
new file mode 100644
index 000000000000..786e37d33889
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -0,0 +1,44 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; 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.
+ */
+#ifndef DIB0070_H
+#define DIB0070_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
+
+struct dib0070_config {
+ u8 i2c_address;
+
+ /* tuner pins controlled externally */
+ int (*reset) (struct dvb_frontend *, int);
+ int (*sleep) (struct dvb_frontend *, int);
+
+ /* offset in kHz */
+ int freq_offset_khz_uhf;
+ int freq_offset_khz_vhf;
+
+ u8 osc_buffer_state; /* 0= normal, 1= tri-state */
+ u32 clock_khz;
+ u8 clock_pad_drive; /* (Drive + 1) * 2mA */
+
+ u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */
+
+ u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
+
+ u8 flip_chip;
+};
+
+extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
+extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
+extern u16 dib0070_wbd_offset(struct dvb_frontend *);
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index b6adea5ffeb8..136b9d2164d7 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -23,7 +23,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 054d7e6d9662..edae0be063f5 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -1,7 +1,7 @@
/*
* Driver for DiBcom DiB3000MC/P-demodulator.
*
- * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
*
* This code is partially based on the previous dib3000mc.c .
@@ -13,10 +13,6 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
-//#include <linux/init.h>
-//#include <linux/delay.h>
-//#include <linux/string.h>
-//#include <linux/slab.h>
#include "dvb_frontend.h"
@@ -26,7 +22,11 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
+static int buggy_sfn_workaround;
+module_param(buggy_sfn_workaround, int, 0644);
+MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
struct dib3000mc_state {
struct dvb_frontend demod;
@@ -42,6 +42,8 @@ struct dib3000mc_state {
fe_bandwidth_t current_bandwidth;
u16 dev_id;
+
+ u8 sfn_workaround_active :1;
};
static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
@@ -71,7 +73,6 @@ static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
}
-
static int dib3000mc_identify(struct dib3000mc_state *state)
{
u16 value;
@@ -92,7 +93,7 @@ static int dib3000mc_identify(struct dib3000mc_state *state)
return 0;
}
-static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
+static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
{
u32 timf;
@@ -103,7 +104,7 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw,
} else
timf = state->timf;
- timf *= (BW_INDEX_TO_KHZ(bw) / 1000);
+ timf *= (bw / 1000);
if (update_offset) {
s16 tim_offs = dib3000mc_read_word(state, 416);
@@ -111,17 +112,17 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw,
if (tim_offs & 0x2000)
tim_offs -= 0x4000;
- if (nfft == 0)
+ if (nfft == TRANSMISSION_MODE_2K)
tim_offs *= 4;
timf += tim_offs;
- state->timf = timf / (BW_INDEX_TO_KHZ(bw) / 1000);
+ state->timf = timf / (bw / 1000);
}
dprintk("timf: %d\n", timf);
- dib3000mc_write_word(state, 23, timf >> 16);
- dib3000mc_write_word(state, 24, timf & 0xffff);
+ dib3000mc_write_word(state, 23, (u16) (timf >> 16));
+ dib3000mc_write_word(state, 24, (u16) (timf ) & 0xffff);
return 0;
}
@@ -209,31 +210,30 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
return ret;
}
-static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
+static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
{
- struct dib3000mc_state *state = demod->demodulator_priv;
u16 bw_cfg[6] = { 0 };
u16 imp_bw_cfg[3] = { 0 };
u16 reg;
/* settings here are for 27.7MHz */
switch (bw) {
- case BANDWIDTH_8_MHZ:
+ case 8000:
bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000:
bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
break;
- case BANDWIDTH_6_MHZ:
+ case 6000:
bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
break;
- case 255 /* BANDWIDTH_5_MHZ */:
+ case 5000:
bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
break;
@@ -257,7 +257,7 @@ static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
// Timing configuration
- dib3000mc_set_timing(state, 0, bw, 0);
+ dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
return 0;
}
@@ -276,7 +276,7 @@ static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode,
for (i = 58; i < 87; i++)
dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
- if (nfft == 1) {
+ if (nfft == TRANSMISSION_MODE_8K) {
dib3000mc_write_word(state, 58, 0x3b);
dib3000mc_write_word(state, 84, 0x00);
dib3000mc_write_word(state, 85, 0x8200);
@@ -376,7 +376,7 @@ static int dib3000mc_init(struct dvb_frontend *demod)
// P_search_maxtrial=1
dib3000mc_write_word(state, 5, 1);
- dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+ dib3000mc_set_bandwidth(state, 8000);
// div_lock_mask
dib3000mc_write_word(state, 4, 0x814);
@@ -397,7 +397,7 @@ static int dib3000mc_init(struct dvb_frontend *demod)
dib3000mc_write_word(state, 180, 0x2FF0);
// Impulse noise configuration
- dib3000mc_set_impulse_noise(state, 0, 1);
+ dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
// output mode set-up
dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
@@ -423,13 +423,13 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
{
u16 cfg[4] = { 0 },reg;
switch (qam) {
- case 0:
+ case QPSK:
cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
break;
- case 1:
+ case QAM_16:
cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
break;
- case 2:
+ case QAM_64:
cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
break;
}
@@ -437,11 +437,11 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
dib3000mc_write_word(state, reg, cfg[reg - 129]);
}
-static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_frontend_parameters *ch, u16 seq)
{
- u16 tmp;
-
- dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
+ u16 value;
+ dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 0);
// if (boost)
// dib3000mc_write_word(state, 100, (11 << 6) + 6);
@@ -455,7 +455,7 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx
dib3000mc_write_word(state, 26, 0x6680);
dib3000mc_write_word(state, 29, 0x1273);
dib3000mc_write_word(state, 33, 5);
- dib3000mc_set_adp_cfg(state, 1);
+ dib3000mc_set_adp_cfg(state, QAM_16);
dib3000mc_write_word(state, 133, 15564);
dib3000mc_write_word(state, 12 , 0x0);
@@ -470,52 +470,98 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx
dib3000mc_write_word(state, 97,0);
dib3000mc_write_word(state, 98,0);
- dib3000mc_set_impulse_noise(state, 0, chan->nfft);
-
- tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
- dib3000mc_write_word(state, 0, tmp);
+ dib3000mc_set_impulse_noise(state, 0, ch->u.ofdm.transmission_mode);
+ value = 0;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+ }
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
+ case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
+ case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
+ default:
+ case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
+ }
+ switch (ch->u.ofdm.constellation) {
+ case QPSK: value |= (0 << 3); break;
+ case QAM_16: value |= (1 << 3); break;
+ default:
+ case QAM_64: value |= (2 << 3); break;
+ }
+ switch (HIERARCHY_1) {
+ case HIERARCHY_2: value |= 2; break;
+ case HIERARCHY_4: value |= 4; break;
+ default:
+ case HIERARCHY_1: value |= 1; break;
+ }
+ dib3000mc_write_word(state, 0, value);
dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
- tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
- if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
- tmp |= chan->vit_code_rate_hp << 1;
- else
- tmp |= chan->vit_code_rate_lp << 1;
- dib3000mc_write_word(state, 181, tmp);
+ value = 0;
+ if (ch->u.ofdm.hierarchy_information == 1)
+ value |= (1 << 4);
+ if (1 == 1)
+ value |= 1;
+ switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ case FEC_2_3: value |= (2 << 1); break;
+ case FEC_3_4: value |= (3 << 1); break;
+ case FEC_5_6: value |= (5 << 1); break;
+ case FEC_7_8: value |= (7 << 1); break;
+ default:
+ case FEC_1_2: value |= (1 << 1); break;
+ }
+ dib3000mc_write_word(state, 181, value);
- // diversity synchro delay
- tmp = dib3000mc_read_word(state, 180) & 0x000f;
- tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
- dib3000mc_write_word(state, 180, tmp);
+ // diversity synchro delay add 50% SFN margin
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_8K: value = 256; break;
+ case TRANSMISSION_MODE_2K:
+ default: value = 64; break;
+ }
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_16: value *= 2; break;
+ case GUARD_INTERVAL_1_8: value *= 4; break;
+ case GUARD_INTERVAL_1_4: value *= 8; break;
+ default:
+ case GUARD_INTERVAL_1_32: value *= 1; break;
+ }
+ value <<= 4;
+ value |= dib3000mc_read_word(state, 180) & 0x000f;
+ dib3000mc_write_word(state, 180, value);
// restart demod
- tmp = dib3000mc_read_word(state, 0);
- dib3000mc_write_word(state, 0, tmp | (1 << 9));
- dib3000mc_write_word(state, 0, tmp);
+ value = dib3000mc_read_word(state, 0);
+ dib3000mc_write_word(state, 0, value | (1 << 9));
+ dib3000mc_write_word(state, 0, value);
msleep(30);
- dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
+ dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->u.ofdm.transmission_mode);
}
-static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *chan)
{
struct dib3000mc_state *state = demod->demodulator_priv;
u16 reg;
// u32 val;
- struct dibx000_ofdm_channel fchan;
+ struct dvb_frontend_parameters schan;
- INIT_OFDM_CHANNEL(&fchan);
- fchan = *chan;
+ schan = *chan;
+ /* TODO what is that ? */
/* a channel for autosearch */
- fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
- fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
- fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
+ schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ schan.u.ofdm.constellation = QAM_64;
+ schan.u.ofdm.code_rate_HP = FEC_2_3;
+ schan.u.ofdm.code_rate_LP = FEC_2_3;
+ schan.u.ofdm.hierarchy_information = 0;
- dib3000mc_set_channel_cfg(state, &fchan, 11);
+ dib3000mc_set_channel_cfg(state, &schan, 11);
reg = dib3000mc_read_word(state, 0);
dib3000mc_write_word(state, 0, reg | (1 << 8));
@@ -539,7 +585,7 @@ static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
return 0; // still pending
}
-static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
struct dib3000mc_state *state = demod->demodulator_priv;
@@ -547,11 +593,17 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe
dib3000mc_set_channel_cfg(state, ch, 0);
// activates isi
- dib3000mc_write_word(state, 29, 0x1073);
-
- dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
+ if (state->sfn_workaround_active) {
+ dprintk("SFN workaround is active\n");
+ dib3000mc_write_word(state, 29, 0x1273);
+ dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
+ } else {
+ dib3000mc_write_word(state, 29, 0x1073);
+ dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
+ }
- if (ch->nfft == 1) {
+ dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation);
+ if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) {
dib3000mc_write_word(state, 26, 38528);
dib3000mc_write_word(state, 33, 8);
} else {
@@ -560,7 +612,7 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe
}
if (dib3000mc_read_word(state, 509) & 0x80)
- dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
+ dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 1);
return 0;
}
@@ -632,13 +684,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib3000mc_state *state = fe->demodulator_priv;
- struct dibx000_ofdm_channel ch;
-
- INIT_OFDM_CHANNEL(&ch);
- FEP2DIB(fep,&ch);
state->current_bandwidth = fep->u.ofdm.bandwidth;
- dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+ dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+
+ /* maybe the parameter has been changed */
+ state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fep);
@@ -651,7 +702,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
int i = 100, found;
- dib3000mc_autosearch_start(fe, &ch);
+ dib3000mc_autosearch_start(fe, fep);
do {
msleep(1);
found = dib3000mc_autosearch_is_irq(fe);
@@ -662,13 +713,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
return 0; // no channel found
dib3000mc_get_frontend(fe, fep);
- FEP2DIB(fep,&ch);
}
/* make this a config parameter */
dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return dib3000mc_tune(fe, &ch);
+ return dib3000mc_tune(fe, fep);
}
static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index f64546c6aeb5..fb18441a8c57 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -2,7 +2,7 @@
* Linux-DVB Driver for DiBcom's DiB7000M and
* first generation DiB7000P-demodulator-family.
*
- * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -19,7 +19,7 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0)
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
struct dib7000m_state {
struct dvb_frontend demod;
@@ -39,8 +39,16 @@ struct dib7000m_state {
fe_bandwidth_t current_bandwidth;
struct dibx000_agc_config *current_agc;
u32 timf;
+ u32 timf_default;
+ u32 internal_clk;
+
+ u8 div_force_off : 1;
+ u8 div_state : 1;
+ u16 div_sync_wait;
u16 revision;
+
+ u8 agc_state;
};
enum dib7000m_power_mode {
@@ -63,7 +71,7 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
};
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
- dprintk("i2c read error on %d\n",reg);
+ dprintk("i2c read error on %d",reg);
return (rb[0] << 8) | rb[1];
}
@@ -79,6 +87,25 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
};
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
}
+static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+{
+ u16 l = 0, r, *n;
+ n = buf;
+ l = *n++;
+ while (l) {
+ r = *n++;
+
+ if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
+ r++;
+
+ do {
+ dib7000m_write_word(state, r, *n++);
+ r++;
+ } while (--l);
+ l = *n++;
+ }
+}
+
static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
{
int ret = 0;
@@ -89,8 +116,7 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
fifo_threshold = 1792;
smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
- dprintk("-I- Setting output mode for demod %p to %d\n",
- &state->demod, mode);
+ dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
switch (mode) {
case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
@@ -117,7 +143,7 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
outreg = 0;
break;
default:
- dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+ dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
break;
}
@@ -129,13 +155,20 @@ static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
ret |= dib7000m_write_word(state, 1795, outreg);
ret |= dib7000m_write_word(state, 1805, sram);
+ if (state->revision == 0x4003) {
+ u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
+ if (mode == OUTMODE_DIVERSITY)
+ clk_cfg1 |= (1 << 1); // P_O_CLK_en
+ dib7000m_write_word(state, 909, clk_cfg1);
+ }
return ret;
}
-static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
+static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
{
/* by default everything is going to be powered off */
u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
+ u8 offset = 0;
/* now, depending on the requested mode, we power on */
switch (mode) {
@@ -170,16 +203,17 @@ static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_p
if (!state->cfg.mobile_mode)
reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
- /* P_sdio_select_clk = 0 on MC */
+ /* P_sdio_select_clk = 0 on MC and after*/
if (state->revision != 0x4000)
reg_906 <<= 1;
- dib7000m_write_word(state, 903, reg_903);
- dib7000m_write_word(state, 904, reg_904);
- dib7000m_write_word(state, 905, reg_905);
- dib7000m_write_word(state, 906, reg_906);
+ if (state->revision == 0x4003)
+ offset = 1;
- return 0;
+ dib7000m_write_word(state, 903 + offset, reg_903);
+ dib7000m_write_word(state, 904 + offset, reg_904);
+ dib7000m_write_word(state, 905 + offset, reg_905);
+ dib7000m_write_word(state, 906 + offset, reg_906);
}
static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
@@ -230,34 +264,55 @@ static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc
break;
}
-// dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914);
-
+// dprintk( "913: %x, 914: %x", reg_913, reg_914);
ret |= dib7000m_write_word(state, 913, reg_913);
ret |= dib7000m_write_word(state, 914, reg_914);
return ret;
}
-static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx)
+static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
{
- struct dib7000m_state *state = demod->demodulator_priv;
u32 timf;
// store the current bandwidth for later use
- state->current_bandwidth = bw_idx;
+ state->current_bandwidth = bw;
if (state->timf == 0) {
- dprintk("-D- Using default timf\n");
- timf = state->cfg.bw->timf;
+ dprintk( "using default timf");
+ timf = state->timf_default;
} else {
- dprintk("-D- Using updated timf\n");
+ dprintk( "using updated timf");
timf = state->timf;
}
- timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80;
+ timf = timf * (bw / 50) / 160;
- dib7000m_write_word(state, 23, (timf >> 16) & 0xffff);
- dib7000m_write_word(state, 24, (timf ) & 0xffff);
+ dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
+ dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
+
+ return 0;
+}
+
+static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+
+ if (state->div_force_off) {
+ dprintk( "diversity combination deactivated - forced by COFDM parameters");
+ onoff = 0;
+ }
+ state->div_state = (u8)onoff;
+
+ if (onoff) {
+ dib7000m_write_word(state, 263 + state->reg_offs, 6);
+ dib7000m_write_word(state, 264 + state->reg_offs, 6);
+ dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
+ } else {
+ dib7000m_write_word(state, 263 + state->reg_offs, 1);
+ dib7000m_write_word(state, 264 + state->reg_offs, 0);
+ dib7000m_write_word(state, 266 + state->reg_offs, 0);
+ }
return 0;
}
@@ -266,7 +321,7 @@ static int dib7000m_sad_calib(struct dib7000m_state *state)
{
/* internal */
-// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth
+// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
@@ -281,10 +336,10 @@ static int dib7000m_sad_calib(struct dib7000m_state *state)
static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
{
- dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
- dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff);
- dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff);
- dib7000m_write_word(state, 22, bw->ifreq & 0xffff);
+ dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
+ dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
+ dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
+ dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
dib7000m_write_word(state, 928, bw->sad_cfg);
}
@@ -325,15 +380,19 @@ static void dib7000m_reset_pll(struct dib7000m_state *state)
static void dib7000mc_reset_pll(struct dib7000m_state *state)
{
const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+ u16 clk_cfg1;
// clk_cfg0
dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
// clk_cfg1
//dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
- dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) |
+ clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
(bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
- (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0));
+ (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
+ dib7000m_write_word(state, 908, clk_cfg1);
+ clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
+ dib7000m_write_word(state, 908, clk_cfg1);
// smpl_cfg
dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
@@ -344,9 +403,6 @@ static void dib7000mc_reset_pll(struct dib7000m_state *state)
static int dib7000m_reset_gpio(struct dib7000m_state *st)
{
/* reset the GPIOs */
- dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",
- st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos);
-
dib7000m_write_word(st, 773, st->cfg.gpio_dir);
dib7000m_write_word(st, 774, st->cfg.gpio_val);
@@ -358,6 +414,107 @@ static int dib7000m_reset_gpio(struct dib7000m_state *st)
return 0;
}
+static u16 dib7000m_defaults_common[] =
+
+{
+ // auto search configuration
+ 3, 2,
+ 0x0004,
+ 0x1000,
+ 0x0814,
+
+ 12, 6,
+ 0x001b,
+ 0x7740,
+ 0x005b,
+ 0x8d80,
+ 0x01c9,
+ 0xc380,
+ 0x0000,
+ 0x0080,
+ 0x0000,
+ 0x0090,
+ 0x0001,
+ 0xd4c0,
+
+ 1, 26,
+ 0x6680, // P_corm_thres Lock algorithms configuration
+
+ 1, 170,
+ 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
+
+ 8, 173,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+
+ 1, 182,
+ 8192, // P_fft_nb_to_cut
+
+ 2, 195,
+ 0x0ccd, // P_pha3_thres
+ 0, // P_cti_use_cpe, P_cti_use_prog
+
+ 1, 205,
+ 0x200f, // P_cspu_regul, P_cspu_win_cut
+
+ 5, 214,
+ 0x023d, // P_adp_regul_cnt
+ 0x00a4, // P_adp_noise_cnt
+ 0x00a4, // P_adp_regul_ext
+ 0x7ff0, // P_adp_noise_ext
+ 0x3ccc, // P_adp_fil
+
+ 1, 226,
+ 0, // P_2d_byp_ti_num
+
+ 1, 255,
+ 0x800, // P_equal_thres_wgn
+
+ 1, 263,
+ 0x0001,
+
+ 1, 281,
+ 0x0010, // P_fec_*
+
+ 1, 294,
+ 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+
+ 0
+};
+
+static u16 dib7000m_defaults[] =
+
+{
+ /* set ADC level to -16 */
+ 11, 76,
+ (1 << 13) - 825 - 117,
+ (1 << 13) - 837 - 117,
+ (1 << 13) - 811 - 117,
+ (1 << 13) - 766 - 117,
+ (1 << 13) - 737 - 117,
+ (1 << 13) - 693 - 117,
+ (1 << 13) - 648 - 117,
+ (1 << 13) - 619 - 117,
+ (1 << 13) - 575 - 117,
+ (1 << 13) - 531 - 117,
+ (1 << 13) - 501 - 117,
+
+ // Tuner IO bank: max drive (14mA)
+ 1, 912,
+ 0x2c8a,
+
+ 1, 1817,
+ 1,
+
+ 0,
+};
+
static int dib7000m_demod_reset(struct dib7000m_state *state)
{
dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
@@ -382,22 +539,47 @@ static int dib7000m_demod_reset(struct dib7000m_state *state)
dib7000mc_reset_pll(state);
if (dib7000m_reset_gpio(state) != 0)
- dprintk("-E- GPIO reset was not successful.\n");
+ dprintk( "GPIO reset was not successful.");
if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
- dprintk("-E- OUTPUT_MODE could not be resetted.\n");
+ dprintk( "OUTPUT_MODE could not be reset.");
/* unforce divstr regardless whether i2c enumeration was done or not */
dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
- dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+ dib7000m_set_bandwidth(state, 8000);
dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
dib7000m_sad_calib(state);
dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+ if (state->cfg.dvbt_mode)
+ dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
+
+ if (state->cfg.mobile_mode)
+ dib7000m_write_word(state, 261 + state->reg_offs, 2);
+ else
+ dib7000m_write_word(state, 224 + state->reg_offs, 1);
+
+ // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
+ if(state->cfg.tuner_is_baseband)
+ dib7000m_write_word(state, 36, 0x0755);
+ else
+ dib7000m_write_word(state, 36, 0x1f55);
+
+ // P_divclksel=3 P_divbitsel=1
+ if (state->revision == 0x4000)
+ dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
+ else
+ dib7000m_write_word(state, 909, (3 << 4) | 1);
+
+ dib7000m_write_tab(state, dib7000m_defaults_common);
+ dib7000m_write_tab(state, dib7000m_defaults);
+
dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
+ state->internal_clk = state->cfg.bw->internal;
+
return 0;
}
@@ -427,7 +609,7 @@ static int dib7000m_agc_soft_split(struct dib7000m_state *state)
(agc - state->current_agc->split.min_thres) /
(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
- dprintk("AGC split_offset: %d\n",split_offset);
+ dprintk( "AGC split_offset: %d",split_offset);
// P_agc_force_split and P_agc_split_offset
return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
@@ -435,35 +617,26 @@ static int dib7000m_agc_soft_split(struct dib7000m_state *state)
static int dib7000m_update_lna(struct dib7000m_state *state)
{
- int i;
u16 dyn_gain;
- // when there is no LNA to program return immediatly
- if (state->cfg.update_lna == NULL)
- return 0;
-
- msleep(60);
- for (i = 0; i < 20; i++) {
- // read dyn_gain here (because it is demod-dependent and not tuner)
+ if (state->cfg.update_lna) {
+ // read dyn_gain here (because it is demod-dependent and not fe)
dyn_gain = dib7000m_read_word(state, 390);
- dprintk("agc global: %d\n", dyn_gain);
-
if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
dib7000m_restart_agc(state);
- msleep(60);
- } else
- break;
+ return 1;
+ }
}
return 0;
}
-static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
+static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
{
struct dibx000_agc_config *agc = NULL;
int i;
- if (state->current_band == band)
- return;
+ if (state->current_band == band && state->current_agc != NULL)
+ return 0;
state->current_band = band;
for (i = 0; i < state->cfg.agc_config_count; i++)
@@ -473,8 +646,8 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
}
if (agc == NULL) {
- dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band);
- return;
+ dprintk( "no valid AGC configuration found for band 0x%02x",band);
+ return -EINVAL;
}
state->current_agc = agc;
@@ -489,7 +662,7 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
- dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
+ dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
/* AGC continued */
@@ -510,7 +683,7 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
if (state->revision > 0x4000) { // settings for the MC
dib7000m_write_word(state, 71, agc->agc1_pt3);
-// dprintk("-D- 929: %x %d %d\n",
+// dprintk( "929: %x %d %d",
// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
} else {
@@ -519,33 +692,160 @@ static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
for (i = 0; i < 9; i++)
dib7000m_write_word(state, 88 + i, b[i]);
}
+ return 0;
}
-static void dib7000m_update_timf_freq(struct dib7000m_state *state)
+static void dib7000m_update_timf(struct dib7000m_state *state)
{
u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
- state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+ state->timf = timf * 160 / (state->current_bandwidth / 50);
dib7000m_write_word(state, 23, (u16) (timf >> 16));
dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
- dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+ dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
+}
+
+static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ u16 cfg_72 = dib7000m_read_word(state, 72);
+ int ret = -1;
+ u8 *agc_state = &state->agc_state;
+ u8 agc_split;
+
+ switch (state->agc_state) {
+ case 0:
+ // set power-up level: interf+analog+AGC
+ dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
+ dib7000m_set_adc_state(state, DIBX000_ADC_ON);
+
+ if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
+ return -1;
+
+ ret = 7; /* ADC power up */
+ (*agc_state)++;
+ break;
+
+ case 1:
+ /* AGC initialization */
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 1);
+
+ dib7000m_write_word(state, 75, 32768);
+ if (!state->current_agc->perform_agc_softsplit) {
+ /* we are using the wbd - so slow AGC startup */
+ dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
+ (*agc_state)++;
+ ret = 5;
+ } else {
+ /* default AGC startup */
+ (*agc_state) = 4;
+ /* wait AGC rough lock time */
+ ret = 7;
+ }
+
+ dib7000m_restart_agc(state);
+ break;
+
+ case 2: /* fast split search path after 5sec */
+ dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
+ dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
+ (*agc_state)++;
+ ret = 14;
+ break;
+
+ case 3: /* split search ended */
+ agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
+ dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
+
+ dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
+ dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
+
+ dib7000m_restart_agc(state);
+
+ dprintk( "SPLIT %p: %hd", demod, agc_split);
+
+ (*agc_state)++;
+ ret = 5;
+ break;
+
+ case 4: /* LNA startup */
+ /* wait AGC accurate lock time */
+ ret = 7;
+
+ if (dib7000m_update_lna(state))
+ // wait only AGC rough lock time
+ ret = 5;
+ else
+ (*agc_state)++;
+ break;
+
+ case 5:
+ dib7000m_agc_soft_split(state);
+
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 0);
+
+ (*agc_state)++;
+ break;
+
+ default:
+ break;
+ }
+ return ret;
}
-static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
{
u16 value, est[4];
- dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz));
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
/* nfft, guard, qam, alpha */
- dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+ value = 0;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
+ case /* 4K MODE */ 255: value |= (2 << 7); break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+ }
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
+ case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
+ case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
+ default:
+ case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
+ }
+ switch (ch->u.ofdm.constellation) {
+ case QPSK: value |= (0 << 3); break;
+ case QAM_16: value |= (1 << 3); break;
+ default:
+ case QAM_64: value |= (2 << 3); break;
+ }
+ switch (HIERARCHY_1) {
+ case HIERARCHY_2: value |= 2; break;
+ case HIERARCHY_4: value |= 4; break;
+ default:
+ case HIERARCHY_1: value |= 1; break;
+ }
+ dib7000m_write_word(state, 0, value);
dib7000m_write_word(state, 5, (seq << 4));
- /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
- value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
- if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
- value |= (ch->vit_code_rate_hp << 1);
- else
- value |= (ch->vit_code_rate_lp << 1);
+ /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
+ value = 0;
+ if (1 != 0)
+ value |= (1 << 6);
+ if (ch->u.ofdm.hierarchy_information == 1)
+ value |= (1 << 4);
+ if (1 == 1)
+ value |= 1;
+ switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ case FEC_2_3: value |= (2 << 1); break;
+ case FEC_3_4: value |= (3 << 1); break;
+ case FEC_5_6: value |= (5 << 1); break;
+ case FEC_7_8: value |= (7 << 1); break;
+ default:
+ case FEC_1_2: value |= (1 << 1); break;
+ }
dib7000m_write_word(state, 267 + state->reg_offs, value);
/* offset loop parameters */
@@ -563,32 +863,38 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_of
dib7000m_write_word(state, 33, (0 << 4) | 0x5);
/* P_dvsy_sync_wait */
- switch (ch->nfft) {
- case 1: value = 256; break;
- case 2: value = 128; break;
- case 0:
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_8K: value = 256; break;
+ case /* 4K MODE */ 255: value = 128; break;
+ case TRANSMISSION_MODE_2K:
default: value = 64; break;
}
- value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
- value <<= 4;
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_16: value *= 2; break;
+ case GUARD_INTERVAL_1_8: value *= 4; break;
+ case GUARD_INTERVAL_1_4: value *= 8; break;
+ default:
+ case GUARD_INTERVAL_1_32: value *= 1; break;
+ }
+ state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
/* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
- if (ch->intlv_native || state->revision > 0x4000)
- value |= (1 << 2) | (2 << 0);
+ if (1 == 1 || state->revision > 0x4000)
+ state->div_force_off = 0;
else
- value |= 0;
- dib7000m_write_word(state, 266 + state->reg_offs, value);
+ state->div_force_off = 1;
+ dib7000m_set_diversity_in(&state->demod, state->div_state);
/* channel estimation fine configuration */
- switch (ch->nqam) {
- case 2:
+ switch (ch->u.ofdm.constellation) {
+ case QAM_64:
est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
break;
- case 1:
+ case QAM_16:
est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
@@ -604,70 +910,48 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_of
for (value = 0; value < 4; value++)
dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
- // set power-up level: interf+analog+AGC
- dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
- dib7000m_set_adc_state(state, DIBX000_ADC_ON);
-
- msleep(7);
-
- //AGC initialization
- if (state->cfg.agc_control)
- state->cfg.agc_control(&state->demod, 1);
-
- dib7000m_restart_agc(state);
-
- // wait AGC rough lock time
- msleep(5);
-
- dib7000m_update_lna(state);
- dib7000m_agc_soft_split(state);
-
- // wait AGC accurate lock time
- msleep(7);
-
- if (state->cfg.agc_control)
- state->cfg.agc_control(&state->demod, 0);
-
// set power-up level: autosearch
dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
}
-static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
struct dib7000m_state *state = demod->demodulator_priv;
- struct dibx000_ofdm_channel auto_ch;
+ struct dvb_frontend_parameters schan;
int ret = 0;
- u32 value;
-
- INIT_OFDM_CHANNEL(&auto_ch);
- auto_ch.RF_kHz = ch->RF_kHz;
- auto_ch.Bw = ch->Bw;
- auto_ch.nqam = 2;
- auto_ch.guard = 0;
- auto_ch.nfft = 1;
- auto_ch.vit_alpha = 1;
- auto_ch.vit_select_hp = 1;
- auto_ch.vit_code_rate_hp = 2;
- auto_ch.vit_code_rate_lp = 3;
- auto_ch.vit_hrch = 0;
- auto_ch.intlv_native = 1;
-
- dib7000m_set_channel(state, &auto_ch, 7);
+ u32 value, factor;
+
+ schan = *ch;
+
+ schan.u.ofdm.constellation = QAM_64;
+ schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.u.ofdm.code_rate_HP = FEC_2_3;
+ schan.u.ofdm.code_rate_LP = FEC_3_4;
+ schan.u.ofdm.hierarchy_information = 0;
+
+ dib7000m_set_channel(state, &schan, 7);
+
+ factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
+ if (factor >= 5000)
+ factor = 1;
+ else
+ factor = 6;
// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
- value = 30 * state->cfg.bw->internal;
+ value = 30 * state->internal_clk * factor;
ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
- value = 100 * state->cfg.bw->internal;
+ value = 100 * state->internal_clk * factor;
ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
- value = 500 * state->cfg.bw->internal;
+ value = 500 * state->internal_clk * factor;
ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
// start search
value = dib7000m_read_word(state, 0);
- ret |= dib7000m_write_word(state, 0, value | (1 << 9));
+ ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
/* clear n_irq_pending */
if (state->revision == 0x4000)
@@ -685,12 +969,12 @@ static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
u16 irq_pending = dib7000m_read_word(state, reg);
if (irq_pending & 0x1) { // failed
- dprintk("#\n");
+ dprintk( "autosearch failed");
return 1;
}
if (irq_pending & 0x2) { // succeeded
- dprintk("!\n");
+ dprintk( "autosearch succeeded");
return 2;
}
return 0; // still pending
@@ -705,7 +989,7 @@ static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
return dib7000m_autosearch_irq(state, 537);
}
-static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
struct dib7000m_state *state = demod->demodulator_priv;
int ret = 0;
@@ -722,182 +1006,103 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel
ret |= dib7000m_write_word(state, 898, 0x0000);
msleep(45);
- ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
+ dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
- // never achieved a lock with that bandwidth so far - wait for timfreq to update
+ // never achieved a lock before - wait for timfreq to update
if (state->timf == 0)
msleep(200);
//dump_reg(state);
/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
value = (6 << 8) | 0x80;
- switch (ch->nfft) {
- case 0: value |= (7 << 12); break;
- case 1: value |= (9 << 12); break;
- case 2: value |= (8 << 12); break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
+ case /* 4K MODE */ 255: value |= (8 << 12); break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
}
ret |= dib7000m_write_word(state, 26, value);
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
value = (0 << 4);
- switch (ch->nfft) {
- case 0: value |= 0x6; break;
- case 1: value |= 0x8; break;
- case 2: value |= 0x7; break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= 0x6; break;
+ case /* 4K MODE */ 255: value |= 0x7; break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= 0x8; break;
}
ret |= dib7000m_write_word(state, 32, value);
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
value = (0 << 4);
- switch (ch->nfft) {
- case 0: value |= 0x6; break;
- case 1: value |= 0x8; break;
- case 2: value |= 0x7; break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= 0x6; break;
+ case /* 4K MODE */ 255: value |= 0x7; break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= 0x8; break;
}
ret |= dib7000m_write_word(state, 33, value);
- // we achieved a lock - it's time to update the osc freq
+ // we achieved a lock - it's time to update the timf freq
if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
- dib7000m_update_timf_freq(state);
+ dib7000m_update_timf(state);
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
return ret;
}
-static int dib7000m_init(struct dvb_frontend *demod)
+static int dib7000m_wakeup(struct dvb_frontend *demod)
{
struct dib7000m_state *state = demod->demodulator_priv;
- int ret = 0;
- u8 o = state->reg_offs;
dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
- dprintk("-E- could not start Slow ADC\n");
-
- if (state->cfg.dvbt_mode)
- dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
-
- if (state->cfg.mobile_mode)
- ret |= dib7000m_write_word(state, 261 + o, 2);
- else
- ret |= dib7000m_write_word(state, 224 + o, 1);
-
- ret |= dib7000m_write_word(state, 173 + o, 0);
- ret |= dib7000m_write_word(state, 174 + o, 0);
- ret |= dib7000m_write_word(state, 175 + o, 0);
- ret |= dib7000m_write_word(state, 176 + o, 0);
- ret |= dib7000m_write_word(state, 177 + o, 0);
- ret |= dib7000m_write_word(state, 178 + o, 0);
- ret |= dib7000m_write_word(state, 179 + o, 0);
- ret |= dib7000m_write_word(state, 180 + o, 0);
-
- // P_corm_thres Lock algorithms configuration
- ret |= dib7000m_write_word(state, 26, 0x6680);
-
- // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
- ret |= dib7000m_write_word(state, 170 + o, 0x0410);
- // P_fft_nb_to_cut
- ret |= dib7000m_write_word(state, 182 + o, 8192);
- // P_pha3_thres
- ret |= dib7000m_write_word(state, 195 + o, 0x0ccd);
- // P_cti_use_cpe, P_cti_use_prog
- ret |= dib7000m_write_word(state, 196 + o, 0);
- // P_cspu_regul, P_cspu_win_cut
- ret |= dib7000m_write_word(state, 205 + o, 0x200f);
- // P_adp_regul_cnt
- ret |= dib7000m_write_word(state, 214 + o, 0x023d);
- // P_adp_noise_cnt
- ret |= dib7000m_write_word(state, 215 + o, 0x00a4);
- // P_adp_regul_ext
- ret |= dib7000m_write_word(state, 216 + o, 0x00a4);
- // P_adp_noise_ext
- ret |= dib7000m_write_word(state, 217 + o, 0x7ff0);
- // P_adp_fil
- ret |= dib7000m_write_word(state, 218 + o, 0x3ccc);
-
- // P_2d_byp_ti_num
- ret |= dib7000m_write_word(state, 226 + o, 0);
-
- // P_fec_*
- ret |= dib7000m_write_word(state, 281 + o, 0x0010);
- // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
- ret |= dib7000m_write_word(state, 294 + o,0x0062);
-
- // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
- if(state->cfg.tuner_is_baseband)
- ret |= dib7000m_write_word(state, 36, 0x0755);
- else
- ret |= dib7000m_write_word(state, 36, 0x1f55);
-
- // auto search configuration
- ret |= dib7000m_write_word(state, 2, 0x0004);
- ret |= dib7000m_write_word(state, 3, 0x1000);
- ret |= dib7000m_write_word(state, 4, 0x0814);
- ret |= dib7000m_write_word(state, 6, 0x001b);
- ret |= dib7000m_write_word(state, 7, 0x7740);
- ret |= dib7000m_write_word(state, 8, 0x005b);
- ret |= dib7000m_write_word(state, 9, 0x8d80);
- ret |= dib7000m_write_word(state, 10, 0x01c9);
- ret |= dib7000m_write_word(state, 11, 0xc380);
- ret |= dib7000m_write_word(state, 12, 0x0000);
- ret |= dib7000m_write_word(state, 13, 0x0080);
- ret |= dib7000m_write_word(state, 14, 0x0000);
- ret |= dib7000m_write_word(state, 15, 0x0090);
- ret |= dib7000m_write_word(state, 16, 0x0001);
- ret |= dib7000m_write_word(state, 17, 0xd4c0);
- ret |= dib7000m_write_word(state, 263 + o,0x0001);
-
- // P_divclksel=3 P_divbitsel=1
- if (state->revision == 0x4000)
- dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
- else
- dib7000m_write_word(state, 909, (3 << 4) | 1);
-
- // Tuner IO bank: max drive (14mA)
- ret |= dib7000m_write_word(state, 912 ,0x2c8a);
+ dprintk( "could not start Slow ADC");
- ret |= dib7000m_write_word(state, 1817, 1);
-
- return ret;
+ return 0;
}
static int dib7000m_sleep(struct dvb_frontend *demod)
{
struct dib7000m_state *st = demod->demodulator_priv;
dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
- return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) |
- dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
+ dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
+ return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
}
static int dib7000m_identify(struct dib7000m_state *state)
{
u16 value;
+
if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
- dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value);
+ dprintk( "wrong Vendor ID (0x%x)",value);
return -EREMOTEIO;
}
state->revision = dib7000m_read_word(state, 897);
if (state->revision != 0x4000 &&
state->revision != 0x4001 &&
- state->revision != 0x4002) {
- dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value);
+ state->revision != 0x4002 &&
+ state->revision != 0x4003) {
+ dprintk( "wrong Device ID (0x%x)",value);
return -EREMOTEIO;
}
/* protect this driver to be used with 7000PC */
if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
- dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n");
+ dprintk( "this driver does not work with DiB7000PC");
return -EREMOTEIO;
}
switch (state->revision) {
- case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break;
- case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break;
- case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break;
+ case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
+ case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
+ case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
+ case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
}
return 0;
@@ -966,41 +1171,45 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000m_state *state = fe->demodulator_priv;
- struct dibx000_ofdm_channel ch;
-
- INIT_OFDM_CHANNEL(&ch);
- FEP2DIB(fep,&ch);
+ int time;
state->current_bandwidth = fep->u.ofdm.bandwidth;
- dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe, fep);
+ /* start up the AGC */
+ state->agc_state = 0;
+ do {
+ time = dib7000m_agc_startup(fe, fep);
+ if (time != -1)
+ msleep(time);
+ } while (time != -1);
+
if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
fep->u.ofdm.constellation == QAM_AUTO ||
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
int i = 800, found;
- dib7000m_autosearch_start(fe, &ch);
+ dib7000m_autosearch_start(fe, fep);
do {
msleep(1);
found = dib7000m_autosearch_is_irq(fe);
} while (found == 0 && i--);
- dprintk("autosearch returns: %d\n",found);
+ dprintk("autosearch returns: %d",found);
if (found == 0 || found == 1)
return 0; // no channel found
dib7000m_get_frontend(fe, fep);
- FEP2DIB(fep, &ch);
}
/* make this a config parameter */
dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return dib7000m_tune(fe, &ch);
+ return dib7000m_tune(fe, fep);
}
static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -1087,7 +1296,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
if (dib7000m_identify(&st) != 0) {
st.i2c_addr = default_addr;
if (dib7000m_identify(&st) != 0) {
- dprintk("DiB7000M #%d: not identified\n", k);
+ dprintk("DiB7000M #%d: not identified", k);
return -EIO;
}
}
@@ -1100,7 +1309,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
/* set new i2c address and force divstart */
dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
- dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+ dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
}
for (k = 0; k < no_of_demods; k++) {
@@ -1135,6 +1344,8 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
demod->demodulator_priv = st;
memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+ st->timf_default = cfg->bw->timf;
+
if (dib7000m_identify(st) != 0)
goto error;
@@ -1172,7 +1383,7 @@ static struct dvb_frontend_ops dib7000m_ops = {
.release = dib7000m_release,
- .init = dib7000m_init,
+ .init = dib7000m_wakeup,
.sleep = dib7000m_sleep,
.set_frontend = dib7000m_set_frontend,
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index aece458cfe12..f45bcfc51cf8 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -1,7 +1,7 @@
/*
* Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
*
- * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -18,7 +18,11 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0)
+static int buggy_sfn_workaround;
+module_param(buggy_sfn_workaround, int, 0644);
+MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
struct dib7000p_state {
struct dvb_frontend demod;
@@ -36,12 +40,21 @@ struct dib7000p_state {
struct dibx000_agc_config *current_agc;
u32 timf;
+ u8 div_force_off : 1;
+ u8 div_state : 1;
+ u16 div_sync_wait;
+
+ u8 agc_state;
+
u16 gpio_dir;
u16 gpio_val;
+
+ u8 sfn_workaround_active :1;
};
enum dib7000p_power_mode {
DIB7000P_POWER_ALL = 0,
+ DIB7000P_POWER_ANALOG_ADC,
DIB7000P_POWER_INTERFACE_ONLY,
};
@@ -55,7 +68,7 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
};
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
- dprintk("i2c read error on %d\n",reg);
+ dprintk("i2c read error on %d",reg);
return (rb[0] << 8) | rb[1];
}
@@ -71,6 +84,22 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
};
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
}
+static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf)
+{
+ u16 l = 0, r, *n;
+ n = buf;
+ l = *n++;
+ while (l) {
+ r = *n++;
+
+ do {
+ dib7000p_write_word(state, r, *n++);
+ r++;
+ } while (--l);
+ l = *n++;
+ }
+}
+
static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
{
int ret = 0;
@@ -80,7 +109,7 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
fifo_threshold = 1792;
smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1);
- dprintk("-I- Setting output mode for demod %p to %d\n",
+ dprintk( "setting output mode for demod %p to %d",
&state->demod, mode);
switch (mode) {
@@ -104,11 +133,14 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
fifo_threshold = 512;
outreg = (1 << 10) | (5 << 6);
break;
+ case OUTMODE_ANALOG_ADC:
+ outreg = (1 << 10) | (3 << 6);
+ break;
case OUTMODE_HIGH_Z: // disable
outreg = 0;
break;
default:
- dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+ dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
break;
}
@@ -122,6 +154,30 @@ static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
return ret;
}
+static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+
+ if (state->div_force_off) {
+ dprintk( "diversity combination deactivated - forced by COFDM parameters");
+ onoff = 0;
+ }
+ state->div_state = (u8)onoff;
+
+ if (onoff) {
+ dib7000p_write_word(state, 204, 6);
+ dib7000p_write_word(state, 205, 16);
+ /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+ dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
+ } else {
+ dib7000p_write_word(state, 204, 1);
+ dib7000p_write_word(state, 205, 0);
+ dib7000p_write_word(state, 207, 0);
+ }
+
+ return 0;
+}
+
static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
{
/* by default everything is powered off */
@@ -134,10 +190,21 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p
case DIB7000P_POWER_ALL:
reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
break;
+
+ case DIB7000P_POWER_ANALOG_ADC:
+ /* dem, cfg, iqc, sad, agc */
+ reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
+ /* nud */
+ reg_776 &= ~((1 << 0));
+ /* Dout */
+ reg_1280 &= ~((1 << 11));
+ /* fall through wanted to enable the interfaces */
+
/* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
break;
+
/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
}
@@ -188,34 +255,31 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad
break;
}
-// dprintk("908: %x, 909: %x\n", reg_908, reg_909);
+// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
dib7000p_write_word(state, 908, reg_908);
dib7000p_write_word(state, 909, reg_909);
}
-static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx)
+static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
{
- struct dib7000p_state *state = demod->demodulator_priv;
u32 timf;
// store the current bandwidth for later use
- state->current_bandwidth = BW_Idx;
+ state->current_bandwidth = bw;
if (state->timf == 0) {
- dprintk("-D- Using default timf\n");
+ dprintk( "using default timf");
timf = state->cfg.bw->timf;
} else {
- dprintk("-D- Using updated timf\n");
+ dprintk( "using updated timf");
timf = state->timf;
}
- timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80;
-
- dprintk("timf: %d\n",timf);
+ timf = timf * (bw / 50) / 160;
- dib7000p_write_word(state, 23, (timf >> 16) & 0xffff);
- dib7000p_write_word(state, 24, (timf ) & 0xffff);
+ dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
+ dib7000p_write_word(state, 24, (u16) ((timf ) & 0xffff));
return 0;
}
@@ -223,7 +287,7 @@ static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx)
static int dib7000p_sad_calib(struct dib7000p_state *state)
{
/* internal */
-// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth
+// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
@@ -236,18 +300,37 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
return 0;
}
+int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ if (value > 4095)
+ value = 4095;
+ state->wbd_ref = value;
+ return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
+}
+
+EXPORT_SYMBOL(dib7000p_set_wbd_ref);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
+ u16 clk_cfg0;
+
+ /* force PLL bypass */
+ clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
+ (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) |
+ (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
+ dib7000p_write_word(state, 900, clk_cfg0);
+
+ /* P_pll_cfg */
dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
- dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) |
- (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0));
+ clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
+ dib7000p_write_word(state, 900, clk_cfg0);
- dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
- dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff);
- dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff);
- dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff);
+ dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
+ dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000 ) & 0xffff));
+ dib7000p_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
+ dib7000p_write_word(state, 22, (u16) ( (bw->ifreq ) & 0xffff));
dib7000p_write_word(state, 72, bw->sad_cfg);
}
@@ -255,7 +338,7 @@ static void dib7000p_reset_pll(struct dib7000p_state *state)
static int dib7000p_reset_gpio(struct dib7000p_state *st)
{
/* reset the GPIOs */
- dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
+ dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
dib7000p_write_word(st, 1029, st->gpio_dir);
dib7000p_write_word(st, 1030, st->gpio_val);
@@ -268,6 +351,120 @@ static int dib7000p_reset_gpio(struct dib7000p_state *st)
return 0;
}
+static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
+{
+ st->gpio_dir = dib7000p_read_word(st, 1029);
+ st->gpio_dir &= ~(1 << num); /* reset the direction bit */
+ st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
+ dib7000p_write_word(st, 1029, st->gpio_dir);
+
+ st->gpio_val = dib7000p_read_word(st, 1030);
+ st->gpio_val &= ~(1 << num); /* reset the direction bit */
+ st->gpio_val |= (val & 0x01) << num; /* set the new value */
+ dib7000p_write_word(st, 1030, st->gpio_val);
+
+ return 0;
+}
+
+int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ return dib7000p_cfg_gpio(state, num, dir, val);
+}
+
+EXPORT_SYMBOL(dib7000p_set_gpio);
+static u16 dib7000p_defaults[] =
+
+{
+ // auto search configuration
+ 3, 2,
+ 0x0004,
+ 0x1000,
+ 0x0814, /* Equal Lock */
+
+ 12, 6,
+ 0x001b,
+ 0x7740,
+ 0x005b,
+ 0x8d80,
+ 0x01c9,
+ 0xc380,
+ 0x0000,
+ 0x0080,
+ 0x0000,
+ 0x0090,
+ 0x0001,
+ 0xd4c0,
+
+ 1, 26,
+ 0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
+
+ /* set ADC level to -16 */
+ 11, 79,
+ (1 << 13) - 825 - 117,
+ (1 << 13) - 837 - 117,
+ (1 << 13) - 811 - 117,
+ (1 << 13) - 766 - 117,
+ (1 << 13) - 737 - 117,
+ (1 << 13) - 693 - 117,
+ (1 << 13) - 648 - 117,
+ (1 << 13) - 619 - 117,
+ (1 << 13) - 575 - 117,
+ (1 << 13) - 531 - 117,
+ (1 << 13) - 501 - 117,
+
+ 1, 142,
+ 0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
+
+ /* disable power smoothing */
+ 8, 145,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+
+ 1, 154,
+ 1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0
+
+ 1, 168,
+ 0x0ccd, // P_pha3_thres, default 0x3000
+
+// 1, 169,
+// 0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
+
+ 1, 183,
+ 0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
+
+ 5, 187,
+ 0x023d, // P_adp_regul_cnt=573, default: 410
+ 0x00a4, // P_adp_noise_cnt=
+ 0x00a4, // P_adp_regul_ext
+ 0x7ff0, // P_adp_noise_ext
+ 0x3ccc, // P_adp_fil
+
+ 1, 198,
+ 0x800, // P_equal_thres_wgn
+
+ 1, 222,
+ 0x0010, // P_fec_ber_rs_len=2
+
+ 1, 235,
+ 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+
+ 2, 901,
+ 0x0006, // P_clk_cfg1
+ (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1
+
+ 1, 905,
+ 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive
+
+ 0,
+};
+
static int dib7000p_demod_reset(struct dib7000p_state *state)
{
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
@@ -292,111 +489,307 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
dib7000p_reset_pll(state);
if (dib7000p_reset_gpio(state) != 0)
- dprintk("-E- GPIO reset was not successful.\n");
+ dprintk( "GPIO reset was not successful.");
if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
- dprintk("-E- OUTPUT_MODE could not be resetted.\n");
+ dprintk( "OUTPUT_MODE could not be reset.");
/* unforce divstr regardless whether i2c enumeration was done or not */
dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
+ dib7000p_set_bandwidth(state, 8000);
+
+ dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+ dib7000p_sad_calib(state);
+ dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+
+ // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
+ if(state->cfg.tuner_is_baseband)
+ dib7000p_write_word(state, 36,0x0755);
+ else
+ dib7000p_write_word(state, 36,0x1f55);
+
+ dib7000p_write_tab(state, dib7000p_defaults);
+
dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+
return 0;
}
+static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
+{
+ u16 tmp = 0;
+ tmp = dib7000p_read_word(state, 903);
+ dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
+ tmp = dib7000p_read_word(state, 900);
+ dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
+}
+
static void dib7000p_restart_agc(struct dib7000p_state *state)
{
// P_restart_iqc & P_restart_agc
- dib7000p_write_word(state, 770, 0x0c00);
+ dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
dib7000p_write_word(state, 770, 0x0000);
}
-static void dib7000p_update_lna(struct dib7000p_state *state)
+static int dib7000p_update_lna(struct dib7000p_state *state)
{
- int i;
u16 dyn_gain;
// when there is no LNA to program return immediatly
- if (state->cfg.update_lna == NULL)
- return;
-
- for (i = 0; i < 5; i++) {
- // read dyn_gain here (because it is demod-dependent and not tuner)
+ if (state->cfg.update_lna) {
+ // read dyn_gain here (because it is demod-dependent and not fe)
dyn_gain = dib7000p_read_word(state, 394);
-
if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
dib7000p_restart_agc(state);
- msleep(5);
- } else
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
+{
+ struct dibx000_agc_config *agc = NULL;
+ int i;
+ if (state->current_band == band && state->current_agc != NULL)
+ return 0;
+ state->current_band = band;
+
+ for (i = 0; i < state->cfg.agc_config_count; i++)
+ if (state->cfg.agc[i].band_caps & band) {
+ agc = &state->cfg.agc[i];
break;
+ }
+
+ if (agc == NULL) {
+ dprintk( "no valid AGC configuration found for band 0x%02x",band);
+ return -EINVAL;
}
+
+ state->current_agc = agc;
+
+ /* AGC */
+ dib7000p_write_word(state, 75 , agc->setup );
+ dib7000p_write_word(state, 76 , agc->inv_gain );
+ dib7000p_write_word(state, 77 , agc->time_stabiliz );
+ dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
+
+ // Demod AGC loop configuration
+ dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
+ dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
+
+ /* AGC continued */
+ dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+ state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+ if (state->wbd_ref != 0)
+ dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
+ else
+ dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
+
+ dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
+
+ dib7000p_write_word(state, 107, agc->agc1_max);
+ dib7000p_write_word(state, 108, agc->agc1_min);
+ dib7000p_write_word(state, 109, agc->agc2_max);
+ dib7000p_write_word(state, 110, agc->agc2_min);
+ dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+ dib7000p_write_word(state, 112, agc->agc1_pt3);
+ dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+ dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+ dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+ return 0;
}
-static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
+static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
- u16 tmp = 0;
- tmp = dib7000p_read_word(state, 903);
- dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
- tmp = dib7000p_read_word(state, 900);
- dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
+ struct dib7000p_state *state = demod->demodulator_priv;
+ int ret = -1;
+ u8 *agc_state = &state->agc_state;
+ u8 agc_split;
+
+ switch (state->agc_state) {
+ case 0:
+ // set power-up level: interf+analog+AGC
+ dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+ dib7000p_set_adc_state(state, DIBX000_ADC_ON);
+ dib7000p_pll_clk_cfg(state);
+
+ if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
+ return -1;
+
+ ret = 7;
+ (*agc_state)++;
+ break;
+
+ case 1:
+ // AGC initialization
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 1);
+
+ dib7000p_write_word(state, 78, 32768);
+ if (!state->current_agc->perform_agc_softsplit) {
+ /* we are using the wbd - so slow AGC startup */
+ /* force 0 split on WBD and restart AGC */
+ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
+ (*agc_state)++;
+ ret = 5;
+ } else {
+ /* default AGC startup */
+ (*agc_state) = 4;
+ /* wait AGC rough lock time */
+ ret = 7;
+ }
+
+ dib7000p_restart_agc(state);
+ break;
+
+ case 2: /* fast split search path after 5sec */
+ dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
+ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
+ (*agc_state)++;
+ ret = 14;
+ break;
+
+ case 3: /* split search ended */
+ agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
+ dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
+
+ dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
+ dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
+
+ dib7000p_restart_agc(state);
+
+ dprintk( "SPLIT %p: %hd", demod, agc_split);
+
+ (*agc_state)++;
+ ret = 5;
+ break;
+
+ case 4: /* LNA startup */
+ // wait AGC accurate lock time
+ ret = 7;
+
+ if (dib7000p_update_lna(state))
+ // wait only AGC rough lock time
+ ret = 5;
+ else // nothing was done, go to the next state
+ (*agc_state)++;
+ break;
+
+ case 5:
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 0);
+ (*agc_state)++;
+ break;
+ default:
+ break;
+ }
+ return ret;
}
-static void dib7000p_update_timf_freq(struct dib7000p_state *state)
+static void dib7000p_update_timf(struct dib7000p_state *state)
{
u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
- state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+ state->timf = timf * 160 / (state->current_bandwidth / 50);
dib7000p_write_word(state, 23, (u16) (timf >> 16));
dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
- dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+ dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);
+
}
-static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
{
- u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208;
+ u16 value, est[4];
+
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
/* nfft, guard, qam, alpha */
- dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+ value = 0;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
+ case /* 4K MODE */ 255: value |= (2 << 7); break;
+ default:
+ case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+ }
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
+ case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
+ case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
+ default:
+ case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
+ }
+ switch (ch->u.ofdm.constellation) {
+ case QPSK: value |= (0 << 3); break;
+ case QAM_16: value |= (1 << 3); break;
+ default:
+ case QAM_64: value |= (2 << 3); break;
+ }
+ switch (HIERARCHY_1) {
+ case HIERARCHY_2: value |= 2; break;
+ case HIERARCHY_4: value |= 4; break;
+ default:
+ case HIERARCHY_1: value |= 1; break;
+ }
+ dib7000p_write_word(state, 0, value);
dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
- /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
- tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
- if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
- tmp |= (ch->vit_code_rate_hp << 1);
- else
- tmp |= (ch->vit_code_rate_lp << 1);
- dib7000p_write_word(state, 208, tmp);
+ /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
+ value = 0;
+ if (1 != 0)
+ value |= (1 << 6);
+ if (ch->u.ofdm.hierarchy_information == 1)
+ value |= (1 << 4);
+ if (1 == 1)
+ value |= 1;
+ switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ case FEC_2_3: value |= (2 << 1); break;
+ case FEC_3_4: value |= (3 << 1); break;
+ case FEC_5_6: value |= (5 << 1); break;
+ case FEC_7_8: value |= (7 << 1); break;
+ default:
+ case FEC_1_2: value |= (1 << 1); break;
+ }
+ dib7000p_write_word(state, 208, value);
+
+ /* offset loop parameters */
+ dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
+ dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
+ dib7000p_write_word(state, 29, 0x1273); // isi
+ dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
/* P_dvsy_sync_wait */
- switch (ch->nfft) {
- case 1: tmp = 256; break;
- case 2: tmp = 128; break;
- case 0:
- default: tmp = 64; break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_8K: value = 256; break;
+ case /* 4K MODE */ 255: value = 128; break;
+ case TRANSMISSION_MODE_2K:
+ default: value = 64; break;
}
- tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
- tmp <<= 4;
-
- /* deactive the possibility of diversity reception if extended interleave */
- /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
- if (ch->intlv_native || ch->nfft == 1)
- tmp |= (1 << 2) | (2 << 0);
- dib7000p_write_word(state, 207, tmp);
+ switch (ch->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_16: value *= 2; break;
+ case GUARD_INTERVAL_1_8: value *= 4; break;
+ case GUARD_INTERVAL_1_4: value *= 8; break;
+ default:
+ case GUARD_INTERVAL_1_32: value *= 1; break;
+ }
+ state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
- dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
- dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073
- dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
- dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
+ /* deactive the possibility of diversity reception if extended interleaver */
+ state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
+ dib7000p_set_diversity_in(&state->demod, state->div_state);
/* channel estimation fine configuration */
- switch (ch->nqam) {
- case 2:
+ switch (ch->u.ofdm.constellation) {
+ case QAM_64:
est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
break;
- case 1:
+ case QAM_16:
est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
@@ -409,66 +802,45 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_of
est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
break;
}
- for (tmp = 0; tmp < 4; tmp++)
- dib7000p_write_word(state, 187 + tmp, est[tmp]);
-
- // set power-up level: interf+analog+AGC
- dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
- dib7000p_set_adc_state(state, DIBX000_ADC_ON);
- dib7000p_pll_clk_cfg(state);
- msleep(7);
-
- // AGC initialization
- if (state->cfg.agc_control)
- state->cfg.agc_control(&state->demod, 1);
-
- dib7000p_restart_agc(state);
-
- // wait AGC rough lock time
- msleep(5);
-
- dib7000p_update_lna(state);
-
- // wait AGC accurate lock time
- msleep(7);
- if (state->cfg.agc_control)
- state->cfg.agc_control(&state->demod, 0);
+ for (value = 0; value < 4; value++)
+ dib7000p_write_word(state, 187 + value, est[value]);
}
-static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
struct dib7000p_state *state = demod->demodulator_priv;
- struct dibx000_ofdm_channel auto_ch;
- u32 value;
-
- INIT_OFDM_CHANNEL(&auto_ch);
- auto_ch.RF_kHz = ch->RF_kHz;
- auto_ch.Bw = ch->Bw;
- auto_ch.nqam = 2;
- auto_ch.guard = 0;
- auto_ch.nfft = 1;
- auto_ch.vit_alpha = 1;
- auto_ch.vit_select_hp = 1;
- auto_ch.vit_code_rate_hp = 2;
- auto_ch.vit_code_rate_lp = 3;
- auto_ch.vit_hrch = 0;
- auto_ch.intlv_native = 1;
-
- dib7000p_set_channel(state, &auto_ch, 7);
+ struct dvb_frontend_parameters schan;
+ u32 value, factor;
+
+ schan = *ch;
+ schan.u.ofdm.constellation = QAM_64;
+ schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.u.ofdm.code_rate_HP = FEC_2_3;
+ schan.u.ofdm.code_rate_LP = FEC_3_4;
+ schan.u.ofdm.hierarchy_information = 0;
+
+ dib7000p_set_channel(state, &schan, 7);
+
+ factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
+ if (factor >= 5000)
+ factor = 1;
+ else
+ factor = 6;
// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
- value = 30 * state->cfg.bw->internal;
+ value = 30 * state->cfg.bw->internal * factor;
dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
- value = 100 * state->cfg.bw->internal;
+ value = 100 * state->cfg.bw->internal * factor;
dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
- value = 500 * state->cfg.bw->internal;
+ value = 500 * state->cfg.bw->internal * factor;
dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
value = dib7000p_read_word(state, 0);
- dib7000p_write_word(state, 0, (1 << 9) | value);
+ dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
dib7000p_read_word(state, 1284);
dib7000p_write_word(state, 0, (u16) value);
@@ -489,7 +861,95 @@ static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
return 0; // still pending
}
-static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
+{
+ static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392};
+ static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
+ 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
+ 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
+ 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
+ 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
+ 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
+ 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
+ 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
+ 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
+ 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
+ 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
+ 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
+ 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
+ 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255};
+
+ u32 xtal = state->cfg.bw->xtal_hz / 1000;
+ int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz;
+ int k;
+ int coef_re[8],coef_im[8];
+ int bw_khz = bw;
+ u32 pha;
+
+ dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
+
+
+ if (f_rel < -bw_khz/2 || f_rel > bw_khz/2)
+ return;
+
+ bw_khz /= 100;
+
+ dib7000p_write_word(state, 142 ,0x0610);
+
+ for (k = 0; k < 8; k++) {
+ pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff;
+
+ if (pha==0) {
+ coef_re[k] = 256;
+ coef_im[k] = 0;
+ } else if(pha < 256) {
+ coef_re[k] = sine[256-(pha&0xff)];
+ coef_im[k] = sine[pha&0xff];
+ } else if (pha == 256) {
+ coef_re[k] = 0;
+ coef_im[k] = 256;
+ } else if (pha < 512) {
+ coef_re[k] = -sine[pha&0xff];
+ coef_im[k] = sine[256 - (pha&0xff)];
+ } else if (pha == 512) {
+ coef_re[k] = -256;
+ coef_im[k] = 0;
+ } else if (pha < 768) {
+ coef_re[k] = -sine[256-(pha&0xff)];
+ coef_im[k] = -sine[pha&0xff];
+ } else if (pha == 768) {
+ coef_re[k] = 0;
+ coef_im[k] = -256;
+ } else {
+ coef_re[k] = sine[pha&0xff];
+ coef_im[k] = -sine[256 - (pha&0xff)];
+ }
+
+ coef_re[k] *= notch[k];
+ coef_re[k] += (1<<14);
+ if (coef_re[k] >= (1<<24))
+ coef_re[k] = (1<<24) - 1;
+ coef_re[k] /= (1<<15);
+
+ coef_im[k] *= notch[k];
+ coef_im[k] += (1<<14);
+ if (coef_im[k] >= (1<<24))
+ coef_im[k] = (1<<24)-1;
+ coef_im[k] /= (1<<15);
+
+ dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
+
+ dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
+ dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
+ dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
+ }
+ dib7000p_write_word(state,143 ,0);
+}
+
+static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
{
struct dib7000p_state *state = demod->demodulator_priv;
u16 tmp = 0;
@@ -505,7 +965,15 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel
msleep(45);
/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
- dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+ tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
+ if (state->sfn_workaround_active) {
+ dprintk( "SFN workaround is active");
+ tmp |= (1 << 9);
+ dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift
+ } else {
+ dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift
+ }
+ dib7000p_write_word(state, 29, tmp);
// never achieved a lock with that bandwidth so far - wait for osc-freq to update
if (state->timf == 0)
@@ -515,28 +983,31 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel
/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
tmp = (6 << 8) | 0x80;
- switch (ch->nfft) {
- case 0: tmp |= (7 << 12); break;
- case 1: tmp |= (9 << 12); break;
- case 2: tmp |= (8 << 12); break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
+ case /* 4K MODE */ 255: tmp |= (8 << 12); break;
+ default:
+ case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
}
dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
tmp = (0 << 4);
- switch (ch->nfft) {
- case 0: tmp |= 0x6; break;
- case 1: tmp |= 0x8; break;
- case 2: tmp |= 0x7; break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
+ case /* 4K MODE */ 255: tmp |= 0x7; break;
+ default:
+ case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
}
dib7000p_write_word(state, 32, tmp);
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
tmp = (0 << 4);
- switch (ch->nfft) {
- case 0: tmp |= 0x6; break;
- case 1: tmp |= 0x8; break;
- case 2: tmp |= 0x7; break;
+ switch (ch->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
+ case /* 4K MODE */ 255: tmp |= 0x7; break;
+ default:
+ case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
}
dib7000p_write_word(state, 33, tmp);
@@ -552,131 +1023,21 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel
// we achieved a lock - it's time to update the osc freq
if ((tmp >> 6) & 0x1)
- dib7000p_update_timf_freq(state);
+ dib7000p_update_timf(state);
+ if (state->cfg.spur_protect)
+ dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
return 0;
}
-static int dib7000p_init(struct dvb_frontend *demod)
+static int dib7000p_wakeup(struct dvb_frontend *demod)
{
- struct dibx000_agc_config *agc;
struct dib7000p_state *state = demod->demodulator_priv;
- int ret = 0;
-
- // Demodulator default configuration
- agc = state->cfg.agc;
-
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-
- /* AGC */
- ret |= dib7000p_write_word(state, 75 , agc->setup );
- ret |= dib7000p_write_word(state, 76 , agc->inv_gain );
- ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz );
- ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
-
- // Demod AGC loop configuration
- ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
- ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
-
- /* AGC continued */
- dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
- state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
-
- if (state->wbd_ref != 0)
- ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
- else
- ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
-
- ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
-
- ret |= dib7000p_write_word(state, 107, agc->agc1_max);
- ret |= dib7000p_write_word(state, 108, agc->agc1_min);
- ret |= dib7000p_write_word(state, 109, agc->agc2_max);
- ret |= dib7000p_write_word(state, 110, agc->agc2_min);
- ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
- ret |= dib7000p_write_word(state, 112, agc->agc1_pt3);
- ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
- ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
- ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
-
- /* disable power smoothing */
- ret |= dib7000p_write_word(state, 145, 0);
- ret |= dib7000p_write_word(state, 146, 0);
- ret |= dib7000p_write_word(state, 147, 0);
- ret |= dib7000p_write_word(state, 148, 0);
- ret |= dib7000p_write_word(state, 149, 0);
- ret |= dib7000p_write_word(state, 150, 0);
- ret |= dib7000p_write_word(state, 151, 0);
- ret |= dib7000p_write_word(state, 152, 0);
-
- // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
- ret |= dib7000p_write_word(state, 26 ,0x6680);
-
- // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
- ret |= dib7000p_write_word(state, 142,0x0410);
- // P_fft_freq_dir=1, P_fft_nb_to_cut=0
- ret |= dib7000p_write_word(state, 154,1 << 13);
- // P_pha3_thres, default 0x3000
- ret |= dib7000p_write_word(state, 168,0x0ccd);
- // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
- //ret |= dib7000p_write_word(state, 169,0x0010);
- // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
- ret |= dib7000p_write_word(state, 183,0x200f);
- // P_adp_regul_cnt=573, default: 410
- ret |= dib7000p_write_word(state, 187,0x023d);
- // P_adp_noise_cnt=
- ret |= dib7000p_write_word(state, 188,0x00a4);
- // P_adp_regul_ext
- ret |= dib7000p_write_word(state, 189,0x00a4);
- // P_adp_noise_ext
- ret |= dib7000p_write_word(state, 190,0x7ff0);
- // P_adp_fil
- ret |= dib7000p_write_word(state, 191,0x3ccc);
-
- ret |= dib7000p_write_word(state, 222,0x0010);
- // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
- ret |= dib7000p_write_word(state, 235,0x0062);
-
- // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
- if(state->cfg.tuner_is_baseband)
- ret |= dib7000p_write_word(state, 36,0x0755);
- else
- ret |= dib7000p_write_word(state, 36,0x1f55);
-
- // auto search configuration
- ret |= dib7000p_write_word(state, 2 ,0x0004);
- ret |= dib7000p_write_word(state, 3 ,0x1000);
-
- /* Equal Lock */
- ret |= dib7000p_write_word(state, 4 ,0x0814);
-
- ret |= dib7000p_write_word(state, 6 ,0x001b);
- ret |= dib7000p_write_word(state, 7 ,0x7740);
- ret |= dib7000p_write_word(state, 8 ,0x005b);
- ret |= dib7000p_write_word(state, 9 ,0x8d80);
- ret |= dib7000p_write_word(state, 10 ,0x01c9);
- ret |= dib7000p_write_word(state, 11 ,0xc380);
- ret |= dib7000p_write_word(state, 12 ,0x0000);
- ret |= dib7000p_write_word(state, 13 ,0x0080);
- ret |= dib7000p_write_word(state, 14 ,0x0000);
- ret |= dib7000p_write_word(state, 15 ,0x0090);
- ret |= dib7000p_write_word(state, 16 ,0x0001);
- ret |= dib7000p_write_word(state, 17 ,0xd4c0);
-
- // P_clk_cfg1
- ret |= dib7000p_write_word(state, 901, 0x0006);
-
- // P_divclksel=3 P_divbitsel=1
- ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
-
- // Tuner IO bank: max drive (14mA) + divout pads max drive
- ret |= dib7000p_write_word(state, 905, 0x2c8e);
-
- ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
- dib7000p_sad_calib(state);
-
- return ret;
+ return 0;
}
static int dib7000p_sleep(struct dvb_frontend *demod)
@@ -688,16 +1049,16 @@ static int dib7000p_sleep(struct dvb_frontend *demod)
static int dib7000p_identify(struct dib7000p_state *st)
{
u16 value;
- dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n",
+ dprintk( "checking demod on I2C address: %d (%x)",
st->i2c_addr, st->i2c_addr);
if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
- dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value);
+ dprintk( "wrong Vendor ID (read=0x%x)",value);
return -EREMOTEIO;
}
if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
- dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value);
+ dprintk( "wrong Device ID (%x)",value);
return -EREMOTEIO;
}
@@ -767,41 +1128,48 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000p_state *state = fe->demodulator_priv;
- struct dibx000_ofdm_channel ch;
-
- INIT_OFDM_CHANNEL(&ch);
- FEP2DIB(fep,&ch);
+ int time;
state->current_bandwidth = fep->u.ofdm.bandwidth;
- dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+
+ /* maybe the parameter has been changed */
+ state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe, fep);
+ /* start up the AGC */
+ state->agc_state = 0;
+ do {
+ time = dib7000p_agc_startup(fe, fep);
+ if (time != -1)
+ msleep(time);
+ } while (time != -1);
+
if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
fep->u.ofdm.constellation == QAM_AUTO ||
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
int i = 800, found;
- dib7000p_autosearch_start(fe, &ch);
+ dib7000p_autosearch_start(fe, fep);
do {
msleep(1);
found = dib7000p_autosearch_is_irq(fe);
} while (found == 0 && i--);
- dprintk("autosearch returns: %d\n",found);
+ dprintk("autosearch returns: %d",found);
if (found == 0 || found == 1)
return 0; // no channel found
dib7000p_get_frontend(fe, fep);
- FEP2DIB(fep, &ch);
}
/* make this a config parameter */
dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return dib7000p_tune(fe, &ch);
+ return dib7000p_tune(fe, fep);
}
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -879,7 +1247,7 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
if (i2c_transfer(i2c_adap, msg, 2) == 2)
if (rx[0] == 0x01 && rx[1] == 0xb3) {
- dprintk("-D- DiB7000PC detected\n");
+ dprintk("-D- DiB7000PC detected");
return 1;
}
@@ -887,11 +1255,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
if (i2c_transfer(i2c_adap, msg, 2) == 2)
if (rx[0] == 0x01 && rx[1] == 0xb3) {
- dprintk("-D- DiB7000PC detected\n");
+ dprintk("-D- DiB7000PC detected");
return 1;
}
- dprintk("-D- DiB7000PC not detected\n");
+ dprintk("-D- DiB7000PC not detected");
return 0;
}
EXPORT_SYMBOL(dib7000pc_detection);
@@ -929,7 +1297,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
/* set new i2c address and force divstart */
dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);
- dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+ dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
}
for (k = 0; k < no_of_demods; k++) {
@@ -1000,7 +1368,7 @@ static struct dvb_frontend_ops dib7000p_ops = {
.release = dib7000p_release,
- .init = dib7000p_init,
+ .init = dib7000p_wakeup,
.sleep = dib7000p_sleep,
.set_frontend = dib7000p_set_frontend,
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 79465cf1aced..eefcac8b5244 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -9,6 +9,7 @@ struct dib7000p_config {
u8 tuner_is_baseband;
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+ u8 agc_config_count;
struct dibx000_agc_config *agc;
struct dibx000_bandwidth_config *bw;
@@ -27,20 +28,19 @@ struct dib7000p_config {
u8 quartz_direct;
+ u8 spur_protect;
+
int (*agc_control) (struct dvb_frontend *, u8 before);
};
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-
-/* TODO
-extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
-extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
-extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
-extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
-*/
+extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
+extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index a1df604366c3..5e17275afd25 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -111,6 +111,8 @@ struct dibx000_bandwidth_config {
u32 ifreq;
u32 timf;
+
+ u32 xtal_hz;
};
enum dibx000_adc_states {
@@ -122,56 +124,17 @@ enum dibx000_adc_states {
DIBX000_VBG_DISABLE,
};
-#define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \
+#define BANDWIDTH_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \
(v) == BANDWIDTH_7_MHZ ? 7000 : \
(v) == BANDWIDTH_6_MHZ ? 6000 : 8000 )
/* Chip output mode. */
-#define OUTMODE_HIGH_Z 0
-#define OUTMODE_MPEG2_PAR_GATED_CLK 1
-#define OUTMODE_MPEG2_PAR_CONT_CLK 2
-#define OUTMODE_MPEG2_SERIAL 7
-#define OUTMODE_DIVERSITY 4
-#define OUTMODE_MPEG2_FIFO 5
-
-/* I hope I can get rid of the following kludge in the near future */
-struct dibx000_ofdm_channel {
- u32 RF_kHz;
- u8 Bw;
- s16 nfft;
- s16 guard;
- s16 nqam;
- s16 vit_hrch;
- s16 vit_select_hp;
- s16 vit_alpha;
- s16 vit_code_rate_hp;
- s16 vit_code_rate_lp;
- u8 intlv_native;
-};
-
-#define FEP2DIB(fep,ch) \
- (ch)->RF_kHz = (fep)->frequency / 1000; \
- (ch)->Bw = (fep)->u.ofdm.bandwidth; \
- (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
- (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
- (ch)->nqam = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \
- (ch)->vit_hrch = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \
- (ch)->vit_select_hp = 1; \
- (ch)->vit_alpha = 1; \
- (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
- (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
- (ch)->intlv_native = 1;
-
-#define INIT_OFDM_CHANNEL(ch) do {\
- (ch)->Bw = 0; \
- (ch)->nfft = -1; \
- (ch)->guard = -1; \
- (ch)->nqam = -1; \
- (ch)->vit_hrch = -1; \
- (ch)->vit_select_hp = -1; \
- (ch)->vit_alpha = -1; \
- (ch)->vit_code_rate_hp = -1; \
- (ch)->vit_code_rate_lp = -1; \
-} while (0)
+#define OUTMODE_HIGH_Z 0
+#define OUTMODE_MPEG2_PAR_GATED_CLK 1
+#define OUTMODE_MPEG2_PAR_CONT_CLK 2
+#define OUTMODE_MPEG2_SERIAL 7
+#define OUTMODE_DIVERSITY 4
+#define OUTMODE_MPEG2_FIFO 5
+#define OUTMODE_ANALOG_ADC 6
#endif
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 5f96ffda91ad..8c8d7342d0b3 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -24,6 +24,59 @@
#include "dvb-pll.h"
+struct dvb_pll_priv {
+ /* pll number */
+ int nr;
+
+ /* i2c details */
+ int pll_i2c_address;
+ struct i2c_adapter *i2c;
+
+ /* the PLL descriptor */
+ struct dvb_pll_desc *pll_desc;
+
+ /* cached frequency/bandwidth */
+ u32 frequency;
+ u32 bandwidth;
+};
+
+#define DVB_PLL_MAX 64
+
+static unsigned int dvb_pll_devcount;
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
+module_param_array(input, int, NULL, 0644);
+MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
+
+static unsigned int id[DVB_PLL_MAX] =
+ { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
+module_param_array(id, int, NULL, 0644);
+MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
+
+/* ----------------------------------------------------------- */
+
+struct dvb_pll_desc {
+ char *name;
+ u32 min;
+ u32 max;
+ u32 iffreq;
+ void (*set)(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params);
+ u8 *initdata;
+ u8 *sleepdata;
+ int count;
+ struct {
+ u32 limit;
+ u32 stepsize;
+ u8 config;
+ u8 cb;
+ } entries[12];
+};
+
/* ----------------------------------------------------------- */
/* descriptions */
@@ -38,7 +91,13 @@
0x50 = AGC Take over point = 103 dBuV */
static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
-struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+/* 0x04 = 166.67 kHz divider
+
+ 0x80 = AGC Time constant 50ms Iagc = 9 uA
+ 0x20 = AGC Take over point = 112 dBuV */
+static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
.name = "Thomson dtt7579",
.min = 177000000,
.max = 858000000,
@@ -52,9 +111,8 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
{ 999999999, 166667, 0xf4, 0x08 },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt7579);
-struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
+static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
.name = "Thomson dtt7610",
.min = 44000000,
.max = 958000000,
@@ -66,19 +124,19 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
{ 999999999, 62500, 0x8e, 0x3c },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt7610);
-static void thomson_dtt759x_bw(u8 *buf, u32 freq, int bandwidth)
+static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (BANDWIDTH_7_MHZ == bandwidth)
+ if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth)
buf[3] |= 0x10;
}
-struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
+static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
.name = "Thomson dtt759x",
.min = 177000000,
.max = 896000000,
- .setbw = thomson_dtt759x_bw,
+ .set = thomson_dtt759x_bw,
.iffreq= 36166667,
.sleepdata = (u8[]){ 2, 0x84, 0x03 },
.count = 5,
@@ -90,9 +148,8 @@ struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
{ 999999999, 166667, 0xfc, 0x08 },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt759x);
-struct dvb_pll_desc dvb_pll_lg_z201 = {
+static struct dvb_pll_desc dvb_pll_lg_z201 = {
.name = "LG z201",
.min = 174000000,
.max = 862000000,
@@ -107,9 +164,8 @@ struct dvb_pll_desc dvb_pll_lg_z201 = {
{ 999999999, 166667, 0xfc, 0x04 },
},
};
-EXPORT_SYMBOL(dvb_pll_lg_z201);
-struct dvb_pll_desc dvb_pll_microtune_4042 = {
+static struct dvb_pll_desc dvb_pll_microtune_4042 = {
.name = "Microtune 4042 FI5",
.min = 57000000,
.max = 858000000,
@@ -121,9 +177,8 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = {
{ 999999999, 62500, 0x8e, 0x31 },
},
};
-EXPORT_SYMBOL(dvb_pll_microtune_4042);
-struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+static struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
.name = "Thomson dtt761x",
.min = 57000000,
@@ -137,9 +192,8 @@ struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
{ 999999999, 62500, 0x8e, 0x3c },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt761x);
-struct dvb_pll_desc dvb_pll_unknown_1 = {
+static struct dvb_pll_desc dvb_pll_unknown_1 = {
.name = "unknown 1", /* used by dntv live dvb-t */
.min = 174000000,
.max = 862000000,
@@ -157,12 +211,11 @@ struct dvb_pll_desc dvb_pll_unknown_1 = {
{ 999999999, 166667, 0xfc, 0x08 },
},
};
-EXPORT_SYMBOL(dvb_pll_unknown_1);
/* Infineon TUA6010XS
* used in Thomson Cable Tuner
*/
-struct dvb_pll_desc dvb_pll_tua6010xs = {
+static struct dvb_pll_desc dvb_pll_tua6010xs = {
.name = "Infineon TUA6010XS",
.min = 44250000,
.max = 858000000,
@@ -174,10 +227,9 @@ struct dvb_pll_desc dvb_pll_tua6010xs = {
{ 999999999, 62500, 0x8e, 0x85 },
},
};
-EXPORT_SYMBOL(dvb_pll_tua6010xs);
/* Panasonic env57h1xd5 (some Philips PLL ?) */
-struct dvb_pll_desc dvb_pll_env57h1xd5 = {
+static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
.name = "Panasonic ENV57H1XD5",
.min = 44250000,
.max = 858000000,
@@ -190,23 +242,24 @@ struct dvb_pll_desc dvb_pll_env57h1xd5 = {
{ 999999999, 166667, 0xc2, 0xa4 },
},
};
-EXPORT_SYMBOL(dvb_pll_env57h1xd5);
/* Philips TDA6650/TDA6651
* used in Panasonic ENV77H11D5
*/
-static void tda665x_bw(u8 *buf, u32 freq, int bandwidth)
+static void tda665x_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (bandwidth == BANDWIDTH_8_MHZ)
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
buf[3] |= 0x08;
}
-struct dvb_pll_desc dvb_pll_tda665x = {
+static struct dvb_pll_desc dvb_pll_tda665x = {
.name = "Philips TDA6650/TDA6651",
.min = 44250000,
.max = 858000000,
- .setbw = tda665x_bw,
+ .set = tda665x_bw,
.iffreq= 36166667,
+ .initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
.count = 12,
.entries = {
{ 93834000, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ },
@@ -223,36 +276,35 @@ struct dvb_pll_desc dvb_pll_tda665x = {
{ 861000000, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ },
}
};
-EXPORT_SYMBOL(dvb_pll_tda665x);
/* Infineon TUA6034
* used in LG TDTP E102P
*/
-static void tua6034_bw(u8 *buf, u32 freq, int bandwidth)
+static void tua6034_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (BANDWIDTH_7_MHZ != bandwidth)
+ if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth)
buf[3] |= 0x08;
}
-struct dvb_pll_desc dvb_pll_tua6034 = {
+static struct dvb_pll_desc dvb_pll_tua6034 = {
.name = "Infineon TUA6034",
.min = 44250000,
.max = 858000000,
.iffreq= 36166667,
.count = 3,
- .setbw = tua6034_bw,
+ .set = tua6034_bw,
.entries = {
{ 174500000, 62500, 0xce, 0x01 },
{ 230000000, 62500, 0xce, 0x02 },
{ 999999999, 62500, 0xce, 0x04 },
},
};
-EXPORT_SYMBOL(dvb_pll_tua6034);
/* Infineon TUA6034
* used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
*/
-struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
.name = "LG TDVS-H06xF",
.min = 54000000,
.max = 863000000,
@@ -265,23 +317,26 @@ struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
{ 999999999, 62500, 0xce, 0x04 },
},
};
-EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
/* Philips FMD1216ME
* used in Medion Hybrid PCMCIA card and USB Box
*/
-static void fmd1216me_bw(u8 *buf, u32 freq, int bandwidth)
+static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (bandwidth == BANDWIDTH_8_MHZ && freq >= 158870000)
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
+ params->frequency >= 158870000)
buf[3] |= 0x08;
}
-struct dvb_pll_desc dvb_pll_fmd1216me = {
+static struct dvb_pll_desc dvb_pll_fmd1216me = {
.name = "Philips FMD1216ME",
.min = 50870000,
.max = 858000000,
.iffreq= 36125000,
- .setbw = fmd1216me_bw,
+ .set = fmd1216me_bw,
+ .initdata = tua603x_agc112,
+ .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
.count = 7,
.entries = {
{ 143870000, 166667, 0xbc, 0x41 },
@@ -293,23 +348,23 @@ struct dvb_pll_desc dvb_pll_fmd1216me = {
{ 999999999, 166667, 0xfc, 0x44 },
}
};
-EXPORT_SYMBOL(dvb_pll_fmd1216me);
/* ALPS TDED4
* used in Nebula-Cards and USB boxes
*/
-static void tded4_bw(u8 *buf, u32 freq, int bandwidth)
+static void tded4_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (bandwidth == BANDWIDTH_8_MHZ)
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
buf[3] |= 0x04;
}
-struct dvb_pll_desc dvb_pll_tded4 = {
+static struct dvb_pll_desc dvb_pll_tded4 = {
.name = "ALPS TDED4",
.min = 47000000,
.max = 863000000,
.iffreq= 36166667,
- .setbw = tded4_bw,
+ .set = tded4_bw,
.count = 4,
.entries = {
{ 153000000, 166667, 0x85, 0x01 },
@@ -318,12 +373,11 @@ struct dvb_pll_desc dvb_pll_tded4 = {
{ 999999999, 166667, 0x85, 0x88 },
}
};
-EXPORT_SYMBOL(dvb_pll_tded4);
/* ALPS TDHU2
* used in AverTVHD MCE A180
*/
-struct dvb_pll_desc dvb_pll_tdhu2 = {
+static struct dvb_pll_desc dvb_pll_tdhu2 = {
.name = "ALPS TDHU2",
.min = 54000000,
.max = 864000000,
@@ -336,16 +390,48 @@ struct dvb_pll_desc dvb_pll_tdhu2 = {
{ 999999999, 62500, 0x85, 0x88 },
}
};
-EXPORT_SYMBOL(dvb_pll_tdhu2);
/* Philips TUV1236D
* used in ATI HDTV Wonder
*/
-struct dvb_pll_desc dvb_pll_tuv1236d = {
+static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ unsigned int new_rf = input[priv->nr];
+
+ if ((new_rf == 0) || (new_rf > 2)) {
+ switch (params->u.vsb.modulation) {
+ case QAM_64:
+ case QAM_256:
+ new_rf = 1;
+ break;
+ case VSB_8:
+ default:
+ new_rf = 2;
+ }
+ }
+
+ switch (new_rf) {
+ case 1:
+ buf[3] |= 0x08;
+ break;
+ case 2:
+ buf[3] &= ~0x08;
+ break;
+ default:
+ printk(KERN_WARNING
+ "%s: unhandled rf input selection: %d",
+ __FUNCTION__, new_rf);
+ }
+}
+
+static struct dvb_pll_desc dvb_pll_tuv1236d = {
.name = "Philips TUV1236D",
.min = 54000000,
.max = 864000000,
.iffreq= 44000000,
+ .set = tuv1236d_rf,
.count = 3,
.entries = {
{ 157250000, 62500, 0xc6, 0x41 },
@@ -353,12 +439,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = {
{ 999999999, 62500, 0xc6, 0x44 },
},
};
-EXPORT_SYMBOL(dvb_pll_tuv1236d);
/* Samsung TBMV30111IN / TBMV30712IN1
* used in Air2PC ATSC - 2nd generation (nxt2002)
*/
-struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
.name = "Samsung TBMV30111IN / TBMV30712IN1",
.min = 54000000,
.max = 860000000,
@@ -373,12 +458,11 @@ struct dvb_pll_desc dvb_pll_samsung_tbmv = {
{ 999999999, 166667, 0xfc, 0x02 },
}
};
-EXPORT_SYMBOL(dvb_pll_samsung_tbmv);
/*
* Philips SD1878 Tuner.
*/
-struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
.name = "Philips SD1878",
.min = 950000,
.max = 2150000,
@@ -391,19 +475,19 @@ struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
{ 2150000, 500, 0xc4, 0xc0},
},
};
-EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261);
/*
* Philips TD1316 Tuner.
*/
-static void td1316_bw(u8 *buf, u32 freq, int bandwidth)
+static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
u8 band;
/* determine band */
- if (freq < 161000000)
+ if (params->frequency < 161000000)
band = 1;
- else if (freq < 444000000)
+ else if (params->frequency < 444000000)
band = 2;
else
band = 4;
@@ -411,16 +495,16 @@ static void td1316_bw(u8 *buf, u32 freq, int bandwidth)
buf[3] |= band;
/* setup PLL filter */
- if (bandwidth == BANDWIDTH_8_MHZ)
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
buf[3] |= 1 << 3;
}
-struct dvb_pll_desc dvb_pll_philips_td1316 = {
+static struct dvb_pll_desc dvb_pll_philips_td1316 = {
.name = "Philips TD1316",
.min = 87000000,
.max = 895000000,
.iffreq= 36166667,
- .setbw = td1316_bw,
+ .set = td1316_bw,
.count = 9,
.entries = {
{ 93834000, 166667, 0xca, 0x60},
@@ -434,10 +518,9 @@ struct dvb_pll_desc dvb_pll_philips_td1316 = {
{ 858834000, 166667, 0xca, 0xe0},
},
};
-EXPORT_SYMBOL(dvb_pll_philips_td1316);
/* FE6600 used on DViCO Hybrid */
-struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
+static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
.name = "Thomson FE6600",
.min = 44250000,
.max = 858000000,
@@ -450,19 +533,20 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
{ 999999999, 166667, 0xf4, 0x18 },
}
};
-EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
-static void opera1_bw(u8 *buf, u32 freq, int bandwidth)
+
+static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
- if (bandwidth == BANDWIDTH_8_MHZ)
+ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
buf[2] |= 0x08;
}
-struct dvb_pll_desc dvb_pll_opera1 = {
+static struct dvb_pll_desc dvb_pll_opera1 = {
.name = "Opera Tuner",
.min = 900000,
.max = 2250000,
.iffreq= 0,
- .setbw = opera1_bw,
+ .set = opera1_bw,
.count = 8,
.entries = {
{ 1064000, 500, 0xe5, 0xc6 },
@@ -475,57 +559,89 @@ struct dvb_pll_desc dvb_pll_opera1 = {
{ 2250000, 500, 0xe5, 0xc4 },
}
};
-EXPORT_SYMBOL(dvb_pll_opera1);
-struct dvb_pll_priv {
- /* i2c details */
- int pll_i2c_address;
- struct i2c_adapter *i2c;
+/* Philips FCV1236D
+ */
+static struct dvb_pll_desc dvb_pll_fcv1236d = {
+/* Bit_0: RF Input select
+ * Bit_1: 0=digital, 1=analog
+ */
+ .name = "Philips FCV1236D",
+ .min = 53000000,
+ .max = 803000000,
+ .iffreq= 44000000,
+ .count = 3,
+ .entries = {
+ { 159000000, 62500, 0x8e, 0xa0 },
+ { 453000000, 62500, 0x8e, 0x90 },
+ { 999999999, 62500, 0x8e, 0x30 },
+ },
+};
- /* the PLL descriptor */
- struct dvb_pll_desc *pll_desc;
+/* ----------------------------------------------------------- */
- /* cached frequency/bandwidth */
- u32 frequency;
- u32 bandwidth;
+static struct dvb_pll_desc *pll_list[] = {
+ [DVB_PLL_UNDEFINED] = NULL,
+ [DVB_PLL_THOMSON_DTT7579] = &dvb_pll_thomson_dtt7579,
+ [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x,
+ [DVB_PLL_THOMSON_DTT7610] = &dvb_pll_thomson_dtt7610,
+ [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201,
+ [DVB_PLL_MICROTUNE_4042] = &dvb_pll_microtune_4042,
+ [DVB_PLL_THOMSON_DTT761X] = &dvb_pll_thomson_dtt761x,
+ [DVB_PLL_UNKNOWN_1] = &dvb_pll_unknown_1,
+ [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs,
+ [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5,
+ [DVB_PLL_TUA6034] = &dvb_pll_tua6034,
+ [DVB_PLL_LG_TDVS_H06XF] = &dvb_pll_lg_tdvs_h06xf,
+ [DVB_PLL_TDA665X] = &dvb_pll_tda665x,
+ [DVB_PLL_FMD1216ME] = &dvb_pll_fmd1216me,
+ [DVB_PLL_TDED4] = &dvb_pll_tded4,
+ [DVB_PLL_TUV1236D] = &dvb_pll_tuv1236d,
+ [DVB_PLL_TDHU2] = &dvb_pll_tdhu2,
+ [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
+ [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
+ [DVB_PLL_PHILIPS_TD1316] = &dvb_pll_philips_td1316,
+ [DVB_PLL_THOMSON_FE6600] = &dvb_pll_thomson_fe6600,
+ [DVB_PLL_OPERA1] = &dvb_pll_opera1,
+ [DVB_PLL_FCV1236D] = &dvb_pll_fcv1236d,
};
/* ----------------------------------------------------------- */
/* code */
-static int debug = 0;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
- u32 freq, int bandwidth)
+static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ struct dvb_pll_desc *desc = priv->pll_desc;
u32 div;
int i;
- if (freq != 0 && (freq < desc->min || freq > desc->max))
- return -EINVAL;
+ if (params->frequency != 0 && (params->frequency < desc->min ||
+ params->frequency > desc->max))
+ return -EINVAL;
for (i = 0; i < desc->count; i++) {
- if (freq > desc->entries[i].limit)
+ if (params->frequency > desc->entries[i].limit)
continue;
break;
}
+
if (debug)
- printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
- desc->name, freq, bandwidth, i, desc->count);
+ printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
+ params->frequency, i, desc->count);
if (i == desc->count)
return -EINVAL;
- div = (freq + desc->iffreq + desc->entries[i].stepsize/2) /
- desc->entries[i].stepsize;
+ div = (params->frequency + desc->iffreq +
+ desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
buf[0] = div >> 8;
buf[1] = div & 0xff;
buf[2] = desc->entries[i].config;
buf[3] = desc->entries[i].cb;
- if (desc->setbw)
- desc->setbw(buf, freq, bandwidth);
+ if (desc->set)
+ desc->set(fe, buf, params);
if (debug)
printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
@@ -534,7 +650,6 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
// calculate the frequency we set it to
return (div * desc->entries[i].stepsize) - desc->iffreq;
}
-EXPORT_SYMBOL(dvb_pll_configure);
static int dvb_pll_release(struct dvb_frontend *fe)
{
@@ -578,18 +693,12 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
{ .addr = priv->pll_i2c_address, .flags = 0,
.buf = buf, .len = sizeof(buf) };
int result;
- u32 bandwidth = 0, frequency = 0;
+ u32 frequency = 0;
if (priv->i2c == NULL)
return -EINVAL;
- // DVBT bandwidth only just now
- if (fe->ops.info.type == FE_OFDM) {
- bandwidth = params->u.ofdm.bandwidth;
- }
-
- if ((result = dvb_pll_configure(priv->pll_desc, buf,
- params->frequency, bandwidth)) < 0)
+ if ((result = dvb_pll_configure(fe, buf, params)) < 0)
return result;
else
frequency = result;
@@ -601,7 +710,7 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
}
priv->frequency = frequency;
- priv->bandwidth = bandwidth;
+ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
return 0;
}
@@ -612,18 +721,12 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
{
struct dvb_pll_priv *priv = fe->tuner_priv;
int result;
- u32 bandwidth = 0, frequency = 0;
+ u32 frequency = 0;
if (buf_len < 5)
return -EINVAL;
- // DVBT bandwidth only just now
- if (fe->ops.info.type == FE_OFDM) {
- bandwidth = params->u.ofdm.bandwidth;
- }
-
- if ((result = dvb_pll_configure(priv->pll_desc, buf+1,
- params->frequency, bandwidth)) < 0)
+ if ((result = dvb_pll_configure(fe, buf+1, params)) < 0)
return result;
else
frequency = result;
@@ -631,7 +734,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
buf[0] = priv->pll_i2c_address;
priv->frequency = frequency;
- priv->bandwidth = bandwidth;
+ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
return 5;
}
@@ -687,13 +790,22 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
struct i2c_adapter *i2c,
- struct dvb_pll_desc *desc)
+ unsigned int pll_desc_id)
{
u8 b1 [] = { 0 };
struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
.buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL;
int ret;
+ struct dvb_pll_desc *desc;
+
+ if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
+ (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
+ pll_desc_id = id[dvb_pll_devcount];
+
+ BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
+
+ desc = pll_list[pll_desc_id];
if (i2c != NULL) {
if (fe->ops.i2c_gate_ctrl)
@@ -713,6 +825,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
priv->pll_i2c_address = pll_addr;
priv->i2c = i2c;
priv->pll_desc = desc;
+ priv->nr = dvb_pll_devcount++;
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
sizeof(struct dvb_tuner_ops));
@@ -720,13 +833,37 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
strncpy(fe->ops.tuner_ops.info.name, desc->name,
sizeof(fe->ops.tuner_ops.info.name));
fe->ops.tuner_ops.info.frequency_min = desc->min;
- fe->ops.tuner_ops.info.frequency_min = desc->max;
+ fe->ops.tuner_ops.info.frequency_max = desc->max;
if (!desc->initdata)
fe->ops.tuner_ops.init = NULL;
if (!desc->sleepdata)
fe->ops.tuner_ops.sleep = NULL;
fe->tuner_priv = priv;
+
+ if ((debug) || (id[priv->nr] == pll_desc_id)) {
+ printk("dvb-pll[%d]", priv->nr);
+ if (i2c != NULL)
+ printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+ printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
+ id[priv->nr] == pll_desc_id ?
+ "insmod option" : "autodetected");
+ }
+ if ((debug) || (input[priv->nr] > 0)) {
+ printk("dvb-pll[%d]", priv->nr);
+ if (i2c != NULL)
+ printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+ printk(": tuner rf input will be ");
+ switch (input[priv->nr]) {
+ case 0:
+ printk("autoselected\n");
+ break;
+ default:
+ printk("set to input %d (insmod option)\n",
+ input[priv->nr]);
+ }
+ }
+
return fe;
}
EXPORT_SYMBOL(dvb_pll_attach);
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 5209f46f0893..e93a8104052b 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -8,50 +8,29 @@
#include <linux/i2c.h>
#include "dvb_frontend.h"
-struct dvb_pll_desc {
- char *name;
- u32 min;
- u32 max;
- u32 iffreq;
- void (*setbw)(u8 *buf, u32 freq, int bandwidth);
- u8 *initdata;
- u8 *sleepdata;
- int count;
- struct {
- u32 limit;
- u32 stepsize;
- u8 config;
- u8 cb;
- } entries[12];
-};
-
-extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
-extern struct dvb_pll_desc dvb_pll_lg_z201;
-extern struct dvb_pll_desc dvb_pll_microtune_4042;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt761x;
-extern struct dvb_pll_desc dvb_pll_unknown_1;
-
-extern struct dvb_pll_desc dvb_pll_tua6010xs;
-extern struct dvb_pll_desc dvb_pll_env57h1xd5;
-extern struct dvb_pll_desc dvb_pll_tua6034;
-extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
-extern struct dvb_pll_desc dvb_pll_tda665x;
-extern struct dvb_pll_desc dvb_pll_fmd1216me;
-extern struct dvb_pll_desc dvb_pll_tded4;
-
-extern struct dvb_pll_desc dvb_pll_tuv1236d;
-extern struct dvb_pll_desc dvb_pll_tdhu2;
-extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
-extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
-extern struct dvb_pll_desc dvb_pll_philips_td1316;
-
-extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
-extern struct dvb_pll_desc dvb_pll_opera1;
-
-extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
- u32 freq, int bandwidth);
+#define DVB_PLL_UNDEFINED 0
+#define DVB_PLL_THOMSON_DTT7579 1
+#define DVB_PLL_THOMSON_DTT759X 2
+#define DVB_PLL_THOMSON_DTT7610 3
+#define DVB_PLL_LG_Z201 4
+#define DVB_PLL_MICROTUNE_4042 5
+#define DVB_PLL_THOMSON_DTT761X 6
+#define DVB_PLL_UNKNOWN_1 7
+#define DVB_PLL_TUA6010XS 8
+#define DVB_PLL_ENV57H1XD5 9
+#define DVB_PLL_TUA6034 10
+#define DVB_PLL_LG_TDVS_H06XF 11
+#define DVB_PLL_TDA665X 12
+#define DVB_PLL_FMD1216ME 13
+#define DVB_PLL_TDED4 14
+#define DVB_PLL_TUV1236D 15
+#define DVB_PLL_TDHU2 16
+#define DVB_PLL_SAMSUNG_TBMV 17
+#define DVB_PLL_PHILIPS_SD1878_TDA8261 18
+#define DVB_PLL_PHILIPS_TD1316 19
+#define DVB_PLL_THOMSON_FE6600 20
+#define DVB_PLL_OPERA1 21
+#define DVB_PLL_FCV1236D 22
/**
* Attach a dvb-pll to the supplied frontend structure.
@@ -59,19 +38,19 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
* @param fe Frontend to attach to.
* @param pll_addr i2c address of the PLL (if used).
* @param i2c i2c adapter to use (set to NULL if not used).
- * @param desc dvb_pll_desc to use.
+ * @param pll_desc_id dvb_pll_desc to use.
* @return Frontend pointer on success, NULL on failure
*/
#if defined(CONFIG_DVB_PLL) || (defined(CONFIG_DVB_PLL_MODULE) && defined(MODULE))
extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
int pll_addr,
struct i2c_adapter *i2c,
- struct dvb_pll_desc *desc);
+ unsigned int pll_desc_id);
#else
static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
int pll_addr,
struct i2c_adapter *i2c,
- struct dvb_pll_desc *desc)
+ unsigned int pll_desc_id)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index 6271b1e7f6ab..fed09dfb2b7c 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -20,7 +20,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
index c967148a5945..684c8ec166cb 100644
--- a/drivers/media/dvb/frontends/isl6421.c
+++ b/drivers/media/dvb/frontends/isl6421.c
@@ -29,7 +29,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index 1aeacb1c4af7..443d9045d4c9 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index e25286e2d431..bdc9fa88b86a 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -35,7 +35,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
index 2d2f58c26226..76f935d9755a 100644
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/media/dvb/frontends/mt2060.c b/drivers/media/dvb/frontends/mt2060.c
index 450fad8d9b65..1305b0e63ce5 100644
--- a/drivers/media/dvb/frontends/mt2060.c
+++ b/drivers/media/dvb/frontends/mt2060.c
@@ -22,7 +22,6 @@
/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
new file mode 100644
index 000000000000..4b93931de4e1
--- /dev/null
+++ b/drivers/media/dvb/frontends/mt2131.c
@@ -0,0 +1,314 @@
+/*
+ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "mt2131.h"
+#include "mt2131_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
+
+static u8 mt2131_config1[] = {
+ 0x01,
+ 0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
+ 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
+ 0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
+ 0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
+};
+
+static u8 mt2131_config2[] = {
+ 0x10,
+ 0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
+};
+
+static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
+{
+ struct i2c_msg msg[2] = {
+ { .addr = priv->cfg->i2c_address, .flags = 0,
+ .buf = &reg, .len = 1 },
+ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
+ .buf = val, .len = 1 },
+ };
+
+ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+ printk(KERN_WARNING "mt2131 I2C read failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
+{
+ u8 buf[2] = { reg, val };
+ struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
+ .buf = buf, .len = 2 };
+
+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "mt2131 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
+{
+ struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+ .flags = 0, .buf = buf, .len = len };
+
+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
+ (int)len);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int mt2131_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct mt2131_priv *priv;
+ int ret=0, i;
+ u32 freq;
+ u8 if_band_center;
+ u32 f_lo1, f_lo2;
+ u32 div1, num1, div2, num2;
+ u8 b[8];
+ u8 lockval = 0;
+
+ priv = fe->tuner_priv;
+ if (fe->ops.info.type == FE_OFDM)
+ priv->bandwidth = params->u.ofdm.bandwidth;
+ else
+ priv->bandwidth = 0;
+
+ freq = params->frequency / 1000; // Hz -> kHz
+ dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
+
+ f_lo1 = freq + MT2131_IF1 * 1000;
+ f_lo1 = (f_lo1 / 250) * 250;
+ f_lo2 = f_lo1 - freq - MT2131_IF2;
+
+ priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000,
+
+ /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
+ num1 = f_lo1 * 64 / (MT2131_FREF / 128);
+ div1 = num1 / 8192;
+ num1 &= 0x1fff;
+
+ /* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
+ num2 = f_lo2 * 64 / (MT2131_FREF / 128);
+ div2 = num2 / 8192;
+ num2 &= 0x1fff;
+
+ if (freq <= 82500) if_band_center = 0x00; else
+ if (freq <= 137500) if_band_center = 0x01; else
+ if (freq <= 192500) if_band_center = 0x02; else
+ if (freq <= 247500) if_band_center = 0x03; else
+ if (freq <= 302500) if_band_center = 0x04; else
+ if (freq <= 357500) if_band_center = 0x05; else
+ if (freq <= 412500) if_band_center = 0x06; else
+ if (freq <= 467500) if_band_center = 0x07; else
+ if (freq <= 522500) if_band_center = 0x08; else
+ if (freq <= 577500) if_band_center = 0x09; else
+ if (freq <= 632500) if_band_center = 0x0A; else
+ if (freq <= 687500) if_band_center = 0x0B; else
+ if (freq <= 742500) if_band_center = 0x0C; else
+ if (freq <= 797500) if_band_center = 0x0D; else
+ if (freq <= 852500) if_band_center = 0x0E; else
+ if (freq <= 907500) if_band_center = 0x0F; else
+ if (freq <= 962500) if_band_center = 0x10; else
+ if (freq <= 1017500) if_band_center = 0x11; else
+ if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
+
+ b[0] = 1;
+ b[1] = (num1 >> 5) & 0xFF;
+ b[2] = (num1 & 0x1F);
+ b[3] = div1;
+ b[4] = (num2 >> 5) & 0xFF;
+ b[5] = num2 & 0x1F;
+ b[6] = div2;
+
+ dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
+ dprintk(1, "PLL freq=%dkHz band=%d\n", (int)freq, (int)if_band_center);
+ dprintk(1, "PLL f_lo1=%dkHz f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
+ dprintk(1, "PLL div1=%d num1=%d div2=%d num2=%d\n",
+ (int)div1, (int)num1, (int)div2, (int)num2);
+ dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
+ (int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
+ (int)b[6]);
+
+ ret = mt2131_writeregs(priv,b,7);
+ if (ret < 0)
+ return ret;
+
+ mt2131_writereg(priv, 0x0b, if_band_center);
+
+ /* Wait for lock */
+ i = 0;
+ do {
+ mt2131_readreg(priv, 0x08, &lockval);
+ if ((lockval & 0x88) == 0x88)
+ break;
+ msleep(4);
+ i++;
+ } while (i < 10);
+
+ return ret;
+}
+
+static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mt2131_priv *priv = fe->tuner_priv;
+ dprintk(1, "%s()\n", __FUNCTION__);
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct mt2131_priv *priv = fe->tuner_priv;
+ dprintk(1, "%s()\n", __FUNCTION__);
+ *bandwidth = priv->bandwidth;
+ return 0;
+}
+
+static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ struct mt2131_priv *priv = fe->tuner_priv;
+ u8 lock_status = 0;
+ u8 afc_status = 0;
+
+ *status = 0;
+
+ mt2131_readreg(priv, 0x08, &lock_status);
+ if ((lock_status & 0x88) == 0x88)
+ *status = TUNER_STATUS_LOCKED;
+
+ mt2131_readreg(priv, 0x09, &afc_status);
+ dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
+ __FUNCTION__, lock_status, afc_status);
+
+ return 0;
+}
+
+static int mt2131_init(struct dvb_frontend *fe)
+{
+ struct mt2131_priv *priv = fe->tuner_priv;
+ int ret;
+ dprintk(1, "%s()\n", __FUNCTION__);
+
+ if ((ret = mt2131_writeregs(priv, mt2131_config1,
+ sizeof(mt2131_config1))) < 0)
+ return ret;
+
+ mt2131_writereg(priv, 0x0b, 0x09);
+ mt2131_writereg(priv, 0x15, 0x47);
+ mt2131_writereg(priv, 0x07, 0xf2);
+ mt2131_writereg(priv, 0x0b, 0x01);
+
+ if ((ret = mt2131_writeregs(priv, mt2131_config2,
+ sizeof(mt2131_config2))) < 0)
+ return ret;
+
+ return ret;
+}
+
+static int mt2131_release(struct dvb_frontend *fe)
+{
+ dprintk(1, "%s()\n", __FUNCTION__);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static const struct dvb_tuner_ops mt2131_tuner_ops = {
+ .info = {
+ .name = "Microtune MT2131",
+ .frequency_min = 48000000,
+ .frequency_max = 860000000,
+ .frequency_step = 50000,
+ },
+
+ .release = mt2131_release,
+ .init = mt2131_init,
+
+ .set_params = mt2131_set_params,
+ .get_frequency = mt2131_get_frequency,
+ .get_bandwidth = mt2131_get_bandwidth,
+ .get_status = mt2131_get_status
+};
+
+struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mt2131_config *cfg, u16 if1)
+{
+ struct mt2131_priv *priv = NULL;
+ u8 id = 0;
+
+ dprintk(1, "%s()\n", __FUNCTION__);
+
+ priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+
+ priv->cfg = cfg;
+ priv->bandwidth = 6000000; /* 6MHz */
+ priv->i2c = i2c;
+
+ if (mt2131_readreg(priv, 0, &id) != 0) {
+ kfree(priv);
+ return NULL;
+ }
+ if ( (id != 0x3E) && (id != 0x3F) ) {
+ printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
+ cfg->i2c_address);
+ kfree(priv);
+ return NULL;
+ }
+
+ printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
+ cfg->i2c_address);
+ memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = priv;
+ return fe;
+}
+EXPORT_SYMBOL(mt2131_attach);
+
+MODULE_AUTHOR("Steven Toth");
+MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h
new file mode 100644
index 000000000000..1e4ffe7dc8c8
--- /dev/null
+++ b/drivers/media/dvb/frontends/mt2131.h
@@ -0,0 +1,54 @@
+/*
+ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MT2131_H__
+#define __MT2131_H__
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct mt2131_config {
+ u8 i2c_address;
+ u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
+};
+
+#if defined(CONFIG_DVB_TUNER_MT2131) || (defined(CONFIG_DVB_TUNER_MT2131_MODULE) && defined(MODULE))
+extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mt2131_config *cfg,
+ u16 if1);
+#else
+static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mt2131_config *cfg,
+ u16 if1)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_TUNER_MT2131 */
+
+#endif /* __MT2131_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/mt2131_priv.h b/drivers/media/dvb/frontends/mt2131_priv.h
new file mode 100644
index 000000000000..e930759c2c00
--- /dev/null
+++ b/drivers/media/dvb/frontends/mt2131_priv.h
@@ -0,0 +1,49 @@
+/*
+ * Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MT2131_PRIV_H__
+#define __MT2131_PRIV_H__
+
+/* Regs */
+#define MT2131_PWR 0x07
+#define MT2131_UPC_1 0x0b
+#define MT2131_AGC_RL 0x10
+#define MT2131_MISC_2 0x15
+
+/* frequency values in KHz */
+#define MT2131_IF1 1220
+#define MT2131_IF2 44000
+#define MT2131_FREF 16000
+
+struct mt2131_priv {
+ struct mt2131_config *cfg;
+ struct i2c_adapter *i2c;
+
+ u32 frequency;
+ u32 bandwidth;
+};
+
+#endif /* __MT2131_PRIV_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/mt2266.c b/drivers/media/dvb/frontends/mt2266.c
new file mode 100644
index 000000000000..03fe8265745f
--- /dev/null
+++ b/drivers/media/dvb/frontends/mt2266.c
@@ -0,0 +1,287 @@
+/*
+ * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
+ *
+ * Copyright (c) 2007 Olivier DANET <odanet@caramail.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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+#include "mt2266.h"
+
+#define I2C_ADDRESS 0x60
+
+#define REG_PART_REV 0
+#define REG_TUNE 1
+#define REG_BAND 6
+#define REG_BANDWIDTH 8
+#define REG_LOCK 0x12
+
+#define PART_REV 0x85
+
+struct mt2266_priv {
+ struct mt2266_config *cfg;
+ struct i2c_adapter *i2c;
+
+ u32 frequency;
+ u32 bandwidth;
+};
+
+/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0)
+
+// Reads a single register
+static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val)
+{
+ struct i2c_msg msg[2] = {
+ { .addr = priv->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
+ };
+ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+ printk(KERN_WARNING "MT2266 I2C read failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Writes a single register
+static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val)
+{
+ u8 buf[2] = { reg, val };
+ struct i2c_msg msg = {
+ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
+ };
+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "MT2266 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Writes a set of consecutive registers
+static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
+{
+ struct i2c_msg msg = {
+ .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+ };
+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Initialisation sequences
+static u8 mt2266_init1[] = {
+ REG_TUNE,
+ 0x00, 0x00, 0x28, 0x00, 0x52, 0x99, 0x3f };
+
+static u8 mt2266_init2[] = {
+ 0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a,
+ 0xd4, 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x77, 0x0f, 0x2d };
+
+static u8 mt2266_init_8mhz[] = {
+ REG_BANDWIDTH,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };
+
+static u8 mt2266_init_7mhz[] = {
+ REG_BANDWIDTH,
+ 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
+
+static u8 mt2266_init_6mhz[] = {
+ REG_BANDWIDTH,
+ 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7 };
+
+#define FREF 30000 // Quartz oscillator 30 MHz
+
+static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct mt2266_priv *priv;
+ int ret=0;
+ u32 freq;
+ u32 tune;
+ u8 lnaband;
+ u8 b[10];
+ int i;
+
+ priv = fe->tuner_priv;
+
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
+
+ freq = params->frequency / 1000; // Hz -> kHz
+ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+ priv->frequency = freq * 1000;
+ tune=2 * freq * (8192/16) / (FREF/16);
+
+ if (freq <= 495000) lnaband = 0xEE; else
+ if (freq <= 525000) lnaband = 0xDD; else
+ if (freq <= 550000) lnaband = 0xCC; else
+ if (freq <= 580000) lnaband = 0xBB; else
+ if (freq <= 605000) lnaband = 0xAA; else
+ if (freq <= 630000) lnaband = 0x99; else
+ if (freq <= 655000) lnaband = 0x88; else
+ if (freq <= 685000) lnaband = 0x77; else
+ if (freq <= 710000) lnaband = 0x66; else
+ if (freq <= 735000) lnaband = 0x55; else
+ if (freq <= 765000) lnaband = 0x44; else
+ if (freq <= 802000) lnaband = 0x33; else
+ if (freq <= 840000) lnaband = 0x22; else lnaband = 0x11;
+
+ msleep(100);
+ mt2266_writeregs(priv,(params->u.ofdm.bandwidth==BANDWIDTH_6_MHZ)?mt2266_init_6mhz:
+ (params->u.ofdm.bandwidth==BANDWIDTH_7_MHZ)?mt2266_init_7mhz:
+ mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
+
+ b[0] = REG_TUNE;
+ b[1] = (tune >> 8) & 0x1F;
+ b[2] = tune & 0xFF;
+ b[3] = tune >> 13;
+ mt2266_writeregs(priv,b,4);
+
+ dprintk("set_parms: tune=%d band=%d",(int)tune,(int)lnaband);
+ dprintk("set_parms: [1..3]: %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3]);
+
+ b[0] = 0x05;
+ b[1] = 0x62;
+ b[2] = lnaband;
+ mt2266_writeregs(priv,b,3);
+
+ //Waits for pll lock or timeout
+ i = 0;
+ do {
+ mt2266_readreg(priv,REG_LOCK,b);
+ if ((b[0] & 0x40)==0x40)
+ break;
+ msleep(10);
+ i++;
+ } while (i<10);
+ dprintk("Lock when i=%i",(int)i);
+ return ret;
+}
+
+static void mt2266_calibrate(struct mt2266_priv *priv)
+{
+ mt2266_writereg(priv,0x11,0x03);
+ mt2266_writereg(priv,0x11,0x01);
+
+ mt2266_writeregs(priv,mt2266_init1,sizeof(mt2266_init1));
+ mt2266_writeregs(priv,mt2266_init2,sizeof(mt2266_init2));
+
+ mt2266_writereg(priv,0x33,0x5e);
+ mt2266_writereg(priv,0x10,0x10);
+ mt2266_writereg(priv,0x10,0x00);
+
+ mt2266_writeregs(priv,mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
+
+ msleep(25);
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0x00);
+ msleep(75);
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
+}
+
+static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mt2266_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct mt2266_priv *priv = fe->tuner_priv;
+ *bandwidth = priv->bandwidth;
+ return 0;
+}
+
+static int mt2266_init(struct dvb_frontend *fe)
+{
+ struct mt2266_priv *priv = fe->tuner_priv;
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0xff);
+ return 0;
+}
+
+static int mt2266_sleep(struct dvb_frontend *fe)
+{
+ struct mt2266_priv *priv = fe->tuner_priv;
+ mt2266_writereg(priv,0x17,0x6d);
+ mt2266_writereg(priv,0x1c,0x00);
+ return 0;
+}
+
+static int mt2266_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static const struct dvb_tuner_ops mt2266_tuner_ops = {
+ .info = {
+ .name = "Microtune MT2266",
+ .frequency_min = 470000000,
+ .frequency_max = 860000000,
+ .frequency_step = 50000,
+ },
+ .release = mt2266_release,
+ .init = mt2266_init,
+ .sleep = mt2266_sleep,
+ .set_params = mt2266_set_params,
+ .get_frequency = mt2266_get_frequency,
+ .get_bandwidth = mt2266_get_bandwidth
+};
+
+struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
+{
+ struct mt2266_priv *priv = NULL;
+ u8 id = 0;
+
+ priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+
+ priv->cfg = cfg;
+ priv->i2c = i2c;
+
+ if (mt2266_readreg(priv,0,&id) != 0) {
+ kfree(priv);
+ return NULL;
+ }
+ if (id != PART_REV) {
+ kfree(priv);
+ return NULL;
+ }
+ printk(KERN_INFO "MT2266: successfully identified\n");
+ memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = priv;
+ mt2266_calibrate(priv);
+ return fe;
+}
+EXPORT_SYMBOL(mt2266_attach);
+
+MODULE_AUTHOR("Olivier DANET");
+MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h
new file mode 100644
index 000000000000..f31dd613ad37
--- /dev/null
+++ b/drivers/media/dvb/frontends/mt2266.h
@@ -0,0 +1,37 @@
+/*
+ * Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
+ *
+ * Copyright (c) 2007 Olivier DANET <odanet@caramail.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.
+ */
+
+#ifndef MT2266_H
+#define MT2266_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct mt2266_config {
+ u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE))
+extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
+#else
+static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_TUNER_MT2266
+
+#endif
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 1ef821825641..0606b9a5b616 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index 87e31ca7e108..5dd9b731f6f2 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -32,7 +32,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index b809f83d9563..fcf964fe1d6b 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -44,12 +44,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "nxt200x.h"
struct nxt200x_state {
@@ -546,11 +544,6 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
nxt200x_writebytes(state, 0x17, buf, 1);
}
- /* get tuning information */
- if (fe->ops.tuner_ops.calc_regs) {
- fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
- }
-
/* set additional params */
switch (p->u.vsb.modulation) {
case QAM_64:
@@ -559,27 +552,24 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* This is just a guess since I am unable to test it */
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 1);
-
- /* set input */
- if (state->config->set_pll_input)
- state->config->set_pll_input(buf+1, 1);
break;
case VSB_8:
/* Set non-punctured clock for VSB */
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
-
- /* set input */
- if (state->config->set_pll_input)
- state->config->set_pll_input(buf+1, 0);
break;
default:
return -EINVAL;
break;
}
- /* write frequency information */
- nxt200x_writetuner(state, buf);
+ if (fe->ops.tuner_ops.calc_regs) {
+ /* get tuning information */
+ fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+
+ /* write frequency information */
+ nxt200x_writetuner(state, buf);
+ }
/* reset the agc now that tuning has been completed */
nxt200x_agc_reset(state);
diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
index 28bc5591b319..bb0ef58d7972 100644
--- a/drivers/media/dvb/frontends/nxt200x.h
+++ b/drivers/media/dvb/frontends/nxt200x.h
@@ -38,9 +38,6 @@ struct nxt200x_config
/* the demodulator's i2c address */
u8 demod_address;
- /* used to set pll input */
- int (*set_pll_input)(u8* buf, int input);
-
/* need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
};
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 4e0aca7c67aa..b314a1f2deed 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -36,7 +36,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
@@ -45,7 +44,6 @@
#include "dvb_math.h"
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "or51132.h"
static int debug;
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 048d7cfe12d3..f02bd9445955 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -32,7 +32,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/string.h>
@@ -223,38 +222,13 @@ static int or51211_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
struct or51211_state* state = fe->demodulator_priv;
- u32 freq = 0;
- u16 tunerfreq = 0;
- u8 buf[4];
/* Change only if we are actually changing the channel */
if (state->current_frequency != param->frequency) {
- freq = 44000 + (param->frequency/1000);
- tunerfreq = freq * 16/1000;
-
- dprintk("set_parameters frequency = %d (tunerfreq = %d)\n",
- param->frequency,tunerfreq);
-
- buf[0] = (tunerfreq >> 8) & 0x7F;
- buf[1] = (tunerfreq & 0xFF);
- buf[2] = 0x8E;
-
- if (param->frequency < 157250000) {
- buf[3] = 0xA0;
- dprintk("set_parameters VHF low range\n");
- } else if (param->frequency < 454000000) {
- buf[3] = 0x90;
- dprintk("set_parameters VHF high range\n");
- } else {
- buf[3] = 0x30;
- dprintk("set_parameters UHF range\n");
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
-
- if (i2c_writebytes(state,0xC2>>1,buf,4))
- printk(KERN_WARNING "or51211:set_parameters error "
- "writing to tuner\n");
/* Set to ATSC mode */
or51211_setmode(fe,0);
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
new file mode 100644
index 000000000000..30e8a705fad4
--- /dev/null
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -0,0 +1,729 @@
+/*
+ Samsung S5H1409 VSB/QAM demodulator driver
+
+ Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "s5h1409.h"
+
+struct s5h1409_state {
+
+ struct i2c_adapter* i2c;
+
+ /* configuration settings */
+ const struct s5h1409_config* config;
+
+ struct dvb_frontend frontend;
+
+ /* previous uncorrected block counter */
+ fe_modulation_t current_modulation;
+
+ u32 current_frequency;
+};
+
+static int debug = 0;
+#define dprintk if (debug) printk
+
+/* Register values to initialise the demod, this will set VSB by default */
+static struct init_tab {
+ u8 reg;
+ u16 data;
+} init_tab[] = {
+ { 0x00, 0x0071, },
+ { 0x01, 0x3213, },
+ { 0x09, 0x0025, },
+ { 0x1c, 0x001d, },
+ { 0x1f, 0x002d, },
+ { 0x20, 0x001d, },
+ { 0x22, 0x0022, },
+ { 0x23, 0x0020, },
+ { 0x29, 0x110f, },
+ { 0x2a, 0x10b4, },
+ { 0x2b, 0x10ae, },
+ { 0x2c, 0x0031, },
+ { 0x31, 0x010d, },
+ { 0x32, 0x0100, },
+ { 0x44, 0x0510, },
+ { 0x54, 0x0104, },
+ { 0x58, 0x2222, },
+ { 0x59, 0x1162, },
+ { 0x5a, 0x3211, },
+ { 0x5d, 0x0370, },
+ { 0x5e, 0x0296, },
+ { 0x61, 0x0010, },
+ { 0x63, 0x4a00, },
+ { 0x65, 0x0800, },
+ { 0x71, 0x0003, },
+ { 0x72, 0x0470, },
+ { 0x81, 0x0002, },
+ { 0x82, 0x0600, },
+ { 0x86, 0x0002, },
+ { 0x8a, 0x2c38, },
+ { 0x8b, 0x2a37, },
+ { 0x92, 0x302f, },
+ { 0x93, 0x3332, },
+ { 0x96, 0x000c, },
+ { 0x99, 0x0101, },
+ { 0x9c, 0x2e37, },
+ { 0x9d, 0x2c37, },
+ { 0x9e, 0x2c37, },
+ { 0xab, 0x0100, },
+ { 0xac, 0x1003, },
+ { 0xad, 0x103f, },
+ { 0xe2, 0x0100, },
+ { 0x28, 0x1010, },
+ { 0xb1, 0x000e, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+ u16 val;
+ u16 data;
+} vsb_snr_tab[] = {
+ { 1023, 770, },
+ { 923, 300, },
+ { 918, 295, },
+ { 915, 290, },
+ { 911, 285, },
+ { 906, 280, },
+ { 901, 275, },
+ { 896, 270, },
+ { 891, 265, },
+ { 885, 260, },
+ { 879, 255, },
+ { 873, 250, },
+ { 864, 245, },
+ { 858, 240, },
+ { 850, 235, },
+ { 841, 230, },
+ { 832, 225, },
+ { 823, 220, },
+ { 812, 215, },
+ { 802, 210, },
+ { 788, 205, },
+ { 778, 200, },
+ { 767, 195, },
+ { 753, 190, },
+ { 740, 185, },
+ { 725, 180, },
+ { 707, 175, },
+ { 689, 170, },
+ { 671, 165, },
+ { 656, 160, },
+ { 637, 155, },
+ { 616, 150, },
+ { 542, 145, },
+ { 519, 140, },
+ { 507, 135, },
+ { 497, 130, },
+ { 492, 125, },
+ { 474, 120, },
+ { 300, 111, },
+ { 0, 0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+ u16 val;
+ u16 data;
+} qam64_snr_tab[] = {
+ { 12, 300, },
+ { 15, 290, },
+ { 18, 280, },
+ { 22, 270, },
+ { 23, 268, },
+ { 24, 266, },
+ { 25, 264, },
+ { 27, 262, },
+ { 28, 260, },
+ { 29, 258, },
+ { 30, 256, },
+ { 32, 254, },
+ { 33, 252, },
+ { 34, 250, },
+ { 35, 249, },
+ { 36, 248, },
+ { 37, 247, },
+ { 38, 246, },
+ { 39, 245, },
+ { 40, 244, },
+ { 41, 243, },
+ { 42, 241, },
+ { 43, 240, },
+ { 44, 239, },
+ { 45, 238, },
+ { 46, 237, },
+ { 47, 236, },
+ { 48, 235, },
+ { 49, 234, },
+ { 50, 233, },
+ { 51, 232, },
+ { 52, 231, },
+ { 53, 230, },
+ { 55, 229, },
+ { 56, 228, },
+ { 57, 227, },
+ { 58, 226, },
+ { 59, 225, },
+ { 60, 224, },
+ { 62, 223, },
+ { 63, 222, },
+ { 65, 221, },
+ { 66, 220, },
+ { 68, 219, },
+ { 69, 218, },
+ { 70, 217, },
+ { 72, 216, },
+ { 73, 215, },
+ { 75, 214, },
+ { 76, 213, },
+ { 78, 212, },
+ { 80, 211, },
+ { 81, 210, },
+ { 83, 209, },
+ { 84, 208, },
+ { 85, 207, },
+ { 87, 206, },
+ { 89, 205, },
+ { 91, 204, },
+ { 93, 203, },
+ { 95, 202, },
+ { 96, 201, },
+ { 104, 200, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+ u16 val;
+ u16 data;
+} qam256_snr_tab[] = {
+ { 12, 400, },
+ { 13, 390, },
+ { 15, 380, },
+ { 17, 360, },
+ { 19, 350, },
+ { 22, 348, },
+ { 23, 346, },
+ { 24, 344, },
+ { 25, 342, },
+ { 26, 340, },
+ { 27, 336, },
+ { 28, 334, },
+ { 29, 332, },
+ { 30, 330, },
+ { 31, 328, },
+ { 32, 326, },
+ { 33, 325, },
+ { 34, 322, },
+ { 35, 320, },
+ { 37, 318, },
+ { 39, 316, },
+ { 40, 314, },
+ { 41, 312, },
+ { 42, 310, },
+ { 43, 308, },
+ { 46, 306, },
+ { 47, 304, },
+ { 49, 302, },
+ { 51, 300, },
+ { 53, 298, },
+ { 54, 297, },
+ { 55, 296, },
+ { 56, 295, },
+ { 57, 294, },
+ { 59, 293, },
+ { 60, 292, },
+ { 61, 291, },
+ { 63, 290, },
+ { 64, 289, },
+ { 65, 288, },
+ { 66, 287, },
+ { 68, 286, },
+ { 69, 285, },
+ { 71, 284, },
+ { 72, 283, },
+ { 74, 282, },
+ { 75, 281, },
+ { 76, 280, },
+ { 77, 279, },
+ { 78, 278, },
+ { 81, 277, },
+ { 83, 276, },
+ { 84, 275, },
+ { 86, 274, },
+ { 87, 273, },
+ { 89, 272, },
+ { 90, 271, },
+ { 92, 270, },
+ { 93, 269, },
+ { 95, 268, },
+ { 96, 267, },
+ { 98, 266, },
+ { 100, 265, },
+ { 102, 264, },
+ { 104, 263, },
+ { 105, 262, },
+ { 106, 261, },
+ { 110, 260, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+{
+ int ret;
+ u8 buf [] = { reg, data >> 8, data & 0xff };
+
+ struct i2c_msg msg = { .addr = state->config->demod_address,
+ .flags = 0, .buf = buf, .len = 3 };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+ "ret == %i)\n", __FUNCTION__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+{
+ int ret;
+ u8 b0 [] = { reg };
+ u8 b1 [] = { 0, 0 };
+
+ struct i2c_msg msg [] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 2 } };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1409_softreset(struct dvb_frontend* fe)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __FUNCTION__);
+
+ s5h1409_writereg(state, 0xf5, 0);
+ s5h1409_writereg(state, 0xf5, 1);
+ return 0;
+}
+
+static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+ int ret = 0;
+
+ dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
+
+ if( (KHz == 44000) || (KHz == 5380) ) {
+ s5h1409_writereg(state, 0x87, 0x01be);
+ s5h1409_writereg(state, 0x88, 0x0436);
+ s5h1409_writereg(state, 0x89, 0x054d);
+ } else {
+ printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __FUNCTION__);
+
+ if(inverted == 1)
+ return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
+ else
+ return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
+}
+
+static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+ fe_modulation_t m)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s(0x%08x)\n", __FUNCTION__, m);
+
+ switch(m) {
+ case VSB_8:
+ dprintk("%s() VSB_8\n", __FUNCTION__);
+ s5h1409_writereg(state, 0xf4, 0);
+ break;
+ case QAM_64:
+ dprintk("%s() QAM_64\n", __FUNCTION__);
+ s5h1409_writereg(state, 0xf4, 1);
+ s5h1409_writereg(state, 0x85, 0x100);
+ break;
+ case QAM_256:
+ dprintk("%s() QAM_256\n", __FUNCTION__);
+ s5h1409_writereg(state, 0xf4, 1);
+ s5h1409_writereg(state, 0x85, 0x101);
+ break;
+ default:
+ dprintk("%s() Invalid modulation\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ state->current_modulation = m;
+ s5h1409_softreset(fe);
+
+ return 0;
+}
+
+static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __FUNCTION__, enable);
+
+ if (enable)
+ return s5h1409_writereg(state, 0xf3, 1);
+ else
+ return s5h1409_writereg(state, 0xf3, 0);
+}
+
+static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __FUNCTION__, enable);
+
+ if (enable)
+ return s5h1409_writereg(state, 0xe3, 0x1100);
+ else
+ return s5h1409_writereg(state, 0xe3, 0);
+}
+
+static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __FUNCTION__, enable);
+
+ return s5h1409_writereg(state, 0xf2, enable);
+}
+
+static int s5h1409_register_reset(struct dvb_frontend* fe)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __FUNCTION__);
+
+ return s5h1409_writereg(state, 0xfa, 0);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1409_set_frontend (struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
+
+ s5h1409_softreset(fe);
+
+ state->current_frequency = p->frequency;
+
+ s5h1409_enable_modulation(fe, p->u.vsb.modulation);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+ to a default state. */
+static int s5h1409_init (struct dvb_frontend* fe)
+{
+ int i;
+
+ struct s5h1409_state* state = fe->demodulator_priv;
+ dprintk("%s()\n", __FUNCTION__);
+
+ s5h1409_sleep(fe, 0);
+ s5h1409_register_reset(fe);
+
+ for (i=0; i < ARRAY_SIZE(init_tab); i++)
+ s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+ /* The datasheet says that after initialisation, VSB is default */
+ state->current_modulation = VSB_8;
+
+ if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
+ s5h1409_writereg(state, 0xab, 0x100); /* Serial */
+ else
+ s5h1409_writereg(state, 0xab, 0x0); /* Parallel */
+
+ s5h1409_set_spectralinversion(fe, state->config->inversion);
+ s5h1409_set_if_freq(fe, state->config->if_freq);
+ s5h1409_set_gpio(fe, state->config->gpio);
+ s5h1409_softreset(fe);
+
+ /* Note: Leaving the I2C gate open here. */
+ s5h1409_i2c_gate_ctrl(fe, 1);
+
+ return 0;
+}
+
+static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+ u16 reg;
+ u32 tuner_status = 0;
+
+ *status = 0;
+
+ /* Get the demodulator status */
+ reg = s5h1409_readreg(state, 0xf1);
+ if(reg & 0x1000)
+ *status |= FE_HAS_VITERBI;
+ if(reg & 0x8000)
+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+
+ switch(state->config->status_mode) {
+ case S5H1409_DEMODLOCKING:
+ if (*status & FE_HAS_VITERBI)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ break;
+ case S5H1409_TUNERLOCKING:
+ /* Get the tuner status */
+ if (fe->ops.tuner_ops.get_status) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (tuner_status)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ break;
+ }
+
+ dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
+
+ return 0;
+}
+
+static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __FUNCTION__);
+
+ for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+ if (v < qam256_snr_tab[i].val) {
+ *snr = qam256_snr_tab[i].data;
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __FUNCTION__);
+
+ for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+ if (v < qam64_snr_tab[i].val) {
+ *snr = qam64_snr_tab[i].data;
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __FUNCTION__);
+
+ for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+ if (v > vsb_snr_tab[i].val) {
+ *snr = vsb_snr_tab[i].data;
+ ret = 0;
+ break;
+ }
+ }
+ dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
+ return ret;
+}
+
+static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+ u16 reg;
+ dprintk("%s()\n", __FUNCTION__);
+
+ reg = s5h1409_readreg(state, 0xf1) & 0x1ff;
+
+ switch(state->current_modulation) {
+ case QAM_64:
+ return s5h1409_qam64_lookup_snr(fe, snr, reg);
+ case QAM_256:
+ return s5h1409_qam256_lookup_snr(fe, snr, reg);
+ case VSB_8:
+ return s5h1409_vsb_lookup_snr(fe, snr, reg);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int s5h1409_read_signal_strength(struct dvb_frontend* fe,
+ u16* signal_strength)
+{
+ return s5h1409_read_snr(fe, signal_strength);
+}
+
+static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ *ucblocks = s5h1409_readreg(state, 0xb5);
+
+ return 0;
+}
+
+static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ return s5h1409_read_ucblocks(fe, ber);
+}
+
+static int s5h1409_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+ p->frequency = state->current_frequency;
+ p->u.vsb.modulation = state->current_modulation;
+
+ return 0;
+}
+
+static int s5h1409_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void s5h1409_release(struct dvb_frontend* fe)
+{
+ struct s5h1409_state* state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1409_ops;
+
+struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct s5h1409_state* state = NULL;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->current_modulation = 0;
+
+ /* check if the demod exists */
+ if (s5h1409_readreg(state, 0x04) != 0x0066)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &s5h1409_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ /* Note: Leaving the I2C gate open here. */
+ s5h1409_writereg(state, 0xf3, 1);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+
+static struct dvb_frontend_ops s5h1409_ops = {
+
+ .info = {
+ .name = "Samsung S5H1409 QAM/8VSB Frontend",
+ .type = FE_ATSC,
+ .frequency_min = 54000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 62500,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+
+ .init = s5h1409_init,
+ .i2c_gate_ctrl = s5h1409_i2c_gate_ctrl,
+ .set_frontend = s5h1409_set_frontend,
+ .get_frontend = s5h1409_get_frontend,
+ .get_tune_settings = s5h1409_get_tune_settings,
+ .read_status = s5h1409_read_status,
+ .read_ber = s5h1409_read_ber,
+ .read_signal_strength = s5h1409_read_signal_strength,
+ .read_snr = s5h1409_read_snr,
+ .read_ucblocks = s5h1409_read_ucblocks,
+ .release = s5h1409_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(s5h1409_attach);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
new file mode 100644
index 000000000000..20f9af1af445
--- /dev/null
+++ b/drivers/media/dvb/frontends/s5h1409.h
@@ -0,0 +1,73 @@
+/*
+ Samsung S5H1409 VSB/QAM demodulator driver
+
+ Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __S5H1409_H__
+#define __S5H1409_H__
+
+#include <linux/dvb/frontend.h>
+
+struct s5h1409_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* serial/parallel output */
+#define S5H1409_PARALLEL_OUTPUT 0
+#define S5H1409_SERIAL_OUTPUT 1
+ u8 output_mode;
+
+ /* GPIO Setting */
+#define S5H1409_GPIO_OFF 0
+#define S5H1409_GPIO_ON 1
+ u8 gpio;
+
+ /* IF Freq in KHz */
+ u16 if_freq;
+
+ /* Spectral Inversion */
+#define S5H1409_INVERSION_OFF 0
+#define S5H1409_INVERSION_ON 1
+ u8 inversion;
+
+ /* Return lock status based on tuner lock, or demod lock */
+#define S5H1409_TUNERLOCKING 0
+#define S5H1409_DEMODLOCKING 1
+ u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
+extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_S5H1409 */
+
+#endif /* __S5H1409_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index d98fd5c2e13e..da876f7bfe32 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -29,7 +29,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 5c2f8f4e0ae5..1aa2539f5099 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -12,7 +12,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 9a343972ff50..17e5cb561cd8 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -680,8 +680,8 @@ static struct dvb_frontend_ops stv0297_ops = {
.info = {
.name = "ST STV0297 DVB-C",
.type = FE_QAM,
- .frequency_min = 64000000,
- .frequency_max = 1300000000,
+ .frequency_min = 47000000,
+ .frequency_max = 862000000,
.frequency_stepsize = 62500,
.symbol_rate_min = 870000,
.symbol_rate_max = 11700000,
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 18768d2f6d40..035dd7ba6519 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -45,7 +45,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
@@ -249,7 +248,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
dprintk ("%s\n", __FUNCTION__);
stv0299_readregs (state, 0x1f, sfr, 3);
- stv0299_readregs (state, 0x1a, &rtf, 1);
+ stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
srate = (sfr[0] << 8) | sfr[1];
srate *= Mclk;
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index e725f612a6b7..4cd9e82c4669 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -439,8 +439,8 @@ static struct dvb_frontend_ops tda10021_ops = {
.name = "Philips TDA10021 DVB-C",
.type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 51000000,
- .frequency_max = 858000000,
+ .frequency_min = 47000000,
+ .frequency_max = 862000000,
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
#if 0
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
index da796e784be3..364bc01971a0 100644
--- a/drivers/media/dvb/frontends/tda10023.c
+++ b/drivers/media/dvb/frontends/tda10023.c
@@ -215,12 +215,6 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
s16 SFIL=0;
u16 NDEC = 0;
- if (sr > (SYSCLK/(2*4)))
- sr=SYSCLK/(2*4);
-
- if (sr<870000)
- sr=870000;
-
if (sr < (u32)(SYSCLK/98.40)) {
NDEC=3;
SFIL=1;
@@ -478,7 +472,7 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
state->i2c = i2c;
memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
state->pwm = pwm;
- for (i=0; i < sizeof(tda10023_inittab)/sizeof(*tda10023_inittab);i+=3) {
+ for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) {
if (tda10023_inittab[i] == 0x00) {
state->reg0 = tda10023_inittab[i+2];
break;
@@ -506,8 +500,8 @@ static struct dvb_frontend_ops tda10023_ops = {
.name = "Philips TDA10023 DVB-C",
.type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 51000000,
- .frequency_max = 858000000,
+ .frequency_min = 47000000,
+ .frequency_max = 862000000,
.symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */
.symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */
.caps = 0x400 | //FE_CAN_QAM_4
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 33a84372c9e6..8415a8a5247a 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -31,7 +31,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index 0f2d4b415560..9a8ddc537f8f 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 67415c9db6f7..011b74f798a0 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
@@ -443,12 +442,12 @@ static struct dvb_frontend_ops tda8083_ops = {
.info = {
.name = "Philips TDA8083 DVB-S",
.type = FE_QPSK,
- .frequency_min = 950000, /* FIXME: guessed! */
- .frequency_max = 1400000, /* FIXME: guessed! */
+ .frequency_min = 920000, /* TDA8060 */
+ .frequency_max = 2200000, /* TDA8060 */
.frequency_stepsize = 125, /* kHz for QPSK frontends */
/* .frequency_tolerance = ???,*/
- .symbol_rate_min = 1000000, /* FIXME: guessed! */
- .symbol_rate_max = 45000000, /* FIXME: guessed! */
+ .symbol_rate_min = 12000000,
+ .symbol_rate_max = 30000000,
/* .symbol_rate_tolerance = ???,*/
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 9b57576bfeb4..066b73b75698 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -410,8 +410,8 @@ static struct dvb_frontend_ops ves1820_ops = {
.name = "VLSI VES1820 DVB-C",
.type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 51000000,
- .frequency_max = 858000000,
+ .frequency_min = 47000000,
+ .frequency_max = 862000000,
.caps = FE_CAN_QAM_16 |
FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index 245f9b7dddfa..a97a7fd2c891 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -21,7 +21,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/string.h>
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
index ce6a9aaf937e..7ac128724df8 100644
--- a/drivers/media/dvb/pluto2/Makefile
+++ b/drivers/media/dvb/pluto2/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 7751628e1415..6d53289b3276 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -108,7 +108,7 @@ config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs"
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146_VV
- select DVB_PLL
+ select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index aa85ecdc6c80..2c1145236ee6 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index ef1108c0bf11..8b8144f77a73 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -40,7 +40,6 @@
#include <linux/smp_lock.h>
#include <linux/kernel.h>
-#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
@@ -137,6 +136,15 @@ static void init_av7110_av(struct av7110 *av7110)
if (ret < 0)
printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
+ 1, (u16) av7110->display_ar);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to set aspect ratio\n");
+ ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
+ 1, av7110->display_panscan);
+ if (ret < 0)
+ printk("dvb-ttpci: unable to set pan scan\n");
+
ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
if (ret < 0)
printk("dvb-ttpci: unable to configure 4:3 wss\n");
@@ -1534,7 +1542,7 @@ static int get_firmware(struct av7110* av7110)
}
/* check if the firmware is available */
- av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
+ av7110->bin_fw = vmalloc(fw->size);
if (NULL == av7110->bin_fw) {
dprintk(1, "out of memory\n");
release_firmware(fw);
@@ -2258,7 +2266,7 @@ static int frontend_init(struct av7110 *av7110)
FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
- FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
@@ -2639,12 +2647,12 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
av7110->mixer.volume_left = volume;
av7110->mixer.volume_right = volume;
- init_av7110_av(av7110);
-
ret = av7110_register(av7110);
if (ret < 0)
goto err_arm_thread_stop_10;
+ init_av7110_av(av7110);
+
/* special case DVB-C: these cards have an analog tuner
plus need some special handling, so we have separate
saa7146_ext_vv data for these... */
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 115002b0390c..0cb439527498 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -194,6 +194,7 @@ struct av7110 {
int video_blank;
struct video_status videostate;
+ u16 display_panscan;
int display_ar;
int trickmode;
#define TRICK_NONE 0
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 58678c05aa53..d75e7e48addc 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -391,7 +391,7 @@ static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
****************************************************************************/
static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf,
- const char *buf, unsigned long count)
+ const u8 *buf, unsigned long count)
{
unsigned long todo = count;
int free;
@@ -436,7 +436,7 @@ static void play_audio_cb(u8 *buf, int count, void *priv)
#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
-static ssize_t dvb_play(struct av7110 *av7110, const u8 __user *buf,
+static ssize_t dvb_play(struct av7110 *av7110, const char __user *buf,
unsigned long count, int nonblock, int type)
{
unsigned long todo = count, n;
@@ -499,7 +499,7 @@ static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf,
return count - todo;
}
-static ssize_t dvb_aplay(struct av7110 *av7110, const u8 __user *buf,
+static ssize_t dvb_aplay(struct av7110 *av7110, const char __user *buf,
unsigned long count, int nonblock, int type)
{
unsigned long todo = count, n;
@@ -959,7 +959,7 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x
#define MIN_IFRAME 400000
-static int play_iframe(struct av7110 *av7110, u8 __user *buf, unsigned int len, int nonblock)
+static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
{
int i, n;
@@ -1082,19 +1082,18 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
case VIDEO_SET_DISPLAY_FORMAT:
{
video_displayformat_t format = (video_displayformat_t) arg;
- u16 val = 0;
switch (format) {
case VIDEO_PAN_SCAN:
- val = VID_PAN_SCAN_PREF;
+ av7110->display_panscan = VID_PAN_SCAN_PREF;
break;
case VIDEO_LETTER_BOX:
- val = VID_VC_AND_PS_PREF;
+ av7110->display_panscan = VID_VC_AND_PS_PREF;
break;
case VIDEO_CENTER_CUT_OUT:
- val = VID_CENTRE_CUT_PREF;
+ av7110->display_panscan = VID_CENTRE_CUT_PREF;
break;
default:
@@ -1104,7 +1103,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
break;
av7110->videostate.display_format = format;
ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
- 1, (u16) val);
+ 1, av7110->display_panscan);
break;
}
@@ -1466,8 +1465,9 @@ int av7110_av_register(struct av7110 *av7110)
av7110->videostate.play_state = VIDEO_STOPPED;
av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
- av7110->videostate.display_format = VIDEO_CENTER_CUT_OUT;
+ av7110->videostate.display_format = VIDEO_LETTER_BOX;
av7110->display_ar = VIDEO_FORMAT_4_3;
+ av7110->display_panscan = VID_VC_AND_PS_PREF;
init_waitqueue_head(&av7110->video_events.wait_queue);
spin_lock_init(&av7110->video_events.lock);
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index e1c1294bb767..c58e3fc509ed 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -151,7 +151,7 @@ static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file,
{
int free;
int non_blocking = file->f_flags & O_NONBLOCK;
- char *page = (char *)__get_free_page(GFP_USER);
+ u8 *page = (u8 *)__get_free_page(GFP_USER);
int res;
if (!page)
@@ -208,7 +208,7 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
return -EINVAL;
DVB_RINGBUFFER_SKIP(cibuf, 2);
- return dvb_ringbuffer_read(cibuf, buf, len, 1);
+ return dvb_ringbuffer_read(cibuf, (u8 *)buf, len, 1);
}
static int dvb_ca_open(struct inode *inode, struct file *file)
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 70aee4eb5da4..a468aa2e4854 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -158,7 +158,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
}
dprintk(4, "writing DRAM block %d\n", i);
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
bootblock ^= 0x1400;
iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
@@ -173,10 +173,10 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
}
if (rest > 4)
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest);
else
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
+ ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
@@ -751,7 +751,7 @@ static int FlushText(struct av7110 *av7110)
return 0;
}
-static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
+static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
{
int i, ret;
unsigned long start;
@@ -978,24 +978,24 @@ static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 ble
static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
{
- int i;
- int length = last - first + 1;
+ int i;
+ int length = last - first + 1;
- if (length * 4 > DATA_BUFF3_SIZE)
- return -EINVAL;
+ if (length * 4 > DATA_BUFF3_SIZE)
+ return -EINVAL;
- for (i = 0; i < length; i++) {
- u32 color, blend, yuv;
+ for (i = 0; i < length; i++) {
+ u32 color, blend, yuv;
- if (get_user(color, colors + i))
- return -EFAULT;
- blend = (color & 0xF0000000) >> 4;
- yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
+ if (get_user(color, colors + i))
+ return -EFAULT;
+ blend = (color & 0xF0000000) >> 4;
+ yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
(color >> 16) & 0xFF) | blend : 0;
- yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
- wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
- }
- return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
+ yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
+ wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
+ }
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
av7110->osdwin,
bpp2pal[av7110->osdbpp[av7110->osdwin]],
first, last);
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 673d9b3f064c..74d940f75da6 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -393,7 +393,7 @@ static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val,
}
/* buffer writes */
-static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, char *val, int count)
+static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, u8 *val, int count)
{
memcpy(av7110->debi_virt, val, count);
av7110_debiwrite(av7110, config, addr, 0, count);
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index a97f166bb523..5d19c402dad1 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -25,7 +25,6 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <asm/bitops.h>
@@ -280,7 +279,7 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
if (count < size)
return -EINVAL;
- page = (char *) vmalloc(size);
+ page = vmalloc(size);
if (!page)
return -ENOMEM;
@@ -356,7 +355,7 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
input_dev->id.vendor = av7110->dev->pci->vendor;
input_dev->id.product = av7110->dev->pci->device;
}
- input_dev->cdev.dev = &av7110->dev->pci->dev;
+ input_dev->dev.parent = &av7110->dev->pci->dev;
/* initial keymap */
memcpy(av7110->ir.key_map, default_key_map, sizeof av7110->ir.key_map);
input_register_keys(&av7110->ir);
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index fcd9994058d0..76cca003252f 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -129,23 +129,25 @@ static struct v4l2_input inputs[4] = {
static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
{
+ struct av7110 *av7110 = dev->ext_priv;
u8 buf[] = { 0x00, reg, data };
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
dprintk(4, "dev: %p\n", dev);
- if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
+ if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
return -1;
return 0;
}
static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
{
+ struct av7110 *av7110 = dev->ext_priv;
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
dprintk(4, "dev: %p\n", dev);
- if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
+ if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
return -1;
return 0;
}
@@ -333,7 +335,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return -EINVAL;
memset(t, 0, sizeof(*t));
- strcpy(t->name, "Television");
+ strcpy((char *)t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 0e817d6f1ce5..3439c9864f67 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -828,29 +828,6 @@ static u8 philips_sd1878_inittab[] = {
0xff, 0xff
};
-static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- u8 buf[4];
- int rc;
- struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
- struct budget *budget = (struct budget *) fe->dvb->priv;
-
- if((params->frequency < 950000) || (params->frequency > 2150000))
- return -EINVAL;
-
- rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
- params->frequency, 0);
- if(rc < 0) return rc;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
-
- return 0;
-}
-
static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
u32 srate, u32 ratio)
{
@@ -921,6 +898,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_TV_STAR 0x0014
#define SUBID_DVBS_TV_STAR_CI 0x0016
#define SUBID_DVBS_EASYWATCH_1 0x001a
+#define SUBID_DVBS_EASYWATCH_2 0x001b
#define SUBID_DVBS_EASYWATCH 0x001e
#define SUBID_DVBC_EASYWATCH 0x002a
@@ -982,10 +960,13 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBS_TV_STAR_CI:
case SUBID_DVBS_CYNERGY1200N:
case SUBID_DVBS_EASYWATCH:
+ case SUBID_DVBS_EASYWATCH_2:
fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
&budget_av->budget.i2c_adap);
if (fe) {
- fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
+ dvb_attach(dvb_pll_attach, fe, 0x60,
+ &budget_av->budget.i2c_adap,
+ DVB_PLL_PHILIPS_SD1878_TDA8261);
}
break;
@@ -1251,7 +1232,7 @@ static struct saa7146_ext_vv vv_data = {
.capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
.flags = 0,
.stds = &standard[0],
- .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
+ .num_stds = ARRAY_SIZE(standard),
.ioctls = &ioctls[0],
.ioctl = av_ioctl,
};
@@ -1264,6 +1245,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
@@ -1287,6 +1269,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
+ MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 9d42f88ebb0e..509349211d4f 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -206,7 +206,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
input_dev->id.vendor = saa->pci->vendor;
input_dev->id.product = saa->pci->device;
}
- input_dev->cdev.dev = &saa->pci->dev;
+ input_dev->dev.parent = &saa->pci->dev;
/* Select keymap and address */
switch (budget_ci->budget.dev->pci->subsystem_device) {
@@ -214,7 +214,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
case 0x100f:
case 0x1011:
case 0x1012:
- case 0x1017:
/* The hauppauge keymap is a superset of these remotes */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_hauppauge_new);
@@ -225,6 +224,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
budget_ci->ir.rc5_device = rc5_device;
break;
case 0x1010:
+ case 0x1017:
/* for the Technotrend 1500 bundled remote */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_tt_1500);
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index b611f2b1f8bc..0252081f013c 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -34,7 +34,6 @@
* the project's page is at http://www.linuxtv.org/dvb/
*/
-#include <linux/moduleparam.h>
#include "budget.h"
#include "ttpci-eeprom.h"
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
index 6ab97f6b53fc..fbe2b9514c21 100644
--- a/drivers/media/dvb/ttusb-budget/Makefile
+++ b/drivers/media/dvb/ttusb-budget/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index b60cdc93d6db..288e79f2cb0f 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -13,7 +13,6 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/delay.h>
#include <linux/time.h>
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile
index b41bf1f06a9f..2d70a8269391 100644
--- a/drivers/media/dvb/ttusb-dec/Makefile
+++ b/drivers/media/dvb/ttusb-dec/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 78c98b089975..5e691fd79904 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -22,7 +22,6 @@
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 194b102140ef..11e962f1a97f 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -111,11 +111,16 @@ config RADIO_AZTECH_PORT
jumper sets the card to 0x358.
config RADIO_GEMTEK
- tristate "GemTek Radio Card support"
+ tristate "GemTek Radio card (or compatible) support"
depends on ISA && VIDEO_V4L2
---help---
Choose Y here if you have this FM radio card, and then fill in the
- port address below.
+ I/O port address and settings below. The following cards either have
+ GemTek Radio tuner or are rebranded GemTek Radio cards:
+
+ - Sound Vision 16 Gold with FM Radio
+ - Typhoon Radio card (some models)
+ - Hama Radio card
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
@@ -126,14 +131,25 @@ config RADIO_GEMTEK
module will be called radio-gemtek.
config RADIO_GEMTEK_PORT
- hex "GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)"
+ hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)"
depends on RADIO_GEMTEK=y
default "34c"
help
Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
0x34c, if you haven't changed the jumper setting on the card. On
Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
- port is 0x28c.
+ port is 0x20c, 0x248 or 0x28c.
+ If automatic I/O port probing is enabled this port will be used only
+ in case of automatic probing failure, ie. as a fallback.
+
+config RADIO_GEMTEK_PROBE
+ bool "Automatic I/O port probing"
+ depends on RADIO_GEMTEK=y
+ default y
+ help
+ Say Y here to enable automatic probing for GemTek Radio card. The
+ following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
+ 0x28c.
config RADIO_GEMTEK_PCI
tristate "GemTek PCI Radio Card support"
@@ -324,8 +340,8 @@ config RADIO_ZOLTRIX_PORT
Enter the I/O port of your Zoltrix radio card.
config USB_DSBR
- tristate "D-Link USB FM radio support (EXPERIMENTAL)"
- depends on USB && VIDEO_V4L2 && EXPERIMENTAL
+ tristate "D-Link/GemTek USB FM radio support"
+ depends on USB && VIDEO_V4L2
---help---
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 5adc27c3ced9..f0a67e93d7fd 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -63,7 +63,7 @@ struct rt_device
static void sleep_delay(long n)
{
/* Sleep nicely for 'n' uS */
- int d=n/(1000000/HZ);
+ int d=n/msecs_to_jiffies(1000);
if(!d)
udelay(n);
else
@@ -392,7 +392,6 @@ static struct video_device rtrack_radio=
.owner = THIS_MODULE,
.name = "RadioTrack radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &rtrack_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 9f1addae6928..9b1f7a99dac0 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -355,7 +355,6 @@ static struct video_device aztech_radio=
.owner = THIS_MODULE,
.name = "Aztech radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &aztech_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 8cf2e9df5c8a..34e317ced5a3 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -329,7 +329,7 @@ cadet_handler(unsigned long data)
init_timer(&readtimer);
readtimer.function=cadet_handler;
readtimer.data=(unsigned long)0;
- readtimer.expires=jiffies+(HZ/20);
+ readtimer.expires=jiffies+msecs_to_jiffies(50);
add_timer(&readtimer);
}
@@ -349,7 +349,7 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
init_timer(&readtimer);
readtimer.function=cadet_handler;
readtimer.data=(unsigned long)0;
- readtimer.expires=jiffies+(HZ/20);
+ readtimer.expires=jiffies+msecs_to_jiffies(50);
add_timer(&readtimer);
}
if(rdsin==rdsout) {
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 5e6f17df204b..99a323131333 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -94,7 +94,6 @@ struct gemtek_pci_card {
u32 iobase;
u32 length;
- u16 model;
u32 current_frequency;
u8 mute;
@@ -377,7 +376,6 @@ static struct video_device vdev_template = {
.owner = THIS_MODULE,
.name = "Gemtek PCI Radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &gemtek_pci_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
@@ -414,8 +412,6 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
goto err_pci;
}
- pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
-
pci_set_drvdata( pci_dev, card );
if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) {
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index b04b6a7fff7c..0c963db03614 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -26,143 +26,383 @@
#include <media/v4l2-common.h>
#include <linux/spinlock.h>
-#include <linux/version.h> /* for KERNEL_VERSION MACRO */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+#define RADIO_VERSION KERNEL_VERSION(0,0,3)
+#define RADIO_BANNER "GemTek Radio card driver: v0.0.3"
-static struct v4l2_queryctrl radio_qctrl[] = {
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_AUDIO_VOLUME,
- .name = "Volume",
- .minimum = 0,
- .maximum = 65535,
- .step = 65535,
- .default_value = 0xff,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }
-};
+/*
+ * Module info.
+ */
+
+MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
+MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
+MODULE_LICENSE("GPL");
+
+/*
+ * Module params.
+ */
#ifndef CONFIG_RADIO_GEMTEK_PORT
#define CONFIG_RADIO_GEMTEK_PORT -1
#endif
+#ifndef CONFIG_RADIO_GEMTEK_PROBE
+#define CONFIG_RADIO_GEMTEK_PROBE 1
+#endif
-static int io = CONFIG_RADIO_GEMTEK_PORT;
-static int radio_nr = -1;
-static spinlock_t lock;
+static int io = CONFIG_RADIO_GEMTEK_PORT;
+static int probe = CONFIG_RADIO_GEMTEK_PROBE;
+static int hardmute;
+static int shutdown = 1;
+static int keepmuted = 1;
+static int initmute = 1;
+static int radio_nr = -1;
-struct gemtek_device
-{
- int port;
- unsigned long curfreq;
+module_param(io, int, 0444);
+MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic"
+ "probing is disabled or fails. The most common I/O ports are: 0x20c "
+ "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
+ " work for the combined sound/radiocard).");
+
+module_param(probe, bool, 0444);
+MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
+ "common I/O ports used by the card are probed.");
+
+module_param(hardmute, bool, 0644);
+MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may "
+ "reduce static noise.");
+
+module_param(shutdown, bool, 0644);
+MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when "
+ "module is unloaded.");
+
+module_param(keepmuted, bool, 0644);
+MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed.");
+
+module_param(initmute, bool, 0444);
+MODULE_PARM_DESC(initmute, "Mute card when module is loaded.");
+
+module_param(radio_nr, int, 0444);
+
+/*
+ * Functions for controlling the card.
+ */
+#define GEMTEK_LOWFREQ (87*16000)
+#define GEMTEK_HIGHFREQ (108*16000)
+
+/*
+ * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal
+ * value 10.7 MHz), reference divisor 6.39 kHz (nominal 6.25 kHz).
+ */
+#define FSCALE 8
+#define IF_OFFSET ((unsigned int)(10.52 * 16000 * (1<<FSCALE)))
+#define REF_FREQ ((unsigned int)(6.39 * 16 * (1<<FSCALE)))
+
+#define GEMTEK_CK 0x01 /* Clock signal */
+#define GEMTEK_DA 0x02 /* Serial data */
+#define GEMTEK_CE 0x04 /* Chip enable */
+#define GEMTEK_NS 0x08 /* No signal */
+#define GEMTEK_MT 0x10 /* Line mute */
+#define GEMTEK_STDF_3_125_KHZ 0x01 /* Standard frequency 3.125 kHz */
+#define GEMTEK_PLL_OFF 0x07 /* PLL off */
+
+#define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */
+
+#define SHORT_DELAY 5 /* usec */
+#define LONG_DELAY 75 /* usec */
+
+struct gemtek_device {
+ unsigned long lastfreq;
int muted;
+ u32 bu2614data;
};
+#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
+#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
+#define BU2614_VOID_BITS 4 /* unused */
+#define BU2614_FMES_BITS 1 /* CT, Frequency measurement beginning data */
+#define BU2614_STDF_BITS 3 /* R0..R2, Standard frequency data */
+#define BU2614_SWIN_BITS 1 /* S, Switch between FMIN / AMIN */
+#define BU2614_SWAL_BITS 1 /* PS, Swallow counter division (AMIN only)*/
+#define BU2614_VOID2_BITS 1 /* unused */
+#define BU2614_FMUN_BITS 1 /* GT, Frequency measurement time & unlock */
+#define BU2614_TEST_BITS 1 /* TS, Test data is input */
+
+#define BU2614_FREQ_SHIFT 0
+#define BU2614_PORT_SHIFT (BU2614_FREQ_BITS + BU2614_FREQ_SHIFT)
+#define BU2614_VOID_SHIFT (BU2614_PORT_BITS + BU2614_PORT_SHIFT)
+#define BU2614_FMES_SHIFT (BU2614_VOID_BITS + BU2614_VOID_SHIFT)
+#define BU2614_STDF_SHIFT (BU2614_FMES_BITS + BU2614_FMES_SHIFT)
+#define BU2614_SWIN_SHIFT (BU2614_STDF_BITS + BU2614_STDF_SHIFT)
+#define BU2614_SWAL_SHIFT (BU2614_SWIN_BITS + BU2614_SWIN_SHIFT)
+#define BU2614_VOID2_SHIFT (BU2614_SWAL_BITS + BU2614_SWAL_SHIFT)
+#define BU2614_FMUN_SHIFT (BU2614_VOID2_BITS + BU2614_VOID2_SHIFT)
+#define BU2614_TEST_SHIFT (BU2614_FMUN_BITS + BU2614_FMUN_SHIFT)
+
+#define MKMASK(field) (((1<<BU2614_##field##_BITS) - 1) << \
+ BU2614_##field##_SHIFT)
+#define BU2614_PORT_MASK MKMASK(PORT)
+#define BU2614_FREQ_MASK MKMASK(FREQ)
+#define BU2614_VOID_MASK MKMASK(VOID)
+#define BU2614_FMES_MASK MKMASK(FMES)
+#define BU2614_STDF_MASK MKMASK(STDF)
+#define BU2614_SWIN_MASK MKMASK(SWIN)
+#define BU2614_SWAL_MASK MKMASK(SWAL)
+#define BU2614_VOID2_MASK MKMASK(VOID2)
+#define BU2614_FMUN_MASK MKMASK(FMUN)
+#define BU2614_TEST_MASK MKMASK(TEST)
-/* local things */
+static struct gemtek_device gemtek_unit;
-/* the correct way to mute the gemtek may be to write the last written
- * frequency || 0x10, but just writing 0x10 once seems to do it as well
+static spinlock_t lock;
+
+/*
+ * Set data which will be sent to BU2614FS.
*/
-static void gemtek_mute(struct gemtek_device *dev)
+#define gemtek_bu2614_set(dev, field, data) ((dev)->bu2614data = \
+ ((dev)->bu2614data & ~field##_MASK) | ((data) << field##_SHIFT))
+
+/*
+ * Transmit settings to BU2614FS over GemTek IC.
+ */
+static void gemtek_bu2614_transmit(struct gemtek_device *dev)
{
- if(dev->muted)
- return;
+ int i, bit, q, mute;
+
spin_lock(&lock);
- outb(0x10, io);
+
+ mute = dev->muted ? GEMTEK_MT : 0x00;
+
+ outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
+ udelay(SHORT_DELAY);
+ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
+ udelay(LONG_DELAY);
+
+ for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) {
+ bit = (q & 1) ? GEMTEK_DA : 0;
+ outb_p(mute | GEMTEK_CE | bit, io);
+ udelay(SHORT_DELAY);
+ outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io);
+ udelay(SHORT_DELAY);
+ }
+
+ outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
+ udelay(SHORT_DELAY);
+ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
+ udelay(LONG_DELAY);
+
spin_unlock(&lock);
- dev->muted = 1;
}
-static void gemtek_unmute(struct gemtek_device *dev)
+/*
+ * Calculate divisor from FM-frequency for BU2614FS (3.125 KHz STDF expected).
+ */
+static unsigned long gemtek_convfreq(unsigned long freq)
{
- if(dev->muted == 0)
+ return ((freq<<FSCALE) + IF_OFFSET + REF_FREQ/2) / REF_FREQ;
+}
+
+/*
+ * Set FM-frequency.
+ */
+static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
+{
+
+ if (keepmuted && hardmute && dev->muted)
return;
- spin_lock(&lock);
- outb(0x20, io);
- spin_unlock(&lock);
+
+ if (freq < GEMTEK_LOWFREQ)
+ freq = GEMTEK_LOWFREQ;
+ else if (freq > GEMTEK_HIGHFREQ)
+ freq = GEMTEK_HIGHFREQ;
+
+ dev->lastfreq = freq;
dev->muted = 0;
+
+ gemtek_bu2614_set(dev, BU2614_PORT, 0);
+ gemtek_bu2614_set(dev, BU2614_FMES, 0);
+ gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */
+ gemtek_bu2614_set(dev, BU2614_SWAL, 0);
+ gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */
+ gemtek_bu2614_set(dev, BU2614_TEST, 0);
+
+ gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
+ gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq));
+
+ gemtek_bu2614_transmit(dev);
}
-static void zero(void)
+/*
+ * Set mute flag.
+ */
+static void gemtek_mute(struct gemtek_device *dev)
{
- outb_p(0x04, io);
- udelay(5);
- outb_p(0x05, io);
- udelay(5);
+ int i;
+ dev->muted = 1;
+
+ if (hardmute) {
+ /* Turn off PLL, disable data output */
+ gemtek_bu2614_set(dev, BU2614_PORT, 0);
+ gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */
+ gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */
+ gemtek_bu2614_set(dev, BU2614_SWAL, 0);
+ gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */
+ gemtek_bu2614_set(dev, BU2614_TEST, 0);
+ gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF);
+ gemtek_bu2614_set(dev, BU2614_FREQ, 0);
+ gemtek_bu2614_transmit(dev);
+ } else {
+ spin_lock(&lock);
+
+ /* Read bus contents (CE, CK and DA). */
+ i = inb_p(io);
+ /* Write it back with mute flag set. */
+ outb_p((i >> 5) | GEMTEK_MT, io);
+ udelay(SHORT_DELAY);
+
+ spin_unlock(&lock);
+ }
}
-static void one(void)
+/*
+ * Unset mute flag.
+ */
+static void gemtek_unmute(struct gemtek_device *dev)
{
- outb_p(0x06, io);
- udelay(5);
- outb_p(0x07, io);
- udelay(5);
+ int i;
+ dev->muted = 0;
+
+ if (hardmute) {
+ /* Turn PLL back on. */
+ gemtek_setfreq(dev, dev->lastfreq);
+ } else {
+ spin_lock(&lock);
+
+ i = inb_p(io);
+ outb_p(i >> 5, io);
+ udelay(SHORT_DELAY);
+
+ spin_unlock(&lock);
+ }
}
-static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
+/*
+ * Get signal strength (= stereo status).
+ */
+static inline int gemtek_getsigstr(void)
{
- int i;
+ return inb_p(io) & GEMTEK_NS ? 0 : 1;
+}
-/* freq = 78.25*((float)freq/16000.0 + 10.52); */
+/*
+ * Check if requested card acts like GemTek Radio card.
+ */
+static int gemtek_verify(int port)
+{
+ static int verified = -1;
+ int i, q;
- freq /= 16;
- freq += 10520;
- freq *= 7825;
- freq /= 100000;
+ if (verified == port)
+ return 1;
spin_lock(&lock);
- /* 2 start bits */
- outb_p(0x03, io);
- udelay(5);
- outb_p(0x07, io);
- udelay(5);
+ q = inb_p(port); /* Read bus contents before probing. */
+ /* Try to turn on CE, CK and DA respectively and check if card responds
+ properly. */
+ for (i = 0; i < 3; ++i) {
+ outb_p(1 << i, port);
+ udelay(SHORT_DELAY);
- /* 28 frequency bits (lsb first) */
- for (i = 0; i < 14; i++)
- if (freq & (1 << i))
- one();
- else
- zero();
- /* 36 unknown bits */
- for (i = 0; i < 11; i++)
- zero();
- one();
- for (i = 0; i < 4; i++)
- zero();
- one();
- zero();
-
- /* 2 end bits */
- outb_p(0x03, io);
- udelay(5);
- outb_p(0x07, io);
- udelay(5);
+ if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
+ spin_unlock(&lock);
+ return 0;
+ }
+ }
+ outb_p(q >> 5, port); /* Write bus contents back. */
+ udelay(SHORT_DELAY);
spin_unlock(&lock);
+ verified = port;
- return 0;
+ return 1;
}
-static int gemtek_getsigstr(struct gemtek_device *dev)
+/*
+ * Automatic probing for card.
+ */
+static int gemtek_probe(void)
{
- spin_lock(&lock);
- inb(io);
- udelay(5);
- spin_unlock(&lock);
- if (inb(io) & 8) /* bit set = no signal present */
- return 0;
- return 1; /* signal present */
+ int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
+ int i;
+
+ if (!probe) {
+ printk(KERN_INFO "Automatic device probing disabled.\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "Automatic device probing enabled.\n");
+
+ for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
+ printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]);
+
+ if (!request_region(ioports[i], 1, "gemtek-probe")) {
+ printk(KERN_WARNING "I/O port 0x%x busy!\n",
+ ioports[i]);
+ continue;
+ }
+
+ if (gemtek_verify(ioports[i])) {
+ printk(KERN_INFO "Card found from I/O port "
+ "0x%x!\n", ioports[i]);
+
+ release_region(ioports[i], 1);
+
+ io = ioports[i];
+ return io;
+ }
+
+ release_region(ioports[i], 1);
+ }
+
+ printk(KERN_ERR "Automatic probing failed!\n");
+
+ return -1;
}
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *v)
+/*
+ * Video 4 Linux stuff.
+ */
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .default_value = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ }, {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535,
+ .default_value = 0xff,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
+};
+
+static struct file_operations gemtek_fops = {
+ .owner = THIS_MODULE,
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .llseek = no_llseek
+};
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
{
strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
strlcpy(v->card, "GemTek", sizeof(v->card));
@@ -172,28 +412,29 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
-
if (v->index > 0)
return -EINVAL;
strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO;
- v->rangelow = (87*16000);
- v->rangehigh = (108*16000);
- v->rxsubchans = V4L2_TUNER_SUB_MONO;
- v->capability = V4L2_TUNER_CAP_LOW;
- v->audmode = V4L2_TUNER_MODE_MONO;
- v->signal = 0xffff*gemtek_getsigstr(rt);
+ v->rangelow = GEMTEK_LOWFREQ;
+ v->rangehigh = GEMTEK_HIGHFREQ;
+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ v->signal = 0xffff * gemtek_getsigstr();
+ if (v->signal) {
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ } else {
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+
return 0;
}
-static int vidioc_s_tuner(struct file *file, void *priv,
- struct v4l2_tuner *v)
+static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
{
if (v->index > 0)
return -EINVAL;
@@ -201,38 +442,35 @@ static int vidioc_s_tuner(struct file *file, void *priv,
}
static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+ struct v4l2_frequency *f)
{
struct video_device *dev = video_devdata(file);
struct gemtek_device *rt = dev->priv;
- rt->curfreq = f->frequency;
- /* needs to be called twice in order for getsigstr to work */
- gemtek_setfreq(rt, rt->curfreq);
- gemtek_setfreq(rt, rt->curfreq);
+ gemtek_setfreq(rt, f->frequency);
+
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+ struct v4l2_frequency *f)
{
struct video_device *dev = video_devdata(file);
struct gemtek_device *rt = dev->priv;
f->type = V4L2_TUNER_RADIO;
- f->frequency = rt->curfreq;
+ f->frequency = rt->lastfreq;
return 0;
}
static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
+ struct v4l2_queryctrl *qc)
{
int i;
- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) {
if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]),
- sizeof(*qc));
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
return 0;
}
}
@@ -240,7 +478,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
}
static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
+ struct v4l2_control *ctrl)
{
struct video_device *dev = video_devdata(file);
struct gemtek_device *rt = dev->priv;
@@ -260,7 +498,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
}
static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
+ struct v4l2_control *ctrl)
{
struct video_device *dev = video_devdata(file);
struct gemtek_device *rt = dev->priv;
@@ -282,8 +520,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return -EINVAL;
}
-static int vidioc_g_audio (struct file *file, void *priv,
- struct v4l2_audio *a)
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
if (a->index > 1)
return -EINVAL;
@@ -306,100 +543,102 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
return 0;
}
-static int vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
if (a->index != 0)
return -EINVAL;
return 0;
}
-static struct gemtek_device gemtek_unit;
-
-static const struct file_operations gemtek_fops = {
- .owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
- .ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
+static struct video_device gemtek_radio = {
+ .owner = THIS_MODULE,
+ .name = "GemTek Radio card",
+ .type = VID_TYPE_TUNER,
+ .hardware = VID_HARDWARE_GEMTEK,
+ .fops = &gemtek_fops,
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl
};
-static struct video_device gemtek_radio=
-{
- .owner = THIS_MODULE,
- .name = "GemTek radio",
- .type = VID_TYPE_TUNER,
- .hardware = 0,
- .fops = &gemtek_fops,
- .vidioc_querycap = vidioc_querycap,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
-};
+/*
+ * Initialization / cleanup related stuff.
+ */
+/*
+ * Initilize card.
+ */
static int __init gemtek_init(void)
{
- if(io==-1)
- {
- printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x020c or io=0x248 for the combined sound/radiocard)\n");
- return -EINVAL;
- }
+ printk(KERN_INFO RADIO_BANNER "\n");
- if (!request_region(io, 4, "gemtek"))
- {
- printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
- return -EBUSY;
- }
+ spin_lock_init(&lock);
- gemtek_radio.priv=&gemtek_unit;
+ gemtek_probe();
+ if (io) {
+ if (!request_region(io, 1, "gemtek")) {
+ printk(KERN_ERR "I/O port 0x%x already in use.\n", io);
+ return -EBUSY;
+ }
- if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1)
- {
- release_region(io, 4);
+ if (!gemtek_verify(io))
+ printk(KERN_WARNING "Card at I/O port 0x%x does not "
+ "respond properly, check your "
+ "configuration.\n", io);
+ else
+ printk(KERN_INFO "Using I/O port 0x%x.\n", io);
+ } else if (probe) {
+ printk(KERN_ERR "Automatic probing failed and no "
+ "fixed I/O port defined.\n");
+ return -ENODEV;
+ } else {
+ printk(KERN_ERR "Automatic probing disabled but no fixed "
+ "I/O port defined.");
return -EINVAL;
}
- printk(KERN_INFO "GemTek Radio Card driver.\n");
- spin_lock_init(&lock);
+ gemtek_radio.priv = &gemtek_unit;
- /* this is _maybe_ unnecessary */
- outb(0x01, io);
+ if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO,
+ radio_nr) == -1) {
+ release_region(io, 1);
+ return -EBUSY;
+ }
- /* mute card - prevents noisy bootups */
- gemtek_unit.muted = 0;
- gemtek_mute(&gemtek_unit);
+ /* Set defaults */
+ gemtek_unit.lastfreq = GEMTEK_LOWFREQ;
+ gemtek_unit.bu2614data = 0;
+
+ if (initmute)
+ gemtek_mute(&gemtek_unit);
return 0;
}
-MODULE_AUTHOR("Jonas Munsin");
-MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard)).");
-module_param(radio_nr, int, 0);
-
-static void __exit gemtek_cleanup(void)
+/*
+ * Module cleanup
+ */
+static void __exit gemtek_exit(void)
{
+ if (shutdown) {
+ hardmute = 1; /* Turn off PLL */
+ gemtek_mute(&gemtek_unit);
+ } else {
+ printk(KERN_INFO "Module unloaded but card not muted!\n");
+ }
+
video_unregister_device(&gemtek_radio);
- release_region(io,4);
+ release_region(io, 1);
}
module_init(gemtek_init);
-module_exit(gemtek_cleanup);
-
-/*
- Local variables:
- compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c"
- End:
-*/
+module_exit(gemtek_exit);
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 9b493b3298cd..82aedfc95d4f 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -297,7 +297,6 @@ static struct video_device rtrack2_radio=
.owner = THIS_MODULE,
.name = "RadioTrack II radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &rtrack2_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index dc33f19c0e2c..395165367f37 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -297,7 +297,6 @@ static struct video_device fmi_radio=
.owner = THIS_MODULE,
.name = "SF16FMx radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &fmi_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index e6c125def5cb..c432c44bd634 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -442,7 +442,6 @@ static struct video_device fmr2_radio=
.owner = THIS_MODULE,
.name = "SF16FMR2 radio",
. type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &fmr2_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index e43acfd7e533..535ffe8c8102 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -173,7 +173,7 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
i--;
p--;
temp = temp/2;
- }
+ }
spin_lock(&lock);
@@ -369,7 +369,6 @@ static struct video_device terratec_radio=
.owner = THIS_MODULE,
.name = "TerraTec ActiveRadio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &terratec_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index c27c629d99df..c11981fed827 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -349,7 +349,6 @@ static struct video_device trust_radio=
.owner = THIS_MODULE,
.name = "Trust FM Radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &trust_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 8ff5a23a9f01..1366326474e5 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -349,7 +349,6 @@ static struct video_device typhoon_radio =
.owner = THIS_MODULE,
.name = "Typhoon Radio",
.type = VID_TYPE_TUNER,
- .hardware = 0,
.fops = &typhoon_fops,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 4d45a40016de..2e571eb9313a 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -148,6 +148,15 @@ config VIDEO_WM8739
To compile this driver as a module, choose M here: the
module will be called wm8739.
+config VIDEO_VP27SMPX
+ tristate "Panasonic VP27s internal MPX"
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ ---help---
+ Support for the internal MPX of the Panasonic VP27s tuner.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vp27smpx.
+
comment "Video decoders"
config VIDEO_BT819
@@ -197,6 +206,13 @@ config VIDEO_OV7670
OV7670 VGA camera. It currently only works with the M88ALP01
controller.
+config VIDEO_TCM825X
+ tristate "TCM825x camera sensor support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This is a driver for the Toshiba TCM825x VGA camera sensor.
+ It is used for example in Nokia N800.
+
config VIDEO_SAA7110
tristate "Philips SAA7110 video decoder"
depends on VIDEO_V4L1 && I2C
@@ -348,7 +364,7 @@ endmenu # encoder / decoder chips
config VIDEO_VIVI
tristate "Virtual Video Driver"
depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
- select VIDEO_BUF
+ select VIDEOBUF_VMALLOC
default n
---help---
Enables a virtual video driver. This device shows a color bar
@@ -500,7 +516,7 @@ config VIDEO_VINO
config VIDEO_STRADIS
tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && !PPC64
+ depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS
help
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
driver for PCI. There is a product page at
@@ -511,7 +527,7 @@ config VIDEO_ZORAN_ZR36060
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux"
- depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && !PPC64
+ depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && 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
@@ -652,6 +668,8 @@ config VIDEO_HEXIUM_GEMINI
source "drivers/media/video/cx88/Kconfig"
+source "drivers/media/video/cx23885/Kconfig"
+
source "drivers/media/video/ivtv/Kconfig"
config VIDEO_M32R_AR
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 9c2de501612f..b5a064163e03 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -4,19 +4,19 @@
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
-tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
- mt20xx.o tda8290.o tea5767.o tda9887.o
+tuner-objs := tuner-core.o tuner-types.o tda9887.o
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \
+ v4l2-int-device.o
ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
endif
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
-obj-$(CONFIG_VIDEO_BT848) += ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
@@ -59,9 +59,8 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
obj-$(CONFIG_VIDEO_MEYE) += meye.o
-obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_CX88) += cx88/
-obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
@@ -71,6 +70,7 @@ obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_MXB) += mxb.o
@@ -80,8 +80,17 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
obj-$(CONFIG_TUNER_3036) += tuner-3036.o
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-obj-$(CONFIG_VIDEO_BUF) += video-buf.o
-obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o
+
+obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
+obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
+obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
+obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
+obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
+
+obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
+obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
+obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
+obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
@@ -95,6 +104,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
@@ -112,6 +123,9 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
+obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+obj-$(CONFIG_VIDEO_CX23885) += cx23885/
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 823cd6cc471e..cbab53fc6243 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -38,23 +38,23 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_encoder.h>
MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(x) (x)->name
-#include <linux/video_encoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 05c7820fe53e..0d0c554bfdf7 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -34,23 +34,23 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_encoder.h>
MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(s) (s)->name
-#include <linux/video_encoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 649f52f9ad27..19e9929ffa0f 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -23,7 +23,6 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
@@ -442,7 +441,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
{
struct video_window *w = arg;
DEBUG(1, "VIDIOCGWIN:\n");
- memset(w, 0, sizeof(w));
+ memset(w, 0, sizeof(*w));
w->width = ar->width;
w->height = ar->height;
return 0;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 59a43603b5cb..12d1b9248be5 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -38,23 +38,24 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_decoder.h>
+
MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(s) (s)->name
-#include <linux/video_decoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 853b1a3d6a1d..e1028a76c042 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -38,23 +38,23 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/video_encoder.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(s) (s)->name
-#include <linux/video_encoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index 2e4cf1efdd21..b767b098d14b 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -257,7 +257,7 @@ static int bt866_write(struct bt866 *encoder,
printk(KERN_WARNING "%s: I/O error #%d "
"(write 0x%02x/0x%02x)\n",
encoder->i2c->name, err, encoder->addr, subaddr);
- schedule_timeout_interruptible(HZ/10);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
}
if (err == 3) {
printk(KERN_WARNING "%s: giving up\n",
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 58eae887a629..2ca162b390a2 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -4,7 +4,7 @@ config VIDEO_BT848
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
- select VIDEO_BUF
+ select VIDEOBUF_DMA_SG
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 6b31e50fb951..dd6a7d68b07f 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -27,12 +27,12 @@
#include <linux/delay.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/firmware.h>
+#include <net/checksum.h>
#include <asm/io.h>
@@ -45,7 +45,7 @@ static void boot_msp34xx(struct bttv *btv, int pin);
static void boot_bt832(struct bttv *btv);
static void hauppauge_eeprom(struct bttv *btv);
static void avermedia_eeprom(struct bttv *btv);
-static void osprey_eeprom(struct bttv *btv);
+static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
static void modtec_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
static void init_RTV24(struct bttv *btv);
@@ -178,8 +178,8 @@ static struct CARD {
/* this seems to happen as well ... */
{ 0xff1211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" },
- { 0x3000121a, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
- { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
+ { 0x3000121a, BTTV_BOARD_VOODOOTV_200, "3Dfx VoodooTV 200" },
+ { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM" },
{ 0x3060121a, BTTV_BOARD_STB2, "3Dfx VoodooTV 100/ STB OEM" },
{ 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
@@ -313,6 +313,7 @@ static struct CARD {
{ 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" },
{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "},
+ { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" },
{ 0, -1, NULL }
};
@@ -329,7 +330,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.muxsel = { 2, 3, 1, 0 },
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -344,7 +345,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 2, 0, 0, 0 },
.gpiomute = 10,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -359,7 +360,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 1, 2, 3 },
.gpiomute = 4,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -387,13 +388,13 @@ struct tvcard bttv_tvcards[] = {
.name = "Intel Create and Share PCI/ Smart Video Recorder III",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 0 },
.needs_tvaudio = 0,
- .tuner_type = 4,
+ .tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -408,7 +409,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 1, 0, 1 },
.gpiomute = 3,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -423,7 +424,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0x0c, 0x04, 0x08, 0x04 },
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = avermedia_tvphone_audio,
@@ -433,13 +434,13 @@ struct tvcard bttv_tvcards[] = {
.name = "MATRIX-Vision MV-Delta",
.video_inputs = 5,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 3,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
.gpiomux = { 0 },
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -457,7 +458,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -488,7 +489,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 4,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -503,7 +504,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0x20001,0x10001, 0, 0 },
.gpiomute = 10,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -519,7 +520,7 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 13, 14, 11, 7 },
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -553,7 +554,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 4,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -568,7 +569,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0, 1, 0 },
.gpiomute = 10,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -587,7 +588,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0x002000,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
},
[BTTV_BOARD_WINVIEW_601] = {
.name = "Leadtek WinView 601",
@@ -600,7 +601,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
.gpiomute = 0xcfa007,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = winview_audio,
@@ -616,7 +617,7 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 1, 0, 0, 0 },
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -624,13 +625,13 @@ struct tvcard bttv_tvcards[] = {
.name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
.video_inputs = 4,
.audio_inputs = 1,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0x8dff00,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 0 },
.no_msp34xx = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -643,7 +644,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.muxsel = { 2, 3, 1, 1 },
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -674,7 +675,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -683,7 +684,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 3,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 7,
.muxsel = { 2, 3, -1 },
.digital_mode = DIGITAL_MODE_CAMERA,
@@ -708,7 +709,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_remote = 1,
@@ -740,7 +741,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 1, 2, 3 },
.gpiomute = 4,
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -813,13 +814,13 @@ struct tvcard bttv_tvcards[] = {
.name = "Imagenation PXC200",
.video_inputs = 5,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1, /* was: 4 */
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0},
.gpiomux = { 0 },
.needs_tvaudio = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.muxsel_hook = PXC200_muxsel,
@@ -836,7 +837,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0x0800, 0x1000, 0x1000 },
.gpiomute = 0x1800,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -860,13 +861,13 @@ struct tvcard bttv_tvcards[] = {
.name = "Intel Create and Share PCI/ Smart Video Recorder III",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 0 },
.needs_tvaudio = 0,
- .tuner_type = 4,
+ .tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -911,7 +912,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.pll = PLL_28,
.has_radio = 1,
- .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+ .tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = winfast2000_audio,
@@ -928,7 +929,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0x800, 0x1000, 0x1000 },
.gpiomute = 0x1800,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -945,7 +946,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0x800, 0x1000, 0x1000 },
.gpiomute = 0x1800,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
@@ -962,7 +963,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0x29,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -978,7 +979,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0x551c00,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = 1,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_remote = 1,
@@ -995,7 +996,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 1,
.needs_tvaudio = 0,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1030,7 +1031,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 13, 4, 11, 7 },
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
@@ -1048,7 +1049,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = 1,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1063,7 +1064,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
.gpiomute = 0xff3ffc,
.no_msp34xx = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1074,14 +1075,14 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 3,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 1, 1, 0, 2 },
.gpiomute = 3,
.no_msp34xx = 1,
.pll = PLL_NONE,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1089,14 +1090,14 @@ struct tvcard bttv_tvcards[] = {
.name = "MATRIX-Vision MV-Delta 2",
.video_inputs = 5,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 3,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
.gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1112,7 +1113,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 0xbcb03f,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = 21,
+ .tuner_type = TUNER_TEMIC_4039FR5_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1129,7 +1130,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.no_msp34xx = 1,
.pll = PLL_35,
- .tuner_type = 1,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
@@ -1148,7 +1149,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 1,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1206,7 +1207,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 1, 2, 3 },
.gpiomute = 4,
.pll = PLL_28,
- .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
+ .tuner_type = UNSET /* TUNER_ALPS_TMDH2_NTSC */,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1234,7 +1235,7 @@ struct tvcard bttv_tvcards[] = {
1= FM stereo Radio from Tuner */
.needs_tvaudio = 0,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1277,7 +1278,7 @@ struct tvcard bttv_tvcards[] = {
0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
0x0880: Tuner A2 stereo */
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1313,7 +1314,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0x800, 0x1000, 0x1000 },
.gpiomute = 0x1800,
.pll = PLL_28,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1324,7 +1325,7 @@ struct tvcard bttv_tvcards[] = {
.name = "GrandTec 'Grand Video Capture' (Bt848)",
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.gpiomask = 0,
.muxsel = { 3, 1 },
@@ -1332,7 +1333,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_35,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1365,7 +1366,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 2, 0, 0, 0 },
.gpiomute = 1,
.pll = PLL_28,
- .tuner_type = 0,
+ .tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1377,7 +1378,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.audio_inputs = 2,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 11,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 2, 0, 0, 1 },
@@ -1392,7 +1393,7 @@ struct tvcard bttv_tvcards[] = {
.name = "AG Electronics GMV1",
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.gpiomask = 0xF,
.muxsel = { 2, 2 },
@@ -1400,7 +1401,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.needs_tvaudio = 0,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1447,7 +1448,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 1,
.muxsel = { 2, 3, 0, 1 },
.gpiomux = { 0, 0, 1, 0 },
@@ -1476,7 +1477,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1517,13 +1518,35 @@ struct tvcard bttv_tvcards[] = {
/* ---- card 0x44 ---------------------------------- */
[BTTV_BOARD_VOODOOTV_FM] = {
- .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+ .name = "3Dfx VoodooTV FM (Euro)",
/* try "insmod msp3400 simple=0" if you have
* sound problems with this card. */
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
+ .gpiomask = 0x4f8a00,
+ /* 0x100000: 1=MSP enabled (0=disable again)
+ * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+ .gpiomux = {0x947fff, 0x987fff,0x947fff,0x947fff },
+ .gpiomute = 0x947fff,
+ /* tvtuner, radio, external,internal, mute, stereo
+ * tuner, Composit, SVid, Composit-on-Svid-adapter */
+ .muxsel = { 2, 3 ,0 ,1 },
+ .tuner_type = TUNER_MT2032,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .has_radio = 1,
+ },
+ [BTTV_BOARD_VOODOOTV_200] = {
+ .name = "VoodooTV 200 (USA)",
+ /* try "insmod msp3400 simple=0" if you have
+ * sound problems with this card. */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = UNSET,
.gpiomask = 0x4f8a00,
/* 0x100000: 1=MSP enabled (0=disable again)
* 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
@@ -1543,8 +1566,8 @@ struct tvcard bttv_tvcards[] = {
.name = "Active Imaging AIMMS",
.video_inputs = 1,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
@@ -1564,7 +1587,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 13,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = 25,
+ .tuner_type = TUNER_LG_PAL_I_FM,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_remote = 1,
@@ -1580,7 +1603,7 @@ struct tvcard bttv_tvcards[] = {
.name = "Lifeview FlyVideo 98EZ (capture only) LR51",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 2,
.muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */
.pll = PLL_28,
@@ -1606,7 +1629,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.no_tda9875 = 1,
.pll = PLL_28,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */
@@ -1626,13 +1649,13 @@ struct tvcard bttv_tvcards[] = {
.name = "Sensoray 311",
.video_inputs = 5,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 4,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
.gpiomux = { 0 },
.needs_tvaudio = 0,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1641,15 +1664,15 @@ struct tvcard bttv_tvcards[] = {
.name = "RemoteVision MX (RV605)",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0x00,
.gpiomask2 = 0x07ff,
.muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
.no_msp34xx = 1,
.no_tda9875 = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.muxsel_hook = rv605_muxsel,
@@ -1693,15 +1716,15 @@ struct tvcard bttv_tvcards[] = {
.name = "GrandTec Multi Capture Card (Bt878)",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0 },
.gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1724,7 +1747,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
/* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
@@ -1744,10 +1767,10 @@ struct tvcard bttv_tvcards[] = {
/* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
.name = "DSP Design TCVIDEO",
.video_inputs = 4,
- .svhs = -1,
+ .svhs = UNSET,
.muxsel = { 2, 3, 1, 0 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -1762,7 +1785,7 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 0, 1, 1 },
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1791,11 +1814,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */
.video_inputs = 4, /* id-inputs-clock */
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 3,
.muxsel = { 3, 2, 0, 1 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1806,11 +1829,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
.video_inputs = 3,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 2,
.muxsel = { 2, 3, 1 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1823,11 +1846,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 101 (848)", /* 0x05-40C0-C1 */
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 3, 1 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1838,11 +1861,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */
.video_inputs = 1,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 0 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1853,11 +1876,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 0, 1 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1868,8 +1891,8 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */
.video_inputs = 1,
.audio_inputs = 1,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 0 },
.pll = PLL_28,
.tuner_type = UNSET,
@@ -1885,7 +1908,7 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */
.video_inputs = 2,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 0, 1 },
.pll = PLL_28,
@@ -1900,7 +1923,7 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */
.video_inputs = 2,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
@@ -1915,11 +1938,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 500", /* 500 */
.video_inputs = 2,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1930,9 +1953,9 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 540", /* 540 */
.video_inputs = 4,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -1945,7 +1968,7 @@ struct tvcard bttv_tvcards[] = {
.name = "Osprey 2000", /* 2000 */
.video_inputs = 2,
.audio_inputs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 2, 3 },
.pll = PLL_28,
@@ -1961,11 +1984,11 @@ struct tvcard bttv_tvcards[] = {
.name = "IDS Eagle",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 0,
.muxsel = { 0, 1, 2, 3 },
.muxsel_hook = eagle_muxsel,
@@ -1978,8 +2001,8 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.audio_inputs = 0,
.svhs = 1,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.no_msp34xx = 1,
@@ -2020,13 +2043,13 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 3,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1},
.gpiomux = { 0, 1, 2, 3},
.gpiomute = 4,
.needs_tvaudio = 1,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
@@ -2035,7 +2058,7 @@ struct tvcard bttv_tvcards[] = {
.name = "Euresys Picolo",
.video_inputs = 3,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 2,
.gpiomask = 0,
.no_msp34xx = 1,
@@ -2052,8 +2075,8 @@ struct tvcard bttv_tvcards[] = {
.name = "ProVideo PV150", /* 0x4f */
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0,
.muxsel = { 2, 3 },
.gpiomux = { 0 },
@@ -2080,7 +2103,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = 2,
+ .tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = adtvk503_audio,
@@ -2098,7 +2121,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 1,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
/* Notes:
@@ -2121,7 +2144,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0,
.no_tda9875 = 1,
.no_tda7432 = 1,
- .tuner_type = 1,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
@@ -2138,11 +2161,11 @@ struct tvcard bttv_tvcards[] = {
.name = "IVC-200",
.video_inputs = 1,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 0xdf,
.muxsel = { 2 },
.pll = PLL_28,
@@ -2151,9 +2174,9 @@ struct tvcard bttv_tvcards[] = {
.name = "Grand X-Guard / Trust 814PCI",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .tuner_type = 4,
+ .tuner = UNSET,
+ .svhs = UNSET,
+ .tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.gpiomask2 = 0xff,
@@ -2169,14 +2192,14 @@ struct tvcard bttv_tvcards[] = {
[BTTV_BOARD_NEBULA_DIGITV] = {
.name = "Nebula Electronics DigiTV",
.video_inputs = 1,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 2, 3, 1, 0 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_dvb = 1,
@@ -2189,15 +2212,15 @@ struct tvcard bttv_tvcards[] = {
.name = "ProVideo PV143",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0 },
.gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2206,14 +2229,14 @@ struct tvcard bttv_tvcards[] = {
.name = "PHYTEC VD-009-X1 MiniDIN (bt878)",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1, /* card has no tuner */
+ .tuner = UNSET, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
.muxsel = { 2, 3, 1, 0 },
.gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2221,14 +2244,14 @@ struct tvcard bttv_tvcards[] = {
.name = "PHYTEC VD-009-X1 Combi (bt878)",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1, /* card has no tuner */
+ .tuner = UNSET, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2238,7 +2261,7 @@ struct tvcard bttv_tvcards[] = {
.name = "PHYTEC VD-009 MiniDIN (bt878)",
.video_inputs = 10,
.audio_inputs = 0,
- .tuner = -1, /* card has no tuner */
+ .tuner = UNSET, /* card has no tuner */
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
@@ -2248,7 +2271,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2256,7 +2279,7 @@ struct tvcard bttv_tvcards[] = {
.name = "PHYTEC VD-009 Combi (bt878)",
.video_inputs = 10,
.audio_inputs = 0,
- .tuner = -1, /* card has no tuner */
+ .tuner = UNSET, /* card has no tuner */
.svhs = 9,
.gpiomask = 0x00,
.gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
@@ -2266,7 +2289,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2274,11 +2297,11 @@ struct tvcard bttv_tvcards[] = {
.name = "IVC-100",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 0xdf,
.muxsel = { 2, 3, 1, 0 },
.pll = PLL_28,
@@ -2288,11 +2311,11 @@ struct tvcard bttv_tvcards[] = {
.name = "IVC-120G",
.video_inputs = 16,
.audio_inputs = 0, /* card has no audio */
- .tuner = -1, /* card has no tuner */
- .tuner_type = -1,
+ .tuner = UNSET, /* card has no tuner */
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1, /* card has no svhs */
+ .svhs = UNSET, /* card has no svhs */
.needs_tvaudio = 0,
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -2333,7 +2356,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 3,
.audio_inputs = 0,
.svhs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -2364,9 +2387,9 @@ struct tvcard bttv_tvcards[] = {
.name = "SIMUS GVC1100",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
@@ -2395,14 +2418,14 @@ struct tvcard bttv_tvcards[] = {
.name = "LMLBT4",
.video_inputs = 4, /* IN1,IN2,IN3,IN4 */
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 2, 3, 1, 0 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.needs_tvaudio = 0,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2452,8 +2475,8 @@ struct tvcard bttv_tvcards[] = {
.name = "Euresys Picolo Tetra",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0,
.gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
.no_msp34xx = 1,
@@ -2464,7 +2487,7 @@ struct tvcard bttv_tvcards[] = {
.pll = PLL_28,
.needs_tvaudio = 0,
.muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2490,7 +2513,7 @@ struct tvcard bttv_tvcards[] = {
.name = "AVerMedia AVerTV DVB-T 771",
.video_inputs = 2,
.svhs = 1,
- .tuner = -1,
+ .tuner = UNSET,
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2509,14 +2532,14 @@ struct tvcard bttv_tvcards[] = {
/* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */
.name = "AverMedia AverTV DVB-T 761",
.video_inputs = 2,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_dvb = 1,
@@ -2528,8 +2551,8 @@ struct tvcard bttv_tvcards[] = {
.name = "MATRIX Vision Sigma-SQ",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0x0,
.muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3 },
@@ -2537,7 +2560,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2546,15 +2569,15 @@ struct tvcard bttv_tvcards[] = {
.name = "MATRIX Vision Sigma-SLC",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0x0,
.muxsel = { 2, 2, 2, 2 },
.muxsel_hook = sigmaSLC_muxsel,
.gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2566,7 +2589,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.audio_inputs = 1,
.tuner = 0,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 0xFF,
.muxsel = { 2, 3, 1, 1 },
.gpiomux = { 2, 0, 0, 0 },
@@ -2584,14 +2607,14 @@ struct tvcard bttv_tvcards[] = {
[BTTV_BOARD_DVICO_DVBT_LITE] = {
/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
.name = "DViCO FusionHDTV DVB-T Lite",
- .tuner = -1,
+ .tuner = UNSET,
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.pll = PLL_28,
.no_video = 1,
.has_dvb = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2634,14 +2657,14 @@ struct tvcard bttv_tvcards[] = {
.name = "Tibet Systems 'Progress DVR' CS16",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
.pll = PLL_28,
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.muxsel_hook = tibetCS16_muxsel,
@@ -2661,11 +2684,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Kodicom 4400R (master)",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1,
+ .svhs = UNSET,
/* GPIO bits 0-9 used for analog switch:
* 00 - 03: camera selector
* 04 - 06: channel (controller) selector
@@ -2693,11 +2716,11 @@ struct tvcard bttv_tvcards[] = {
.name = "Kodicom 4400R (slave)",
.video_inputs = 16,
.audio_inputs = 0,
- .tuner = -1,
- .tuner_type = -1,
+ .tuner = UNSET,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .svhs = -1,
+ .svhs = UNSET,
.gpiomask = 0x010000,
.no_gpioirq = 1,
.muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
@@ -2717,7 +2740,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.muxsel = { 2, 3, 1, 0 },
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
@@ -2820,13 +2843,28 @@ struct tvcard bttv_tvcards[] = {
.has_remote = 1,
},
/* ---- card 0x8c ---------------------------------- */
+ /* Has four Bt878 chips behind a PCI bridge, each chip has:
+ one external BNC composite input (mux 2)
+ three internal composite inputs (unknown muxes)
+ an 18-bit stereo A/D (CS5331A), which has:
+ one external stereo unblanced (RCA) audio connection
+ one (or 3?) internal stereo balanced (XLR) audio connection
+ input is selected via gpio to a 14052B mux
+ (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300)
+ gain is controlled via an X9221A chip on the I2C bus @0x28
+ sample rate is controlled via gpio to an MK1413S
+ (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3)
+ There is neither a tuner nor an svideo input. */
[BTTV_BOARD_OSPREY440] = {
.name = "Osprey 440",
- .video_inputs = 1,
- .audio_inputs = 1,
- .tuner = -1,
- .svhs = 1,
- .muxsel = { 2 },
+ .video_inputs = 4,
+ .audio_inputs = 2, /* this is meaningless */
+ .tuner = UNSET,
+ .svhs = UNSET,
+ .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */
+ .gpiomask = 0x303,
+ .gpiomute = 0x000, /* int + 32kHz */
+ .gpiomux = { 0, 0, 0x000, 0x100},
.pll = PLL_28,
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
@@ -2848,7 +2886,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomute = 1,
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = 2,
+ .tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2875,14 +2913,14 @@ struct tvcard bttv_tvcards[] = {
.name = "Hauppauge ImpactVCB (bt878)",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.gpiomask = 0x0f, /* old: 7 */
.muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2914,10 +2952,10 @@ struct tvcard bttv_tvcards[] = {
.name = "SSAI Security Video Interface",
.video_inputs = 4,
.audio_inputs = 0,
- .tuner = -1,
- .svhs = -1,
+ .tuner = UNSET,
+ .svhs = UNSET,
.muxsel = { 0, 1, 2, 3 },
- .tuner_type = -1,
+ .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
@@ -2925,12 +2963,47 @@ struct tvcard bttv_tvcards[] = {
.name = "SSAI Ultrasound Video Interface",
.video_inputs = 2,
.audio_inputs = 0,
- .tuner = -1,
+ .tuner = UNSET,
.svhs = 1,
.muxsel = { 2, 0, 1, 3 },
- .tuner_type = -1,
+ .tuner_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
+ /* ---- card 0x94---------------------------------- */
+ [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+ .name = "DViCO FusionHDTV 2",
+ .tuner = 0,
+ .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1 },
+ .gpiomask = 0x00e00007,
+ .gpiomux = { 0x00400005, 0, 0x00000001, 0 },
+ .gpiomute = 0x00c00007,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ },
+ /* ---- card 0x95---------------------------------- */
+ [BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
+ .name = "Typhoon TV-Tuner PCI (50684)",
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x3014f,
+ .muxsel = { 2, 3, 1, 1 },
+ .gpiomux = { 0x20001,0x10001, 0, 0 },
+ .gpiomute = 10,
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
},
};
@@ -3040,7 +3113,7 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
static void flyvideo_gpio(struct bttv *btv)
{
int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
- int tuner=-1,ttype;
+ int tuner=UNSET,ttype;
gpio_inout(0xffffff, 0);
udelay(8); /* without this we would see the 0x1800 mask */
@@ -3085,7 +3158,7 @@ static void flyvideo_gpio(struct bttv *btv)
* gpio & 0x001000 output bit for audio routing */
if(is_capture_only)
- tuner=4; /* No tuner present */
+ tuner = TUNER_ABSENT; /* No tuner present */
printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
@@ -3093,7 +3166,7 @@ static void flyvideo_gpio(struct bttv *btv)
btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
is_capture_only?"yes":"no ");
- if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */
+ if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */
btv->tuner_type = tuner;
btv->has_radio = has_radio;
@@ -3219,15 +3292,15 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input)
btaor((2)<<5, ~(3<<5), BT848_IFORM);
gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]);
- /* composite */
- /* set chroma ADC to sleep */
- btor(BT848_ADC_C_SLEEP, BT848_ADC);
- /* set to composite video */
- btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
- btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+ /* composite */
+ /* set chroma ADC to sleep */
+ btor(BT848_ADC_C_SLEEP, BT848_ADC);
+ /* set to composite video */
+ btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+ btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
- /* switch sync drive off */
- gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
+ /* switch sync drive off */
+ gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
}
static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
@@ -3302,6 +3375,7 @@ void __devinit bttv_init_card1(struct bttv *btv)
case BTTV_BOARD_HAUPPAUGE878:
boot_msp34xx(btv,5);
break;
+ case BTTV_BOARD_VOODOOTV_200:
case BTTV_BOARD_VOODOOTV_FM:
boot_msp34xx(btv,20);
break;
@@ -3328,10 +3402,9 @@ void __devinit bttv_init_card1(struct bttv *btv)
/* initialization part two -- after registering i2c bus */
void __devinit bttv_init_card2(struct bttv *btv)
{
- int tda9887;
int addr=ADDR_UNSET;
- btv->tuner_type = -1;
+ btv->tuner_type = UNSET;
if (BTTV_BOARD_UNKNOWN == btv->c.type) {
bttv_readee(btv,eeprom_data,0xa0);
@@ -3396,7 +3469,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
}
break;
- case BTTV_BOARD_STB2:
+ case BTTV_BOARD_STB2:
if (btv->cardid == 0x3060121a) {
/* Fix up entry for 3DFX VoodooTV 100,
which is an OEM STB card variant. */
@@ -3412,11 +3485,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
case BTTV_BOARD_OSPREY2xx:
case BTTV_BOARD_OSPREY2x0_SVID:
case BTTV_BOARD_OSPREY2x0:
+ case BTTV_BOARD_OSPREY440:
case BTTV_BOARD_OSPREY500:
case BTTV_BOARD_OSPREY540:
case BTTV_BOARD_OSPREY2000:
bttv_readee(btv,eeprom_data,0xa0);
- osprey_eeprom(btv);
+ osprey_eeprom(btv, eeprom_data);
break;
case BTTV_BOARD_IDS_EAGLE:
init_ids_eagle(btv);
@@ -3479,7 +3553,15 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
if (UNSET != tuner[btv->c.nr])
btv->tuner_type = tuner[btv->c.nr];
- printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type);
+
+ if (btv->tuner_type == TUNER_ABSENT ||
+ bttv_tvcards[btv->c.type].tuner == UNSET)
+ printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
+ else if(btv->tuner_type == UNSET)
+ printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
+ else
+ printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
+ btv->tuner_type);
if (btv->tuner_type != UNSET) {
struct tuner_setup tun_setup;
@@ -3521,6 +3603,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
if (!autoload)
return;
+ if (bttv_tvcards[btv->c.type].tuner == UNSET)
+ return; /* no tuner or related drivers to load */
+
/* try to detect audio/fader chips */
if (!bttv_tvcards[btv->c.type].no_msp34xx &&
bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0)
@@ -3541,17 +3626,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
if (bttv_tvcards[btv->c.type].needs_tvaudio)
request_module("tvaudio");
- /* tuner modules */
- tda9887 = 0;
- if (btv->tda9887_conf)
- tda9887 = 1;
- if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
- bttv_I2CRead(btv, I2C_ADDR_TDA9887, "TDA9887") >=0)
- tda9887 = 1;
- /* Hybrid DVB card, DOES have a tda9887 */
- if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE)
- tda9887 = 1;
- if (btv->tuner_type != UNSET)
+ if (btv->tuner_type != UNSET && btv->tuner_type != TUNER_ABSENT)
request_module("tuner");
}
@@ -3706,106 +3781,119 @@ static int __devinit pvr_boot(struct bttv *btv)
/* ----------------------------------------------------------------------- */
/* some osprey specific stuff */
-static void __devinit osprey_eeprom(struct bttv *btv)
+static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
{
- int i = 0;
- unsigned char *ee = eeprom_data;
- unsigned long serial = 0;
-
- if (btv->c.type == 0) {
- /* this might be an antique... check for MMAC label in eeprom */
- if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) {
- unsigned char checksum = 0;
- for (i = 0; i < 21; i++)
- checksum += ee[i];
- if (checksum != ee[21])
- return;
- btv->c.type = BTTV_BOARD_OSPREY1x0_848;
- for (i = 12; i < 21; i++)
- serial *= 10, serial += ee[i] - '0';
- }
- } else {
- unsigned short type;
- int offset = 4*16;
-
- for (; offset < 8*16; offset += 16) {
- unsigned short checksum = 0;
- /* verify the checksum */
- for (i = 0; i < 14; i++)
- checksum += ee[i+offset];
- checksum = ~checksum; /* no idea why */
- if ((((checksum>>8)&0x0FF) == ee[offset+14]) &&
- ((checksum & 0x0FF) == ee[offset+15])) {
- break;
- }
- }
-
- if (offset >= 8*16)
- return;
-
- /* found a valid descriptor */
- type = (ee[offset+4]<<8) | (ee[offset+5]);
-
- switch(type) {
- /* 848 based */
- case 0x0004:
- btv->c.type = BTTV_BOARD_OSPREY1x0_848;
- break;
- case 0x0005:
- btv->c.type = BTTV_BOARD_OSPREY101_848;
- break;
-
- /* 878 based */
- case 0x0012:
- case 0x0013:
- btv->c.type = BTTV_BOARD_OSPREY1x0;
- break;
- case 0x0014:
- case 0x0015:
- btv->c.type = BTTV_BOARD_OSPREY1x1;
- break;
- case 0x0016:
- case 0x0017:
- case 0x0020:
- btv->c.type = BTTV_BOARD_OSPREY1x1_SVID;
- break;
- case 0x0018:
- case 0x0019:
- case 0x001E:
- case 0x001F:
- btv->c.type = BTTV_BOARD_OSPREY2xx;
- break;
- case 0x001A:
- case 0x001B:
- btv->c.type = BTTV_BOARD_OSPREY2x0_SVID;
- break;
- case 0x0040:
- btv->c.type = BTTV_BOARD_OSPREY500;
- break;
- case 0x0050:
- case 0x0056:
- btv->c.type = BTTV_BOARD_OSPREY540;
- /* bttv_osprey_540_init(btv); */
- break;
- case 0x0060:
- case 0x0070:
- case 0x00A0:
- btv->c.type = BTTV_BOARD_OSPREY2x0;
- /* enable output on select control lines */
- gpio_inout(0xffffff,0x000303);
- break;
- default:
- /* unknown...leave generic, but get serial # */
- break;
- }
- serial = (ee[offset+6] << 24)
- | (ee[offset+7] << 16)
- | (ee[offset+8] << 8)
- | (ee[offset+9]);
- }
-
- printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n",
- btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial);
+ int i;
+ u32 serial = 0;
+ int cardid = -1;
+
+ /* This code will nevery actually get called in this case.... */
+ if (btv->c.type == BTTV_BOARD_UNKNOWN) {
+ /* this might be an antique... check for MMAC label in eeprom */
+ if (!strncmp(ee, "MMAC", 4)) {
+ u8 checksum = 0;
+ for (i = 0; i < 21; i++)
+ checksum += ee[i];
+ if (checksum != ee[21])
+ return;
+ cardid = BTTV_BOARD_OSPREY1x0_848;
+ for (i = 12; i < 21; i++)
+ serial *= 10, serial += ee[i] - '0';
+ }
+ } else {
+ unsigned short type;
+
+ for (i = 4*16; i < 8*16; i += 16) {
+ u16 checksum = ip_compute_csum(ee + i, 16);
+
+ if ((checksum&0xff) + (checksum>>8) == 0xff)
+ break;
+ }
+ if (i >= 8*16)
+ return;
+ ee += i;
+
+ /* found a valid descriptor */
+ type = be16_to_cpup((u16*)(ee+4));
+
+ switch(type) {
+ /* 848 based */
+ case 0x0004:
+ cardid = BTTV_BOARD_OSPREY1x0_848;
+ break;
+ case 0x0005:
+ cardid = BTTV_BOARD_OSPREY101_848;
+ break;
+
+ /* 878 based */
+ case 0x0012:
+ case 0x0013:
+ cardid = BTTV_BOARD_OSPREY1x0;
+ break;
+ case 0x0014:
+ case 0x0015:
+ cardid = BTTV_BOARD_OSPREY1x1;
+ break;
+ case 0x0016:
+ case 0x0017:
+ case 0x0020:
+ cardid = BTTV_BOARD_OSPREY1x1_SVID;
+ break;
+ case 0x0018:
+ case 0x0019:
+ case 0x001E:
+ case 0x001F:
+ cardid = BTTV_BOARD_OSPREY2xx;
+ break;
+ case 0x001A:
+ case 0x001B:
+ cardid = BTTV_BOARD_OSPREY2x0_SVID;
+ break;
+ case 0x0040:
+ cardid = BTTV_BOARD_OSPREY500;
+ break;
+ case 0x0050:
+ case 0x0056:
+ cardid = BTTV_BOARD_OSPREY540;
+ /* bttv_osprey_540_init(btv); */
+ break;
+ case 0x0060:
+ case 0x0070:
+ case 0x00A0:
+ cardid = BTTV_BOARD_OSPREY2x0;
+ /* enable output on select control lines */
+ gpio_inout(0xffffff,0x000303);
+ break;
+ case 0x00D8:
+ cardid = BTTV_BOARD_OSPREY440;
+ break;
+ default:
+ /* unknown...leave generic, but get serial # */
+ printk(KERN_INFO "bttv%d: "
+ "osprey eeprom: unknown card type 0x%04x\n",
+ btv->c.nr, type);
+ break;
+ }
+ serial = be32_to_cpup((u32*)(ee+6));
+ }
+
+ printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
+ btv->c.nr, cardid,
+ cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+
+ if (cardid<0 || btv->c.type == cardid)
+ return;
+
+ /* card type isn't set correctly */
+ if (card[btv->c.nr] < bttv_num_tvcards) {
+ printk(KERN_WARNING "bttv%d: osprey eeprom: "
+ "Not overriding user specified card type\n", btv->c.nr);
+ } else {
+ printk(KERN_INFO "bttv%d: osprey eeprom: "
+ "Changing card type from %d to %d\n", btv->c.nr,
+ btv->c.type, cardid);
+ btv->c.type = cardid;
+ }
}
/* ----------------------------------------------------------------------- */
@@ -3865,11 +3953,15 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm)
if(norm==VIDEO_MODE_NTSC) {
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x957fff;
dprintk("bttv_tda9880_setnorm to NTSC\n");
}
else {
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x947fff;
dprintk("bttv_tda9880_setnorm to PAL\n");
}
/* set GPIO according */
@@ -4163,7 +4255,7 @@ static int tea5757_read(struct bttv *btv)
bus_low(btv,btv->mbox_clk);
udelay(10);
- timeout= jiffies + HZ;
+ timeout= jiffies + msecs_to_jiffies(1000);
/* wait for DATA line to go low; error if it doesn't */
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index b1fedb0f6431..7a332b3efe51 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -30,7 +30,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -155,13 +154,14 @@ MODULE_LICENSE("GPL");
/* ----------------------------------------------------------------------- */
/* sysfs */
-static ssize_t show_card(struct class_device *cd, char *buf)
+static ssize_t show_card(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct video_device *vfd = to_video_device(cd);
struct bttv *btv = dev_get_drvdata(vfd->dev);
return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
}
-static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
+static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
/* ----------------------------------------------------------------------- */
/* dvb auto-load setup */
@@ -1218,7 +1218,14 @@ audio_mux(struct bttv *btv, int input, int mute)
break;
case TVAUDIO_INPUT_TUNER:
default:
- route.input = MSP_INPUT_DEFAULT;
+ /* This is the only card that uses TUNER2, and afaik,
+ is the only difference between the VOODOOTV_FM
+ and VOODOOTV_200 */
+ if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
+ route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
+ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
+ else
+ route.input = MSP_INPUT_DEFAULT;
break;
}
route.output = MSP_OUTPUT_DEFAULT;
@@ -1253,7 +1260,7 @@ i2c_vidiocschan(struct bttv *btv)
v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
- if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
+ if (btv->c.type == BTTV_BOARD_VOODOOTV_FM || btv->c.type == BTTV_BOARD_VOODOOTV_200)
bttv_tda9880_setnorm(btv,btv->tvnorm);
}
@@ -1323,6 +1330,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
switch (btv->c.type) {
case BTTV_BOARD_VOODOOTV_FM:
+ case BTTV_BOARD_VOODOOTV_200:
bttv_tda9880_setnorm(btv,norm);
break;
}
@@ -2251,6 +2259,24 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr);
return 0;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return -EINVAL;
+ /* bt848 has a 12-bit register space */
+ reg->reg &= 0xfff;
+ if (cmd == VIDIOC_DBG_G_REGISTER)
+ reg->val = btread(reg->reg);
+ else
+ btwrite(reg->val, reg->reg);
+ return 0;
+ }
+#endif
default:
return -ENOIOCTLCMD;
@@ -2557,7 +2583,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
if (check_btres(fh, RESOURCE_OVERLAY)) {
struct bttv_buffer *new;
- new = videobuf_alloc(sizeof(*new));
+ new = videobuf_pci_alloc(sizeof(*new));
new->crop = btv->crop[!!fh->do_crop].rect;
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
retval = bttv_switch_overlay(btv,fh,new);
@@ -3023,7 +3049,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&fh->cap.lock);
if (*on) {
fh->ov.tvnorm = btv->tvnorm;
- new = videobuf_alloc(sizeof(*new));
+ new = videobuf_pci_alloc(sizeof(*new));
new->crop = btv->crop[!!fh->do_crop].rect;
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
} else {
@@ -3046,6 +3072,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
V4L2_MEMORY_MMAP);
if (retval < 0)
goto fh_unlock_and_return;
+
+ gbuffers = retval;
memset(mbuf,0,sizeof(*mbuf));
mbuf->frames = gbuffers;
mbuf->size = gbuffers * gbufsize;
@@ -3116,9 +3144,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
retval = -EIO;
/* fall through */
case STATE_DONE:
- videobuf_dma_sync(&fh->cap,&buf->vb.dma);
+ {
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ videobuf_dma_sync(&fh->cap,dma);
bttv_dma_free(&fh->cap,btv,buf);
break;
+ }
default:
retval = -EINVAL;
break;
@@ -3312,7 +3343,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
if (check_btres(fh, RESOURCE_OVERLAY)) {
struct bttv_buffer *new;
- new = videobuf_alloc(sizeof(*new));
+ new = videobuf_pci_alloc(sizeof(*new));
new->crop = btv->crop[!!fh->do_crop].rect;
bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
retval = bttv_switch_overlay(btv,fh,new);
@@ -3561,6 +3592,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY:
case VIDIOC_LOG_STATUS:
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
return bttv_common_ioctls(btv,cmd,arg);
default:
@@ -3669,7 +3702,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
mutex_unlock(&fh->cap.lock);
return POLLERR;
}
- fh->cap.read_buf = videobuf_alloc(fh->cap.msize);
+ fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
if (NULL == fh->cap.read_buf) {
mutex_unlock(&fh->cap.lock);
return POLLERR;
@@ -3736,13 +3769,13 @@ static int bttv_open(struct inode *inode, struct file *file)
fh->ov.setup_ok = 0;
v4l2_prio_open(&btv->prio,&fh->prio);
- videobuf_queue_init(&fh->cap, &bttv_video_qops,
+ videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
btv->c.pci, &btv->s_lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct bttv_buffer),
fh);
- videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
+ videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
btv->c.pci, &btv->s_lock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
@@ -3943,6 +3976,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
case VIDIOC_LOG_STATUS:
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
return bttv_common_ioctls(btv,cmd,arg);
default:
@@ -4583,9 +4618,9 @@ static int __devinit bttv_register_video(struct bttv *btv)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->c.nr,btv->video_dev->minor & 0x1f);
- if (class_device_create_file(&btv->video_dev->class_dev,
- &class_device_attr_card)<0) {
- printk(KERN_ERR "bttv%d: class_device_create_file 'card' "
+ if (device_create_file(&btv->video_dev->class_dev,
+ &dev_attr_card)<0) {
+ printk(KERN_ERR "bttv%d: device_create_file 'card' "
"failed\n", btv->c.nr);
goto err;
}
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
index 84154c26f9c5..dce6dae5740e 100644
--- a/drivers/media/video/bt8xx/bttv-gpio.c
+++ b/drivers/media/video/bt8xx/bttv-gpio.c
@@ -106,11 +106,9 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
int bttv_sub_del_devices(struct bttv_core *core)
{
- struct bttv_sub_device *sub;
- struct list_head *item,*save;
+ struct bttv_sub_device *sub, *save;
- list_for_each_safe(item,save,&core->subs) {
- sub = list_entry(item,struct bttv_sub_device,list);
+ list_for_each_entry_safe(sub, save, &core->subs, list) {
list_del(&sub->list);
device_unregister(&sub->dev);
}
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index 0dfa49b66418..844f1762c45a 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -28,7 +28,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 6f74c8042bc3..e7c521b8444a 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -19,7 +19,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -153,7 +152,7 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir)
{
if (ir->polling) {
setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
- ir->timer.expires = jiffies + HZ;
+ ir->timer.expires = jiffies + msecs_to_jiffies(1000);
add_timer(&ir->timer);
} else if (ir->rc5_gpio) {
/* set timer_end for code completion */
@@ -313,7 +312,7 @@ int bttv_input_init(struct bttv *btv)
input_dev->id.vendor = btv->c.pci->vendor;
input_dev->id.product = btv->c.pci->device;
}
- input_dev->cdev.dev = &btv->c.pci->dev;
+ input_dev->dev.parent = &btv->c.pci->dev;
btv->remote = ir;
bttv_ir_start(btv, ir);
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index e7104d9cb4bd..58986f1a5f1a 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -574,10 +574,12 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
void
bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
{
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_unmap(q, &buf->vb.dma);
- videobuf_dma_free(&buf->vb.dma);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top);
buf->vb.state = STATE_NEEDS_INIT;
@@ -699,6 +701,7 @@ int
bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
{
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
dprintk(KERN_DEBUG
"bttv%d: buffer field: %s format: %s size: %dx%d\n",
@@ -716,25 +719,25 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
switch (buf->vb.field) {
case V4L2_FIELD_TOP:
- bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->top,dma->sglist,
/* offset */ 0,bpl,
/* padding */ 0,/* skip_lines */ 0,
buf->vb.height);
break;
case V4L2_FIELD_BOTTOM:
- bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->bottom,dma->sglist,
0,bpl,0,0,buf->vb.height);
break;
case V4L2_FIELD_INTERLACED:
- bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->top,dma->sglist,
0,bpl,bpl,0,buf->vb.height >> 1);
- bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->bottom,dma->sglist,
bpl,bpl,bpl,0,buf->vb.height >> 1);
break;
case V4L2_FIELD_SEQ_TB:
- bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->top,dma->sglist,
0,bpl,0,0,buf->vb.height >> 1);
- bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
+ bttv_risc_packed(btv,&buf->bottom,dma->sglist,
bpf,bpl,0,0,buf->vb.height >> 1);
break;
default:
@@ -767,7 +770,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,/* both_fields */ 0,
tvnorm,&buf->crop);
- bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
+ bttv_risc_planar(btv, &buf->top, dma->sglist,
0,buf->vb.width,0,buf->vb.height,
uoffset,voffset,buf->fmt->hshift,
buf->fmt->vshift,0);
@@ -776,7 +779,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,0,
tvnorm,&buf->crop);
- bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
+ bttv_risc_planar(btv, &buf->bottom, dma->sglist,
0,buf->vb.width,0,buf->vb.height,
uoffset,voffset,buf->fmt->hshift,
buf->fmt->vshift,0);
@@ -789,14 +792,14 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
ypadding = buf->vb.width;
cpadding = buf->vb.width >> buf->fmt->hshift;
bttv_risc_planar(btv,&buf->top,
- buf->vb.dma.sglist,
+ dma->sglist,
0,buf->vb.width,ypadding,lines,
uoffset,voffset,
buf->fmt->hshift,
buf->fmt->vshift,
cpadding);
bttv_risc_planar(btv,&buf->bottom,
- buf->vb.dma.sglist,
+ dma->sglist,
ypadding,buf->vb.width,ypadding,lines,
uoffset+cpadding,
voffset+cpadding,
@@ -812,7 +815,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
ypadding = buf->vb.width;
cpadding = buf->vb.width >> buf->fmt->hshift;
bttv_risc_planar(btv,&buf->top,
- buf->vb.dma.sglist,
+ dma->sglist,
0,buf->vb.width,0,lines,
uoffset >> 1,
voffset >> 1,
@@ -820,7 +823,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
buf->fmt->vshift,
0);
bttv_risc_planar(btv,&buf->bottom,
- buf->vb.dma.sglist,
+ dma->sglist,
lines * ypadding,buf->vb.width,0,lines,
lines * ypadding + (uoffset >> 1),
lines * ypadding + (voffset >> 1),
@@ -839,10 +842,10 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
buf->vb.field = V4L2_FIELD_SEQ_TB;
bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
1,tvnorm,&buf->crop);
- bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
+ bttv_risc_packed(btv, &buf->top, dma->sglist,
/* offset */ 0, RAW_BPL, /* padding */ 0,
/* skip_lines */ 0, RAW_LINES);
- bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
+ bttv_risc_packed(btv, &buf->bottom, dma->sglist,
buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
}
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 93e35de5a181..346ce019bdcb 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -24,7 +24,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
@@ -151,13 +150,14 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
if (redo_dma_risc) {
unsigned int bpl, padding, offset;
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
bpl = 2044; /* max. vbipack */
padding = VBI_BPL - bpl;
if (fh->vbi_fmt.fmt.count[0] > 0) {
rc = bttv_risc_packed(btv, &buf->top,
- buf->vb.dma.sglist,
+ dma->sglist,
/* offset */ 0, bpl,
padding, skip_lines0,
fh->vbi_fmt.fmt.count[0]);
@@ -169,7 +169,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
rc = bttv_risc_packed(btv, &buf->bottom,
- buf->vb.dma.sglist,
+ dma->sglist,
offset, bpl,
padding, skip_lines1,
fh->vbi_fmt.fmt.count[1]);
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index f821ba69db99..19e75d50a107 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -170,6 +170,10 @@
#define BTTV_BOARD_MACHTV_MAGICTV 0x90
#define BTTV_BOARD_SSAI_SECURITY 0x91
#define BTTV_BOARD_SSAI_ULTRASOUND 0x92
+#define BTTV_BOARD_VOODOOTV_200 0x93
+#define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94
+#define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95
+
/* more card-specific defines */
#define PT2254_L_CHANNEL 0x10
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 8f44f02029be..0b92c35a8435 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -33,15 +33,15 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/videodev.h>
-#include <media/v4l2-common.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/mutex.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
+#include <media/v4l2-common.h>
#include <linux/device.h>
-#include <media/video-buf.h>
+#include <media/videobuf-dma-sg.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
#include <media/ir-common.h>
@@ -284,8 +284,8 @@ extern int fini_bttv_i2c(struct bttv *btv);
#define d2printk if (bttv_debug >= 2) printk
#define BTTV_MAX_FBUF 0x208000
-#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */
-#define BTTV_FREE_IDLE (HZ) /* one second */
+#define BTTV_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
+#define BTTV_FREE_IDLE msecs_to_jiffies(1000) /* one second */
struct bttv_pll_info {
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index b4aca7249276..ce0840ccd594 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -23,7 +23,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 7d47cbe6ad25..7f7e3d3398d0 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -104,6 +104,17 @@ static inline void write_lpdata(struct qcam_device *q, int d)
static inline void write_lpcontrol(struct qcam_device *q, int d)
{
+ if (d & 0x20) {
+ /* Set bidirectional mode to reverse (data in) */
+ parport_data_reverse(q->pport);
+ } else {
+ /* Set bidirectional mode to forward (data out) */
+ parport_data_forward(q->pport);
+ }
+
+ /* Now issue the regular port command, but strip out the
+ * direction flag */
+ d &= ~0x20;
parport_write_control(q->pport, d);
}
@@ -344,10 +355,13 @@ static int qc_detect(struct qcam_device *q)
/* Be (even more) liberal in what you accept... */
/* if (count > 30 && count < 200) */
- if (count > 20 && count < 300)
+ if (count > 20 && count < 400) {
return 1; /* found */
- else
+ } else {
+ printk(KERN_ERR "No Quickcam found on port %s\n",
+ q->pport->name);
return 0; /* not found */
+ }
}
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 925ff17efbbc..f76c6a6c3766 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -95,7 +95,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
unsigned long oldjiffies = jiffies;
unsigned int i;
- for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
+ for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
if (qcam_ready1(qcam) == value)
return 0;
@@ -120,7 +120,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
unsigned long oldjiffies = jiffies;
unsigned int i;
- for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
+ for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
if (qcam_ready2(qcam) == value)
return 0;
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index c08f650df423..b63cab336920 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/pci.h>
@@ -63,13 +62,13 @@ MODULE_SUPPORTED_DEVICE("Video");
*/
#define MAX_DMA_BUFS 3
-static int alloc_bufs_at_load = 0;
-module_param(alloc_bufs_at_load, bool, 0444);
-MODULE_PARM_DESC(alloc_bufs_at_load,
- "Non-zero value causes DMA buffers to be allocated at module "
- "load time. This increases the chances of successfully getting "
- "those buffers, but at the cost of nailing down the memory from "
- "the outset.");
+static int alloc_bufs_at_read = 0;
+module_param(alloc_bufs_at_read, bool, 0444);
+MODULE_PARM_DESC(alloc_bufs_at_read,
+ "Non-zero value causes DMA buffers to be allocated when the "
+ "video capture device is read, rather than at module load "
+ "time. This saves memory, but decreases the chances of "
+ "successfully getting those buffers.");
static int n_dma_bufs = 3;
module_param(n_dma_bufs, uint, 0644);
@@ -356,6 +355,7 @@ static int cafe_smbus_write_data(struct cafe_camera *cam,
{
unsigned int rval;
unsigned long flags;
+ DEFINE_WAIT(the_wait);
spin_lock_irqsave(&cam->dev_lock, flags);
rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
@@ -369,10 +369,29 @@ static int cafe_smbus_write_data(struct cafe_camera *cam,
rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
cafe_reg_write(cam, REG_TWSIC1, rval);
spin_unlock_irqrestore(&cam->dev_lock, flags);
- msleep(2); /* Required or things flake */
+ /*
+ * Time to wait for the write to complete. THIS IS A RACY
+ * WAY TO DO IT, but the sad fact is that reading the TWSIC1
+ * register too quickly after starting the operation sends
+ * the device into a place that may be kinder and better, but
+ * which is absolutely useless for controlling the sensor. In
+ * practice we have plenty of time to get into our sleep state
+ * before the interrupt hits, and the worst case is that we
+ * time out and then see that things completed, so this seems
+ * the best way for now.
+ */
+ do {
+ prepare_to_wait(&cam->smbus_wait, &the_wait,
+ TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1); /* even 1 jiffy is too long */
+ finish_wait(&cam->smbus_wait, &the_wait);
+ } while (!cafe_smbus_write_done(cam));
+
+#ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT
wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
CAFE_SMBUS_TIMEOUT);
+#endif
spin_lock_irqsave(&cam->dev_lock, flags);
rval = cafe_reg_read(cam, REG_TWSIC1);
spin_unlock_irqrestore(&cam->dev_lock, flags);
@@ -710,7 +729,7 @@ static void cafe_ctlr_init(struct cafe_camera *cam)
* Here we must wait a bit for the controller to come around.
*/
spin_unlock_irqrestore(&cam->dev_lock, flags);
- mdelay(5); /* FIXME revisit this */
+ msleep(5);
spin_lock_irqsave(&cam->dev_lock, flags);
cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
@@ -1178,7 +1197,7 @@ static int cafe_setup_siobuf(struct cafe_camera *cam, int index)
buf->v4lbuf.field = V4L2_FIELD_NONE;
buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
/*
- * Offset: must be 32-bit even on a 64-bit system. video-buf
+ * Offset: must be 32-bit even on a 64-bit system. videobuf-dma-sg
* just uses the length times the index, but the spec warns
* against doing just that - vma merging problems. So we
* leave a gap between each pair of buffers.
@@ -1483,7 +1502,7 @@ static int cafe_v4l_release(struct inode *inode, struct file *filp)
}
if (cam->users == 0) {
cafe_ctlr_power_down(cam);
- if (! alloc_bufs_at_load)
+ if (alloc_bufs_at_read)
cafe_free_dma_bufs(cam);
}
mutex_unlock(&cam->s_mutex);
@@ -2142,7 +2161,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
/*
* If so requested, try to get our DMA buffers now.
*/
- if (alloc_bufs_at_load) {
+ if (!alloc_bufs_at_read) {
if (cafe_alloc_dma_bufs(cam, 1))
cam_warn(cam, "Unable to alloc DMA buffers at load"
" will try again later.");
@@ -2233,12 +2252,21 @@ static int cafe_pci_resume(struct pci_dev *pdev)
if (ret)
return ret;
ret = pci_enable_device(pdev);
+
if (ret) {
cam_warn(cam, "Unable to re-enable device on resume!\n");
return ret;
}
cafe_ctlr_init(cam);
- cafe_ctlr_power_up(cam);
+ cafe_ctlr_power_down(cam);
+
+ mutex_lock(&cam->s_mutex);
+ if (cam->users > 0) {
+ cafe_ctlr_power_up(cam);
+ __cafe_cam_reset(cam);
+ }
+ mutex_unlock(&cam->s_mutex);
+
set_bit(CF_CONFIG_NEEDED, &cam->flags);
if (cam->state == S_SPECREAD)
cam->state = S_IDLE; /* Don't bother restarting */
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index f065ad12cc61..cefd1381e8de 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -848,6 +848,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOCSFREQ32:
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
+ case VIDIOCGVBIFMT:
+ case VIDIOCSVBIFMT:
#endif
case VIDIOC_QUERYCAP:
case VIDIOC_ENUM_FMT:
@@ -874,7 +876,10 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_ENUMINPUT:
case VIDIOC_ENUMINPUT32:
case VIDIOC_G_CTRL:
+ case VIDIOC_S_CTRL:
case VIDIOC_S_CTRL32:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_G_FREQUENCY:
case VIDIOC_QUERYCTRL:
case VIDIOC_G_INPUT32:
case VIDIOC_S_INPUT32:
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 78c9699eafbb..a1d02e5ce0fd 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -28,7 +28,6 @@
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
index fd771c7a2fe2..a76bd786cf13 100644
--- a/drivers/media/video/cpia2/cpia2_core.c
+++ b/drivers/media/video/cpia2/cpia2_core.c
@@ -663,15 +663,13 @@ int cpia2_reset_camera(struct camera_data *cam)
cpia2_send_command(cam, &cmd);
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
if (cam->params.pnp_id.device_type == DEVICE_STV_672)
retval = apply_vp_patch(cam);
/* wait for vp to go to sleep */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
/***
* If this is a 676, apply VP5 fixes before we start streaming
@@ -720,8 +718,7 @@ int cpia2_reset_camera(struct camera_data *cam)
set_default_user_mode(cam);
/* Give VP time to wake up */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
set_all_properties(cam);
@@ -2227,15 +2224,13 @@ struct camera_data *cpia2_init_camera_struct(void)
{
struct camera_data *cam;
- cam = kmalloc(sizeof(*cam), GFP_KERNEL);
+ cam = kzalloc(sizeof(*cam), GFP_KERNEL);
if (!cam) {
ERR("couldn't kmalloc cpia2 struct\n");
return NULL;
}
- /* Default everything to 0 */
- memset(cam, 0, sizeof(struct camera_data));
cam->present = 1;
mutex_init(&cam->busy_lock);
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 1bda7ad9de11..e3aaba1e0e0a 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -37,7 +37,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
#include "cpia2.h"
#include "cpia2dev.h"
@@ -105,7 +104,7 @@ static struct control_menu_info framerate_controls[] =
{ CPIA2_VP_FRAMERATE_25, "25 fps" },
{ CPIA2_VP_FRAMERATE_30, "30 fps" },
};
-#define NUM_FRAMERATE_CONTROLS (sizeof(framerate_controls)/sizeof(framerate_controls[0]))
+#define NUM_FRAMERATE_CONTROLS (ARRAY_SIZE(framerate_controls))
static struct control_menu_info flicker_controls[] =
{
@@ -113,7 +112,7 @@ static struct control_menu_info flicker_controls[] =
{ FLICKER_50, "50 Hz" },
{ FLICKER_60, "60 Hz" },
};
-#define NUM_FLICKER_CONTROLS (sizeof(flicker_controls)/sizeof(flicker_controls[0]))
+#define NUM_FLICKER_CONTROLS (ARRAY_SIZE(flicker_controls))
static struct control_menu_info lights_controls[] =
{
@@ -122,7 +121,7 @@ static struct control_menu_info lights_controls[] =
{ 128, "Bottom" },
{ 192, "Both" },
};
-#define NUM_LIGHTS_CONTROLS (sizeof(lights_controls)/sizeof(lights_controls[0]))
+#define NUM_LIGHTS_CONTROLS (ARRAY_SIZE(lights_controls))
#define GPIO_LIGHTS_MASK 192
static struct v4l2_queryctrl controls[] = {
@@ -235,7 +234,7 @@ static struct v4l2_queryctrl controls[] = {
.default_value = 0,
},
};
-#define NUM_CONTROLS (sizeof(controls)/sizeof(controls[0]))
+#define NUM_CONTROLS (ARRAY_SIZE(controls))
/******************************************************************************
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index d73c86aeeaac..62304255dcae 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -191,17 +190,21 @@ static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
/* Map the control ID to the correct field in the cx2341x_mpeg_params
struct. Return -EINVAL if the ID is unknown, else return 0. */
-static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
struct v4l2_ext_control *ctrl)
{
switch (ctrl->id) {
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+ if (busy)
+ return -EBUSY;
params->audio_sampling_freq = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
params->audio_encoding = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+ if (busy)
+ return -EBUSY;
params->audio_l2_bitrate = ctrl->value;
break;
case V4L2_CID_MPEG_AUDIO_MODE:
@@ -246,6 +249,8 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
params->video_gop_closure = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+ if (busy)
+ return -EBUSY;
/* MPEG-1 only allows CBR */
if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
@@ -253,9 +258,13 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
params->video_bitrate_mode = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
+ if (busy)
+ return -EBUSY;
params->video_bitrate = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+ if (busy)
+ return -EBUSY;
params->video_bitrate_peak = ctrl->value;
break;
case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
@@ -268,6 +277,8 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
params->video_mute_yuv = ctrl->value;
break;
case V4L2_CID_MPEG_STREAM_TYPE:
+ if (busy)
+ return -EBUSY;
params->stream_type = ctrl->value;
params->video_encoding =
(params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
@@ -632,7 +643,7 @@ static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
(params->audio_crc << 14);
}
-int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
struct v4l2_ext_controls *ctrls, unsigned int cmd)
{
int err = 0;
@@ -664,7 +675,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
if (err)
break;
- err = cx2341x_set_ctrl(params, ctrl);
+ err = cx2341x_set_ctrl(params, busy, ctrl);
if (err)
break;
}
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
new file mode 100644
index 000000000000..72004a07b2d5
--- /dev/null
+++ b/drivers/media/video/cx23885/Kconfig
@@ -0,0 +1,20 @@
+config VIDEO_CX23885
+ tristate "Conexant cx23885 (2388x successor) support"
+ depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+ select I2C_ALGOBIT
+ select FW_LOADER
+ select VIDEO_BTCX
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
+ select VIDEOBUF_DVB
+ select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+ select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_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
+
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
new file mode 100644
index 000000000000..665067022d2a
--- /dev/null
+++ b/drivers/media/video/cx23885/Makefile
@@ -0,0 +1,9 @@
+cx23885-objs := cx23885-cards.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
+
+obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
new file mode 100644
index 000000000000..b9012acabb2f
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -0,0 +1,280 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "cx23885.h"
+
+/* ------------------------------------------------------------------ */
+/* board config info */
+
+struct cx23885_board cx23885_boards[] = {
+ [CX23885_BOARD_UNKNOWN] = {
+ .name = "UNKNOWN/GENERIC",
+ .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",
+ .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_HVR1250] = {
+ .name = "Hauppauge WinTV-HVR1250",
+ .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_DVICO_FUSIONHDTV_5_EXP] = {
+ .name = "DViCO FusionHDTV5 Express",
+ .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 = 0x7911,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1250,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xd500,
+ .card = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
+ },
+};
+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("%s: Your board has no valid PCIe 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",
+ dev->name, dev->name, dev->name, dev->name, dev->name);
+ } else {
+ printk("%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",
+ dev->name, dev->name, dev->name, dev->name);
+ }
+ printk("%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("%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 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
+ case 77001: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
+ case 78501: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */
+ case 78521: /* WinTV-HVR1800 (PCIe, Retail, IR, Dual channel ATSC and MPEG2 HW Encoder */
+ break;
+ default:
+ printk("%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 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_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 */
+ // FIXME: Analog requires the tuner is brought out of reset
+ break;
+ }
+}
+
+int cx23885_ir_init(struct cx23885_dev *dev)
+{
+ switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ /* FIXME: Implement me */
+ break;
+ }
+
+ return 0;
+}
+
+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:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ if (dev->i2c_bus[0].i2c_rc == 0)
+ hauppauge_eeprom(dev, eeprom+0x80);
+ break;
+ }
+
+ switch (dev->board) {
+ 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_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ 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;
+ }
+
+}
+
+/* ------------------------------------------------------------------ */
+
+EXPORT_SYMBOL(cx23885_boards);
+
+/*
+ * 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/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
new file mode 100644
index 000000000000..af16505bd2e0
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -0,0 +1,1530 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/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 "cx23885.h"
+
+MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug = 0;
+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...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/0: " fmt, dev->name , ## arg)
+
+static unsigned int cx23885_devcount;
+
+static DEFINE_MUTEX(devlist);
+static LIST_HEAD(cx23885_devlist);
+
+#define NO_SYNC_LINE (-1U)
+
+/*
+ * CX23885 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
+ */
+
+struct sram_channel cx23885_sram_channels[] = {
+ [SRAM_CH01] = {
+ .name = "test ch1",
+ .cmds_start = 0x10000,
+ .ctrl_start = 0x10500,
+ .cdt = 0x10900,
+ .fifo_start = 0x3000,
+ .fifo_size = 0x1000,
+ .ptr1_reg = DMA1_PTR1,
+ .ptr2_reg = DMA1_PTR2,
+ .cnt1_reg = DMA1_CNT1,
+ .cnt2_reg = DMA1_CNT2,
+ .jumponly = 1,
+ },
+ [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 = 0x10780,
+ .cdt = 0x10400,
+ .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 = 0x10680,
+ .cdt = 0x10480,
+ .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 = "ch7",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
+ .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,
+ },
+};
+
+/* 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
+ */
+
+struct sram_channel cx23887_sram_channels[] = {
+ [SRAM_CH01] = {
+ .name = "test ch1",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
+ .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 = "ch3",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
+ .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 = 0x10680,
+ .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 = "ch7",
+ .cmds_start = 0x0,
+ .ctrl_start = 0x0,
+ .cdt = 0x0,
+ .fifo_start = 0x0,
+ .fifo_size = 0x0,
+ .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 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 = STATE_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("%s: %d buffers handled (should be 1)\n",
+ __FUNCTION__, bc);
+}
+void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+ struct sram_channel *ch);
+
+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", __FUNCTION__,
+ 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", __FUNCTION__,
+ 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, cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC) );
+ cx_write(8 + 4, cpu_to_le32(8) );
+ cx_write(8 + 8, cpu_to_le32(0) );
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+ dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, 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("%s: %s - dma channel status dump\n",
+ dev->name, ch->name);
+ for (i = 0; i < ARRAY_SIZE(name); i++)
+ printk("%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("%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("%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("%s: iq %x: 0x%08x [ arg #%d ]\n",
+ dev->name, i+j, risc, j);
+ }
+ }
+
+ printk("%s: fifo: 0x%08x -> 0x%x\n",
+ dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+ printk("%s: ctrl: 0x%08x -> 0x%x\n",
+ dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
+ printk("%s: ptr1_reg: 0x%08x\n",
+ dev->name, cx_read(ch->ptr1_reg));
+ printk("%s: ptr2_reg: 0x%08x\n",
+ dev->name, cx_read(ch->ptr2_reg));
+ printk("%s: cnt1_reg: 0x%08x\n",
+ dev->name, cx_read(ch->cnt1_reg));
+ printk("%s: cnt2_reg: 0x%08x\n",
+ dev->name, cx_read(ch->cnt2_reg));
+}
+
+void cx23885_risc_disasm(struct cx23885_tsport *port,
+ struct btcx_riscmem *risc)
+{
+ struct cx23885_dev *dev = port->dev;
+ unsigned int i, j, n;
+
+ printk("%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("%s: %04d: ", dev->name, i);
+ n = cx23885_risc_decode(risc->cpu[i]);
+ for (j = 1; j < n; j++)
+ printk("%s: %04d: 0x%08x [ arg #%d ]\n",
+ dev->name, i + j, risc->cpu[i + j], j);
+ if (risc->cpu[i] == RISC_JUMP)
+ break;
+ }
+}
+
+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 */
+ cx_write(PCI_INT_MSK, 0);
+ 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);
+
+}
+
+void cx23885_reset(struct cx23885_dev *dev)
+{
+ dprintk(1, "%s()\n", __FUNCTION__);
+
+ 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);
+
+ mdelay(100);
+
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*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", __FUNCTION__);
+
+ /* 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", __FUNCTION__, 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 */
+
+ 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);
+
+ 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 int cx23885_dev_setup(struct cx23885_dev *dev)
+{
+ int i;
+
+ mutex_init(&dev->lock);
+
+ atomic_inc(&dev->refcount);
+
+ dev->nr = cx23885_devcount++;
+ sprintf(dev->name, "cx23885[%d]", dev->nr);
+
+ mutex_lock(&devlist);
+ list_add_tail(&dev->devlist, &cx23885_devlist);
+ mutex_unlock(&devlist);
+
+ /* Configure the internal memory */
+ if(dev->pci->device == 0x8880) {
+ dev->bridge = CX23885_BRIDGE_887;
+ dev->sram_channels = cx23887_sram_channels;
+ } else
+ if(dev->pci->device == 0x8852) {
+ dev->bridge = CX23885_BRIDGE_885;
+ dev->sram_channels = cx23885_sram_channels;
+ } else
+ BUG();
+
+ dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
+ __FUNCTION__, 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);
+ }
+
+ 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 = (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_init_tsport(dev, &dev->ts1, 1);
+
+ if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ 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--;
+ goto fail_free;
+ }
+
+ /* 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);
+
+ /* 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_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ cx23885_card_setup(dev);
+ cx23885_ir_init(dev);
+
+ if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+ if (cx23885_dvb_register(&dev->ts1) < 0) {
+ printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+ __FUNCTION__);
+ }
+ }
+
+ if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+ if (cx23885_dvb_register(&dev->ts2) < 0) {
+ printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
+ __FUNCTION__);
+ }
+ }
+
+ return 0;
+
+fail_free:
+ kfree(dev);
+ return -ENODEV;
+}
+
+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].portb == CX23885_MPEG_DVB)
+ cx23885_dvb_unregister(&dev->ts1);
+
+ if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ cx23885_dvb_unregister(&dev->ts2);
+
+ 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 u32* cx23885_risc_field(u32 *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 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;
+ u32 *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;
+ if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 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);
+ if (UNSET != bottom_offset)
+ rp = cx23885_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;
+}
+
+int cx23885_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+ struct scatterlist *sglist, unsigned int bpl,
+ unsigned int lines)
+{
+ u32 instructions;
+ u32 *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;
+
+ if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+ rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+
+ /* 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)
+{
+ u32 *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);
+ *(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(&buf->vb, 0, 0);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+ btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
+ buf->vb.state = STATE_NEEDS_INIT;
+}
+
+static int cx23885_start_dma(struct cx23885_tsport *port,
+ struct cx23885_dmaqueue *q,
+ struct cx23885_buffer *buf)
+{
+ struct cx23885_dev *dev = port->dev;
+
+ dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
+ buf->vb.width, buf->vb.height, buf->vb.field);
+
+ /* 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() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+ __FUNCTION__,
+ cx23885_boards[dev->board].portb,
+ cx23885_boards[dev->board].portc );
+ return -EINVAL;
+ }
+
+ udelay(100);
+
+ /* If the port supports SRC SELECT, configure it */
+ if(port->reg_src_sel)
+ cx_write(port->reg_src_sel, port->src_sel_val);
+
+ cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
+ cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
+ cx_write(port->reg_vld_misc, 0x00);
+ 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;
+
+ switch(dev->bridge) {
+ case CX23885_BRIDGE_885:
+ case CX23885_BRIDGE_887:
+ /* enable irqs */
+ dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
+ cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
+ cx_set(port->reg_dma_ctl, port->dma_ctl_val);
+ cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
+ break;
+ default:
+ BUG();
+ }
+
+ cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
+
+ return 0;
+}
+
+static int cx23885_stop_dma(struct cx23885_tsport *port)
+{
+ struct cx23885_dev *dev = port->dev;
+ dprintk(1, "%s()\n", __FUNCTION__);
+
+ /* 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);
+
+ return 0;
+}
+
+static 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", __FUNCTION__);
+ if (list_empty(&q->active))
+ {
+ struct cx23885_buffer *prev;
+ prev = NULL;
+
+ dprintk(5, "%s() queue is empty\n", __FUNCTION__);
+
+ 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 = STATE_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(5, "[%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 = STATE_ACTIVE;
+ buf->count = q->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(5,"[%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 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", __FUNCTION__, buf);
+ if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ return -EINVAL;
+
+ if (STATE_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*/;
+
+ if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+ goto fail;
+ cx23885_risc_databuffer(dev->pci, &buf->risc,
+ videobuf_to_dma(&buf->vb)->sglist,
+ buf->vb.width, buf->vb.height);
+ }
+ buf->vb.state = STATE_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 = STATE_ACTIVE;
+ buf->count = cx88q->count++;
+ mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(1, "[%p/%d] %s - first active\n",
+ buf, buf->vb.i, __FUNCTION__);
+ } 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 = STATE_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, __FUNCTION__);
+ }
+}
+
+/* ----------------------------------------------------------- */
+
+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 = STATE_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", __FUNCTION__);
+ del_timer_sync(&q->timeout);
+ cx23885_stop_dma(port);
+ do_cancel_buffers(port, "cancel", 0);
+}
+
+static void cx23885_timeout(unsigned long data)
+{
+ struct cx23885_tsport *port = (struct cx23885_tsport *)data;
+ struct cx23885_dev *dev = port->dev;
+
+ dprintk(1, "%s()\n",__FUNCTION__);
+
+ if (debug > 5)
+ cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+
+ cx23885_stop_dma(port);
+ do_cancel_buffers(port, "timeout", 1);
+}
+
+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 ts1_status, ts1_mask;
+ u32 ts2_status, ts2_mask;
+ int ts1_count = 0, ts2_count = 0, handled = 0;
+
+ pci_status = cx_read(PCI_INT_STAT);
+ pci_mask = cx_read(PCI_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;
+
+ 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, "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_status & PCI_MSK_RISC_WR) ||
+ (pci_status & PCI_MSK_AL_RD) ||
+ (pci_status & PCI_MSK_AL_WR) ||
+ (pci_status & PCI_MSK_APB_DMA) ||
+ (pci_status & PCI_MSK_VID_C) ||
+ (pci_status & PCI_MSK_VID_B) ||
+ (pci_status & PCI_MSK_VID_A) ||
+ (pci_status & PCI_MSK_AUD_INT) ||
+ (pci_status & PCI_MSK_AUD_EXT) )
+ {
+
+ 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 (ts1_status)
+ handled += cx23885_irq_ts(ts1, ts1_status);
+
+ if (ts2_status)
+ handled += cx23885_irq_ts(ts2, ts2_status);
+
+ if (handled)
+ cx_write(PCI_INT_STAT, pci_status);
+out:
+ return IRQ_RETVAL(handled);
+}
+
+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;
+
+ /* pci init */
+ dev->pci = pci_dev;
+ if (pci_enable_device(pci_dev)) {
+ err = -EIO;
+ goto fail_free;
+ }
+
+ if (cx23885_dev_setup(dev) < 0) {
+ err = -EINVAL;
+ goto fail_free;
+ }
+
+ /* 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);
+ 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;
+ }
+
+ pci_set_drvdata(pci_dev, dev);
+ return 0;
+
+fail_irq:
+ cx23885_dev_unregister(dev);
+fail_free:
+ kfree(dev);
+ return err;
+}
+
+static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
+{
+ struct cx23885_dev *dev = pci_get_drvdata(pci_dev);
+
+ cx23885_shutdown(dev);
+
+ 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);
+
+ cx23885_dev_unregister(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 cx23885_init(void)
+{
+ printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n",
+ (CX23885_VERSION_CODE >> 16) & 0xff,
+ (CX23885_VERSION_CODE >> 8) & 0xff,
+ CX23885_VERSION_CODE & 0xff);
+#ifdef SNAPSHOT
+ printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n",
+ SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
+#endif
+ return pci_register_driver(&cx23885_pci_driver);
+}
+
+static void cx23885_fini(void)
+{
+ pci_unregister_driver(&cx23885_pci_driver);
+}
+
+module_init(cx23885_init);
+module_exit(cx23885_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * 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/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
new file mode 100644
index 000000000000..eda8c05d0931
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -0,0 +1,213 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/suspend.h>
+
+#include "cx23885.h"
+#include <media/v4l2-common.h>
+
+#include "s5h1409.h"
+#include "mt2131.h"
+#include "lgdt330x.h"
+#include "dvb-pll.h"
+
+static unsigned int debug = 0;
+
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg)
+
+/* ------------------------------------------------------------------ */
+
+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 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,
+ .if_freq = 44000,
+ .inversion = S5H1409_INVERSION_OFF,
+ .status_mode = S5H1409_DEMODLOCKING
+};
+
+static struct s5h1409_config hauppauge_hvr1800lp_config = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_SERIAL_OUTPUT,
+ .gpio = S5H1409_GPIO_OFF,
+ .if_freq = 44000,
+ .inversion = S5H1409_INVERSION_OFF,
+ .status_mode = S5H1409_DEMODLOCKING
+};
+
+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 int dvb_register(struct cx23885_tsport *port)
+{
+ struct cx23885_dev *dev = port->dev;
+ struct cx23885_i2c *i2c_bus = NULL;
+
+ /* init struct videobuf_dvb */
+ port->dvb.name = dev->name;
+
+ /* init frontend */
+ switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ i2c_bus = &dev->i2c_bus[0];
+ port->dvb.frontend = dvb_attach(s5h1409_attach,
+ &hauppauge_generic_config,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, port->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_generic_tunerconfig, 0);
+ }
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ i2c_bus = &dev->i2c_bus[0];
+ port->dvb.frontend = dvb_attach(s5h1409_attach,
+ &hauppauge_hvr1800lp_config,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, port->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_generic_tunerconfig, 0);
+ }
+ break;
+ case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
+ i2c_bus = &dev->i2c_bus[0];
+ port->dvb.frontend = dvb_attach(lgdt330x_attach,
+ &fusionhdtv_5_express,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL) {
+ dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
+ &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
+ }
+ break;
+ default:
+ printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+ dev->name);
+ break;
+ }
+ if (NULL == port->dvb.frontend) {
+ printk("%s: frontend initialization failed\n", dev->name);
+ return -1;
+ }
+
+ /* Put the analog decoder in standby to keep it quiet */
+ cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
+
+ /* register everything */
+ return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
+ &dev->pci->dev);
+}
+
+int cx23885_dvb_register(struct cx23885_tsport *port)
+{
+ struct cx23885_dev *dev = port->dev;
+ int err;
+
+ dprintk(1, "%s\n", __FUNCTION__);
+ dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ dev->board,
+ dev->name,
+ dev->pci_bus,
+ dev->pci_slot);
+
+ err = -ENODEV;
+
+ /* dvb stuff */
+ printk("%s: cx23885 based dvb card\n", dev->name);
+ videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
+ sizeof(struct cx23885_buffer), port);
+ err = dvb_register(port);
+ if (err != 0)
+ printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
+
+ return err;
+}
+
+int cx23885_dvb_unregister(struct cx23885_tsport *port)
+{
+ /* dvb */
+ if(port->dvb.frontend)
+ videobuf_dvb_unregister(&port->dvb);
+
+ return 0;
+}
+
+/*
+ * 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/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
new file mode 100644
index 000000000000..b517c8b5a566
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -0,0 +1,382 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include "cx23885.h"
+
+#include <media/v4l2-common.h>
+
+static unsigned int i2c_debug = 0;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan = 0;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg)
+
+#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 last)
+{
+ struct cx23885_i2c *bus = i2c_adap->algo_data;
+ struct cx23885_dev *dev = bus->dev;
+ u32 wdata, addr, ctrl;
+ int retval, cnt;
+
+ dprintk(1, "%s()\n", __FUNCTION__);
+ /* 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", __FUNCTION__);
+ 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;
+
+ 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) {
+ 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 || !last)
+ ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+ 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) {
+ printk(" %02x", msg->buf[cnt]);
+ if (!(ctrl & I2C_NOSTOP))
+ printk(" >\n");
+ }
+ }
+ return msg->len;
+
+ eio:
+ retval = -EIO;
+ err:
+ printk(" ERR: %d\n", retval);
+ return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ const struct i2c_msg *msg, int last)
+{
+ struct cx23885_i2c *bus = i2c_adap->algo_data;
+ struct cx23885_dev *dev = bus->dev;
+ u32 ctrl, cnt;
+ int retval;
+
+ dprintk(1, "%s()\n", __FUNCTION__);
+
+ /* 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", __FUNCTION__);
+ return 0;
+ }
+
+ for(cnt = 0; cnt < msg->len; cnt++) {
+
+ ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+ if (cnt < msg->len-1 || !last)
+ 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) {
+ if (!(ctrl & I2C_NOSTOP))
+ printk(" <R %02x", (msg->addr << 1) +1);
+ printk(" =%02x", msg->buf[cnt]);
+ if (!(ctrl & I2C_NOSTOP))
+ printk(" >\n");
+ }
+ }
+ return msg->len;
+
+ eio:
+ retval = -EIO;
+ err:
+ printk(" 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", __FUNCTION__, num);
+
+ for (i = 0 ; i < num; i++) {
+ dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
+ __FUNCTION__, num, msgs[i].addr, msgs[i].len);
+ if (msgs[i].flags & I2C_M_RD) {
+ /* read */
+ retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num);
+ if (retval < 0)
+ goto err;
+ } else {
+ /* write */
+ retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num);
+ if (retval < 0)
+ goto err;
+ }
+ }
+ return num;
+
+ err:
+ return retval;
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+ struct cx23885_dev *dev = i2c_get_adapdata(client->adapter);
+
+ dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
+ client->driver->driver.name, client->addr, client->name);
+
+ if (!client->driver->command)
+ return 0;
+
+ return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+ struct cx23885_dev *dev = i2c_get_adapdata(client->adapter);
+
+ dprintk(1, "i2c detach [client=%s]\n", client->name);
+
+ return 0;
+}
+
+void cx23885_call_i2c_clients(struct cx23885_i2c *bus,
+ unsigned int cmd, void *arg)
+{
+ if (bus->i2c_rc != 0)
+ return;
+
+ i2c_clients_command(&bus->i2c_adap, cmd, arg);
+}
+
+static int cx23885_algo_control(struct i2c_adapter *adap,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+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,
+ .algo_control = cx23885_algo_control,
+ .functionality = cx23885_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter cx23885_i2c_adap_template = {
+ .name = "cx23885",
+ .owner = THIS_MODULE,
+ .id = I2C_HW_B_CX23885,
+ .algo = &cx23885_i2c_algo_template,
+ .client_register = attach_inform,
+ .client_unregister = detach_inform,
+};
+
+static struct i2c_client cx23885_i2c_client_template = {
+ .name = "cx23885 internal",
+};
+
+static char *i2c_devs[128] = {
+ [ 0x1c >> 1 ] = "lgdt3303",
+ [ 0x86 >> 1 ] = "tda9887",
+ [ 0x32 >> 1 ] = "cx24227",
+ [ 0x88 >> 1 ] = "cx25837",
+ [ 0x84 >> 1 ] = "tda8295",
+ [ 0xa0 >> 1 ] = "eeprom",
+ [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+ [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275",
+};
+
+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("%s: i2c scan: found device @ 0x%x [%s]\n",
+ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ }
+}
+
+/* init + register i2c algo-bit adapter */
+int cx23885_i2c_register(struct cx23885_i2c *bus)
+{
+ struct cx23885_dev *dev = bus->dev;
+
+ dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
+
+ memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
+ sizeof(bus->i2c_adap));
+ memcpy(&bus->i2c_algo, &cx23885_i2c_algo_template,
+ sizeof(bus->i2c_algo));
+ memcpy(&bus->i2c_client, &cx23885_i2c_client_template,
+ sizeof(bus->i2c_client));
+
+ bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+ strlcpy(bus->i2c_adap.name, bus->dev->name,
+ sizeof(bus->i2c_adap.name));
+
+ bus->i2c_algo.data = bus;
+ bus->i2c_adap.algo_data = bus;
+ i2c_add_adapter(&bus->i2c_adap);
+
+ bus->i2c_client.adapter = &bus->i2c_adap;
+
+ if (0 == bus->i2c_rc) {
+ printk("%s: i2c bus %d registered\n", dev->name, bus->nr);
+ if (i2c_scan)
+ do_i2c_scan(dev->name, &bus->i2c_client);
+ } else
+ printk("%s: i2c bus %d register FAILED\n", dev->name, bus->nr);
+
+ return bus->i2c_rc;
+}
+
+int cx23885_i2c_unregister(struct cx23885_i2c *bus)
+{
+ i2c_del_adapter(&bus->i2c_adap);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+EXPORT_SYMBOL(cx23885_call_i2c_clients);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
new file mode 100644
index 000000000000..162169f9091b
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -0,0 +1,431 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _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 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_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_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_RISCI2 (1 << 4)
+#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_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 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.h b/drivers/media/video/cx23885/cx23885.h
new file mode 100644
index 000000000000..dec4dc2fcbb4
--- /dev/null
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -0,0 +1,301 @@
+/*
+ * Driver for the Conexant CX23885 PCIe bridge
+ *
+ * Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-common.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 "cx23885-reg.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX23885_VERSION_CODE KERNEL_VERSION(0,0,1)
+
+#define UNSET (-1U)
+
+#define CX23885_MAXBOARDS 8
+
+/* Max number of inputs by card */
+#define MAX_CX23885_INPUT 8
+
+#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
+
+enum cx23885_itype {
+ CX23885_VMUX_COMPOSITE1 = 1,
+ CX23885_VMUX_COMPOSITE2,
+ CX23885_VMUX_COMPOSITE3,
+ CX23885_VMUX_COMPOSITE4,
+ CX23885_VMUX_SVIDEO,
+ 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;
+ u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+typedef enum {
+ CX23885_MPEG_UNDEFINED = 0,
+ CX23885_MPEG_DVB
+} port_t;
+
+struct cx23885_board {
+ char *name;
+ port_t portb, portc;
+ struct cx23885_input input[MAX_CX23885_INPUT];
+};
+
+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_algo_bit_data i2c_algo;
+ 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 dvb;
+
+ /* 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;
+};
+
+struct cx23885_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;
+ int pci_irqmask;
+
+ /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+ struct cx23885_i2c i2c_bus[3];
+
+ int nr;
+ struct mutex 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,
+ } bridge;
+};
+
+#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)
+
+extern int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+ struct sram_channel *ch,
+ unsigned int bpl, u32 risc);
+
+/* ----------------------------------------------------------- */
+/* 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 void cx23885_card_list(struct cx23885_dev *dev);
+extern int cx23885_ir_init(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-i2c.c */
+extern int cx23885_i2c_register(struct cx23885_i2c *bus);
+extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
+extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
+ void *arg);
+
+/*
+ * 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/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index f897c1ebd5f3..3d46a776df36 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -157,13 +157,12 @@ void cx25840_audio_set_path(struct i2c_client *client)
{
struct cx25840_state *state = i2c_get_clientdata(client);
+ /* assert soft reset */
+ cx25840_and_or(client, 0x810, ~0x1, 0x01);
+
/* stop microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0);
- /* assert soft reset */
- if (!state->is_cx25836)
- cx25840_and_or(client, 0x810, ~0x1, 0x01);
-
/* Mute everything to prevent the PFFT! */
cx25840_write(client, 0x8d3, 0x1f);
@@ -181,32 +180,46 @@ void cx25840_audio_set_path(struct i2c_client *client)
set_audclk_freq(client, state->audclk_freq);
- /* deassert soft reset */
- if (!state->is_cx25836)
- cx25840_and_or(client, 0x810, ~0x1, 0x00);
-
if (state->aud_input != CX25840_AUDIO_SERIAL) {
/* When the microcontroller detects the
* audio format, it will unmute the lines */
cx25840_and_or(client, 0x803, ~0x10, 0x10);
}
+
+ /* deassert soft reset */
+ cx25840_and_or(client, 0x810, ~0x1, 0x00);
}
static int get_volume(struct i2c_client *client)
{
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ int vol;
+
+ if (state->unmute_volume >= 0)
+ return state->unmute_volume;
+
/* Volume runs +18dB to -96dB in 1/2dB steps
* change to fit the msp3400 -114dB to +12dB range */
/* check PATH1_VOLUME */
- int vol = 228 - cx25840_read(client, 0x8d4);
+ vol = 228 - cx25840_read(client, 0x8d4);
vol = (vol / 2) + 23;
return vol << 9;
}
static void set_volume(struct i2c_client *client, int volume)
{
- /* First convert the volume to msp3400 values (0-127) */
- int vol = volume >> 9;
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ int vol;
+
+ if (state->unmute_volume >= 0) {
+ state->unmute_volume = volume;
+ return;
+ }
+
+ /* Convert the volume to msp3400 values (0-127) */
+ vol = volume >> 9;
+
/* now scale it up to cx25840 values
* -114dB to -96dB maps to 0
* this should be 19, but in my testing that was 4dB too loud */
@@ -284,30 +297,26 @@ static void set_balance(struct i2c_client *client, int balance)
static int get_mute(struct i2c_client *client)
{
- /* check SRC1_MUTE_EN */
- return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
+ struct cx25840_state *state = i2c_get_clientdata(client);
+
+ return state->unmute_volume >= 0;
}
static void set_mute(struct i2c_client *client, int mute)
{
struct cx25840_state *state = i2c_get_clientdata(client);
- if (state->aud_input != CX25840_AUDIO_SERIAL) {
- /* 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. */
- if (mute) {
- /* disable microcontroller */
- cx25840_and_or(client, 0x803, ~0x10, 0x00);
- cx25840_write(client, 0x8d3, 0x1f);
- } else {
- /* enable microcontroller */
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
- }
- } else {
- /* SRC1_MUTE_EN */
- cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+ if (mute && state->unmute_volume == -1) {
+ int vol = get_volume(client);
+
+ set_volume(client, 0);
+ state->unmute_volume = vol;
+ }
+ else if (!mute && state->unmute_volume != -1) {
+ int vol = state->unmute_volume;
+
+ state->unmute_volume = -1;
+ set_volume(client, vol);
}
}
@@ -319,18 +328,18 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
switch (cmd) {
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ if (!state->is_cx25836)
+ cx25840_and_or(client, 0x810, ~0x1, 1);
if (state->aud_input != CX25840_AUDIO_SERIAL) {
cx25840_and_or(client, 0x803, ~0x10, 0);
cx25840_write(client, 0x8d3, 0x1f);
}
- if (!state->is_cx25836)
- cx25840_and_or(client, 0x810, ~0x1, 1);
retval = set_audclk_freq(client, *(u32 *)arg);
- if (!state->is_cx25836)
- cx25840_and_or(client, 0x810, ~0x1, 0);
if (state->aud_input != CX25840_AUDIO_SERIAL) {
cx25840_and_or(client, 0x803, ~0x10, 0x10);
}
+ if (!state->is_cx25836)
+ cx25840_and_or(client, 0x810, ~0x1, 0);
return retval;
case VIDIOC_G_CTRL:
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 67bda9f9a44b..15f191e170d2 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/i2c.h>
+#include <linux/delay.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/cx25840.h>
@@ -133,7 +134,9 @@ static void init_dll1(struct i2c_client *client)
cx25840_write(client, 0x159, 0x23);
cx25840_write(client, 0x15a, 0x87);
cx25840_write(client, 0x15b, 0x06);
+ udelay(10);
cx25840_write(client, 0x159, 0xe1);
+ udelay(10);
cx25840_write(client, 0x15a, 0x86);
cx25840_write(client, 0x159, 0xe0);
cx25840_write(client, 0x159, 0xe1);
@@ -147,6 +150,7 @@ static void init_dll2(struct i2c_client *client)
cx25840_write(client, 0x15d, 0xe3);
cx25840_write(client, 0x15e, 0x86);
cx25840_write(client, 0x15f, 0x06);
+ udelay(10);
cx25840_write(client, 0x15d, 0xe1);
cx25840_write(client, 0x15d, 0xe0);
cx25840_write(client, 0x15d, 0xe1);
@@ -165,9 +169,7 @@ static void cx25836_initialize(struct i2c_client *client)
/* 3c. */
cx25840_and_or(client, 0x159, ~0x02, 0x02);
/* 3d. */
- /* There should be a 10-us delay here, but since the
- i2c bus already has a 10-us delay we don't need to do
- anything */
+ udelay(10);
/* 3e. */
cx25840_and_or(client, 0x159, ~0x02, 0x00);
/* 3f. */
@@ -179,9 +181,18 @@ static void cx25836_initialize(struct i2c_client *client)
cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
}
-static void cx25840_initialize(struct i2c_client *client, int loadfw)
+static void cx25840_work_handler(struct work_struct *work)
{
+ struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work);
+ cx25840_loadfw(state->c);
+ wake_up(&state->fw_wait);
+}
+
+static void cx25840_initialize(struct i2c_client *client)
+{
+ DEFINE_WAIT(wait);
struct cx25840_state *state = i2c_get_clientdata(client);
+ struct workqueue_struct *q;
/* datasheet startup in numbered steps, refer to page 3-77 */
/* 2. */
@@ -197,8 +208,19 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
cx25840_write(client, 0x13c, 0x01);
cx25840_write(client, 0x13c, 0x00);
/* 5. */
- if (loadfw)
- cx25840_loadfw(client);
+ /* Do the firmware load in a work handler to prevent.
+ Otherwise the kernel is blocked waiting for the
+ bit-banging i2c interface to finish uploading the
+ firmware. */
+ INIT_WORK(&state->fw_work, cx25840_work_handler);
+ init_waitqueue_head(&state->fw_wait);
+ q = create_singlethread_workqueue("cx25840_fw");
+ prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
+ queue_work(q, &state->fw_work);
+ schedule();
+ finish_wait(&state->fw_wait, &wait);
+ destroy_workqueue(q);
+
/* 6. */
cx25840_write(client, 0x115, 0x8c);
cx25840_write(client, 0x116, 0x07);
@@ -251,8 +273,13 @@ static void input_change(struct i2c_client *client)
}
cx25840_and_or(client, 0x401, ~0x60, 0);
cx25840_and_or(client, 0x401, ~0x60, 0x60);
+ cx25840_and_or(client, 0x810, ~0x01, 1);
- if (std & V4L2_STD_525_60) {
+ if (state->radio) {
+ cx25840_write(client, 0x808, 0xf9);
+ cx25840_write(client, 0x80b, 0x00);
+ }
+ else if (std & V4L2_STD_525_60) {
/* Certain Hauppauge PVR150 models have a hardware bug
that causes audio to drop out. For these models the
audio standard must be set explicitly.
@@ -281,11 +308,7 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x80b, 0x10);
}
- if (cx25840_read(client, 0x803) & 0x10) {
- /* restart audio decoder microcontroller */
- cx25840_and_or(client, 0x803, ~0x10, 0x00);
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
- }
+ cx25840_and_or(client, 0x810, ~0x01, 0);
}
static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
@@ -625,6 +648,22 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
struct v4l2_tuner *vt = arg;
struct v4l2_routing *route = arg;
+ /* ignore these commands */
+ switch (cmd) {
+ case TUNER_SET_TYPE_ADDR:
+ return 0;
+ }
+
+ if (!state->is_initialized) {
+ v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd);
+ /* initialize on first use */
+ state->is_initialized = 1;
+ if (state->is_cx25836)
+ cx25836_initialize(client);
+ else
+ cx25840_initialize(client);
+ }
+
switch (cmd) {
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the
@@ -825,7 +864,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
if (state->is_cx25836)
cx25836_initialize(client);
else
- cx25840_initialize(client, 0);
+ cx25840_initialize(client);
break;
case VIDIOC_G_CHIP_IDENT:
@@ -856,17 +895,16 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return 0;
- state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
- if (state == 0)
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == 0)
return -ENOMEM;
- client = &state->c;
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_cx25840;
snprintf(client->name, sizeof(client->name) - 1, "cx25840");
- v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1);
device_id = cx25840_read(client, 0x101) << 8;
device_id |= cx25840_read(client, 0x100);
@@ -875,42 +913,44 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
* 0x83 for the cx2583x and 0x84 for the cx2584x */
if ((device_id & 0xff00) == 0x8300) {
id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
- state->is_cx25836 = 1;
}
else if ((device_id & 0xff00) == 0x8400) {
id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
- state->is_cx25836 = 0;
}
else {
v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
- kfree(state);
+ kfree(client);
return 0;
}
+ state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+
/* Note: revision '(device_id & 0x0f) == 2' was never built. The
marking skips from 0x1 == 22 to 0x3 == 23. */
v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
(device_id & 0xfff0) >> 4,
(device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f),
- address << 1, adapter->name);
+ client->addr << 1, client->adapter->name);
i2c_set_clientdata(client, state);
+ state->c = client;
+ state->is_cx25836 = ((device_id & 0xff00) == 0x8300);
state->vid_input = CX25840_COMPOSITE7;
state->aud_input = CX25840_AUDIO8;
state->audclk_freq = 48000;
state->pvr150_workaround = 0;
state->audmode = V4L2_TUNER_MODE_LANG1;
+ state->unmute_volume = -1;
state->vbi_line_offset = 8;
state->id = id;
state->rev = device_id;
i2c_attach_client(client);
- if (state->is_cx25836)
- cx25836_initialize(client);
- else
- cx25840_initialize(client, 1);
-
return 0;
}
@@ -932,6 +972,7 @@ static int cx25840_detach_client(struct i2c_client *client)
}
kfree(state);
+ kfree(client);
return 0;
}
@@ -1056,9 +1097,10 @@ static void log_audio_status(struct i2c_client *client)
}
v4l_info(client, "Detected audio standard: %s\n", p);
v4l_info(client, "Audio muted: %s\n",
- (mute_ctl & 0x2) ? "yes" : "no");
+ (state->unmute_volume >= 0) ? "yes" : "no");
v4l_info(client, "Audio microcontroller: %s\n",
- (download_ctl & 0x10) ? "running" : "stopped");
+ (download_ctl & 0x10) ?
+ ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
switch (audio_config >> 4) {
case 0x00: p = "undefined"; break;
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index f4b56d2fd6b6..ea669b1f084d 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -35,17 +35,21 @@ extern int cx25840_debug;
#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
struct cx25840_state {
- struct i2c_client c;
+ struct i2c_client *c;
int pvr150_workaround;
int radio;
enum cx25840_video_input vid_input;
enum cx25840_audio_input aud_input;
u32 audclk_freq;
int audmode;
+ int unmute_volume; /* -1 if not muted */
int vbi_line_offset;
u32 id;
u32 rev;
int is_cx25836;
+ int is_initialized;
+ wait_queue_head_t fw_wait; /* wake up when the fw load is finished */
+ struct work_struct fw_work; /* work entry for fw load */
};
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 0f9d96963618..eeb5224ca101 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -4,7 +4,7 @@ config VIDEO_CX88
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
- select VIDEO_BUF
+ select VIDEOBUF_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
@@ -46,8 +46,8 @@ config VIDEO_CX88_BLACKBIRD
config VIDEO_CX88_DVB
tristate "DVB/ATSC Support for cx2388x based TV cards"
depends on VIDEO_CX88 && DVB_CORE
- select VIDEO_BUF_DVB
- select DVB_PLL
+ 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
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 2d666b56020c..90c36c5705c3 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -3,6 +3,7 @@
* 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>
@@ -27,7 +28,9 @@
#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/driver.h>
@@ -46,21 +49,16 @@
#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
****************************************************************************/
-/* These can be replaced after done */
-#define MIXER_ADDR_LAST MAX_CX88_INPUT
-
struct cx88_audio_dev {
struct cx88_core *core;
struct cx88_dmaqueue q;
/* pci i/o */
struct pci_dev *pci;
- unsigned char pci_rev,pci_lat;
/* audio controls */
int irq;
@@ -68,24 +66,17 @@ struct cx88_audio_dev {
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;
-
- int mixer_volume[MIXER_ADDR_LAST+1][2];
- int capture_source[MIXER_ADDR_LAST+1][2];
-
- long int read_count;
- long int read_offset;
-
- struct cx88_buffer *buf;
+ struct videobuf_dmabuf *dma_risc;
- long opened;
- struct snd_pcm_substream *substream;
+ struct cx88_buffer *buf;
+ struct snd_pcm_substream *substream;
};
typedef struct cx88_audio_dev snd_cx88_card_t;
@@ -98,7 +89,6 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
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};
-static struct snd_card *snd_cx88_cards[SNDRV_CARDS];
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
@@ -136,38 +126,39 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
struct cx88_core *core=chip->core;
struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
-
- dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start);
+ /* 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, &cx88_sram_channels[SRAM_CH25],
- buf->bpl, buf->risc.dma);
+ 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);
-
- dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02));
- /* enable irqs */
- cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02);
+ 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,
- (1<<16)|
- (1<<12)|
- (1<<4)|
- (1<<0)
- );
+ 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, &cx88_sram_channels[SRAM_CH25]);
+ cx88_sram_channel_dump(chip->core, audio_ch);
return 0;
}
@@ -184,13 +175,9 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
cx_clear(MO_AUD_DMACNTRL, 0x11);
/* disable irqs */
- cx_clear(MO_PCI_INTMSK, 0x02);
- cx_clear(MO_AUD_INTMSK,
- (1<<16)|
- (1<<12)|
- (1<<4)|
- (1<<0)
- );
+ 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]);
@@ -198,7 +185,7 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
return 0;
}
-#define MAX_IRQ_LOOP 10
+#define MAX_IRQ_LOOP 50
/*
* BOARD Specific: IRQ dma bits
@@ -223,42 +210,32 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
{
struct cx88_core *core = chip->core;
u32 status, mask;
- u32 count;
status = cx_read(MO_AUD_INTSTAT);
mask = cx_read(MO_AUD_INTMSK);
- if (0 == (status & mask)) {
- spin_unlock(&chip->reg_lock);
+ 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 & (1 << 16)) {
- printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name);
+ 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]);
}
-
- /* risc1 downstream */
- if (status & 0x01) {
- spin_lock(&chip->reg_lock);
- count = cx_read(MO_AUDD_GPCNT);
- spin_unlock(&chip->reg_lock);
- if (chip->read_count == 0)
- chip->read_count += chip->dma_size;
+ if (status & AUD_INT_DN_SYNC) {
+ dprintk(1, "Downstream sync error\n");
+ cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
+ return;
}
-
- if (chip->read_count >= chip->period_size) {
- dprintk(2, "Elapsing period\n");
+ /* risc1 downstream */
+ if (status & AUD_INT_DN_RISCI1) {
+ atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
snd_pcm_period_elapsed(chip->substream);
}
-
- dprintk(3,"Leaving audio IRQ handler...\n");
-
/* FIXME: Any other status should deserve a special handling? */
}
@@ -273,27 +250,26 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id)
int loop, handled = 0;
for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02);
+ status = cx_read(MO_PCI_INTSTAT) &
+ (core->pci_irqmask | PCI_INT_AUDINT);
if (0 == status)
goto out;
- dprintk( 3, "cx8801_irq\n" );
- dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
- dprintk( 3, " status: %d\n", status );
+ 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 & 0x02)
- {
- dprintk( 2, " ALSA IRQ handling\n" );
+ if (status & core->pci_irqmask)
+ cx88_core_irq(core, status);
+ if (status & PCI_INT_AUDINT)
cx8801_aud_irq(chip);
- }
- };
+ }
if (MAX_IRQ_LOOP == loop) {
- dprintk( 0, "clearing mask\n" );
- dprintk(1,"%s/0: irq loop -- clearing mask\n",
+ printk(KERN_ERR
+ "%s/1: IRQ loop detected, disabling interrupts\n",
core->name);
- cx_clear(MO_PCI_INTMSK,0x02);
+ cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
}
out:
@@ -306,14 +282,15 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n");
- videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc);
- videobuf_dma_free(&chip->dma_risc);
+ videobuf_pci_dma_unmap(chip->pci, 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;
+ return 0;
}
/****************************************************************************
@@ -323,6 +300,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
/*
* Digital hardware definition
*/
+#define DEFAULT_FIFO_SIZE 4096
static struct snd_pcm_hardware snd_cx88_digital_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -333,22 +311,18 @@ static struct snd_pcm_hardware snd_cx88_digital_hw = {
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = (2*2048),
- .period_bytes_min = 2048,
- .period_bytes_max = 2048,
- .periods_min = 2,
- .periods_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 runtime free
- */
-static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime)
-{
-}
-/*
* audio pcm capture open callback
*/
static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
@@ -357,26 +331,24 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
int err;
- if (test_and_set_bit(0, &chip->opened))
- return -EBUSY;
-
- err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
if (err < 0)
goto _error;
chip->substream = substream;
- chip->read_count = 0;
- chip->read_offset = 0;
-
- runtime->private_free = snd_card_cx88_runtime_free;
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");
- clear_bit(0, &chip->opened);
- smp_mb__after_clear_bit();
return err;
}
@@ -385,11 +357,6 @@ _error:
*/
static int snd_cx88_close(struct snd_pcm_substream *substream)
{
- snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-
- clear_bit(0, &chip->opened);
- smp_mb__after_clear_bit();
-
return 0;
}
@@ -400,55 +367,67 @@ 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_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));
- dprintk(1,"Setting buffer\n");
-
- buf = kzalloc(sizeof(*buf),GFP_KERNEL);
+ buf = videobuf_pci_alloc(sizeof(*buf));
if (NULL == buf)
return -ENOMEM;
buf->vb.memory = V4L2_MEMORY_MMAP;
+ buf->vb.field = V4L2_FIELD_NONE;
buf->vb.width = chip->period_size;
+ buf->bpl = chip->period_size;
buf->vb.height = chip->num_periods;
buf->vb.size = chip->dma_size;
- buf->vb.field = V4L2_FIELD_NONE;
- videobuf_dma_init(&buf->vb.dma);
- videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,
+ dma=videobuf_to_dma(&buf->vb);
+ videobuf_dma_init(dma);
+ ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+ if (ret < 0)
+ goto error;
- videobuf_pci_dma_map(chip->pci,&buf->vb.dma);
+ ret = videobuf_pci_dma_map(chip->pci,dma);
+ if (ret < 0)
+ goto error;
+ ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+ buf->vb.width, buf->vb.height, 1);
+ if (ret < 0)
+ goto error;
- cx88_risc_databuffer(chip->pci, &buf->risc,
- buf->vb.dma.sglist,
- buf->vb.width, buf->vb.height);
-
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ /* 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->vb.state = STATE_PREPARED;
- buf->bpl = chip->period_size;
chip->buf = buf;
- chip->dma_risc = buf->vb.dma;
+ chip->dma_risc = dma;
- dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages);
- substream->runtime->dma_area = chip->dma_risc.vmalloc;
+ substream->runtime->dma_area = chip->dma_risc->vmalloc;
+ substream->runtime->dma_bytes = chip->dma_size;
+ substream->runtime->dma_addr = 0;
return 0;
+
+error:
+ kfree(buf);
+ return ret;
}
/*
@@ -475,7 +454,6 @@ static int snd_cx88_prepare(struct snd_pcm_substream *substream)
return 0;
}
-
/*
* trigger callback
*/
@@ -484,6 +462,7 @@ 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) {
@@ -510,17 +489,24 @@ 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;
- if (chip->read_count) {
- chip->read_count -= snd_pcm_lib_period_bytes(substream);
- chip->read_offset += snd_pcm_lib_period_bytes(substream);
- if (chip->read_offset == chip->dma_size)
- chip->read_offset = 0;
- }
+ count = atomic_read(&chip->count);
- dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count);
- return bytes_to_frames(runtime, chip->read_offset);
+// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
+// 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);
}
/*
@@ -535,6 +521,7 @@ static struct snd_pcm_ops snd_cx88_pcm_ops = {
.prepare = snd_cx88_prepare,
.trigger = snd_cx88_card_trigger,
.pointer = snd_cx88_pointer,
+ .page = snd_cx88_page,
};
/*
@@ -562,7 +549,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *info)
{
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- info->count = 1;
+ info->count = 2;
info->value.integer.min = 0;
info->value.integer.max = 0x3f;
@@ -575,8 +562,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
{
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[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
+ 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;
}
@@ -587,16 +578,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core=chip->core;
- int v;
- u32 old_control;
-
+ int v, b;
+ int changed = 0;
+ u32 old;
+
+ b = value->value.integer.value[1] - value->value.integer.value[0];
+ if (b < 0) {
+ v = 0x3f - value->value.integer.value[0];
+ b = (-b) | 0x40;
+ } else {
+ v = 0x3f - value->value.integer.value[1];
+ }
+ /* Do we really know this will always be called with IRQs on? */
spin_lock_irq(&chip->reg_lock);
- old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
- v = 0x3f - (value->value.integer.value[0] & 0x3f);
- cx_andor(AUD_VOL_CTL, 0x3f, v);
+ old = cx_read(AUD_VOL_CTL);
+ if (v != (old & 0x3f)) {
+ cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
+ changed = 1;
+ }
+ if (cx_read(AUD_BAL_CTL) != b) {
+ cx_write(AUD_BAL_CTL, b);
+ changed = 1;
+ }
spin_unlock_irq(&chip->reg_lock);
- return v != old_control;
+ return changed;
}
static struct snd_kcontrol_new snd_cx88_capture_volume = {
@@ -665,6 +671,7 @@ static int __devinit snd_cx88_create(struct snd_card *card,
snd_cx88_card_t *chip;
struct cx88_core *core;
int err;
+ unsigned char pci_lat;
*rchip = NULL;
@@ -709,13 +716,12 @@ static int __devinit snd_cx88_create(struct snd_card *card,
}
/* print pci info */
- pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev);
- pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat);
+ 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), chip->pci_rev, pci->irq,
- chip->pci_lat,(unsigned long long)pci_resource_start(pci,0));
+ 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);
@@ -753,17 +759,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
return (err);
err = snd_cx88_pcm(chip, 0, "CX88 Digital");
-
- if (err < 0) {
- snd_card_free(card);
- return (err);
- }
+ if (err < 0)
+ goto error;
err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
- if (err < 0) {
- snd_card_free(card);
- return (err);
- }
+ if (err < 0)
+ goto error;
strcpy (card->driver, "CX88x");
sprintf(card->shortname, "Conexant CX%x", pci->device);
@@ -775,16 +776,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
card->driver,devno);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return (err);
- }
- snd_cx88_cards[devno] = card;
-
+ if (err < 0)
+ goto error;
pci_set_drvdata(pci,card);
devno++;
return 0;
+
+error:
+ snd_card_free(card);
+ return err;
}
/*
* ALSA destructor
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index a80b1cb1abe8..6d6f5048d762 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -27,7 +27,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
@@ -56,8 +55,7 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
/* ------------------------------------------------------------------ */
-#define OLD_BLACKBIRD_FIRM_IMAGE_SIZE 262144
-#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
+#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
/* defines below are from ivtv-driver.h */
@@ -405,7 +403,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev)
u32 value;
int i;
- for (i = 0; i < dev->fw_size; i++) {
+ for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
memory_read(dev->core, i, &value);
if (value == signature[signaturecnt])
signaturecnt++;
@@ -453,15 +451,12 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
return -1;
}
- if ((firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) &&
- (firmware->size != OLD_BLACKBIRD_FIRM_IMAGE_SIZE)) {
- dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d or %d)\n",
- firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE,
- OLD_BLACKBIRD_FIRM_IMAGE_SIZE);
+ 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;
}
- dev->fw_size = firmware->size;
if (0 != memcmp(firmware->data, magic, 8)) {
dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
@@ -738,14 +733,14 @@ static int vidioc_querycap (struct file *file, void *priv,
struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx88_blackbird");
- strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+ strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
cap->version = CX88_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
- if (UNSET != core->tuner_type)
+ if (UNSET != core->board.tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
@@ -881,7 +876,7 @@ static int vidioc_g_ext_ctrls (struct file *file, void *priv,
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
- return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS);
+ return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS);
}
static int vidioc_s_ext_ctrls (struct file *file, void *priv,
@@ -894,7 +889,7 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv,
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
- err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS);
+ err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
if (!err) {
err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
dev->params = p;
@@ -912,7 +907,7 @@ static int vidioc_try_ext_ctrls (struct file *file, void *priv,
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
- err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS);
+ err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
return err;
}
@@ -994,7 +989,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
struct cx8802_fh *fh = priv;
struct cx88_core *core = fh->dev->core;
- if (unlikely(UNSET == core->tuner_type))
+ if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
f->type = V4L2_TUNER_ANALOG_TV;
@@ -1032,7 +1027,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
u32 reg;
- if (unlikely(UNSET == core->tuner_type))
+ if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1053,7 +1048,7 @@ static int vidioc_s_tuner (struct file *file, void *priv,
{
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
- if (UNSET == core->tuner_type)
+ if (UNSET == core->board.tuner_type)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1082,7 +1077,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
struct cx8802_driver *drv = NULL;
int err;
- dev = cx8802_get_device(inode);
+ dev = cx8802_get_device(inode);
dprintk( 1, "%s\n", __FUNCTION__);
@@ -1116,7 +1111,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
file->private_data = fh;
fh->dev = dev;
- videobuf_queue_init(&fh->mpegq, &blackbird_qops,
+ videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
@@ -1239,7 +1234,7 @@ static struct video_device cx8802_mpeg_template =
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_s_std = vidioc_s_std,
.tvnorms = CX88_NORMS,
- .current_norm = V4L2_STD_NTSC_M,
+ .current_norm = V4L2_STD_NTSC_M,
};
/* ------------------------------------------------------------------ */
@@ -1250,7 +1245,7 @@ static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
struct cx88_core *core = drv->core;
int err = 0;
- switch (core->board) {
+ 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.
@@ -1272,7 +1267,7 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
struct cx88_core *core = drv->core;
int err = 0;
- switch (core->board) {
+ switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_HVR1300:
/* Exit leaving the cx23416 on the bus */
break;
@@ -1320,13 +1315,13 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
dprintk( 1, "%s\n", __FUNCTION__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
- core->board,
+ core->boardnr,
core->name,
core->pci_bus,
core->pci_slot);
err = -ENODEV;
- if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
+ if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
goto fail_core;
dev->width = 720;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index e61102dc8ad7..a4eb6a87a761 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -27,10 +27,26 @@
#include "cx88.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");
+
/* ------------------------------------------------------------------ */
/* board config info */
-struct cx88_board cx88_boards[] = {
+static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
.tuner_type = UNSET,
@@ -575,35 +591,34 @@ struct cx88_board cx88_boards[] = {
.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,
- .gpio1 = 0x00000000,
- .gpio2 = 0x00000000,
- .gpio3 = 0x00000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00008400,
- .gpio1 = 0x00000000,
- .gpio2 = 0x00000000,
- .gpio3 = 0x00000000,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00008400,
- .gpio1 = 0x00000000,
- .gpio2 = 0x00000000,
- .gpio3 = 0x00000000,
}},
.radio = {
.type = CX88_RADIO,
- .vmux = 2,
- .gpio0 = 0x00008400,
- .gpio1 = 0x00000000,
- .gpio2 = 0x00000000,
- .gpio3 = 0x00000000,
+ .gpio0 = 0x00008404,
},
.mpeg = CX88_MPEG_DVB,
},
@@ -1335,13 +1350,32 @@ struct cx88_board cx88_boards[] = {
/* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
},
+ [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,
+ }},
+ },
};
-const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
/* ------------------------------------------------------------------ */
/* PCI subsystem IDs */
-struct cx88_subid cx88_subids[] = {
+static const struct cx88_subid cx88_subids[] = {
{
.subvendor = 0x0070,
.subdevice = 0x3400,
@@ -1641,9 +1675,12 @@ struct cx88_subid cx88_subids[] = {
.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,
},
};
-const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
/* ----------------------------------------------------------------------- */
/* some leadtek specific stuff */
@@ -1664,12 +1701,12 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
return;
}
- core->has_radio = 1;
- core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
+ core->board.tuner_type = (eeprom_data[6] == 0x13) ?
+ TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
"tuner=%d, eeprom[0]=0x%02x\n",
- core->name, core->tuner_type, eeprom_data[0]);
+ core->name, core->board.tuner_type, eeprom_data[0]);
}
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -1677,9 +1714,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
struct tveeprom tv;
tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
- core->tuner_type = tv.tuner_type;
+ core->board.tuner_type = tv.tuner_type;
core->tuner_formats = tv.tuner_formats;
- core->has_radio = tv.has_radio;
+ core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
/* Make sure we support the board model */
switch (tv.model)
@@ -1769,8 +1806,9 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
name ? name : "unknown");
if (NULL == name)
return;
- core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
- core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm;
+ core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+ core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
+ CX88_RADIO : 0;
}
/* ----------------------------------------------------------------------- */
@@ -1809,7 +1847,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
/* ----------------------------------------------------------------------- */
-void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
{
int i;
@@ -1830,14 +1868,14 @@ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
}
printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
core->name);
- for (i = 0; i < cx88_bcount; i++)
+ for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
printk("%s: card=%d -> %s\n",
core->name, i, cx88_boards[i].name);
}
-void cx88_card_setup_pre_i2c(struct cx88_core *core)
+static void cx88_card_setup_pre_i2c(struct cx88_core *core)
{
- switch (core->board) {
+ 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 */
@@ -1851,7 +1889,7 @@ void cx88_card_setup_pre_i2c(struct cx88_core *core)
}
}
-void cx88_card_setup(struct cx88_core *core)
+static void cx88_card_setup(struct cx88_core *core)
{
static u8 eeprom[256];
@@ -1860,7 +1898,7 @@ void cx88_card_setup(struct cx88_core *core)
tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
}
- switch (core->board) {
+ switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_ROSLYN:
if (0 == core->i2c_rc)
@@ -1904,7 +1942,7 @@ void cx88_card_setup(struct cx88_core *core)
msleep(1);
cx_set(MO_GP0_IO, 0x00000101);
if (0 == core->i2c_rc &&
- core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
+ core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
dvico_fusionhdtv_hybrid_init(core);
break;
case CX88_BOARD_KWORLD_DVB_T:
@@ -1942,13 +1980,148 @@ void cx88_card_setup(struct cx88_core *core)
}
break;
}
- if (cx88_boards[core->board].radio.type == CX88_RADIO)
- core->has_radio = 1;
}
/* ------------------------------------------------------------------ */
-EXPORT_SYMBOL(cx88_boards);
+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);
+
+ 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);
+ if (0 != cx88_get_resources(core, pci)) {
+ 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;
+
+ /* 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));
+
+ printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ core->name,pci->subsystem_vendor,
+ pci->subsystem_device, core->board.name,
+ core->boardnr, card[core->nr] == core->boardnr ?
+ "insmod option" : "autodetected");
+
+ if (tuner[core->nr] != UNSET)
+ core->board.tuner_type = tuner[core->nr];
+ if (radio[core->nr] != UNSET)
+ core->board.radio_type = radio[core->nr];
+
+ printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n",
+ core->name, core->board.tuner_type, core->board.radio_type);
+
+ /* init hardware */
+ cx88_reset(core);
+ cx88_card_setup_pre_i2c(core);
+ cx88_i2c_init(core, pci);
+ cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
+ cx88_card_setup(core);
+ cx88_ir_init(core, pci);
+
+ return core;
+}
+
+/* ------------------------------------------------------------------ */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index f31ec96924b9..62e8dd24c5f5 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -52,22 +51,6 @@ static unsigned int core_debug = 0;
module_param(core_debug,int,0644);
MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
-static unsigned int latency = UNSET;
-module_param(latency,int,0444);
-MODULE_PARM_DESC(latency,"pci latency timer");
-
-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 nicam = 0;
module_param(nicam,int,0644);
MODULE_PARM_DESC(nicam,"tv audio is nicam");
@@ -85,13 +68,15 @@ 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 u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
struct scatterlist *sg;
- unsigned int line,todo;
+ unsigned int line,todo,sol;
/* sync instruction */
if (sync_line != NO_SYNC_LINE)
@@ -104,15 +89,19 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
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|RISC_SOL|RISC_EOL|bpl);
+ *(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|RISC_SOL|
+ *(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);
@@ -163,10 +152,10 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
rp = risc->cpu;
if (UNSET != top_offset)
rp = cx88_risc_field(rp, sglist, top_offset, 0,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
if (UNSET != bottom_offset)
rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
- bpl, padding, lines);
+ bpl, padding, lines, 0);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -176,7 +165,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
- unsigned int lines)
+ unsigned int lines, unsigned int lpi)
{
u32 instructions;
u32 *rp;
@@ -193,7 +182,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
/* write risc instructions */
rp = risc->cpu;
- rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);
+ rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -224,10 +213,12 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
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(&buf->vb,0,0);
- videobuf_dma_unmap(q, &buf->vb.dma);
- videobuf_dma_free(&buf->vb.dma);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
buf->vb.state = STATE_NEEDS_INIT;
}
@@ -451,10 +442,13 @@ void cx88_sram_channel_dump(struct cx88_core *core,
printk("%s: cmds: %-12s: 0x%08x\n",
core->name,name[i],
cx_read(ch->cmds_start + 4*i));
- for (i = 0; i < 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);
- cx88_risc_decode(risc);
+ 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);
@@ -514,7 +508,7 @@ int cx88_core_irq(struct cx88_core *core, u32 status)
{
int handled = 0;
- if (status & (1<<18)) {
+ if (status & PCI_INT_IR_SMPINT) {
cx88_ir_irq(core);
handled++;
}
@@ -738,7 +732,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
value |= (1 << 15);
value |= (1 << 16);
}
- if (INPUT(core->input)->type == CX88_VMUX_SVIDEO)
+ 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)
@@ -833,7 +827,7 @@ static int set_tvaudio(struct cx88_core *core)
{
v4l2_std_id norm = core->tvnorm;
- if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)
+ if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
return 0;
if (V4L2_STD_PAL_BG & norm) {
@@ -997,61 +991,6 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
/* ------------------------------------------------------------------ */
-static int cx88_pci_quirks(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;
-}
-
-/* ------------------------------------------------------------------ */
-
struct video_device *cx88_vdev_init(struct cx88_core *core,
struct pci_dev *pci,
struct video_device *template,
@@ -1067,122 +1006,38 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
vfd->dev = &pci->dev;
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
- core->name, type, cx88_boards[core->board].name);
+ core->name, type, core->board.name);
return vfd;
}
-static int get_ressources(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: can't get MMIO memory @ 0x%llx\n",
- core->name,(unsigned long long)pci_resource_start(pci,0));
- return -EBUSY;
-}
-
struct cx88_core* cx88_core_get(struct pci_dev *pci)
{
struct cx88_core *core;
- struct list_head *item;
- int i;
mutex_lock(&devlist);
- list_for_each(item,&cx88_devlist) {
- core = list_entry(item, struct cx88_core, 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 != get_ressources(core,pci))
- goto fail_unlock;
+ if (0 != cx88_get_resources(core, pci)) {
+ mutex_unlock(&devlist);
+ return NULL;
+ }
atomic_inc(&core->refcount);
mutex_unlock(&devlist);
return core;
}
- core = kzalloc(sizeof(*core),GFP_KERNEL);
- if (NULL == core)
- goto fail_unlock;
-
- atomic_inc(&core->refcount);
- core->pci_bus = pci->bus->number;
- core->pci_slot = PCI_SLOT(pci->devfn);
- core->pci_irqmask = 0x00fc00;
- mutex_init(&core->lock);
-
- core->nr = cx88_devcount++;
- sprintf(core->name,"cx88[%d]",core->nr);
- if (0 != get_ressources(core,pci)) {
- printk(KERN_ERR "CORE %s No more PCI ressources for "
- "subsystem: %04x:%04x, board: %s\n",
- core->name,pci->subsystem_vendor,
- pci->subsystem_device,
- cx88_boards[core->board].name);
-
- cx88_devcount--;
- goto fail_free;
- }
- list_add_tail(&core->devlist,&cx88_devlist);
-
- /* 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;
-
- /* board config */
- core->board = UNSET;
- if (card[core->nr] < cx88_bcount)
- core->board = card[core->nr];
- for (i = 0; UNSET == core->board && i < cx88_idcount; i++)
- if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
- pci->subsystem_device == cx88_subids[i].subdevice)
- core->board = cx88_subids[i].card;
- if (UNSET == core->board) {
- core->board = CX88_BOARD_UNKNOWN;
- cx88_card_list(core,pci);
+
+ core = cx88_core_create(pci, cx88_devcount);
+ if (NULL != core) {
+ cx88_devcount++;
+ list_add_tail(&core->devlist, &cx88_devlist);
}
- printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
- core->name,pci->subsystem_vendor,
- pci->subsystem_device,cx88_boards[core->board].name,
- core->board, card[core->nr] == core->board ?
- "insmod option" : "autodetected");
-
- core->tuner_type = tuner[core->nr];
- core->radio_type = radio[core->nr];
- if (UNSET == core->tuner_type)
- core->tuner_type = cx88_boards[core->board].tuner_type;
- if (UNSET == core->radio_type)
- core->radio_type = cx88_boards[core->board].radio_type;
- if (!core->tuner_addr)
- core->tuner_addr = cx88_boards[core->board].tuner_addr;
- if (!core->radio_addr)
- core->radio_addr = cx88_boards[core->board].radio_addr;
-
- printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
- core->tuner_type, core->tuner_addr<<1,
- core->radio_type, core->radio_addr<<1);
-
- core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
-
- /* init hardware */
- cx88_reset(core);
- cx88_card_setup_pre_i2c(core);
- cx88_i2c_init(core,pci);
- cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
- cx88_card_setup(core);
- cx88_ir_init(core,pci);
mutex_unlock(&devlist);
return core;
-
-fail_free:
- kfree(core);
-fail_unlock:
- mutex_unlock(&devlist);
- return NULL;
}
void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
@@ -1229,6 +1084,9 @@ 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
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index dbfe4dc9cf8c..d16e5c6d21c0 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -35,9 +35,7 @@
#include "mt352.h"
#include "mt352_priv.h"
-#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
-# include "cx88-vp3054-i2c.h"
-#endif
+#include "cx88-vp3054-i2c.h"
#include "zl10353.h"
#include "cx22702.h"
#include "or51132.h"
@@ -199,7 +197,7 @@ static struct mt352_config dvico_fusionhdtv_dual = {
.demod_init = dvico_dual_demod_init,
};
-#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
+#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 u8 clock_config [] = { 0x89, 0x38, 0x38 };
@@ -223,64 +221,6 @@ static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
-{
- struct cx8802_dev *dev= fe->dvb->priv;
-
- /* this message is to set up ATC and ALC */
- static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
- struct i2c_msg msg =
- { .addr = dev->core->pll_addr, .flags = 0,
- .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
- int err;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
-{
- struct cx8802_dev *dev= fe->dvb->priv;
- u8 buf[4];
- struct i2c_msg msg =
- { .addr = dev->core->pll_addr, .flags = 0,
- .buf = buf, .len = 4 };
- int err;
-
- /* Switch PLL to DVB mode */
- err = philips_fmd1216_pll_init(fe);
- if (err)
- return err;
-
- /* Tune PLL */
- dvb_pll_configure(dev->core->pll_desc, buf,
- params->frequency,
- params->u.ofdm.bandwidth);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
-
- printk(KERN_WARNING "cx88-dvb: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, dev->core->pll_addr, buf[0], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
static struct mt352_config dntv_live_dvbt_pro_config = {
.demod_address = 0x0f,
.no_tuner = 1,
@@ -370,18 +310,8 @@ static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
return 0;
}
-static int nxt200x_set_pll_input(u8* buf, int input)
-{
- if (input)
- buf[3] |= 0x08;
- else
- buf[3] &= ~0x08;
- return 0;
-}
-
static struct nxt200x_config ati_hdtvwonder = {
.demod_address = 0x0a,
- .set_pll_input = nxt200x_set_pll_input,
.set_ts_params = nxt200x_set_ts_param,
};
@@ -448,7 +378,7 @@ static int dvb_register(struct cx8802_dev *dev)
dev->ts_gen_cntrl = 0x0c;
/* init frontend */
- switch (dev->core->board) {
+ switch (dev->core->boardnr) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
dev->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
@@ -456,7 +386,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_thomson_dtt759x);
+ DVB_PLL_THOMSON_DTT759X);
}
break;
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
@@ -469,7 +399,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
&dev->core->i2c_adap,
- &dvb_pll_thomson_dtt7579);
+ DVB_PLL_THOMSON_DTT7579);
}
break;
case CX88_BOARD_WINFAST_DTV2000H:
@@ -482,7 +412,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- &dev->core->i2c_adap, &dvb_pll_fmd1216me);
+ &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -491,7 +421,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
break;
}
/* ZL10353 replaces MT352 on later cards */
@@ -500,7 +430,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
@@ -511,7 +441,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
break;
}
/* ZL10353 replaces MT352 on later cards */
@@ -520,7 +450,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_thomson_dtt7579);
+ NULL, DVB_PLL_THOMSON_DTT7579);
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
@@ -529,7 +459,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_lg_z201);
+ NULL, DVB_PLL_LG_Z201);
}
break;
case CX88_BOARD_KWORLD_DVB_T:
@@ -540,20 +470,19 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_unknown_1);
+ NULL, DVB_PLL_UNKNOWN_1);
}
break;
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
- dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_fmd1216me;
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
&((struct vp3054_i2c_state *)dev->card_priv)->adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
}
#else
- printk("%s: built without vp3054 support\n", dev->core->name);
+ printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
#endif
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
@@ -563,7 +492,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_thomson_fe6600);
+ DVB_PLL_THOMSON_FE6600);
}
break;
case CX88_BOARD_PCHDTV_HD3000:
@@ -572,7 +501,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_thomson_dtt761x);
+ DVB_PLL_THOMSON_DTT761X);
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
@@ -594,7 +523,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_microtune_4042);
+ DVB_PLL_MICROTUNE_4042);
}
}
break;
@@ -614,7 +543,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_thomson_dtt761x);
+ DVB_PLL_THOMSON_DTT761X);
}
}
break;
@@ -634,7 +563,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_lg_tdvs_h06xf);
+ DVB_PLL_LG_TDVS_H06XF);
}
}
break;
@@ -654,7 +583,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
&dev->core->i2c_adap,
- &dvb_pll_lg_tdvs_h06xf);
+ DVB_PLL_LG_TDVS_H06XF);
}
}
break;
@@ -664,7 +593,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_tuv1236d);
+ NULL, DVB_PLL_TUV1236D);
}
break;
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -696,19 +625,15 @@ static int dvb_register(struct cx8802_dev *dev)
}
break;
default:
- printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+ printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->core->name);
break;
}
if (NULL == dev->dvb.frontend) {
- printk("%s: frontend initialization failed\n",dev->core->name);
+ printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name);
return -1;
}
- if (dev->core->pll_desc) {
- dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
- dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
- }
/* Ensure all frontends negotiate bus access */
dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
@@ -728,7 +653,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
int err = 0;
dprintk( 1, "%s\n", __FUNCTION__);
- switch (core->board) {
+ 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
@@ -751,7 +676,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
int err = 0;
dprintk( 1, "%s\n", __FUNCTION__);
- switch (core->board) {
+ switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_HVR1300:
/* Do Nothing, leave the cx22702 on the bus. */
break;
@@ -769,24 +694,23 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
dprintk( 1, "%s\n", __FUNCTION__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
- core->board,
+ core->boardnr,
core->name,
core->pci_bus,
core->pci_slot);
err = -ENODEV;
- if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
+ if (!(core->board.mpeg & CX88_MPEG_DVB))
goto fail_core;
-#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
+ /* If vp3054 isn't enabled, a stub will just return 0 */
err = vp3054_i2c_probe(dev);
if (0 != err)
goto fail_core;
-#endif
/* dvb stuff */
- printk("%s/2: cx2388x based dvb card\n", core->name);
- videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
+ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+ videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP,
@@ -794,7 +718,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
dev);
err = dvb_register(dev);
if (err != 0)
- printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);
+ printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
+ core->name, err);
fail_core:
return err;
@@ -807,9 +732,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
/* dvb */
videobuf_dvb_unregister(&dev->dvb);
-#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
vp3054_i2c_remove(dev);
-#endif
return 0;
}
@@ -825,7 +748,7 @@ static struct cx8802_driver cx8802_dvb_driver = {
static int dvb_init(void)
{
- printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n",
+ printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n",
(CX88_VERSION_CODE >> 16) & 0xff,
(CX88_VERSION_CODE >> 8) & 0xff,
CX88_VERSION_CODE & 0xff);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 7919a1f9da06..c8b1c50625f4 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -28,7 +28,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -108,28 +107,28 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command)
return 0;
- if (core->radio_type != UNSET) {
- if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) {
+ if (core->board.radio_type != UNSET) {
+ if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
tun_setup.mode_mask = T_RADIO;
- tun_setup.type = core->radio_type;
- tun_setup.addr = core->radio_addr;
+ tun_setup.type = core->board.radio_type;
+ tun_setup.addr = core->board.radio_addr;
client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
}
}
- if (core->tuner_type != UNSET) {
- if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) {
+ if (core->board.tuner_type != UNSET) {
+ if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
tun_setup.mode_mask = T_ANALOG_TV;
- tun_setup.type = core->tuner_type;
- tun_setup.addr = core->tuner_addr;
+ tun_setup.type = core->board.tuner_type;
+ tun_setup.addr = core->board.tuner_addr;
client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
}
}
- if (core->tda9887_conf)
- client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
+ if (core->board.tda9887_conf)
+ client->driver->command(client, TDA9887_SET_CONFIG, &core->board.tda9887_conf);
return 0;
}
@@ -146,7 +145,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
if (0 != core->i2c_rc)
return;
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
@@ -160,7 +159,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
i2c_clients_command(&core->i2c_adap, cmd, arg);
}
-static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
+static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
.setsda = cx8800_bit_setsda,
.setscl = cx8800_bit_setscl,
.getsda = cx8800_bit_getsda,
@@ -171,18 +170,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
/* ----------------------------------------------------------------------- */
-static struct i2c_adapter cx8800_i2c_adap_template = {
- .name = "cx2388x",
- .owner = THIS_MODULE,
- .id = I2C_HW_B_CX2388x,
- .client_register = attach_inform,
- .client_unregister = detach_inform,
-};
-
-static struct i2c_client cx8800_i2c_client_template = {
- .name = "cx88xx internal",
-};
-
static char *i2c_devs[128] = {
[ 0x1c >> 1 ] = "lgdt330x",
[ 0x86 >> 1 ] = "tda9887/cx22702",
@@ -212,26 +199,27 @@ 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;
- cx8800_i2c_algo_template.udelay=i2c_udelay;
- memcpy(&core->i2c_adap, &cx8800_i2c_adap_template,
- sizeof(core->i2c_adap));
memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
sizeof(core->i2c_algo));
- memcpy(&core->i2c_client, &cx8800_i2c_client_template,
- sizeof(core->i2c_client));
- if (core->tuner_type != TUNER_ABSENT)
+ if (core->board.tuner_type != TUNER_ABSENT)
core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
- if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB)
+ if (core->board.mpeg & CX88_MPEG_DVB)
core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
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_adap.id = I2C_HW_B_CX2388x;
+ core->i2c_adap.client_register = attach_inform;
+ core->i2c_adap.client_unregister = detach_inform;
+ core->i2c_algo.udelay = i2c_udelay;
core->i2c_algo.data = core;
i2c_set_adapdata(&core->i2c_adap,core);
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);
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 8136673fe9e8..e52de3968c63 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -27,7 +27,6 @@
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include "cx88.h"
#include <media/ir-common.h>
@@ -74,7 +73,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
/* read gpio value */
gpio = cx_read(ir->gpio_addr);
- if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) {
+ 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.
@@ -90,9 +90,14 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
auxgpio = cx_read(MO_GP1_IO);
/* Take out the parity part */
gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
- } else
+ break;
+ case CX88_BOARD_WINFAST_DTV1000:
+ 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;
@@ -107,7 +112,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
(gpio & ir->mask_keydown) ? " down" : "",
(gpio & ir->mask_keyup) ? " up" : "");
- if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) {
+ if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
u32 gpio_key = cx_read(MO_GP0_IO);
data = (data << 4) | ((gpio_key & 0xf0) >> 4);
@@ -148,34 +153,30 @@ static void ir_timer(unsigned long data)
static void cx88_ir_work(struct work_struct *work)
{
struct cx88_IR *ir = container_of(work, struct cx88_IR, work);
- unsigned long timeout;
cx88_ir_handle_key(ir);
- timeout = jiffies + (ir->polling * HZ / 1000);
- mod_timer(&ir->timer, timeout);
+ mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
-static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
+void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
{
if (ir->polling) {
+ setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
INIT_WORK(&ir->work, cx88_ir_work);
- init_timer(&ir->timer);
- ir->timer.function = ir_timer;
- ir->timer.data = (unsigned long)ir;
schedule_work(&ir->work);
}
if (ir->sampling) {
- core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
+ core->pci_irqmask |= PCI_INT_IR_SMPINT;
cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
cx_write(MO_DDSCFG_IO, 0x5); /* enable */
}
}
-static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
+void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
{
if (ir->sampling) {
cx_write(MO_DDSCFG_IO, 0x0);
- core->pci_irqmask &= ~(1 << 18);
+ core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
}
if (ir->polling) {
@@ -202,7 +203,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->input = input_dev;
/* detect & configure */
- switch (core->board) {
+ switch (core->boardnr) {
case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_KWORLD_DVB_T_CX22702:
@@ -222,7 +223,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_HVR1100:
- case CX88_BOARD_HAUPPAUGE_HVR1300:
case CX88_BOARD_HAUPPAUGE_HVR3000:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
@@ -236,6 +236,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->polling = 50; /* ms */
break;
case CX88_BOARD_WINFAST2000XP_EXPERT:
+ case CX88_BOARD_WINFAST_DTV1000:
ir_codes = ir_codes_winfast;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0x8f8;
@@ -312,8 +313,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
}
/* init input device */
- snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
- cx88_boards[core->board].name);
+ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
@@ -328,7 +328,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
input_dev->id.vendor = pci->vendor;
input_dev->id.product = pci->device;
}
- input_dev->cdev.dev = &pci->dev;
+ input_dev->dev.parent = &pci->dev;
/* record handles to ourself */
ir->core = core;
core->ir = ir;
@@ -404,7 +404,7 @@ void cx88_ir_irq(struct cx88_core *core)
ir_dump_samples(ir->samples, ir->scount);
/* decode it */
- switch (core->board) {
+ switch (core->boardnr) {
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
@@ -442,7 +442,6 @@ void cx88_ir_irq(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_HVR1100:
- case CX88_BOARD_HAUPPAUGE_HVR1300:
case CX88_BOARD_HAUPPAUGE_HVR3000:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 543b05ebc0e7..a652f294d23d 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -23,12 +23,10 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
#include <asm/delay.h>
#include "cx88.h"
@@ -56,9 +54,9 @@ static void request_module_async(struct work_struct *work)
{
struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
- if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB)
+ if (dev->core->board.mpeg & CX88_MPEG_DVB)
request_module("cx88-dvb");
- if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD)
+ if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
request_module("cx88-blackbird");
}
@@ -96,7 +94,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
if ( (core->active_type_id == CX88_MPEG_DVB) &&
- (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
+ (core->board.mpeg & CX88_MPEG_DVB) ) {
dprintk( 1, "cx8802_start_dma doing .dvb\n");
/* negedge driven & software reset */
@@ -104,7 +102,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
udelay(100);
cx_write(MO_PINMUX_IO, 0x00);
cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
- switch (core->board) {
+ 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:
@@ -125,7 +123,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
udelay(100);
} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
- (cx88_boards[core->board].mpeg & 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 */
@@ -139,7 +137,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
udelay(100);
} else {
printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
- cx88_boards[core->board].mpeg );
+ core->board.mpeg );
return -EINVAL;
}
@@ -149,7 +147,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
/* enable irqs */
dprintk( 1, "setting the interrupt mask\n" );
- cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
cx_set(MO_TS_INTMSK, 0x1f0011);
/* start dma */
@@ -167,7 +165,7 @@ static int cx8802_stop_dma(struct cx8802_dev *dev)
cx_clear(MO_TS_DMACNTRL, 0x11);
/* disable irqs */
- cx_clear(MO_PCI_INTMSK, 0x000004);
+ cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
cx_clear(MO_TS_INTMSK, 0x1f0011);
/* Reset the controller */
@@ -181,43 +179,43 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
struct cx88_buffer *buf;
struct list_head *item;
- dprintk( 1, "cx8802_restart_queue\n" );
+ 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 = STATE_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 = STATE_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;
- }
+ 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 = STATE_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 = STATE_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;
}
@@ -239,6 +237,7 @@ 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", __FUNCTION__, buf);
@@ -254,8 +253,8 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
cx88_risc_databuffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist,
- buf->vb.width, buf->vb.height);
+ dma->sglist,
+ buf->vb.width, buf->vb.height, 0);
}
buf->vb.state = STATE_PREPARED;
return 0;
@@ -336,7 +335,7 @@ static void cx8802_timeout(unsigned long data)
{
struct cx8802_dev *dev = (struct cx8802_dev*)data;
- dprintk(0, "%s\n",__FUNCTION__);
+ dprintk(1, "%s\n",__FUNCTION__);
if (debug)
cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -414,7 +413,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
int loop, handled = 0;
for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
+ status = cx_read(MO_PCI_INTSTAT) &
+ (core->pci_irqmask | PCI_INT_TSINT);
if (0 == status)
goto out;
dprintk( 1, "cx8802_irq\n" );
@@ -425,7 +425,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id)
if (status & core->pci_irqmask)
cx88_core_irq(core,status);
- if (status & 0x04)
+ if (status & PCI_INT_TSINT)
cx8802_mpeg_irq(dev);
};
if (MAX_IRQ_LOOP == loop) {
@@ -580,7 +580,7 @@ struct cx8802_dev * cx8802_get_device(struct inode *inode)
list_for_each(list,&cx8802_devlist) {
h = list_entry(list, struct cx8802_dev, devlist);
- if (h->mpeg_dev->minor == minor)
+ if (h->mpeg_dev && h->mpeg_dev->minor == minor)
return h;
}
@@ -676,22 +676,24 @@ int cx8802_register_driver(struct cx8802_driver *drv)
struct list_head *list;
int err = 0, i = 0;
- printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
- drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
- drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+ 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_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
+ printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
return err;
}
list_for_each(list,&cx8802_devlist) {
h = list_entry(list, struct cx8802_dev, devlist);
- printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
- h->core->name,h->pci->subsystem_vendor,
- h->pci->subsystem_device,cx88_boards[h->core->board].name,
- h->core->board);
+ printk(KERN_INFO
+ "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+ h->core->name, h->pci->subsystem_vendor,
+ h->pci->subsystem_device, h->core->board.name,
+ h->core->boardnr);
/* Bring up a new struct for each driver instance */
driver = kzalloc(sizeof(*drv),GFP_KERNEL);
@@ -713,7 +715,9 @@ int cx8802_register_driver(struct cx8802_driver *drv)
list_add_tail(&driver->devlist,&h->drvlist.devlist);
mutex_unlock(&drv->core->lock);
} else {
- printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
+ printk(KERN_ERR
+ "%s/2: cx8802 probe failed, err = %d\n",
+ h->core->name, err);
}
}
@@ -733,17 +737,20 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
struct list_head *list2, *q;
int err = 0, i = 0;
- printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
- drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
+ 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");
list_for_each(list,&cx8802_devlist) {
i++;
h = list_entry(list, struct cx8802_dev, devlist);
- printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
- h->core->name,h->pci->subsystem_vendor,
- h->pci->subsystem_device,cx88_boards[h->core->board].name,
- h->core->board);
+ printk(KERN_INFO
+ "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+ h->core->name, h->pci->subsystem_vendor,
+ h->pci->subsystem_device, h->core->board.name,
+ h->core->boardnr);
list_for_each_safe(list2, q, &h->drvlist.devlist) {
d = list_entry(list2, struct cx8802_driver, devlist);
@@ -758,7 +765,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
list_del(list2);
mutex_unlock(&drv->core->lock);
} else
- printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", h->core->name, err);
}
@@ -783,7 +791,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
err = -ENODEV;
- if (!cx88_boards[core->board].mpeg)
+ if (!core->board.mpeg)
goto fail_core;
err = -ENOMEM;
@@ -866,7 +874,7 @@ static struct pci_driver cx8802_pci_driver = {
static int cx8802_init(void)
{
- printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
+ printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n",
(CX88_VERSION_CODE >> 16) & 0xff,
(CX88_VERSION_CODE >> 8) & 0xff,
CX88_VERSION_CODE & 0xff);
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index d3bf5b17b1d4..2ec52d1cdea0 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -582,6 +582,28 @@
/* ---------------------------------------------------------------------- */
/* 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
@@ -590,6 +612,19 @@
#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
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 1cc2d286a1cb..76e5c78d8ae4 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -36,7 +36,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/freezer.h>
#include <linux/kernel.h>
@@ -62,6 +61,10 @@ static unsigned int always_analog = 0;
module_param(always_analog,int,0644);
MODULE_PARM_DESC(always_analog,"force analog audio out");
+static unsigned int radio_deemphasis = 0;
+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)
@@ -140,7 +143,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
cx88_start_audio_dma(core);
- if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+ 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 */
@@ -149,7 +152,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx_write(AUD_I2SCNTL, 0);
/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
}
- if ((always_analog) || (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))) {
+ if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
ctl |= EN_DAC_ENABLE;
cx_write(AUD_CTL, ctl);
}
@@ -678,6 +681,10 @@ static void set_audio_standard_FM(struct cx88_core *core,
};
/* 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},
@@ -688,6 +695,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
set_audio_start(core, SEL_FMRADIO);
switch (deemph) {
+ default:
case FM_NO_DEEMPH:
set_audio_registers(core, fm_no_deemph);
break;
@@ -757,7 +765,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
set_audio_standard_EIAJ(core);
break;
case WW_FM:
- set_audio_standard_FM(core, FM_NO_DEEMPH);
+ set_audio_standard_FM(core, radio_deemphasis);
break;
case WW_NONE:
default:
@@ -790,9 +798,9 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
core->astat = reg;
/* TODO
- Reading from AUD_STATUS is not enough
- for auto-detecting sap/dual-fm/nicam.
- Add some code here later.
+ Reading from AUD_STATUS is not enough
+ for auto-detecting sap/dual-fm/nicam.
+ Add some code here later.
*/
return;
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 86c1cf8334bc..babb08556406 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -2,7 +2,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -67,7 +66,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
cx_set(MO_VID_INTMSK, 0x0f0088);
/* enable capture */
@@ -91,7 +90,7 @@ int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
cx_clear(VID_CAPTURE_CONTROL,0x18);
/* disable irqs */
- cx_clear(MO_PCI_INTMSK, 0x000001);
+ cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
cx_clear(MO_VID_INTMSK, 0x0f0088);
return 0;
}
@@ -100,7 +99,6 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
{
struct cx88_buffer *buf;
- struct list_head *item;
if (list_empty(&q->active))
return 0;
@@ -109,10 +107,8 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.i);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each(item,&q->active) {
- buf = list_entry(item, struct cx88_buffer, vb.queue);
+ list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
- }
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
@@ -173,6 +169,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return -EINVAL;
if (STATE_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;
@@ -181,7 +178,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
cx88_risc_buffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist,
+ dma->sglist,
0, buf->vb.width * buf->vb.height,
buf->vb.width, 0,
buf->vb.height);
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 98fa35421bdd..231ae6c4dd22 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -28,7 +28,6 @@
#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>
@@ -36,7 +35,6 @@
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/kthread.h>
-#include <linux/dma-mapping.h>
#include <asm/div64.h>
#include "cx88.h"
@@ -369,17 +367,17 @@ 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);
+ 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);
+ 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) {
+ switch (INPUT(input).type) {
case CX88_VMUX_SVIDEO:
cx_set(MO_AFECFG_IO, 0x00000001);
cx_set(MO_INPUT_FORMAT, 0x00010010);
@@ -394,9 +392,9 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
break;
}
- if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+ if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
/* sets sound input from external adc */
- if (INPUT(input)->extadc)
+ if (INPUT(input).extadc)
cx_set(AUD_CTL, EN_I2SIN_ENABLE);
else
cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
@@ -424,7 +422,7 @@ static int start_video_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
+ 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
@@ -457,7 +455,7 @@ static int stop_video_dma(struct cx8800_dev *dev)
cx_clear(VID_CAPTURE_CONTROL,0x06);
/* disable irqs */
- cx_clear(MO_PCI_INTMSK, 0x000001);
+ cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
cx_clear(MO_VID_INTMSK, 0x0f0011);
return 0;
}
@@ -468,17 +466,14 @@ static int restart_video_queue(struct cx8800_dev *dev,
{
struct cx88_core *core = dev->core;
struct cx88_buffer *buf, *prev;
- struct list_head *item;
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(item,&q->active) {
- buf = list_entry(item, struct cx88_buffer, vb.queue);
- buf->count = q->count++;
- }
+ list_for_each_entry(buf, &q->active, vb.queue)
+ buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
@@ -536,6 +531,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
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 == fh->fmt);
@@ -568,30 +564,30 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
switch (buf->vb.field) {
case V4L2_FIELD_TOP:
cx88_risc_buffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist, 0, UNSET,
+ dma->sglist, 0, UNSET,
buf->bpl, 0, buf->vb.height);
break;
case V4L2_FIELD_BOTTOM:
cx88_risc_buffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist, UNSET, 0,
+ dma->sglist, UNSET, 0,
buf->bpl, 0, buf->vb.height);
break;
case V4L2_FIELD_INTERLACED:
cx88_risc_buffer(dev->pci, &buf->risc,
- buf->vb.dma.sglist, 0, buf->bpl,
+ 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,
- buf->vb.dma.sglist,
+ 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,
- buf->vb.dma.sglist,
+ dma->sglist,
buf->bpl * (buf->vb.height >> 1), 0,
buf->bpl, 0,
buf->vb.height >> 1);
@@ -714,12 +710,10 @@ static int video_open(struct inode *inode, struct file *file)
struct cx8800_dev *h,*dev = NULL;
struct cx88_core *core;
struct cx8800_fh *fh;
- struct list_head *list;
enum v4l2_buf_type type = 0;
int radio = 0;
- list_for_each(list,&cx8800_devlist) {
- h = list_entry(list, struct cx8800_dev, devlist);
+ list_for_each_entry(h, &cx8800_devlist, devlist) {
if (h->video_dev->minor == minor) {
dev = h;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -754,13 +748,13 @@ static int video_open(struct inode *inode, struct file *file)
fh->height = 240;
fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
- videobuf_queue_init(&fh->vidq, &cx8800_video_qops,
+ videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct cx88_buffer),
fh);
- videobuf_queue_init(&fh->vbiq, &cx8800_vbi_qops,
+ videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
@@ -768,12 +762,11 @@ static int video_open(struct inode *inode, struct file *file)
fh);
if (fh->radio) {
- int board = core->board;
dprintk(1,"video_open: setting radio device\n");
- cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
- cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
- cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
- cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
+ 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);
core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
@@ -1079,8 +1072,7 @@ static int vidioc_querycap (struct file *file, void *priv,
struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx8800");
- strlcpy(cap->card, cx88_boards[core->board].name,
- sizeof(cap->card));
+ strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
cap->version = CX88_VERSION_CODE;
cap->capabilities =
@@ -1088,7 +1080,7 @@ static int vidioc_querycap (struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE;
- if (UNSET != core->tuner_type)
+ if (UNSET != core->board.tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
@@ -1108,28 +1100,9 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
{
- struct cx8800_fh *fh = priv;
- struct videobuf_queue *q;
- struct v4l2_requestbuffers req;
- unsigned int i;
- int err;
+ struct cx8800_fh *fh = priv;
- q = get_queue(fh);
- memset(&req,0,sizeof(req));
- req.type = q->type;
- req.count = 8;
- req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(q,&req);
- if (err < 0)
- return err;
-
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return 0;
+ return videobuf_cgmbuf (get_queue(fh), mbuf, 8);
}
#endif
@@ -1222,14 +1195,14 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i)
n = i->index;
if (n >= 4)
return -EINVAL;
- if (0 == INPUT(n)->type)
+ if (0 == INPUT(n).type)
return -EINVAL;
memset(i,0,sizeof(*i));
i->index = n;
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))
+ 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;
@@ -1298,7 +1271,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
u32 reg;
- if (unlikely(UNSET == core->tuner_type))
+ if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1319,7 +1292,7 @@ static int vidioc_s_tuner (struct file *file, void *priv,
{
struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
- if (UNSET == core->tuner_type)
+ if (UNSET == core->board.tuner_type)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1334,7 +1307,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
struct cx8800_fh *fh = priv;
struct cx88_core *core = fh->dev->core;
- if (unlikely(UNSET == core->tuner_type))
+ if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
@@ -1349,7 +1322,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
int cx88_set_freq (struct cx88_core *core,
struct v4l2_frequency *f)
{
- if (unlikely(UNSET == core->tuner_type))
+ if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
@@ -1420,8 +1393,7 @@ static int radio_querycap (struct file *file, void *priv,
struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx8800");
- strlcpy(cap->card, cx88_boards[core->board].name,
- sizeof(cap->card));
+ strlcpy(cap->card, core->board.name, sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
cap->version = CX88_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
@@ -1608,7 +1580,8 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);
+ status = cx_read(MO_PCI_INTSTAT) &
+ (core->pci_irqmask | PCI_INT_VIDINT);
if (0 == status)
goto out;
cx_write(MO_PCI_INTSTAT, status);
@@ -1616,7 +1589,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
if (status & core->pci_irqmask)
cx88_core_irq(core,status);
- if (status & 0x01)
+ if (status & PCI_INT_VIDINT)
cx8800_vid_irq(dev);
};
if (10 == loop) {
@@ -1717,6 +1690,10 @@ static struct video_device cx8800_radio_template =
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
};
/* ----------------------------------------------------------- */
@@ -1818,26 +1795,32 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
err = request_irq(pci_dev->irq, cx8800_irq,
IRQF_SHARED | IRQF_DISABLED, core->name, dev);
if (err < 0) {
- printk(KERN_ERR "%s: can't get IRQ %d\n",
+ 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);
/* load and configure helper modules */
- if (TUNER_ABSENT != core->tuner_type)
+ if (TUNER_ABSENT != core->board.tuner_type)
request_module("tuner");
- if (cx88_boards[ core->board ].audio_chip == AUDIO_CHIP_WM8775)
+ if (core->board.audio_chip == AUDIO_CHIP_WM8775)
request_module("wm8775");
+ switch (core->boardnr) {
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+ request_module("ir-kbd-i2c");
+ request_module("rtc-isl1208");
+ }
+
/* register v4l devices */
dev->video_dev = cx88_vdev_init(core,dev->pci,
&cx8800_video_template,"video");
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[core->nr]);
if (err < 0) {
- printk(KERN_INFO "%s: can't register video device\n",
+ printk(KERN_ERR "%s/0: can't register video device\n",
core->name);
goto fail_unreg;
}
@@ -1848,20 +1831,20 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[core->nr]);
if (err < 0) {
- printk(KERN_INFO "%s/0: can't register vbi device\n",
+ printk(KERN_ERR "%s/0: can't register vbi device\n",
core->name);
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device vbi%d\n",
core->name,dev->vbi_dev->minor & 0x1f);
- if (core->has_radio) {
+ if (core->board.radio.type == CX88_RADIO) {
dev->radio_dev = cx88_vdev_init(core,dev->pci,
&cx8800_radio_template,"radio");
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[core->nr]);
if (err < 0) {
- printk(KERN_INFO "%s/0: can't register radio device\n",
+ printk(KERN_ERR "%s/0: can't register radio device\n",
core->name);
goto fail_unreg;
}
@@ -1881,8 +1864,14 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
mutex_unlock(&core->lock);
/* start tvaudio thread */
- if (core->tuner_type != TUNER_ABSENT)
+ 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);
+ }
+ }
return 0;
fail_unreg:
@@ -1931,17 +1920,19 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
/* stop video+vbi capture */
spin_lock(&dev->slock);
if (!list_empty(&dev->vidq.active)) {
- printk("%s: suspend video\n", core->name);
+ 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: suspend vbi\n", core->name);
+ 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, core->ir);
/* FIXME -- shutdown device */
cx88_shutdown(core);
@@ -1962,8 +1953,8 @@ static int cx8800_resume(struct pci_dev *pci_dev)
if (dev->state.disabled) {
err=pci_enable_device(pci_dev);
if (err) {
- printk(KERN_ERR "%s: can't enable device\n",
- core->name);
+ printk(KERN_ERR "%s/0: can't enable device\n",
+ core->name);
return err;
}
@@ -1971,9 +1962,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
}
err= pci_set_power_state(pci_dev, PCI_D0);
if (err) {
- printk(KERN_ERR "%s: can't enable device\n",
- core->name);
-
+ printk(KERN_ERR "%s/0: can't set power state\n", core->name);
pci_disable_device(pci_dev);
dev->state.disabled = 1;
@@ -1983,15 +1972,19 @@ static int cx8800_resume(struct pci_dev *pci_dev)
/* FIXME: re-initialize hardware */
cx88_reset(core);
+ if (core->ir)
+ cx88_ir_start(core, core->ir);
+
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* restart video+vbi capture */
spin_lock(&dev->slock);
if (!list_empty(&dev->vidq.active)) {
- printk("%s: resume video\n", core->name);
+ printk("%s/0: resume video\n", core->name);
restart_video_queue(dev,&dev->vidq);
}
if (!list_empty(&dev->vbiq.active)) {
- printk("%s: resume vbi\n", core->name);
+ printk("%s/0: resume vbi\n", core->name);
cx8800_restart_vbi_queue(dev,&dev->vbiq);
}
spin_unlock(&dev->slock);
@@ -2027,7 +2020,7 @@ static struct pci_driver cx8800_pci_driver = {
static int cx8800_init(void)
{
- printk(KERN_INFO "cx2388x v4l2 driver version %d.%d.%d loaded\n",
+ printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %d.%d.%d loaded\n",
(CX88_VERSION_CODE >> 16) & 0xff,
(CX88_VERSION_CODE >> 8) & 0xff,
CX88_VERSION_CODE & 0xff);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 82bc3a28aa22..77c37889232b 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -23,7 +23,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -94,7 +93,7 @@ static int vp3054_bit_getsda(void *data)
/* ----------------------------------------------------------------------- */
-static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
.setsda = vp3054_bit_setsda,
.setscl = vp3054_bit_setscl,
.getsda = vp3054_bit_getsda,
@@ -105,19 +104,13 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
/* ----------------------------------------------------------------------- */
-static struct i2c_adapter vp3054_i2c_adap_template = {
- .name = "cx2388x",
- .owner = THIS_MODULE,
- .id = I2C_HW_B_CX2388x,
-};
-
int vp3054_i2c_probe(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
struct vp3054_i2c_state *vp3054_i2c;
int rc;
- if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
return 0;
dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
@@ -125,8 +118,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
return -ENOMEM;
vp3054_i2c = dev->card_priv;
- memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template,
- sizeof(vp3054_i2c->adap));
memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
sizeof(vp3054_i2c->algo));
@@ -135,6 +126,8 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
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->adap.id = I2C_HW_B_CX2388x;
vp3054_i2c->algo.data = dev;
i2c_set_adapdata(&vp3054_i2c->adap, dev);
vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
@@ -158,7 +151,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev)
struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
if (vp3054_i2c == NULL ||
- dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
return;
i2c_del_adapter(&vp3054_i2c->adap);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
index 637a7d232238..be99c931dc3e 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.h
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h
@@ -30,5 +30,12 @@ struct vp3054_i2c_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
index 738d4f20c580..42e0a9b8c550 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -28,11 +28,11 @@
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/video-buf.h>
+#include <media/videobuf-dma-sg.h>
#include <media/cx2341x.h>
#include <media/audiochip.h>
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
-#include <media/video-buf-dvb.h>
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
+#include <media/videobuf-dvb.h>
#endif
#include "btcx-risc.h"
@@ -209,6 +209,7 @@ extern struct sram_channel cx88_sram_channels[];
#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
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -225,8 +226,8 @@ enum cx88_itype {
struct cx88_input {
enum cx88_itype type;
- unsigned int vmux;
u32 gpio0, gpio1, gpio2, gpio3;
+ unsigned int vmux:2;
unsigned int extadc:1;
};
@@ -249,7 +250,7 @@ struct cx88_subid {
u32 card;
};
-#define INPUT(nr) (&cx88_boards[core->board].input[nr])
+#define INPUT(nr) (core->board.input[nr])
/* ----------------------------------------------------------- */
/* device / file handle status */
@@ -258,7 +259,7 @@ struct cx88_subid {
#define RESOURCE_VIDEO 2
#define RESOURCE_VBI 4
-#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */
+#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
/* buffer for one video frame */
struct cx88_buffer {
@@ -303,21 +304,14 @@ struct cx88_core {
u32 i2c_state, i2c_rc;
/* config info -- analog */
- 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 has_radio;
+ unsigned int boardnr;
+ struct cx88_board board;
/* Supported V4L _STD_ tuner formats */
unsigned int tuner_formats;
/* config info -- dvb */
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
- struct dvb_pll_desc *pll_desc;
- unsigned int pll_addr;
+#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
@@ -463,13 +457,10 @@ struct cx8802_dev {
u32 mailbox;
int width;
int height;
- int fw_size;
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
/* for dvb only */
struct videobuf_dvb dvb;
- void* fe_handle;
- int (*fe_release)(void *handle);
void *card_priv;
#endif
@@ -528,7 +519,7 @@ cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
extern int
cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
- unsigned int lines);
+ 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);
@@ -589,15 +580,9 @@ extern void cx88_call_i2c_clients(struct cx88_core *core,
/* ----------------------------------------------------------- */
/* cx88-cards.c */
-extern struct cx88_board cx88_boards[];
-extern const unsigned int cx88_bcount;
-
-extern struct cx88_subid cx88_subids[];
-extern const unsigned int cx88_idcount;
-
-extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci);
-extern void cx88_card_setup(struct cx88_core *core);
-extern void cx88_card_setup_pre_i2c(struct cx88_core *core);
+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);
/* ----------------------------------------------------------- */
/* cx88-tvaudio.c */
@@ -629,6 +614,8 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board
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);
+void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir);
+void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir);
/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
index 0fcc935828f8..255dae303708 100644
--- a/drivers/media/video/dpc7146.c
+++ b/drivers/media/video/dpc7146.c
@@ -92,7 +92,6 @@ static int dpc_probe(struct saa7146_dev* dev)
{
struct dpc* dpc = NULL;
struct i2c_client *client;
- struct list_head *item;
dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
if( NULL == dpc ) {
@@ -116,11 +115,9 @@ static int dpc_probe(struct saa7146_dev* dev)
}
/* loop through all i2c-devices on the bus and look who is there */
- list_for_each(item,&dpc->i2c_adapter.clients) {
- client = list_entry(item, struct i2c_client, list);
+ list_for_each_entry(client, &dpc->i2c_adapter.clients, list)
if( I2C_SAA7111A == client->addr )
dpc->saa7111a = client;
- }
/* check if all devices are present */
if( 0 == dpc->saa7111a ) {
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 255a47dfb84f..d3282ec62c5b 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/vmalloc.h>
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 55d45b0032cf..e3894b68c4ee 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -22,7 +22,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 2c7b158ce7e1..b8d5327c438d 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -252,10 +252,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
int minor = iminor(inode);
int errCode = 0;
struct em28xx *h,*dev = NULL;
- struct list_head *list;
- list_for_each(list,&em28xx_devlist) {
- h = list_entry(list, struct em28xx, devlist);
+ list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor) {
dev = h;
dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -268,8 +266,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
if (NULL == dev)
return -ENODEV;
- filp->private_data=dev;
-
em28xx_videodbg("open minor=%d type=%s users=%d\n",
minor,v4l2_type_names[dev->type],dev->users);
@@ -1772,6 +1768,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n");
em28xx_devused&=~(1<<nr);
+ kfree(dev);
return -ENOMEM;
}
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig
index 664676f44068..dcc1a0335440 100644
--- a/drivers/media/video/et61x251/Kconfig
+++ b/drivers/media/video/et61x251/Kconfig
@@ -1,6 +1,6 @@
config USB_ET61X251
tristate "USB ET61X[12]51 PC Camera Controller support"
- depends on VIDEO_V4L1
+ depends on VIDEO_V4L2
---help---
Say Y here if you want support for cameras based on Etoms ET61X151
or ET61X251 PC Camera Controllers.
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
index 262f98e12409..02c741d8f85a 100644
--- a/drivers/media/video/et61x251/et61x251.h
+++ b/drivers/media/video/et61x251/et61x251.h
@@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <linux/stddef.h>
#include <linux/string.h>
+#include <linux/kref.h>
#include "et61x251_sensor.h"
@@ -134,7 +135,7 @@ struct et61x251_module_param {
};
static DEFINE_MUTEX(et61x251_sysfs_lock);
-static DECLARE_RWSEM(et61x251_disconnect);
+static DECLARE_RWSEM(et61x251_dev_lock);
struct et61x251_device {
struct video_device* v4ldev;
@@ -158,12 +159,14 @@ struct et61x251_device {
struct et61x251_sysfs_attr sysfs;
struct et61x251_module_param module_param;
+ struct kref kref;
enum et61x251_dev_state state;
u8 users;
- struct mutex dev_mutex, fileop_mutex;
+ struct completion probe;
+ struct mutex open_mutex, fileop_mutex;
spinlock_t queue_lock;
- wait_queue_head_t open, wait_frame, wait_stream;
+ wait_queue_head_t wait_open, wait_frame, wait_stream;
};
/*****************************************************************************/
@@ -177,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
void
et61x251_attach_sensor(struct et61x251_device* cam,
- struct et61x251_sensor* sensor)
+ const struct et61x251_sensor* sensor)
{
memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
}
@@ -195,8 +198,8 @@ do { \
else if ((level) == 2) \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
- dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -205,8 +208,8 @@ do { \
if ((level) == 1 || (level) == 2) \
pr_info("et61x251: " fmt "\n", ## args); \
else if ((level) == 3) \
- pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -222,8 +225,8 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+ __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index a6525513cd1e..d5fef4c01c87 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/device.h>
@@ -45,11 +44,11 @@
#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \
"PC Camera Controllers"
-#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
+#define ET61X251_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia"
#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ET61X251_MODULE_LICENSE "GPL"
-#define ET61X251_MODULE_VERSION "1:1.04"
-#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4)
+#define ET61X251_MODULE_VERSION "1:1.09"
+#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 9)
/*****************************************************************************/
@@ -245,7 +244,8 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index)
static int
-et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
+et61x251_i2c_wait(struct et61x251_device* cam,
+ const struct et61x251_sensor* sensor)
{
int i, r;
@@ -270,7 +270,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
int
et61x251_i2c_try_read(struct et61x251_device* cam,
- struct et61x251_sensor* sensor, u8 address)
+ const struct et61x251_sensor* sensor, u8 address)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -303,7 +303,8 @@ et61x251_i2c_try_read(struct et61x251_device* cam,
int
et61x251_i2c_try_write(struct et61x251_device* cam,
- struct et61x251_sensor* sensor, u8 address, u8 value)
+ const struct et61x251_sensor* sensor, u8 address,
+ u8 value)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -615,7 +616,7 @@ static int et61x251_start_transfer(struct et61x251_device* cam)
return 0;
free_urbs:
- for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++)
+ for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++)
usb_free_urb(cam->urb[i]);
free_buffers:
@@ -682,7 +683,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
if (len < 4) {
strncpy(str, buff, len);
- str[len+1] = '\0';
+ str[len] = '\0';
} else {
strncpy(str, buff, 4);
str[4] = '\0';
@@ -705,7 +706,8 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
NOTE 2: buffers are PAGE_SIZE long
*/
-static ssize_t et61x251_show_reg(struct class_device* cd, char* buf)
+static ssize_t et61x251_show_reg(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct et61x251_device* cam;
ssize_t count;
@@ -728,7 +730,8 @@ static ssize_t et61x251_show_reg(struct class_device* cd, char* buf)
static ssize_t
-et61x251_store_reg(struct class_device* cd, const char* buf, size_t len)
+et61x251_store_reg(struct device* cd,
+ struct device_attribute *attr, const char* buf, size_t len)
{
struct et61x251_device* cam;
u8 index;
@@ -760,7 +763,8 @@ et61x251_store_reg(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t et61x251_show_val(struct class_device* cd, char* buf)
+static ssize_t et61x251_show_val(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct et61x251_device* cam;
ssize_t count;
@@ -791,7 +795,8 @@ static ssize_t et61x251_show_val(struct class_device* cd, char* buf)
static ssize_t
-et61x251_store_val(struct class_device* cd, const char* buf, size_t len)
+et61x251_store_val(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct et61x251_device* cam;
u8 value;
@@ -829,7 +834,8 @@ et61x251_store_val(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf)
+static ssize_t et61x251_show_i2c_reg(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct et61x251_device* cam;
ssize_t count;
@@ -854,7 +860,8 @@ static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf)
static ssize_t
-et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
+et61x251_store_i2c_reg(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct et61x251_device* cam;
u8 index;
@@ -886,7 +893,8 @@ et61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf)
+static ssize_t et61x251_show_i2c_val(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct et61x251_device* cam;
ssize_t count;
@@ -922,7 +930,8 @@ static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf)
static ssize_t
-et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
+et61x251_store_i2c_val(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct et61x251_device* cam;
u8 value;
@@ -965,42 +974,40 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
}
-static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
- et61x251_show_reg, et61x251_store_reg);
-static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
- et61x251_show_val, et61x251_store_val);
-static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
- et61x251_show_i2c_reg, et61x251_store_i2c_reg);
-static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
- et61x251_show_i2c_val, et61x251_store_i2c_val);
+static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
+ et61x251_show_reg, et61x251_store_reg);
+static DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
+ et61x251_show_val, et61x251_store_val);
+static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
+ et61x251_show_i2c_reg, et61x251_store_i2c_reg);
+static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
+ et61x251_show_i2c_val, et61x251_store_i2c_val);
static int et61x251_create_sysfs(struct et61x251_device* cam)
{
- struct video_device *v4ldev = cam->v4ldev;
+ struct device *classdev = &(cam->v4ldev->class_dev);
int err = 0;
- if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+ if ((err = device_create_file(classdev, &dev_attr_reg)))
goto err_out;
- if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+ if ((err = device_create_file(classdev, &dev_attr_val)))
goto err_reg;
if (cam->sensor.sysfs_ops) {
- if ((err = video_device_create_file(v4ldev,
- &class_device_attr_i2c_reg)))
+ if ((err = device_create_file(classdev, &dev_attr_i2c_reg)))
goto err_val;
- if ((err = video_device_create_file(v4ldev,
- &class_device_attr_i2c_val)))
+ if ((err = device_create_file(classdev, &dev_attr_i2c_val)))
goto err_i2c_reg;
}
err_i2c_reg:
if (cam->sensor.sysfs_ops)
- video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
+ device_remove_file(classdev, &dev_attr_i2c_reg);
err_val:
- video_device_remove_file(v4ldev, &class_device_attr_val);
+ device_remove_file(classdev, &dev_attr_val);
err_reg:
- video_device_remove_file(v4ldev, &class_device_attr_reg);
+ device_remove_file(classdev, &dev_attr_reg);
err_out:
return err;
}
@@ -1103,7 +1110,8 @@ static int et61x251_init(struct et61x251_device* cam)
int err = 0;
if (!(cam->state & DEV_INITIALIZED)) {
- init_waitqueue_head(&cam->open);
+ mutex_init(&cam->open_mutex);
+ init_waitqueue_head(&cam->wait_open);
qctrl = s->qctrl;
rect = &(s->cropcap.defrect);
cam->compression.quality = ET61X251_COMPRESSION_QUALITY;
@@ -1177,64 +1185,80 @@ static int et61x251_init(struct et61x251_device* cam)
return 0;
}
+/*****************************************************************************/
-static void et61x251_release_resources(struct et61x251_device* cam)
+static void et61x251_release_resources(struct kref *kref)
{
+ struct et61x251_device *cam;
+
mutex_lock(&et61x251_sysfs_lock);
+ cam = container_of(kref, struct et61x251_device, kref);
+
DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
+ usb_put_dev(cam->usbdev);
+ kfree(cam->control_buffer);
+ kfree(cam);
mutex_unlock(&et61x251_sysfs_lock);
-
- kfree(cam->control_buffer);
}
-/*****************************************************************************/
static int et61x251_open(struct inode* inode, struct file* filp)
{
struct et61x251_device* cam;
int err = 0;
- /*
- This is the only safe way to prevent race conditions with
- disconnect
- */
- if (!down_read_trylock(&et61x251_disconnect))
+ if (!down_read_trylock(&et61x251_dev_lock))
return -ERESTARTSYS;
cam = video_get_drvdata(video_devdata(filp));
- if (mutex_lock_interruptible(&cam->dev_mutex)) {
- up_read(&et61x251_disconnect);
+ if (wait_for_completion_interruptible(&cam->probe)) {
+ up_read(&et61x251_dev_lock);
return -ERESTARTSYS;
}
+ kref_get(&cam->kref);
+
+ if (mutex_lock_interruptible(&cam->open_mutex)) {
+ kref_put(&cam->kref, et61x251_release_resources);
+ up_read(&et61x251_dev_lock);
+ return -ERESTARTSYS;
+ }
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ err = -ENODEV;
+ goto out;
+ }
+
if (cam->users) {
- DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ DBG(2, "Device /dev/video%d is already in use",
+ cam->v4ldev->minor);
+ DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
err = -EWOULDBLOCK;
goto out;
}
- mutex_unlock(&cam->dev_mutex);
- err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
+ DBG(2, "A blocking open() has been requested. Wait for the "
+ "device to be released...");
+ up_read(&et61x251_dev_lock);
+ err = wait_event_interruptible_exclusive(cam->wait_open,
+ (cam->state & DEV_DISCONNECTED)
|| !cam->users);
- if (err) {
- up_read(&et61x251_disconnect);
- return err;
- }
+ down_read(&et61x251_dev_lock);
+ if (err)
+ goto out;
if (cam->state & DEV_DISCONNECTED) {
- up_read(&et61x251_disconnect);
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
- mutex_lock(&cam->dev_mutex);
}
-
if (cam->state & DEV_MISCONFIGURED) {
err = et61x251_init(cam);
if (err) {
@@ -1259,36 +1283,32 @@ static int et61x251_open(struct inode* inode, struct file* filp)
DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
out:
- mutex_unlock(&cam->dev_mutex);
- up_read(&et61x251_disconnect);
+ mutex_unlock(&cam->open_mutex);
+ if (err)
+ kref_put(&cam->kref, et61x251_release_resources);
+ up_read(&et61x251_dev_lock);
return err;
}
static int et61x251_release(struct inode* inode, struct file* filp)
{
- struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_device* cam;
- mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
+ down_write(&et61x251_dev_lock);
- et61x251_stop_transfer(cam);
+ cam = video_get_drvdata(video_devdata(filp));
+ et61x251_stop_transfer(cam);
et61x251_release_buffers(cam);
-
- if (cam->state & DEV_DISCONNECTED) {
- et61x251_release_resources(cam);
- usb_put_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
- kfree(cam);
- return 0;
- }
-
cam->users--;
- wake_up_interruptible_nr(&cam->open, 1);
+ wake_up_interruptible_nr(&cam->wait_open, 1);
DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
- mutex_unlock(&cam->dev_mutex);
+ kref_put(&cam->kref, et61x251_release_resources);
+
+ up_write(&et61x251_dev_lock);
return 0;
}
@@ -1324,7 +1344,7 @@ et61x251_read(struct file* filp, char __user * buf,
DBG(3, "Close and open the device again to choose the read "
"method");
mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
+ return -EBUSY;
}
if (cam->io == IO_NONE) {
@@ -1504,7 +1524,12 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
return -EIO;
}
- if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -EACCES;
+ }
+
+ if (cam->io != IO_MMAP ||
size != PAGE_ALIGN(cam->frame[0].buf.length)) {
mutex_unlock(&cam->fileop_mutex);
return -EINVAL;
@@ -1535,7 +1560,6 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
vma->vm_ops = &et61x251_vm_ops;
vma->vm_private_data = &cam->frame[i];
-
et61x251_vm_open(vma);
mutex_unlock(&cam->fileop_mutex);
@@ -1764,7 +1788,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_CROP failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
/* Preserve R,G or B origin */
@@ -1921,6 +1945,8 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
+ pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_ET61X251) ?
+ 0 : V4L2_COLORSPACE_SRGB;
pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251)
? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
@@ -1996,6 +2022,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
pix->pixelformat = pfmt->pixelformat;
pix->priv = pfmt->priv; /* bpp */
+ pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) ?
+ 0 : V4L2_COLORSPACE_SRGB;
pix->colorspace = pfmt->colorspace;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
? 0 : (pix->width * pix->priv) / 8;
@@ -2013,7 +2041,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_FMT failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2129,14 +2157,14 @@ et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg)
if (cam->io == IO_READ) {
DBG(3, "Close and open the device again to choose the mmap "
"I/O method");
- return -EINVAL;
+ return -EBUSY;
}
for (i = 0; i < cam->nbuffers; i++)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_REQBUFS failed. "
"Previous buffers are still mapped.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2284,9 +2312,6 @@ et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg)
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
return -EINVAL;
- if (list_empty(&cam->inqueue))
- return -EINVAL;
-
cam->stream = STREAM_ON;
DBG(3, "Stream on");
@@ -2535,8 +2560,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- mutex_init(&cam->dev_mutex);
-
DBG(2, "ET61X[12]51 PC Camera Controller detected "
"(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
@@ -2568,7 +2591,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->release = video_device_release;
video_set_drvdata(cam->v4ldev, cam);
- mutex_lock(&cam->dev_mutex);
+ init_completion(&cam->probe);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]);
@@ -2578,7 +2601,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(1, "Free /dev/videoX node not found");
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
goto fail;
}
@@ -2599,11 +2622,15 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
"device controlling. Error #%d", err);
#else
DBG(2, "Optional device control through 'sysfs' interface disabled");
+ DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
+ "configuration option to enable it.");
#endif
usb_set_intfdata(intf, cam);
+ kref_init(&cam->kref);
+ usb_get_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
return 0;
@@ -2620,40 +2647,31 @@ fail:
static void et61x251_usb_disconnect(struct usb_interface* intf)
{
- struct et61x251_device* cam = usb_get_intfdata(intf);
-
- if (!cam)
- return;
+ struct et61x251_device* cam;
- down_write(&et61x251_disconnect);
+ down_write(&et61x251_dev_lock);
- mutex_lock(&cam->dev_mutex);
+ cam = usb_get_intfdata(intf);
DBG(2, "Disconnecting %s...", cam->v4ldev->name);
- wake_up_interruptible_all(&cam->open);
-
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
- "memory deallocation are deferred on close.",
+ "memory deallocation are deferred.",
cam->v4ldev->minor);
cam->state |= DEV_MISCONFIGURED;
et61x251_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
wake_up_interruptible(&cam->wait_frame);
wake_up(&cam->wait_stream);
- usb_get_dev(cam->usbdev);
- } else {
+ } else
cam->state |= DEV_DISCONNECTED;
- et61x251_release_resources(cam);
- }
- mutex_unlock(&cam->dev_mutex);
+ wake_up_interruptible_all(&cam->wait_open);
- if (!cam->users)
- kfree(cam);
+ kref_put(&cam->kref, et61x251_release_resources);
- up_write(&et61x251_disconnect);
+ up_write(&et61x251_dev_lock);
}
diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h
index 5fadb5de68bf..e14586330623 100644
--- a/drivers/media/video/et61x251/et61x251_sensor.h
+++ b/drivers/media/video/et61x251/et61x251_sensor.h
@@ -22,7 +22,7 @@
#define _ET61X251_SENSOR_H_
#include <linux/usb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
#include <linux/device.h>
#include <linux/stddef.h>
#include <linux/errno.h>
@@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id);
extern void
et61x251_attach_sensor(struct et61x251_device* cam,
- struct et61x251_sensor* sensor);
+ const struct et61x251_sensor* sensor);
/*****************************************************************************/
@@ -56,10 +56,10 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index);
extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
extern int et61x251_i2c_try_write(struct et61x251_device*,
- struct et61x251_sensor*, u8 address,
+ const struct et61x251_sensor*, u8 address,
u8 value);
extern int et61x251_i2c_try_read(struct et61x251_device*,
- struct et61x251_sensor*, u8 address);
+ const struct et61x251_sensor*, u8 address);
extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
u8 data2, u8 data3, u8 data4, u8 data5,
u8 data6, u8 data7, u8 data8, u8 address);
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
index b06643409842..04b7fbb310a8 100644
--- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c
+++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
@@ -69,7 +69,7 @@ static int tas5130d1b_set_ctrl(struct et61x251_device* cam,
}
-static struct et61x251_sensor tas5130d1b = {
+static const struct et61x251_sensor tas5130d1b = {
.name = "TAS5130D1B",
.interface = ET61X251_I2C_3WIRES,
.rsta = ET61X251_I2C_RSTA_STOP,
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index ed92b6f7187a..d98dd0d1e373 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -10,6 +10,8 @@
* Ulrich Mueller <ulrich.mueller42@web.de>
* modified for em2820 based USB TV tuners by
* Markus Rechberger <mrechberger@gmail.com>
+ * modified for DViCO Fusion HDTV 5 RT GOLD by
+ * Chaogui Zhang <czhang1974@gmail.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
@@ -28,7 +30,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -37,6 +38,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/i2c-id.h>
#include <linux/workqueue.h>
#include <asm/semaphore.h>
@@ -60,21 +62,22 @@ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults
/* ----------------------------------------------------------------------- */
-static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
+ int size, int offset)
{
- unsigned char buf[3];
+ unsigned char buf[6];
int start, range, toggle, dev, code;
/* poll IR chip */
- if (3 != i2c_master_recv(&ir->c,buf,3))
+ if (size != i2c_master_recv(&ir->c,buf,size))
return -EIO;
/* split rc5 data block ... */
- start = (buf[0] >> 7) & 1;
- range = (buf[0] >> 6) & 1;
- toggle = (buf[0] >> 5) & 1;
- dev = buf[0] & 0x1f;
- code = (buf[1] >> 2) & 0x3f;
+ start = (buf[offset] >> 7) & 1;
+ range = (buf[offset] >> 6) & 1;
+ toggle = (buf[offset] >> 5) & 1;
+ dev = buf[offset] & 0x1f;
+ code = (buf[offset+1] >> 2) & 0x3f;
/* rc5 has two start bits
* the first bit must be one
@@ -96,6 +99,16 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static inline int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+}
+
+static inline int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+}
+
static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char b;
@@ -130,6 +143,30 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char buf[4];
+
+ /* poll IR chip */
+ if (4 != i2c_master_recv(&ir->c,buf,4)) {
+ dprintk(1,"read error\n");
+ return -EIO;
+ }
+
+ if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
+ dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3]);
+
+ /* no key pressed or signal from other ir remote */
+ if(buf[0] != 0x1 || buf[1] != 0xfe)
+ return 0;
+
+ *ir_key = buf[2];
+ *ir_raw = (buf[2] << 8) | buf[3];
+
+ return 1;
+}
+
static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char b;
@@ -270,8 +307,9 @@ static void ir_timer(unsigned long data)
static void ir_work(struct work_struct *work)
{
struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+
ir_key_poll(ir);
- mod_timer(&ir->timer, jiffies+HZ/10);
+ mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100));
}
/* ----------------------------------------------------------------------- */
@@ -351,12 +389,30 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir_type = IR_TYPE_OTHER;
ir_codes = ir_codes_empty;
break;
+ case 0x6b:
+ name = "FusionHDTV";
+ ir->get_key = get_key_fusionhdtv;
+ ir_type = IR_TYPE_RC5;
+ ir_codes = ir_codes_fusionhdtv_mce;
+ break;
case 0x7a:
case 0x47:
case 0x71:
- /* Handled by saa7134-input */
- name = "SAA713x remote";
- ir_type = IR_TYPE_OTHER;
+ if (adap->id == I2C_HW_B_CX2388x) {
+ /* Handled by cx88-input */
+ name = "CX2388x remote";
+ ir_type = IR_TYPE_RC5;
+ ir->get_key = get_key_haup_xvr;
+ if (hauppauge == 1) {
+ ir_codes = ir_codes_hauppauge_new;
+ } else {
+ ir_codes = ir_codes_rc5_tv;
+ }
+ } else {
+ /* Handled by saa7134-input */
+ name = "SAA713x remote";
+ ir_type = IR_TYPE_OTHER;
+ }
break;
default:
/* shouldn't happen */
@@ -450,6 +506,8 @@ static int ir_probe(struct i2c_adapter *adap)
static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 };
static const int probe_em28XX[] = { 0x30, 0x47, -1 };
+ static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
+ static const int probe_cx23885[] = { 0x6b, -1 };
const int *probe = NULL;
struct i2c_client c;
unsigned char buf;
@@ -468,6 +526,11 @@ static int ir_probe(struct i2c_adapter *adap)
case I2C_HW_B_EM28XX:
probe = probe_em28XX;
break;
+ case I2C_HW_B_CX2388x:
+ probe = probe_cx88;
+ case I2C_HW_B_CX23885:
+ probe = probe_cx23885;
+ break;
}
if (NULL == probe)
return 0;
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
index 1aaeaa02f158..854cc9c30ca9 100644
--- a/drivers/media/video/ivtv/Kconfig
+++ b/drivers/media/video/ivtv/Kconfig
@@ -1,6 +1,7 @@
config VIDEO_IVTV
tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
+ select I2C_ALGOBIT
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
@@ -13,14 +14,31 @@ config VIDEO_IVTV
select VIDEO_CS53L32A
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 cx23416 based
+ 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.
+ 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 && EXPERIMENTAL
+ 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
index 7e95148fbf4f..e8eefd96d897 100644
--- a/drivers/media/video/ivtv/Makefile
+++ b/drivers/media/video/ivtv/Makefile
@@ -1,7 +1,8 @@
-ivtv-objs := ivtv-audio.o ivtv-cards.o ivtv-controls.o \
+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-video.o ivtv-yuv.o
+ ivtv-vbi.o ivtv-yuv.o
obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
+obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
diff --git a/drivers/media/video/ivtv/ivtv-audio.c b/drivers/media/video/ivtv/ivtv-audio.c
deleted file mode 100644
index d702b8b539a1..000000000000
--- a/drivers/media/video/ivtv/ivtv-audio.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Audio-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-mailbox.h"
-#include "ivtv-i2c.h"
-#include "ivtv-gpio.h"
-#include "ivtv-cards.h"
-#include "ivtv-audio.h"
-#include <media/msp3400.h>
-#include <linux/videodev.h>
-
-/* Selects the audio input and output according to the current
- settings. */
-int ivtv_audio_set_io(struct ivtv *itv)
-{
- struct v4l2_routing route;
- u32 audio_input;
- int mux_input;
-
- /* Determine which input to use */
- if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
- audio_input = itv->card->radio_input.audio_input;
- mux_input = itv->card->radio_input.muxer_input;
- } else {
- audio_input = itv->card->audio_inputs[itv->audio_input].audio_input;
- mux_input = itv->card->audio_inputs[itv->audio_input].muxer_input;
- }
-
- /* handle muxer chips */
- route.input = mux_input;
- route.output = 0;
- ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
-
- route.input = audio_input;
- if (itv->card->hw_audio & IVTV_HW_MSP34XX) {
- route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
- }
- return ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route);
-}
-
-void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route)
-{
- ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
-}
-
-void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq)
-{
- static u32 freqs[3] = { 44100, 48000, 32000 };
-
- /* The audio clock of the digitizer must match the codec sample
- rate otherwise you get some very strange effects. */
- if (freq > 2)
- return;
- ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]);
-}
-
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
index 8eab02083887..b6a8be622d3c 100644
--- a/drivers/media/video/ivtv/ivtv-cards.c
+++ b/drivers/media/video/ivtv/ivtv-cards.c
@@ -616,7 +616,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
.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_TVAUDIO |
+ .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 = {
@@ -654,7 +654,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
.hw_audio = IVTV_HW_GPIO,
.hw_audio_ctrl = IVTV_HW_WM8739,
.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
- IVTV_HW_TVAUDIO | IVTV_HW_WM8739,
+ 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 },
@@ -823,9 +823,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
/* ------------------------------------------------------------------------- */
-#ifdef HAVE_XC3028
-
-/* Yuan PG600-2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 cards */
+/* 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 },
@@ -835,29 +833,87 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
static const struct ivtv_card ivtv_card_pg600v2 = {
.type = IVTV_CARD_PG600V2,
- .name = "Yuan PG600-2, GotView PCI DVD Lite, Club3D ZAP-TV1x01",
+ .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,
.video_inputs = {
- { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
- { IVTV_CARD_INPUT_SVIDEO1, 1,
+ { IVTV_CARD_INPUT_SVIDEO1, 0,
CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 0, 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 },
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 },
},
- .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
.pci_list = ivtv_pci_pg600v2,
};
-#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* 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_SVIDEO1, 0,
+ CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE3 },
+ },
+ .audio_inputs = {
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
+ },
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 },
+ },
+ .pci_list = ivtv_pci_club3d,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* 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,
+ .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 },
+ },
+ .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 },
+ },
+ .pci_list = ivtv_pci_avertv_mce116,
+};
static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_pvr250,
@@ -878,9 +934,9 @@ static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_gotview_pci_dvd2,
&ivtv_card_yuan_mpc622,
&ivtv_card_dctmvtvp1,
-#ifdef HAVE_XC3028
&ivtv_card_pg600v2,
-#endif
+ &ivtv_card_club3d,
+ &ivtv_card_avertv_mce116,
/* Variations of standard cards but with the same PCI IDs.
These cards must come last in this list. */
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 91e9e90c14a5..ff46e5ae8653 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -18,6 +18,68 @@
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_LAST 20
+
+/* 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_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
+
/* hardware flags */
#define IVTV_HW_CX25840 (1 << 0)
#define IVTV_HW_SAA7115 (1 << 1)
@@ -33,7 +95,8 @@
#define IVTV_HW_UPD6408X (1 << 11)
#define IVTV_HW_SAA717X (1 << 12)
#define IVTV_HW_WM8739 (1 << 13)
-#define IVTV_HW_GPIO (1 << 14)
+#define IVTV_HW_VP27SMPX (1 << 14)
+#define IVTV_HW_GPIO (1 << 15)
#define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
@@ -205,3 +268,5 @@ 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
index 7a876c3e5b19..8c02fa661591 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -21,7 +21,7 @@
#include "ivtv-driver.h"
#include "ivtv-cards.h"
#include "ivtv-ioctl.h"
-#include "ivtv-audio.h"
+#include "ivtv-routing.h"
#include "ivtv-i2c.h"
#include "ivtv-mailbox.h"
#include "ivtv-controls.h"
@@ -231,8 +231,10 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg)
}
IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+ static u32 freqs[3] = { 44100, 48000, 32000 };
struct cx2341x_mpeg_params p = itv->params;
- int err = cx2341x_ext_ctrls(&p, arg, cmd);
+ int err = cx2341x_ext_ctrls(&p, atomic_read(&itv->capturing), arg, cmd);
+ unsigned idx;
if (err)
return err;
@@ -254,7 +256,11 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg)
}
itv->params = p;
itv->dualwatch_stereo_mode = p.audio_properties & 0x0300;
- ivtv_audio_set_audio_clock_freq(itv, p.audio_properties & 0x03);
+ idx = p.audio_properties & 0x03;
+ /* The audio clock of the digitizer must match the codec sample
+ rate otherwise you get some very strange effects. */
+ if (idx < sizeof(freqs))
+ ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]);
return err;
}
return -EINVAL;
@@ -282,7 +288,7 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg)
}
IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n");
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
- return cx2341x_ext_ctrls(&itv->params, arg, cmd);
+ return cx2341x_ext_ctrls(&itv->params, 0, arg, cmd);
return -EINVAL;
}
@@ -292,7 +298,7 @@ int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg)
IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
- return cx2341x_ext_ctrls(&itv->params, arg, cmd);
+ return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), arg, cmd);
return -EINVAL;
}
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h
index 5a11149725ad..bb8a6a5ed2bc 100644
--- a/drivers/media/video/ivtv/ivtv-controls.h
+++ b/drivers/media/video/ivtv/ivtv-controls.h
@@ -18,4 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef IVTV_CONTROLS_H
+#define IVTV_CONTROLS_H
+
int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg);
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index efc66355339a..511a66252413 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -52,12 +52,12 @@
#include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include "ivtv-vbi.h"
-#include "ivtv-audio.h"
+#include "ivtv-routing.h"
#include "ivtv-gpio.h"
#include "ivtv-yuv.h"
-#include <linux/vermagic.h>
#include <media/tveeprom.h>
+#include <media/saa7115.h>
#include <media/v4l2-chip-ident.h>
/* var to keep track of the number of array elements in use */
@@ -87,17 +87,16 @@ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
-const u32 yuv_offset[4] = {
- IVTV_YUV_BUFFER_OFFSET,
- IVTV_YUV_BUFFER_OFFSET_1,
- IVTV_YUV_BUFFER_OFFSET_2,
- IVTV_YUV_BUFFER_OFFSET_3
-};
-
/* 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 };
-static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+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 cardtype_c = 1;
static int tuner_c = 1;
@@ -107,6 +106,18 @@ 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;
@@ -171,17 +182,27 @@ MODULE_PARM_DESC(cardtype,
"\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n"
"\t\t\t17 = Yuan MPC622\n"
"\t\t\t18 = Digital Cowboy DCT-MTVP1\n"
-#ifdef HAVE_XC3028
- "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01\n"
-#endif
+ "\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\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: errors only\n"
- "\t\t\t(debug = 511 gives full debugging)");
+ "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");
MODULE_PARM_DESC(ivtv_pci_latency,
"Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
"\t\t\tDefault: Yes");
@@ -202,7 +223,7 @@ 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 MB)\n"
+ "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"
@@ -211,7 +232,7 @@ 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 MB)\n"
+ "Decoder VBI buffers (in kB)\n"
"\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS));
MODULE_PARM_DESC(newi2c,
"Use new I2C implementation\n"
@@ -276,9 +297,10 @@ int ivtv_waitq(wait_queue_head_t *waitq)
}
/* Generic utility functions */
-int ivtv_sleep_timeout(int timeout, int intr)
+int ivtv_msleep_timeout(unsigned int msecs, int intr)
{
int ret;
+ int timeout = msecs_to_jiffies(msecs);
do {
set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
@@ -339,6 +361,7 @@ static void ivtv_process_eeprom(struct ivtv *itv)
/* 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:
@@ -426,7 +449,7 @@ static void ivtv_process_eeprom(struct ivtv *itv)
if (itv->options.newi2c == -1 && tv.has_ir != -1 && tv.has_ir != 2) {
itv->options.newi2c = (tv.has_ir & 2) ? 1 : 0;
if (itv->options.newi2c) {
- IVTV_INFO("reopen i2c bus for IR-blaster support\n");
+ IVTV_INFO("Reopen i2c bus for IR-blaster support\n");
exit_ivtv_i2c(itv);
init_ivtv_i2c(itv);
}
@@ -539,13 +562,13 @@ static void ivtv_process_options(struct ivtv *itv)
const char *chipname;
int i, j;
- itv->options.megabytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
- itv->options.megabytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
- itv->options.megabytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
- itv->options.megabytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
- itv->options.megabytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers;
- itv->options.megabytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers;
- itv->options.megabytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers;
+ 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->num];
itv->options.tuner = tuner[itv->num];
itv->options.radio = radio[itv->num];
@@ -622,6 +645,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
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);
@@ -643,7 +667,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
cx2341x_fill_defaults(&itv->params);
itv->params.port = CX2341X_PORT_MEMORY;
itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
- init_waitqueue_head(&itv->cap_w);
+ init_waitqueue_head(&itv->eos_waitq);
init_waitqueue_head(&itv->event_waitq);
init_waitqueue_head(&itv->vsync_waitq);
init_waitqueue_head(&itv->dma_waitq);
@@ -689,14 +713,6 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv)
break;
itv->nof_audio_inputs = i;
- /* 0x00EF = saa7114(239) 0x00F0 = saa7115(240) 0x0106 = micro */
- if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
- itv->digitizer = 0xF1;
- else if (itv->card->hw_all & IVTV_HW_SAA7114)
- itv->digitizer = 0xEF;
- else /* cx25840 */
- itv->digitizer = 0x140;
-
if (itv->card->hw_all & IVTV_HW_CX25840) {
itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */
} else {
@@ -725,6 +741,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
u16 cmd;
+ u8 card_rev;
unsigned char pci_latency;
IVTV_DEBUG_INFO("Enabling pci device\n");
@@ -771,7 +788,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
}
IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev);
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 64 && ivtv_pci_latency) {
@@ -788,7 +805,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
"irq: %d, latency: %d, memory: 0x%lx\n",
- itv->dev->device, itv->card_rev, dev->bus->number,
+ itv->dev->device, card_rev, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
itv->dev->irq, pci_latency, (unsigned long)itv->base_addr);
@@ -806,18 +823,19 @@ static void ivtv_request_module(struct ivtv *itv, const char *name)
static void ivtv_load_and_init_modules(struct ivtv *itv)
{
- struct v4l2_control ctrl;
u32 hw = itv->card->hw_all;
int i;
/* load modules */
#ifndef CONFIG_VIDEO_TUNER
if (hw & IVTV_HW_TUNER) {
- ivtv_request_module(itv, "tuner");
-#ifdef HAVE_XC3028
- if (itv->options.tuner == TUNER_XCEIVE_XC3028)
- ivtv_request_module(itv, "xc3028-tuner");
-#endif
+ if (itv->options.tuner == TUNER_XCEIVE_XC3028) {
+ IVTV_INFO("Xceive tuner not yet supported, only composite and S-Video inputs will be available\n");
+ itv->tunerid = 1;
+ }
+ else {
+ ivtv_request_module(itv, "tuner");
+ }
}
#endif
#ifndef CONFIG_VIDEO_CX25840
@@ -846,6 +864,10 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
if (hw & IVTV_HW_MSP34XX)
ivtv_request_module(itv, "msp3400");
#endif
+#ifndef CONFIG_VIDEO_VP27SMPX
+ if (hw & IVTV_HW_VP27SMPX)
+ ivtv_request_module(itv, "vp27smpx");
+#endif
if (hw & IVTV_HW_TVAUDIO)
ivtv_request_module(itv, "tvaudio");
#ifndef CONFIG_VIDEO_WM8775
@@ -886,13 +908,17 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
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) {
+ struct v4l2_crystal_freq crystal_freq;
- if (hw & IVTV_HW_CX25840) {
- /* CX25840_CID_ENABLE_PVR150_WORKAROUND */
- ctrl.id = V4L2_CID_PRIVATE_BASE;
- ctrl.value = itv->pvr150_workaround;
- itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl);
+ /* The crystal frequency of GVMVPRX is 24.576MHz */
+ crystal_freq.freq = SAA7115_FREQ_24_576_MHZ;
+ crystal_freq.flags = SAA7115_FREQ_FL_UCGC;
+ itv->video_dec_func(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+ }
+ 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;
@@ -938,18 +964,15 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int retval = 0;
- int video_input;
int yuv_buf_size;
int vbi_buf_size;
- int fw_retry_count = 3;
struct ivtv *itv;
- struct v4l2_frequency vf;
spin_lock(&ivtv_cards_lock);
/* Make sure we've got a place for this card */
if (ivtv_cards_active == IVTV_MAX_CARDS) {
- printk(KERN_ERR "ivtv: Maximum number of cards detected (%d).\n",
+ printk(KERN_ERR "ivtv: Maximum number of cards detected (%d)\n",
ivtv_cards_active);
spin_unlock(&ivtv_cards_lock);
return -ENOMEM;
@@ -964,9 +987,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
itv->dev = dev;
itv->num = ivtv_cards_active++;
snprintf(itv->name, sizeof(itv->name) - 1, "ivtv%d", itv->num);
- if (itv->num) {
- printk(KERN_INFO "ivtv: ====================== NEXT CARD ======================\n");
- }
+ IVTV_INFO("Initializing card #%d\n", itv->num);
spin_unlock(&ivtv_cards_lock);
@@ -982,6 +1003,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr);
+ mutex_lock(&itv->serialize_lock);
+
/* PCI Device Setup */
if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) {
if (retval == -EIO)
@@ -1032,22 +1055,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
goto free_io;
}
- 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) {
- IVTV_ERR("Error initializing firmware\n");
- goto free_i2c;
- }
-
- /* Try and get firmware versions */
- IVTV_DEBUG_INFO("Getting firmware version..\n");
- ivtv_firmware_versions(itv);
-
/* Check yuv output filter table */
if (itv->has_cx23415) ivtv_yuv_filter_check(itv);
@@ -1135,43 +1142,22 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
if (itv->options.radio > 0)
itv->v4l2_cap |= V4L2_CAP_RADIO;
- if (itv->options.tuner > -1) {
+ if (itv->options.tuner > -1 && itv->tunerid == 0) {
struct tuner_setup setup;
setup.addr = ADDR_UNSET;
setup.type = itv->options.tuner;
setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
-#ifdef HAVE_XC3028
- setup.initmode = V4L2_TUNER_ANALOG_TV;
- if (itv->options.tuner == TUNER_XCEIVE_XC3028) {
- setup.gpio_write = ivtv_reset_tuner_gpio;
- setup.gpio_priv = itv;
- }
-#endif
ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup);
}
- vf.tuner = 0;
- vf.type = V4L2_TUNER_ANALOG_TV;
- vf.frequency = 6400; /* the tuner 'baseline' frequency */
- if (itv->std & V4L2_STD_NTSC_M) {
- /* Why on earth? */
- vf.frequency = 1076; /* ch. 4 67250*16/1000 */
- }
-
/* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
are not. */
itv->tuner_std = itv->std;
- video_input = itv->active_input;
- itv->active_input++; /* Force update of input */
- ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &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_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf);
+ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+ ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
+ }
retval = ivtv_streams_setup(itv);
if (retval) {
@@ -1179,11 +1165,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
goto free_i2c;
}
- if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
- ivtv_init_mpeg_decoder(itv);
- }
- ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std);
-
IVTV_DEBUG_IRQ("Masking interrupts\n");
/* clear interrupt mask, effectively disabling interrupts */
ivtv_set_irq_mask(itv, 0xffffffff);
@@ -1195,26 +1176,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_ERR("Failed to register irq %d\n", retval);
goto free_streams;
}
-
- /* 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);
-
- /* 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);
- else
- ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
-
- if (itv->has_cx23415)
- ivtv_set_osd_alpha(itv);
-
- IVTV_INFO("Initialized %s, card #%d\n", itv->card_name, itv->num);
-
+ mutex_unlock(&itv->serialize_lock);
+ IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
return 0;
free_irq:
@@ -1232,68 +1195,146 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
free_workqueue:
destroy_workqueue(itv->irq_work_queues);
+ mutex_unlock(&itv->serialize_lock);
err:
if (retval == 0)
retval = -ENODEV;
IVTV_ERR("Error %d on initialization\n", retval);
+ spin_lock(&ivtv_cards_lock);
kfree(ivtv_cards[ivtv_cards_active]);
ivtv_cards[ivtv_cards_active] = NULL;
+ spin_unlock(&ivtv_cards_lock);
return retval;
}
-static void ivtv_remove(struct pci_dev *pci_dev)
+int ivtv_init_on_first_open(struct ivtv *itv)
{
- struct ivtv *itv = pci_get_drvdata(pci_dev);
+ struct v4l2_frequency vf;
+ int fw_retry_count = 3;
+ int video_input;
+
+ 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) {
+ struct v4l2_control ctrl;
+
+ /* CX25840_CID_ENABLE_PVR150_WORKAROUND */
+ ctrl.id = V4L2_CID_PRIVATE_BASE;
+ ctrl.value = itv->pvr150_workaround;
+ itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl);
+ }
+
+ 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 */
+ }
- IVTV_DEBUG_INFO("Removing Card #%d.\n", itv->num);
+ video_input = itv->active_input;
+ itv->active_input++; /* Force update of input */
+ ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &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_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf);
+
+ if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+ ivtv_init_mpeg_decoder(itv);
+ }
+ ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std);
+
+ /* 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);
- /* Stop all captures */
- IVTV_DEBUG_INFO(" Stopping all streams.\n");
- if (atomic_read(&itv->capturing) > 0)
- ivtv_stop_all_captures(itv);
+ /* 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);
+ }
+ else
+ ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
+ return 0;
+}
- /* Stop all decoding */
- IVTV_DEBUG_INFO(" Stopping decoding.\n");
- if (atomic_read(&itv->decoding) > 0) {
- int type;
+static void ivtv_remove(struct pci_dev *pci_dev)
+{
+ struct ivtv *itv = pci_get_drvdata(pci_dev);
- 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],
- VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
+ IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num);
+
+ 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");
+ 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],
+ VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
+ }
+ ivtv_halt_firmware(itv);
}
/* Interrupts */
- IVTV_DEBUG_INFO(" Disabling interrupts.\n");
ivtv_set_irq_mask(itv, 0xffffffff);
del_timer_sync(&itv->dma_timer);
/* Stop all Work Queues */
- IVTV_DEBUG_INFO(" Stop Work Queues.\n");
flush_workqueue(itv->irq_work_queues);
destroy_workqueue(itv->irq_work_queues);
- IVTV_DEBUG_INFO(" Stopping Firmware.\n");
- ivtv_halt_firmware(itv);
-
- IVTV_DEBUG_INFO(" Unregistering v4l devices.\n");
ivtv_streams_cleanup(itv);
- IVTV_DEBUG_INFO(" Freeing dma resources.\n");
ivtv_udma_free(itv);
exit_ivtv_i2c(itv);
- IVTV_DEBUG_INFO(" Releasing irq.\n");
free_irq(itv->dev->irq, (void *)itv);
+ ivtv_iounmap(itv);
- if (itv->dev) {
- ivtv_iounmap(itv);
- }
-
- IVTV_DEBUG_INFO(" Releasing mem.\n");
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)
@@ -1314,28 +1355,27 @@ static struct pci_driver ivtv_pci_driver = {
static int module_start(void)
{
- printk(KERN_INFO "ivtv: ==================== START INIT IVTV ====================\n");
- printk(KERN_INFO "ivtv: version %s (" VERMAGIC_STRING ") loading\n", IVTV_VERSION);
+ printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
memset(ivtv_cards, 0, sizeof(ivtv_cards));
/* Validate parameters */
if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) {
- printk(KERN_ERR "ivtv: ivtv_first_minor must be between 0 and %d. Exiting...\n",
+ 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 > 511) {
+ if (ivtv_debug < 0 || ivtv_debug > 2047) {
ivtv_debug = 0;
- printk(KERN_INFO "ivtv: debug value must be >= 0 and <= 511!\n");
+ 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 INIT IVTV ====================\n");
+ printk(KERN_INFO "ivtv: End initialization\n");
return 0;
}
@@ -1345,6 +1385,7 @@ static void module_cleanup(void)
pci_unregister_driver(&ivtv_pci_driver);
+ spin_lock(&ivtv_cards_lock);
for (i = 0; i < ivtv_cards_active; i++) {
if (ivtv_cards[i] == NULL)
continue;
@@ -1353,13 +1394,15 @@ static void module_cleanup(void)
}
kfree(ivtv_cards[i]);
}
+ spin_unlock(&ivtv_cards_lock);
}
-/* Note: These symbols are exported because they are used by the ivtv-fb
+/* 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_cards_active);
EXPORT_SYMBOL(ivtv_cards);
+EXPORT_SYMBOL(ivtv_cards_lock);
EXPORT_SYMBOL(ivtv_api);
EXPORT_SYMBOL(ivtv_vapi);
EXPORT_SYMBOL(ivtv_vapi_result);
@@ -1370,6 +1413,7 @@ 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);
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
index e6e56f175f3f..3bda1df63cb6 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -38,7 +38,6 @@
#include <linux/version.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -63,77 +62,20 @@
#include <media/tuner.h>
#include <media/cx2341x.h>
-/* #define HAVE_XC3028 1 */
+#include <linux/ivtv.h>
-#include <media/ivtv.h>
+/* Memory layout */
#define IVTV_ENCODER_OFFSET 0x00000000
-#define IVTV_ENCODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */
-
+#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 /* Last half isn't needed 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
-/* Buffers on hardware offsets */
-#define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */
-#define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */
-#define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */
-#define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */
-#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
-
-extern const u32 yuv_offset[4];
-
-/* Maximum ivtv driver instances.
- Based on 6 PVR500s each with two PVR15s...
- TODO: make this dynamic. I believe it is only a global in order to support
- ivtv-fb. There must be a better way to do that. */
-#define IVTV_MAX_CARDS 12
-
-/* 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 */
-#ifdef HAVE_XC3028
-#define IVTV_CARD_PG600V2 18 /* Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 */
-#define IVTV_CARD_LAST 18
-#else
-#define IVTV_CARD_LAST 17
-#endif
-
-/* 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)
+/* 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
@@ -146,70 +88,8 @@ extern const u32 yuv_offset[4];
#define IVTV_DEC_STREAM_TYPE_YUV 8
#define IVTV_MAX_STREAMS 9
-#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 */
-
-#define IVTV_ENC_MEM_START 0x00000000
-#define IVTV_DEC_MEM_START 0x01000000
-
-/* 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_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
-
-/* Decoder Buffer hardware size on Chip */
-#define IVTV_DEC_MAX_BUF 0x00100000 /* max bytes in decoder buffer */
-#define IVTV_DEC_MIN_BUF 0x00010000 /* min bytes in dec buffer */
-
-/* ======================================================================== */
-/* ========================== START USER SETTABLE DMA VARIABLES =========== */
-/* ======================================================================== */
-
#define IVTV_DMA_SG_OSD_ENT (2883584/PAGE_SIZE) /* sg entities */
-/* 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
-#define IVTV_DEFAULT_ENC_PCM_BUFFERS 1
-#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1
-#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1
-#define IVTV_DEFAULT_DEC_VBI_BUFFERS 1
-
-/* ======================================================================== */
-/* ========================== END USER SETTABLE DMA VARIABLES ============= */
-/* ======================================================================== */
-
-/* Decoder Status Register */
-#define IVTV_DMA_ERR_LIST 0x00000010
-#define IVTV_DMA_ERR_WRITE 0x00000008
-#define IVTV_DMA_ERR_READ 0x00000004
-#define IVTV_DMA_SUCCESS_WRITE 0x00000002
-#define IVTV_DMA_SUCCESS_READ 0x00000001
-#define IVTV_DMA_READ_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_READ)
-#define IVTV_DMA_WRITE_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE)
-#define IVTV_DMA_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE | IVTV_DMA_ERR_READ)
-
/* DMA Registers */
#define IVTV_REG_DMAXFER (0x0000)
#define IVTV_REG_DMASTATUS (0x0004)
@@ -232,42 +112,24 @@ extern const u32 yuv_offset[4];
#define IVTV_REG_VPU (0x9058)
#define IVTV_REG_APU (0xA064)
-#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)
-
/* i2c stuff */
#define I2C_CLIENTS_MAX 16
/* debugging */
+extern int ivtv_debug;
-#define IVTV_DBGFLG_WARN (1 << 0)
-#define IVTV_DBGFLG_INFO (1 << 1)
-#define IVTV_DBGFLG_API (1 << 2)
-#define IVTV_DBGFLG_DMA (1 << 3)
-#define IVTV_DBGFLG_IOCTL (1 << 4)
-#define IVTV_DBGFLG_I2C (1 << 5)
-#define IVTV_DBGFLG_IRQ (1 << 6)
-#define IVTV_DBGFLG_DEC (1 << 7)
-#define IVTV_DBGFLG_YUV (1 << 8)
+#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)
/* NOTE: extra space before comma in 'itv->num , ## args' is required for
gcc-2.95, otherwise it won't compile. */
@@ -276,43 +138,37 @@ extern const u32 yuv_offset[4];
if ((x) & ivtv_debug) \
printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \
} while (0)
-#define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args)
-#define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info",fmt , ## args)
-#define IVTV_DEBUG_API(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args)
-#define IVTV_DEBUG_DMA(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args)
+#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_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_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_FB_DEBUG(x, type, fmt, args...) \
+#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
do { \
- if ((x) & ivtv_debug) \
- printk(KERN_INFO "ivtv%d-fb " type ": " fmt, itv->num , ## args); \
+ if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \
+ printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \
} while (0)
-#define IVTV_FB_DEBUG_WARN(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args)
-#define IVTV_FB_DEBUG_INFO(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args)
-#define IVTV_FB_DEBUG_API(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args)
-#define IVTV_FB_DEBUG_DMA(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args)
-#define IVTV_FB_DEBUG_IOCTL(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
-#define IVTV_FB_DEBUG_I2C(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args)
-#define IVTV_FB_DEBUG_IRQ(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args)
-#define IVTV_FB_DEBUG_DEC(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args)
-#define IVTV_FB_DEBUG_YUV(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args)
+#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...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args)
#define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args)
#define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args)
-#define IVTV_FB_ERR(fmt, args...) printk(KERN_ERR "ivtv%d-fb: " fmt, itv->num , ## args)
-#define IVTV_FB_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d-fb: " fmt, itv->num , ## args)
-#define IVTV_FB_INFO(fmt, args...) printk(KERN_INFO "ivtv%d-fb: " fmt, itv->num , ## args)
-
-/* Values for IVTV_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
-#define MPEG_FRAME_TYPE_IFRAME 1
-#define MPEG_FRAME_TYPE_IFRAME_PFRAME 3
-#define MPEG_FRAME_TYPE_ALL 7
/* output modes (cx23415 only) */
#define OUT_NONE 0
@@ -323,22 +179,14 @@ extern const u32 yuv_offset[4];
#define IVTV_MAX_PGM_INDEX (400)
-extern int ivtv_debug;
-
-
struct ivtv_options {
- int megabytes[IVTV_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 */
- int newi2c; /* New I2C algorithm */
+ 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 */
};
-#define IVTV_MBOX_DMA_START 6
-#define IVTV_MBOX_DMA_END 8
-#define IVTV_MBOX_DMA 9
-#define IVTV_MBOX_FIELD_DISPLAYED 8
-
/* ivtv-specific mailbox template */
struct ivtv_mailbox {
u32 flags;
@@ -362,7 +210,7 @@ struct ivtv_mailbox_data {
};
/* per-buffer bit flags */
-#define IVTV_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */
+#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 */
@@ -383,23 +231,25 @@ struct ivtv_mailbox_data {
#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_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_ENC_VBI 8 /* VBI DMA */
#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_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 */
@@ -408,7 +258,7 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */
/* Scatter-Gather array element, used in DMA transfers */
-struct ivtv_SG_element {
+struct ivtv_sg_element {
u32 src;
u32 dst;
u32 size;
@@ -418,9 +268,11 @@ 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];
+ struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT];
dma_addr_t SG_handle;
int SG_length;
@@ -440,21 +292,21 @@ struct ivtv_dma_page_info {
struct ivtv_buffer {
struct list_head list;
dma_addr_t dma_handle;
- unsigned long b_flags;
+ unsigned short b_flags;
+ unsigned short dma_xfer_cnt;
char *buf;
-
u32 bytesused;
u32 readpos;
};
struct ivtv_queue {
- struct list_head list;
- u32 buffers;
- u32 length;
- u32 bytesused;
+ 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; /* forward reference */
struct ivtv_stream {
/* These first four fields are always set, even if the stream
@@ -465,11 +317,13 @@ struct ivtv_stream {
int type; /* stream type */
u32 id;
- 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 */
+ 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;
@@ -490,47 +344,53 @@ struct ivtv_stream {
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_element *SGarray;
- struct ivtv_SG_element *PIOarray;
- dma_addr_t SG_handle;
- int SG_length;
+ struct ivtv_sg_element *sg_pending;
+ struct ivtv_sg_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 {
- u32 open_id;
- int type;
- enum v4l2_priority prio;
+ u32 open_id; /* unique ID for this file descriptor */
+ int type; /* stream type */
+ int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */
+ enum v4l2_priority prio; /* priority */
struct ivtv *itv;
};
-#define IVTV_YUV_UPDATE_HORIZONTAL 0x01
-#define IVTV_YUV_UPDATE_VERTICAL 0x02
-
struct yuv_frame_info
{
u32 update;
- int src_x;
- int src_y;
- unsigned int src_w;
- unsigned int src_h;
- int dst_x;
- int dst_y;
- unsigned int dst_w;
- unsigned int dst_h;
- int pan_x;
- int pan_y;
+ 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;
- int tru_x;
+ s32 tru_x;
u32 tru_w;
u32 tru_h;
u32 offset_y;
+ s32 lace_mode;
};
#define IVTV_YUV_MODE_INTERLACED 0x00
@@ -603,7 +463,6 @@ struct yuv_playback_info
int decode_height;
int frame_interlaced;
- int frame_interlaced_last;
int lace_mode;
int lace_threshold;
@@ -614,6 +473,11 @@ struct yuv_playback_info
u32 yuv_forced_update;
int update_frame;
+
+ int sync_field[4]; /* Field to sync on */
+ int field_delay[4]; /* Flag to extend duration of previous frame */
+ u8 fields_lapsed; /* Counter used when delaying a frame */
+
struct yuv_frame_info new_frame_info[4];
struct yuv_frame_info old_frame_info;
struct yuv_frame_info old_frame_info_args;
@@ -625,38 +489,61 @@ struct yuv_playback_info
#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 {
- u32 dec_start;
- u32 enc_start, enc_size;
- int fpi;
- u32 frame;
- u32 dma_offset;
- u8 cc_data_odd[256];
- u8 cc_data_even[256];
- int cc_pos;
- u8 cc_no_update;
- u8 vps[5];
- u8 vps_found;
- int wss;
- u8 wss_found;
- u8 wss_no_update;
- u32 raw_decoder_line_size;
- u8 raw_decoder_sav_odd_field;
- u8 raw_decoder_sav_even_field;
- u32 sliced_decoder_line_size;
- u8 sliced_decoder_sav_odd_field;
- u8 sliced_decoder_sav_even_field;
- struct v4l2_format in;
- /* convenience pointer to sliced struct in vbi_in union */
- struct v4l2_sliced_vbi_format *sliced_in;
- u32 service_set_in;
- u32 service_set_out;
- int insert_mpeg;
-
- /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
- One for /dev/vbi0 and one for /dev/vbi8 */
- struct v4l2_sliced_vbi_data sliced_data[36];
- struct v4l2_sliced_vbi_data sliced_dec_data[36];
+ /* 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.
@@ -673,12 +560,9 @@ struct vbi_info {
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;
- u32 inserted_frame;
-
- u32 start[2], count;
- u32 raw_size;
- u32 sliced_size;
+ 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 */
@@ -686,130 +570,132 @@ struct ivtv_card;
/* Struct to hold info about ivtv cards */
struct ivtv {
- int num; /* board number, -1 during init! */
- char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */
- struct pci_dev *dev; /* PCI device */
+ /* General fixed card data */
+ int num; /* board number, -1 during init! */
+ char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */
+ struct pci_dev *dev; /* PCI device */
const struct ivtv_card *card; /* card information */
- const char *card_name; /* full name of the card */
- u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */
- u8 is_50hz;
- u8 is_60hz;
- u8 is_out_50hz;
- u8 is_out_60hz;
- 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 */
-
- /* controlling Video decoder function */
+ const char *card_name; /* full name of the card */
+ 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 */
+ int tunerid; /* userspace tuner ID for experimental Xceive tuner support */
+ v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */
+ /* controlling video decoder function */
int (*video_dec_func)(struct ivtv *, unsigned int, void *);
+ u32 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 */
+
+
+ /* 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 */
+ struct cx2341x_mpeg_params params; /* current encoder parameters */
+
+
+ /* 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 workqueue_struct *irq_work_queues; /* workqueue for PIO/YUV/VBI actions */
+ struct work_struct irq_work_queue; /* 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;
+ struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];/* pointers to all I2C clients */
+ int i2c_state; /* i2c bit state */
+ struct mutex i2c_bus_lock; /* lock i2c bus */
+
+
+ /* 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 */
+ struct v4l2_prio_state prio; /* priority state */
+ 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 */
+ u16 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 */
- struct ivtv_options options; /* User options */
- int stream_buf_size[IVTV_MAX_STREAMS]; /* Stream buffer size */
- struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* Stream data */
- int speed;
- u8 speed_mute_audio;
- unsigned long i_flags; /* global ivtv flags */
- atomic_t capturing; /* count number of active capture streams */
- atomic_t decoding; /* count number of active decoding streams */
- u32 irq_rr_idx; /* Round-robin stream index */
- int cur_dma_stream; /* index of stream doing DMA */
- int cur_pio_stream; /* index of stream doing PIO */
- u32 dma_data_req_offset;
- u32 dma_data_req_size;
- int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */
- spinlock_t lock; /* lock access to this struct */
- int search_pack_header;
-
- spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
-
- /* User based DMA for OSD */
- struct ivtv_user_dma udma;
-
- 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. */
-
- u32 base_addr;
- u32 irqmask;
-
- struct v4l2_prio_state prio;
- struct workqueue_struct *irq_work_queues;
- struct work_struct irq_work_queue;
- struct timer_list dma_timer; /* Timer used to catch unfinished DMAs */
-
- struct vbi_info vbi;
-
- struct ivtv_mailbox_data enc_mbox;
- struct ivtv_mailbox_data dec_mbox;
- struct ivtv_api_cache api_cache[256]; /* Cached API Commands */
-
- u8 card_rev;
- volatile void __iomem *enc_mem, *dec_mem, *reg_mem;
-
- u32 pgm_info_offset;
- u32 pgm_info_num;
- u32 pgm_info_write_idx;
- u32 pgm_info_read_idx;
- struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX];
-
- u64 mpg_data_received;
- u64 vbi_data_inserted;
-
- wait_queue_head_t cap_w;
- /* when the next decoder event arrives this queue is woken up */
- wait_queue_head_t event_waitq;
- /* when the next decoder vsync arrives this queue is woken up */
- wait_queue_head_t vsync_waitq;
- /* when the current DMA is finished this queue is woken up */
- wait_queue_head_t dma_waitq;
/* OSD support */
unsigned long osd_video_pbase;
- int osd_global_alpha_state; /* 0=off : 1=on */
- int osd_local_alpha_state; /* 0=off : 1=on */
- int osd_color_key_state; /* 0=off : 1=on */
- u8 osd_global_alpha; /* Current global alpha */
- u32 osd_color_key; /* Current color key */
- u32 osd_pixelformat; /* Current pixel format */
- struct v4l2_rect osd_rect; /* Current OSD position and size */
- struct v4l2_rect main_rect; /* Current Main window position and size */
-
- u32 last_dec_timing[3]; /* Store last retrieved pts/scr/frame values */
-
- /* i2c */
- struct i2c_adapter i2c_adap;
- struct i2c_algo_bit_data i2c_algo;
- struct i2c_client i2c_client;
- struct mutex i2c_bus_lock;
- int i2c_state;
- struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
-
- /* v4l2 and User settings */
-
- /* codec settings */
- struct cx2341x_mpeg_params params;
- u32 audio_input;
- u32 active_input;
- u32 active_output;
- v4l2_std_id std;
- v4l2_std_id std_out;
- v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
- u8 audio_stereo_mode;
- u8 audio_bilingual_mode;
-
- /* dualwatch */
- unsigned long dualwatch_jiffies;
- u16 dualwatch_stereo_mode;
-
- /* Digitizer type */
- int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
-
- u32 lastVsyncFrame;
-
- struct yuv_playback_info yuv_info;
- struct osd_info *osd_info;
+ 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 */
};
/* Globals */
@@ -831,7 +717,7 @@ int ivtv_set_output_mode(struct ivtv *itv, int mode);
struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv);
/* Return non-zero if a signal is pending */
-int ivtv_sleep_timeout(int timeout, int intr);
+int ivtv_msleep_timeout(unsigned int msecs, int intr);
/* Wait on queue, returns -EINTR if interrupted */
int ivtv_waitq(wait_queue_head_t *waitq);
@@ -840,6 +726,9 @@ int ivtv_waitq(wait_queue_head_t *waitq);
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);
+
/* 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
@@ -867,4 +756,4 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
#define write_dec_sync(val, addr) \
do { write_dec(val, addr); read_dec(addr); } while (0)
-#endif /* IVTV_DRIVER_H */
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 555d5e6369c3..da50fa4a72a5 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -27,10 +27,9 @@
#include "ivtv-irq.h"
#include "ivtv-vbi.h"
#include "ivtv-mailbox.h"
-#include "ivtv-audio.h"
+#include "ivtv-routing.h"
#include "ivtv-streams.h"
#include "ivtv-yuv.h"
-#include "ivtv-controls.h"
#include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include <media/saa7115.h>
@@ -190,7 +189,9 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
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[] = { V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_B, 0 };
+ 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) {
@@ -199,7 +200,7 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
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) & 3];
+ e->flags = mapping[read_enc(addr + 12) & 7];
i++;
}
itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
@@ -218,7 +219,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
/* Process pending program info updates and pending VBI data */
ivtv_update_pgm_info(itv);
- if (jiffies - itv->dualwatch_jiffies > HZ) {
+ if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
itv->dualwatch_jiffies = jiffies;
ivtv_dualwatch(itv);
}
@@ -245,8 +246,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
/* do we have new data? */
buf = ivtv_dequeue(s, &s->q_full);
if (buf) {
- if (!test_and_clear_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags))
+ 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);
@@ -256,19 +258,19 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
}
return buf;
}
- /* return if file was opened with O_NONBLOCK */
- if (non_block) {
- *err = -EAGAIN;
- return NULL;
- }
/* return if end of stream */
if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
- clear_bit(IVTV_F_S_STREAMOFF, &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 */
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added to the waitqueue */
@@ -376,10 +378,20 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
int rc;
buf = ivtv_get_buffer(s, non_block, &rc);
- if (buf == NULL && rc == -EAGAIN && tot_written)
- break;
- if (buf == NULL)
+ /* 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);
@@ -406,7 +418,7 @@ static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t co
ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0;
struct ivtv *itv = s->itv;
- IVTV_DEBUG_INFO("read %zd from %s, got %zd\n", count, s->name, rc);
+ IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
if (rc > 0)
pos += rc;
return rc;
@@ -497,9 +509,11 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
struct ivtv_stream *s = &itv->streams[id->type];
int rc;
- IVTV_DEBUG_IOCTL("read %zd bytes from %s\n", count, s->name);
+ IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+ mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id);
+ mutex_unlock(&itv->serialize_lock);
if (rc)
return rc;
return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@@ -535,7 +549,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
int rc;
DEFINE_WAIT(wait);
- IVTV_DEBUG_IOCTL("write %zd bytes to %s\n", count, s->name);
+ 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 &&
@@ -549,8 +563,11 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
/* 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(itv, user_buf, count);
+ ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems);
+ return elems * sizeof(struct v4l2_sliced_vbi_data);
}
mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
@@ -610,7 +627,9 @@ retry:
}
/* Start decoder (returns 0 if already started) */
+ mutex_lock(&itv->serialize_lock);
rc = ivtv_start_decoding(id, itv->speed);
+ mutex_unlock(&itv->serialize_lock);
if (rc) {
IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
@@ -643,7 +662,7 @@ retry:
to transfer the rest. */
if (count && !(filp->f_flags & O_NONBLOCK))
goto retry;
- IVTV_DEBUG_INFO("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
+ IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
return bytes_written;
}
@@ -655,6 +674,7 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
int res = 0;
/* add stream's waitq to the poll list */
+ IVTV_DEBUG_HI_FILE("Decoder poll\n");
poll_wait(filp, &s->waitq, wait);
set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
@@ -677,16 +697,21 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
/* Start a capture if there is none */
if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
- int rc = ivtv_start_capture(id);
+ 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 (eof || s->q_full.length)
@@ -699,7 +724,7 @@ 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_IOCTL("close() of %s\n", s->name);
+ IVTV_DEBUG_FILE("close() of %s\n", s->name);
/* 'Unclaim' this stream */
@@ -726,10 +751,11 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
ivtv_stop_v4l2_encode_stream(s, 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);
+ 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)
@@ -737,13 +763,14 @@ 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_IOCTL("close() of %s\n", s->name);
+ IVTV_DEBUG_FILE("close() of %s\n", s->name);
/* 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);
@@ -751,12 +778,11 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
/* Restore registers we've changed & clean up any mess we've made */
ivtv_yuv_close(itv);
}
- if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV)
- itv->output_mode = OUT_NONE;
- else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG)
- itv->output_mode = OUT_NONE;
+ 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);
}
@@ -766,7 +792,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
struct ivtv *itv = id->itv;
struct ivtv_stream *s = &itv->streams[id->type];
- IVTV_DEBUG_IOCTL("close() of %s\n", s->name);
+ IVTV_DEBUG_FILE("close %s\n", s->name);
v4l2_prio_close(&itv->prio, &id->prio);
@@ -779,6 +805,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
/* 'Unclaim' this stream */
/* Stop radio */
+ mutex_lock(&itv->serialize_lock);
if (id->type == IVTV_ENC_STREAM_TYPE_RAD) {
/* Closing radio device, return to TV mode */
ivtv_mute(itv);
@@ -799,52 +826,40 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_unmute(itv);
ivtv_release_stream(s);
} else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+ struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
+
ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_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);
}
kfree(id);
+ mutex_unlock(&itv->serialize_lock);
return 0;
}
-int ivtv_v4l2_open(struct inode *inode, struct file *filp)
+static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
{
- int x, y = 0;
+ struct ivtv *itv = s->itv;
struct ivtv_open_id *item;
- struct ivtv *itv = NULL;
- struct ivtv_stream *s = NULL;
- int minor = iminor(inode);
-
- /* Find which card this open was on */
- spin_lock(&ivtv_cards_lock);
- for (x = 0; itv == NULL && x < ivtv_cards_active; x++) {
- /* find out which stream this open was on */
- for (y = 0; y < IVTV_MAX_STREAMS; y++) {
- s = &ivtv_cards[x]->streams[y];
- if (s->v4l2dev && s->v4l2dev->minor == minor) {
- itv = ivtv_cards[x];
- break;
- }
- }
- }
- spin_unlock(&ivtv_cards_lock);
- if (itv == NULL) {
- /* Couldn't find a device registered
- on that minor, shouldn't happen! */
- printk(KERN_WARNING "ivtv: no ivtv device found on minor %d\n", minor);
- return -ENXIO;
- }
+ IVTV_DEBUG_FILE("open %s\n", s->name);
- if (y == IVTV_DEC_STREAM_TYPE_MPG &&
+ 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 (y == IVTV_DEC_STREAM_TYPE_YUV &&
+ 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 (y == IVTV_DEC_STREAM_TYPE_YUV) {
+ 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; */
@@ -859,7 +874,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
return -ENOMEM;
}
item->itv = itv;
- item->type = y;
+ item->type = s->type;
v4l2_prio_open(&itv->prio, &item->prio);
item->open_id = itv->open_id++;
@@ -873,12 +888,20 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
return -EBUSY;
}
+ 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 */
+ 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_i2c_clients(itv, AUDC_SET_RADIO, NULL);
- /* Mark that the radio is being used. */
- set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X)
@@ -893,45 +916,65 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
}
/* YUV or MPG Decoding Mode? */
- if (y == IVTV_DEC_STREAM_TYPE_MPG)
+ if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
- else if (y == IVTV_DEC_STREAM_TYPE_YUV)
- {
+ else if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
- }
-
return 0;
}
-void ivtv_mute(struct ivtv *itv)
+int ivtv_v4l2_open(struct inode *inode, struct file *filp)
{
- struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 1 };
+ int res, x, y = 0;
+ struct ivtv *itv = NULL;
+ struct ivtv_stream *s = NULL;
+ int minor = iminor(inode);
+
+ /* Find which card this open was on */
+ spin_lock(&ivtv_cards_lock);
+ for (x = 0; itv == NULL && x < ivtv_cards_active; x++) {
+ /* find out which stream this open was on */
+ for (y = 0; y < IVTV_MAX_STREAMS; y++) {
+ s = &ivtv_cards[x]->streams[y];
+ if (s->v4l2dev && s->v4l2dev->minor == minor) {
+ itv = ivtv_cards[x];
+ break;
+ }
+ }
+ }
+ spin_unlock(&ivtv_cards_lock);
+
+ if (itv == NULL) {
+ /* Couldn't find a device registered
+ on that minor, shouldn't happen! */
+ IVTV_WARN("No ivtv device found on minor %d\n", minor);
+ return -ENXIO;
+ }
- /* Mute sound to avoid pop */
- ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl);
+ mutex_lock(&itv->serialize_lock);
+ if (ivtv_init_on_first_open(itv)) {
+ IVTV_ERR("Failed to initialize on minor %d\n", minor);
+ mutex_unlock(&itv->serialize_lock);
+ return -ENXIO;
+ }
+ res = ivtv_serialized_open(s, filp);
+ mutex_unlock(&itv->serialize_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)
{
- struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 0 };
-
- /* initialize or refresh input */
- if (atomic_read(&itv->capturing) == 0)
- ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
- ivtv_sleep_timeout(HZ / 10, 0);
-
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);
}
-
- /* Unmute */
- ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl);
IVTV_DEBUG_INFO("Unmute\n");
}
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h
index 74a1745fabbc..2c8d5186c9c3 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.h
+++ b/drivers/media/video/ivtv/ivtv-fileops.h
@@ -18,6 +18,9 @@
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 inode *inode, struct file *filp);
ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
@@ -42,3 +45,5 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type);
/* 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
index d4c910b782af..425eb1063904 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.c
+++ b/drivers/media/video/ivtv/ivtv-firmware.c
@@ -36,7 +36,7 @@
#define IVTV_CMD_SPU_STOP 0x00000001
#define IVTV_CMD_SDRAM_PRECHARGE_INIT 0x0000001A
#define IVTV_CMD_SDRAM_REFRESH_INIT 0x80000640
-#define IVTV_SDRAM_SLEEPTIME (60 * HZ / 100) /* 600 ms */
+#define IVTV_SDRAM_SLEEPTIME 600
#define IVTV_DECODE_INIT_MPEG_FILENAME "v4l-cx2341x-init.mpg"
#define IVTV_DECODE_INIT_MPEG_SIZE (152*1024)
@@ -56,14 +56,12 @@ retry:
volatile u32 __iomem *dst = (volatile u32 __iomem *)mem;
const u32 *src = (const u32 *)fw->data;
- /* temporarily allow 256 KB encoding firmwares as well for
- compatibility with blackbird cards */
- if (fw->size != size && fw->size != 256 * 1024) {
+ 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);
+ IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size);
release_firmware(fw);
retries--;
goto retry;
@@ -74,12 +72,12 @@ retry:
dst++;
src++;
}
+ IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size);
release_firmware(fw);
- IVTV_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
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");
+ 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;
}
@@ -91,7 +89,7 @@ void ivtv_halt_firmware(struct ivtv *itv)
if (itv->enc_mbox.mbox)
ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0);
- ivtv_sleep_timeout(HZ / 100, 0);
+ ivtv_msleep_timeout(10, 0);
itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL;
IVTV_DEBUG_INFO("Stopping VDM\n");
@@ -115,7 +113,7 @@ void ivtv_halt_firmware(struct ivtv *itv)
IVTV_DEBUG_INFO("Stopping SPU\n");
write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU);
- ivtv_sleep_timeout(HZ / 100, 0);
+ 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);
@@ -131,9 +129,8 @@ void ivtv_halt_firmware(struct ivtv *itv)
write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH);
}
- IVTV_DEBUG_INFO("Sleeping for %dms (600 recommended)\n",
- (int)(IVTV_SDRAM_SLEEPTIME * 1000 / HZ));
- ivtv_sleep_timeout(IVTV_SDRAM_SLEEPTIME, 0);
+ IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME);
+ ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0);
}
void ivtv_firmware_versions(struct ivtv *itv)
@@ -206,12 +203,12 @@ int ivtv_firmware_init(struct ivtv *itv)
/* start firmware */
write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU);
- ivtv_sleep_timeout(HZ / 10, 0);
+ 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_sleep_timeout(HZ / 10, 0);
+ ivtv_msleep_timeout(100, 0);
/* find mailboxes and ping firmware */
itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE);
@@ -266,7 +263,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
IVTV_DECODE_INIT_MPEG_FILENAME);
} else {
ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0);
- ivtv_sleep_timeout(HZ / 10, 0);
+ ivtv_msleep_timeout(100, 0);
}
ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
}
diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h
index 8b2ffe658905..041ba94e65bc 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.h
+++ b/drivers/media/video/ivtv/ivtv-firmware.h
@@ -19,7 +19,12 @@
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);
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index bc8f8ca2961f..132fb5f71366 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -115,40 +115,13 @@ void ivtv_reset_ir_gpio(struct ivtv *itv)
curout = (curout & ~0xF) | 1;
write_reg(curout, IVTV_REG_GPIO_OUT);
/* We could use something else for smaller time */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ 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);
}
-#ifdef HAVE_XC3028
-int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr)
-{
- int curdir, curout;
- struct ivtv *itv = (struct ivtv *) priv;
-
- if (itv->card->type != IVTV_CARD_PG600V2 || itv->options.tuner != TUNER_XCEIVE_XC3028)
- return -EINVAL;
- IVTV_INFO("Resetting tuner.\n");
- curout = read_reg(IVTV_REG_GPIO_OUT);
- curdir = read_reg(IVTV_REG_GPIO_DIR);
- curdir |= (1 << 12); /* GPIO bit 12 */
-
- curout &= ~(1 << 12);
- write_reg(curout, IVTV_REG_GPIO_OUT);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
-
- curout |= (1 << 12);
- write_reg(curout, IVTV_REG_GPIO_OUT);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
-
- return 0;
-}
-#endif
void ivtv_gpio_init(struct ivtv *itv)
{
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h
index c301d2a39346..964a265d91a9 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.h
+++ b/drivers/media/video/ivtv/ivtv-gpio.h
@@ -18,8 +18,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef IVTV_GPIO_H
+#define IVTV_GPIO_H
+
/* GPIO stuff */
void ivtv_gpio_init(struct ivtv *itv);
void ivtv_reset_ir_gpio(struct ivtv *itv);
-int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr);
+int ivtv_reset_tuner_gpio(void *dev, int cmd, int value);
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg);
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 50624c6a62a5..285fca676a69 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -109,6 +109,7 @@ static const u8 hw_driverids[] = {
I2C_DRIVERID_UPD64083,
I2C_DRIVERID_SAA717X,
I2C_DRIVERID_WM8739,
+ I2C_DRIVERID_VP27SMPX,
0 /* IVTV_HW_GPIO dummy driver ID */
};
@@ -128,6 +129,7 @@ static const char * const hw_drivernames[] = {
"upd64083",
"saa717x",
"wm8739",
+ "vp27smpx",
"gpio",
};
@@ -144,7 +146,7 @@ static int attach_inform(struct i2c_client *client)
}
}
if (i == I2C_CLIENTS_MAX) {
- IVTV_ERR("insufficient room for new I2C client!\n");
+ IVTV_ERR("Insufficient room for new I2C client\n");
}
return 0;
}
@@ -236,7 +238,7 @@ static int ivtv_ack(struct ivtv *itv)
int ret = 0;
if (ivtv_getscl(itv) == 1) {
- IVTV_DEBUG_I2C("SCL was high starting an ack\n");
+ 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");
@@ -263,7 +265,7 @@ static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
{
int i, bit;
- IVTV_DEBUG_I2C("write %x\n",byte);
+ 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)) {
@@ -318,7 +320,7 @@ static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
ivtv_scldelay(itv);
ivtv_setscl(itv, 0);
ivtv_scldelay(itv);
- IVTV_DEBUG_I2C("read %x\n",*byte);
+ IVTV_DEBUG_HI_I2C("read %x\n",*byte);
return 0;
}
@@ -330,7 +332,7 @@ static int ivtv_start(struct ivtv *itv)
sda = ivtv_getsda(itv);
if (sda != 1) {
- IVTV_DEBUG_I2C("SDA was low at start\n");
+ 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");
@@ -355,7 +357,7 @@ static int ivtv_stop(struct ivtv *itv)
int i;
if (ivtv_getscl(itv) != 0) {
- IVTV_DEBUG_I2C("SCL not low when stopping\n");
+ 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");
@@ -534,14 +536,13 @@ static struct i2c_adapter ivtv_i2c_adap_template = {
#endif
};
-static struct i2c_algo_bit_data ivtv_i2c_algo_template = {
- NULL, /* ?? */
- ivtv_setsda_old, /* setsda function */
- ivtv_setscl_old, /* " */
- ivtv_getsda_old, /* " */
- ivtv_getscl_old, /* " */
- 10, /* udelay */
- 200 /* timeout */
+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 = 5,
+ .timeout = 200,
};
static struct i2c_client ivtv_i2c_client_template = {
@@ -569,7 +570,7 @@ int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg
}
}
if (cmd != VIDIOC_G_CHIP_IDENT)
- IVTV_ERR("i2c addr 0x%02x not found for command 0x%x!\n", addr, cmd);
+ IVTV_ERR("i2c addr 0x%02x not found for command 0x%x\n", addr, cmd);
return -ENODEV;
}
@@ -640,7 +641,7 @@ int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg)
addr = ivtv_i2c_hw_addr(itv, hw);
if (addr < 0) {
- IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x!\n",
+ IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x\n",
hw, ivtv_i2c_hw_name(hw), cmd);
return addr;
}
@@ -655,7 +656,7 @@ int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg)
addr = ivtv_i2c_id_addr(itv, id);
if (addr < 0) {
if (cmd != VIDIOC_G_CHIP_IDENT)
- IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x!\n",
+ IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x\n",
id, ivtv_i2c_id_name(id), cmd);
return addr;
}
@@ -696,7 +697,7 @@ int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg)
void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg)
{
if (itv->i2c_adap.algo == NULL) {
- IVTV_ERR("adapter is not set");
+ IVTV_ERR("Adapter is not set");
return;
}
i2c_clients_command(&itv->i2c_adap, cmd, arg);
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h
index 5d210adb5c52..677c3292855e 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.h
+++ b/drivers/media/video/ivtv/ivtv-i2c.h
@@ -18,6 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef IVTV_I2C_H
+#define IVTV_I2C_H
+
int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg);
@@ -34,3 +37,5 @@ void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg);
/* init + register i2c algo-bit adapter */
int __devinit init_ivtv_i2c(struct ivtv *itv);
void __devexit 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
index 57af1762de1f..206eee7542db 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -25,8 +25,7 @@
#include "ivtv-queue.h"
#include "ivtv-fileops.h"
#include "ivtv-vbi.h"
-#include "ivtv-audio.h"
-#include "ivtv-video.h"
+#include "ivtv-routing.h"
#include "ivtv-streams.h"
#include "ivtv-yuv.h"
#include "ivtv-ioctl.h"
@@ -164,7 +163,7 @@ 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_color_key_state, itv->osd_color_key);
+ 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)
@@ -285,6 +284,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
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, vc->play.speed);
}
@@ -309,6 +312,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
if (atomic_read(&itv->decoding) > 0) {
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
(vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);
+ set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
}
break;
@@ -317,8 +321,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
if (try) break;
if (itv->output_mode != OUT_MPG)
return -EBUSY;
- if (atomic_read(&itv->decoding) > 0) {
- ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 0);
+ 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;
@@ -420,7 +426,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
- fmt->fmt.win.chromakey = itv->osd_color_key;
+ fmt->fmt.win.chromakey = itv->osd_chroma_key;
fmt->fmt.win.global_alpha = itv->osd_global_alpha;
break;
@@ -540,7 +546,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
if (set_fmt) {
- itv->osd_color_key = fmt->fmt.win.chromakey;
+ itv->osd_chroma_key = fmt->fmt.win.chromakey;
itv->osd_global_alpha = fmt->fmt.win.global_alpha;
ivtv_set_osd_alpha(itv);
}
@@ -577,9 +583,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
/* set raw VBI format */
if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- if (set_fmt && streamtype == IVTV_ENC_STREAM_TYPE_VBI &&
- itv->vbi.sliced_in->service_set &&
- atomic_read(&itv->capturing) > 0) {
+ if (set_fmt && atomic_read(&itv->capturing) > 0) {
return -EBUSY;
}
if (set_fmt) {
@@ -617,7 +621,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
return 0;
if (set == 0)
return -EINVAL;
- if (atomic_read(&itv->capturing) > 0 && itv->vbi.sliced_in->service_set == 0) {
+ if (atomic_read(&itv->capturing) > 0) {
return -EBUSY;
}
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
@@ -670,13 +674,21 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
case VIDIOC_INT_S_AUDIO_ROUTING: {
struct v4l2_routing *route = arg;
- ivtv_audio_set_route(itv, route);
+ ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
break;
}
- case VIDIOC_INT_RESET:
- ivtv_reset_ir_gpio(itv);
+ case VIDIOC_INT_RESET: {
+ u32 val = *(u32 *)arg;
+
+ if ((val == 0 && itv->options.newi2c) || (val & 0x01)) {
+ ivtv_reset_ir_gpio(itv);
+ }
+ if (val & 0x02) {
+ itv->video_dec_func(itv, cmd, 0);
+ }
break;
+ }
default:
return -EINVAL;
@@ -687,6 +699,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
{
struct ivtv_open_id *id = NULL;
+ u32 data[CX2341X_MBOX_MAX_DATA];
if (filp) id = (struct ivtv_open_id *)filp->private_data;
@@ -891,6 +904,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
IVTV_DEBUG_INFO("Input unchanged\n");
break;
}
+ if (atomic_read(&itv->capturing) > 0) {
+ return -EBUSY;
+ }
IVTV_DEBUG_INFO("Changing input from %d to %d\n",
itv->active_input, inp);
@@ -1092,14 +1108,21 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_ENC_INDEX: {
struct v4l2_enc_idx *idx = arg;
+ struct v4l2_enc_idx_entry *e = idx->entry;
+ int entries;
int i;
- idx->entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
+ entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
IVTV_MAX_PGM_INDEX;
- if (idx->entries > V4L2_ENC_IDX_ENTRIES)
- idx->entries = V4L2_ENC_IDX_ENTRIES;
- for (i = 0; i < idx->entries; i++) {
- idx->entry[i] = itv->pgm_info[(itv->pgm_info_read_idx + i) % 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;
break;
@@ -1113,12 +1136,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
memset(&enc->raw, 0, sizeof(enc->raw));
switch (enc->cmd) {
case V4L2_ENC_CMD_START:
+ IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
enc->flags = 0;
if (try)
return 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;
if (try)
return 0;
@@ -1126,6 +1151,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return 0;
case V4L2_ENC_CMD_PAUSE:
+ IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
enc->flags = 0;
if (try)
return 0;
@@ -1138,6 +1164,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
break;
case V4L2_ENC_CMD_RESUME:
+ IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
enc->flags = 0;
if (try)
return 0;
@@ -1149,6 +1176,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_unmute(itv);
break;
default:
+ IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
return -EINVAL;
}
break;
@@ -1156,22 +1184,58 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_FBUF: {
struct v4l2_framebuffer *fb = arg;
+ 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,
+ };
memset(fb, 0, sizeof(*fb));
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
- break;
+ return -EINVAL;
fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
- V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_GLOBAL_ALPHA;
- fb->fmt.pixelformat = itv->osd_pixelformat;
+ 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->base = (void *)itv->osd_video_pbase;
+ 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 (itv->osd_local_alpha_state)
- fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
- if (itv->osd_color_key_state)
- fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+ pixfmt &= 7;
+ /* no local alpha for RGB565 or unknown formats */
+ if (pixfmt == 1 || pixfmt > 4)
+ break;
+ /* 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;
+ }
break;
}
@@ -1179,10 +1243,21 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
struct v4l2_framebuffer *fb = arg;
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
- break;
+ 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) != 0;
- itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 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);
+ break;
+ }
+
+ case VIDIOC_OVERLAY: {
+ int *on = arg;
+
+ if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+ return -EINVAL;
+ ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);
break;
}
@@ -1194,6 +1269,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
int i;
IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
+ IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
if (itv->hw_flags & IVTV_HW_TVEEPROM) {
struct tveeprom tv;
@@ -1202,32 +1278,72 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
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\n", audin.name);
+ 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[] = {
+ static const char * const output_modes[5] = {
"None",
"MPEG Streaming",
"YUV Streaming",
"YUV Frames",
"Passthrough",
};
+ static const char * const audio_modes[5] = {
+ "Stereo",
+ "Left",
+ "Right",
+ "Mono",
+ "Swapped"
+ };
+ 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);
- IVTV_INFO("Audio Output: %s\n", audout.name);
+ IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
+ audio_modes[itv->audio_stereo_mode],
+ audio_modes[itv->audio_bilingual_mode]);
if (mode < 0 || mode > OUT_PASSTHROUGH)
mode = OUT_NONE;
- IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
+ 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",
+ IVTV_INFO("Tuner: %s\n",
test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
cx2341x_log_status(&itv->params, itv->name);
- IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
+ 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];
@@ -1237,7 +1353,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(s->buffers - s->q_free.buffers) * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
- IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
+ IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
break;
}
@@ -1273,6 +1389,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
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);
@@ -1381,9 +1499,9 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
int try = (cmd == VIDEO_TRY_COMMAND);
if (try)
- IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND\n");
+ IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);
else
- IVTV_DEBUG_IOCTL("VIDEO_COMMAND\n");
+ IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);
return ivtv_video_command(itv, id, vc, try);
}
@@ -1414,11 +1532,15 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
return 0;
if (nonblocking)
return -EAGAIN;
- /* wait for event */
+ /* 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 ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0)
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");
@@ -1455,6 +1577,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_AUDOUT:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_S_FBUF:
+ case VIDIOC_OVERLAY:
ret = v4l2_prio_check(&itv->prio, &id->prio);
if (ret)
return ret;
@@ -1508,6 +1631,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_TRY_ENCODER_CMD:
case VIDIOC_G_FBUF:
case VIDIOC_S_FBUF:
+ case VIDIOC_OVERLAY:
if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
v4l_printk_ioctl(cmd);
@@ -1548,12 +1672,9 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
return 0;
}
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
- struct ivtv *itv = id->itv;
-
/* Filter dvb ioctls that cannot be handled by video_usercopy */
switch (cmd) {
case VIDEO_SELECT_SOURCE:
@@ -1588,3 +1709,16 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
}
return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl);
}
+
+int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
+ struct ivtv *itv = id->itv;
+ int res;
+
+ mutex_lock(&itv->serialize_lock);
+ res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
+ mutex_unlock(&itv->serialize_lock);
+ return res;
+}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h
index cbccf7a9f65c..a03351b6853d 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.h
+++ b/drivers/media/video/ivtv/ivtv-ioctl.h
@@ -18,6 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef IVTV_IOCTL_H
+#define IVTV_IOCTL_H
+
u16 service2vbi(int type);
void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
u16 get_service_set(struct v4l2_sliced_vbi_format *fmt);
@@ -26,3 +29,5 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg);
void ivtv_set_osd_alpha(struct ivtv *itv);
int ivtv_set_speed(struct ivtv *itv, int speed);
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index ba98bf054f2e..fd1688e4757d 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -19,12 +19,9 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-firmware.h"
-#include "ivtv-fileops.h"
#include "ivtv-queue.h"
#include "ivtv-udma.h"
#include "ivtv-irq.h"
-#include "ivtv-ioctl.h"
#include "ivtv-mailbox.h"
#include "ivtv-vbi.h"
#include "ivtv-yuv.h"
@@ -45,10 +42,9 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
{
struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
struct ivtv_buffer *buf;
- struct list_head *p;
int i = 0;
- IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
+ IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
s->v4l2dev == NULL || !ivtv_use_pio(s)) {
itv->cur_pio_stream = -1;
@@ -56,22 +52,20 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
return;
}
- IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
- buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
- list_for_each(p, &s->q_dma.list) {
- struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
- u32 size = s->PIOarray[i].size & 0x3ffff;
+ 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->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
+ 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->PIOarray[i].src, size);
+ memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size);
}
- if (s->PIOarray[i].size & 0x80000000)
- break;
i++;
+ if (i == s->sg_processing_size)
+ break;
}
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
}
@@ -100,12 +94,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
{
struct ivtv *itv = s->itv;
struct ivtv_buffer *buf;
- struct list_head *p;
u32 bytes_needed = 0;
u32 offset, size;
u32 UVoffset = 0, UVsize = 0;
int skip_bufs = s->q_predma.buffers;
- int idx = s->SG_length;
+ int idx = s->sg_pending_size;
int rc;
/* sanity checks */
@@ -123,7 +116,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
case IVTV_ENC_STREAM_TYPE_MPG:
offset = data[1];
size = data[2];
- s->dma_pts = 0;
+ s->pending_pts = 0;
break;
case IVTV_ENC_STREAM_TYPE_YUV:
@@ -131,13 +124,13 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
size = data[2];
UVoffset = data[3];
UVsize = data[4];
- s->dma_pts = ((u64) data[5] << 32) | data[6];
+ 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->dma_pts = read_dec(offset - 8) |
+ s->pending_pts = read_dec(offset - 8) |
((u64)(read_dec(offset - 12)) << 32);
if (itv->has_cx23415)
offset += IVTV_DECODER_OFFSET;
@@ -150,13 +143,13 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
IVTV_DEBUG_INFO("VBI offset == 0\n");
return -1;
}
- s->dma_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32);
+ 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->dma_pts = 0;
+ s->pending_pts = 0;
offset += IVTV_DECODER_OFFSET;
break;
default:
@@ -165,17 +158,17 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
}
/* if this is the start of the DMA then fill in the magic cookie */
- if (s->SG_length == 0) {
+ 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->dma_backup = read_dec(offset - IVTV_DECODER_OFFSET);
+ s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET);
write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET);
}
else {
- s->dma_backup = read_enc(offset);
+ s->pending_backup = read_enc(offset);
write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset);
}
- s->dma_offset = offset;
+ s->pending_offset = offset;
}
bytes_needed = size;
@@ -187,7 +180,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
bytes_needed += UVsize;
}
- IVTV_DEBUG_DMA("%s %s: 0x%08x bytes at 0x%08x\n",
+ 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);
@@ -202,18 +195,17 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
}
s->buffers_stolen = rc;
- /* got the buffers, now fill in SGarray (DMA) */
+ /* 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(p, &s->q_predma.list) {
- struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
-
+ list_for_each_entry(buf, &s->q_predma.list, list) {
if (skip_bufs-- > 0)
continue;
- s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
- s->SGarray[idx].src = cpu_to_le32(offset);
- s->SGarray[idx].size = cpu_to_le32(s->buf_size);
+ s->sg_pending[idx].dst = buf->dma_handle;
+ s->sg_pending[idx].src = offset;
+ s->sg_pending[idx].size = s->buf_size;
buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
+ buf->dma_xfer_cnt = s->dma_xfer_cnt;
s->q_predma.bytesused += buf->bytesused;
size -= buf->bytesused;
@@ -229,7 +221,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
}
idx++;
}
- s->SG_length = idx;
+ s->sg_pending_size = idx;
return 0;
}
@@ -242,7 +234,7 @@ static void dma_post(struct ivtv_stream *s)
u32 *u32buf;
int x = 0;
- IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
+ 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);
@@ -251,7 +243,7 @@ static void dma_post(struct ivtv_stream *s)
/* Sync Buffer */
ivtv_buf_sync_for_cpu(s, buf);
- if (x == 0) {
+ if (x == 0 && ivtv_use_dma(s)) {
offset = s->dma_last_offset;
if (u32buf[offset / 4] != DMA_MAGIC_COOKIE)
{
@@ -286,14 +278,12 @@ static void dma_post(struct ivtv_stream *s)
/* 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)
- set_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags);
+ 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(p, &s->q_dma.list) {
- buf = list_entry(p, struct ivtv_buffer, list);
-
+ 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);
@@ -313,7 +303,6 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
{
struct ivtv *itv = s->itv;
struct ivtv_buffer *buf;
- struct list_head *p;
u32 y_size = itv->params.height * itv->params.width;
u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
int y_done = 0;
@@ -321,19 +310,16 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
unsigned long flags = 0;
int idx = 0;
- IVTV_DEBUG_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
- buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
- list_for_each(p, &s->q_predma.list) {
- struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
-
+ IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
+ 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 >= y_size) {
offset = uv_offset;
y_done = 1;
}
- s->SGarray[idx].src = cpu_to_le32(buf->dma_handle);
- s->SGarray[idx].dst = cpu_to_le32(offset);
- s->SGarray[idx].size = cpu_to_le32(buf->bytesused);
+ 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;
@@ -342,10 +328,7 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
ivtv_buf_sync_for_device(s, buf);
idx++;
}
- s->SG_length = idx;
-
- /* Mark last buffer size for Interrupt flag */
- s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
+ s->sg_pending_size = idx;
/* Sync Hardware SG List of buffers */
ivtv_stream_sync_for_device(s);
@@ -361,6 +344,34 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int 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);
+}
+
+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);
+}
+
/* start the encoder DMA */
static void ivtv_dma_enc_start(struct ivtv_stream *s)
{
@@ -368,14 +379,13 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
int i;
- IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+ 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->SGarray[s->SG_length - 1].size =
- cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
+ 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.
@@ -386,41 +396,42 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
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_length &&
- s->SG_length + s_vbi->SG_length <= s->buffers) {
+ 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->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
- for (i = 0; i < s_vbi->SG_length; i++) {
- s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
+ 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];
}
- itv->vbi.dma_offset = s_vbi->dma_offset;
- s_vbi->SG_length = 0;
+ 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_DMA("include DMA for %s\n", s->name);
+ IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name);
}
- /* Mark last buffer size for Interrupt flag */
- s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
+ s->dma_xfer_cnt++;
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_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)) {
- for (i = 0; i < s->SG_length; i++) {
- s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
- s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
- }
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 {
- /* 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_retries = 0;
+ ivtv_dma_enc_start_xfer(s);
set_bit(IVTV_F_I_DMA, &itv->i_flags);
itv->cur_dma_stream = s->type;
- itv->dma_timer.expires = jiffies + HZ / 10;
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
add_timer(&itv->dma_timer);
}
}
@@ -431,13 +442,18 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
- /* put SG Handle into register 0x0c */
- write_reg(s->SG_handle, IVTV_REG_DECDMAADDR);
- write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+ s->dma_xfer_cnt++;
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_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;
- itv->dma_timer.expires = jiffies + HZ / 10;
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
add_timer(&itv->dma_timer);
}
@@ -445,26 +461,43 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
{
struct ivtv_stream *s = NULL;
struct ivtv_buffer *buf;
- int hw_stream_type;
+ int hw_stream_type = 0;
- IVTV_DEBUG_IRQ("DEC DMA READ\n");
- del_timer(&itv->dma_timer);
- if (read_reg(IVTV_REG_DMASTATUS) & 0x14) {
- IVTV_DEBUG_WARN("DEC DMA ERROR %x\n", read_reg(IVTV_REG_DMASTATUS));
- write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+ IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
+ if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
+ del_timer(&itv->dma_timer);
+ return;
}
+
if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
- if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
- s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
- hw_stream_type = 2;
+ 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++;
+ }
}
- else {
- s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
- hw_stream_type = 0;
+ if (s->sg_processed < s->sg_processing_size) {
+ /* DMA next buffer */
+ ivtv_dma_dec_start_xfer(s);
+ return;
}
- IVTV_DEBUG_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused);
-
- ivtv_stream_sync_for_cpu(s);
+ 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
@@ -482,6 +515,7 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
}
wake_up(&s->waitq);
}
+ del_timer(&itv->dma_timer);
clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
clear_bit(IVTV_F_I_DMA, &itv->i_flags);
itv->cur_dma_stream = -1;
@@ -493,33 +527,46 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s;
- del_timer(&itv->dma_timer);
ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
- IVTV_DEBUG_IRQ("ENC DMA COMPLETE %x %d\n", data[0], data[1]);
- if (test_and_clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags))
- data[1] = 3;
- else if (data[1] > 2)
+ IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
+ if (itv->cur_dma_stream < 0) {
+ del_timer(&itv->dma_timer);
return;
- s = &itv->streams[ivtv_stream_map[data[1]]];
+ }
+ s = &itv->streams[itv->cur_dma_stream];
+ ivtv_stream_sync_for_cpu(s);
+
if (data[0] & 0x18) {
- IVTV_DEBUG_WARN("ENC DMA ERROR %x\n", data[0]);
+ 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);
- ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[1]);
+ 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;
}
- s->SG_length = 0;
+ del_timer(&itv->dma_timer);
clear_bit(IVTV_F_I_DMA, &itv->i_flags);
itv->cur_dma_stream = -1;
dma_post(s);
- ivtv_stream_sync_for_cpu(s);
if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
- u32 tmp;
-
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
- tmp = s->dma_offset;
- s->dma_offset = itv->vbi.dma_offset;
dma_post(s);
- s->dma_offset = tmp;
}
+ s->sg_processing_size = 0;
+ s->sg_processed = 0;
wake_up(&itv->dma_waitq);
}
@@ -532,9 +579,7 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
return;
}
s = &itv->streams[itv->cur_pio_stream];
- IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
- s->SG_length = 0;
- clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
+ 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);
@@ -546,13 +591,8 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
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)) {
- u32 tmp;
-
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
- tmp = s->dma_offset;
- s->dma_offset = itv->vbi.dma_offset;
dma_post(s);
- s->dma_offset = tmp;
}
wake_up(&itv->dma_waitq);
}
@@ -564,19 +604,23 @@ static void ivtv_irq_dma_err(struct ivtv *itv)
del_timer(&itv->dma_timer);
ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
- read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
+ read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
+ write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, 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];
/* retry */
- write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
ivtv_dma_dec_start(s);
else
ivtv_dma_enc_start(s);
return;
}
+ 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;
@@ -590,14 +634,13 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
/* Get DMA destination and size arguments from card */
ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data);
- IVTV_DEBUG_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]);
+ 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;
}
- clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
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);
@@ -610,7 +653,7 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s;
- IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
+ IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
/* If more than two VBI buffers are pending, then
@@ -621,20 +664,17 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
DMA the data. Since at most four VBI DMA buffers are available,
we just drop the old requests when there are already three
requests queued. */
- if (s->SG_length > 2) {
- struct list_head *p;
- list_for_each(p, &s->q_predma.list) {
- struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
+ if (s->sg_pending_size > 2) {
+ struct ivtv_buffer *buf;
+ list_for_each_entry(buf, &s->q_predma.list, list)
ivtv_buf_sync_for_cpu(s, buf);
- }
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
- s->SG_length = 0;
+ s->sg_pending_size = 0;
}
/* if we can append the data, and the MPEG stream isn't capturing,
then start a DMA request for just the VBI data. */
if (!stream_enc_dma_append(s, data) &&
!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
- set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
}
}
@@ -644,7 +684,7 @@ 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_IRQ("DEC VBI REINSERT\n");
+ 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);
@@ -669,7 +709,7 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
itv->dma_data_req_offset = data[1];
s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
}
- IVTV_DEBUG_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused,
+ 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);
@@ -695,23 +735,27 @@ static void ivtv_irq_vsync(struct ivtv *itv)
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
- if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) ||
- (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) {
+ if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 &&
+ ((itv->last_vsync_field & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) ||
+ (frame != (itv->last_vsync_field & 1) && !itv->yuv_info.frame_interlaced)) {
int next_dma_frame = last_dma_frame;
- if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.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) & 0x3;
- atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame);
+ if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) {
+ if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.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) & 0x3;
+ atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame);
+ itv->yuv_info.fields_lapsed = -1;
+ }
}
}
- if (frame != (itv->lastVsyncFrame & 1)) {
+ if (frame != (itv->last_vsync_field & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv);
- itv->lastVsyncFrame += 1;
+ 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);
@@ -728,7 +772,10 @@ static void ivtv_irq_vsync(struct ivtv *itv)
wake_up(&s->waitq);
/* Send VBI to saa7127 */
- if (frame) {
+ 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);
}
@@ -746,10 +793,12 @@ static void ivtv_irq_vsync(struct ivtv *itv)
set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
}
+
+ itv->yuv_info.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)
+#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)
{
@@ -774,7 +823,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
*/
if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
/* vsync is enabled, see if we're in a new field */
- if ((itv->lastVsyncFrame & 1) != (read_reg(0x28c0) & 1)) {
+ if ((itv->last_vsync_field & 1) != (read_reg(0x28c0) & 1)) {
/* New field, looks like we missed it */
IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16);
vsync_force = 1;
@@ -791,10 +840,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
/* Exclude interrupts noted below from the output, otherwise the log is flooded with
these messages */
if (combo & ~0xff6d0400)
- IVTV_DEBUG_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo);
+ IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo);
if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) {
- IVTV_DEBUG_IRQ("DEC DMA COMPLETE\n");
+ IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n");
}
if (combo & IVTV_IRQ_DMA_READ) {
@@ -828,7 +877,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
if (combo & IVTV_IRQ_ENC_EOS) {
IVTV_DEBUG_IRQ("ENC EOS\n");
set_bit(IVTV_F_I_EOS, &itv->i_flags);
- wake_up(&itv->cap_w);
+ wake_up(&itv->eos_waitq);
}
if (combo & IVTV_IRQ_DEC_DATA_REQ) {
@@ -850,8 +899,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
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;
+ 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))
@@ -868,8 +918,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
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;
+ 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))
@@ -880,8 +931,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
}
- if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
+ if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
+ }
spin_unlock(&itv->dma_reg_lock);
diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h
index a43348a30309..f879a5822e71 100644
--- a/drivers/media/video/ivtv/ivtv-irq.h
+++ b/drivers/media/video/ivtv/ivtv-irq.h
@@ -19,8 +19,35 @@
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 work_struct *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
index 6ae42a3b03cc..b05436da7136 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.c
+++ b/drivers/media/video/ivtv/ivtv-mailbox.c
@@ -37,8 +37,10 @@
#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 */
@@ -50,7 +52,7 @@ struct ivtv_api_info {
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_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),
@@ -77,11 +79,11 @@ static const struct ivtv_api_info api_info[256] = {
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_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_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),
@@ -95,14 +97,14 @@ static const struct ivtv_api_info api_info[256] = {
/* MPEG decoder API */
API_ENTRY(CX2341X_DEC_PING_FW, API_FAST_RESULT),
- API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_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_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),
@@ -175,9 +177,9 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
/* Sleep before a retry, if not atomic */
if (!(flags & API_NO_WAIT_MB)) {
- if (jiffies - then > retries * HZ / 100)
+ if (jiffies - then > msecs_to_jiffies(10*retries))
break;
- ivtv_sleep_timeout(HZ / 100, 0);
+ ivtv_msleep_timeout(10, 0);
}
}
return -ENODEV;
@@ -212,7 +214,7 @@ 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 = HZ;
+ int api_timeout = msecs_to_jiffies(1000);
int flags, mb, i;
unsigned long then;
@@ -223,11 +225,16 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
}
if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
- IVTV_ERR("Invalid API call: cmd = 0x%02x, args = %d\n", cmd, args);
+ IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
return -EINVAL;
}
- IVTV_DEBUG_API("API Call: %s\n", api_info[cmd].name);
+ 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++)
@@ -237,7 +244,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
data, then just return 0 as there is no need to issue this command again.
Just an optimization to prevent unnecessary use of mailboxes. */
if (itv->api_cache[cmd].last_jiffies &&
- jiffies - itv->api_cache[cmd].last_jiffies < HZ * 1800 &&
+ 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;
@@ -262,7 +269,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
}
if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
- api_timeout = HZ / 10;
+ api_timeout = msecs_to_jiffies(100);
mb = get_mailbox(itv, mbdata, flags);
if (mb < 0) {
@@ -284,6 +291,13 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
/* 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 (jiffies - then > api_timeout) {
IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
@@ -295,11 +309,12 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
if (flags & API_NO_WAIT_RES)
mdelay(1);
else
- ivtv_sleep_timeout(HZ / 100, 0);
+ ivtv_msleep_timeout(1, 0);
}
- if (jiffies - then > HZ / 10)
- IVTV_DEBUG_WARN("%s took %lu jiffies (%d per HZ)\n",
- api_info[cmd].name, jiffies - then, HZ);
+ if (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]);
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h
index 79b8aec14370..71a54eef8fc7 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.h
+++ b/drivers/media/video/ivtv/ivtv-mailbox.h
@@ -18,8 +18,16 @@
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 *mbox, int mb, 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, int cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index a04f9387f63d..39a216713244 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -20,9 +20,7 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-streams.h"
#include "ivtv-queue.h"
-#include "ivtv-mailbox.h"
int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes)
{
@@ -60,6 +58,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu
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);
@@ -87,7 +86,7 @@ struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
}
static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
- struct ivtv_queue *to, int clear, int full)
+ struct ivtv_queue *to, int clear)
{
struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list);
@@ -97,13 +96,7 @@ static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
from->bytesused -= buf->bytesused - buf->readpos;
/* special handling for q_free */
if (clear)
- buf->bytesused = buf->readpos = buf->b_flags = 0;
- else if (full) {
- /* special handling for stolen buffers, assume
- all bytes are used. */
- buf->bytesused = s->buf_size;
- buf->readpos = buf->b_flags = 0;
- }
+ 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;
@@ -112,7 +105,7 @@ static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
/* 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.
+ 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
@@ -133,7 +126,7 @@ int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_
int rc = 0;
int from_free = from == &s->q_free;
int to_free = to == &s->q_free;
- int bytes_available;
+ int bytes_available, bytes_steal;
spin_lock_irqsave(&s->qlock, flags);
if (needed_bytes == 0) {
@@ -142,32 +135,47 @@ int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_
}
bytes_available = from_free ? from->length : from->bytesused;
- bytes_available += steal ? steal->length : 0;
+ bytes_steal = (from_free && steal) ? steal->length : 0;
- if (bytes_available < needed_bytes) {
+ 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) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- ivtv_queue_move_buf(s, from, to, 1, 0);
+ ivtv_queue_move_buf(s, from, to, 1);
}
}
else {
u32 old_bytesused = to->bytesused;
while (to->bytesused - old_bytesused < needed_bytes) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- ivtv_queue_move_buf(s, from, to, to_free, rc);
+ ivtv_queue_move_buf(s, from, to, to_free);
}
}
spin_unlock_irqrestore(&s->qlock, flags);
@@ -185,7 +193,7 @@ void ivtv_flush_queues(struct ivtv_stream *s)
int ivtv_stream_alloc(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
- int SGsize = sizeof(struct ivtv_SG_element) * s->buffers;
+ int SGsize = sizeof(struct ivtv_sg_element) * s->buffers;
int i;
if (s->buffers == 0)
@@ -195,27 +203,33 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
s->dma != PCI_DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
- if (ivtv_might_use_pio(s)) {
- s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
- if (s->PIOarray == NULL) {
- IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
- return -ENOMEM;
- }
+ s->sg_pending = kzalloc(SGsize, GFP_KERNEL);
+ 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;
- /* Allocate DMA SG Arrays */
- s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
- if (s->SGarray == NULL) {
- IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
- if (ivtv_might_use_pio(s)) {
- kfree(s->PIOarray);
- s->PIOarray = NULL;
- }
+ s->sg_processing = kzalloc(SGsize, GFP_KERNEL);
+ 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);
+ 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;
}
- s->SG_length = 0;
if (ivtv_might_use_dma(s)) {
- s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
+ s->sg_handle = pci_map_single(itv->dev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma);
ivtv_stream_sync_for_cpu(s);
}
@@ -262,16 +276,19 @@ void ivtv_stream_free(struct ivtv_stream *s)
}
/* Free SG Array/Lists */
- if (s->SGarray != NULL) {
- if (s->SG_handle != IVTV_DMA_UNMAPPED) {
- pci_unmap_single(s->itv->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
- s->SG_handle = IVTV_DMA_UNMAPPED;
+ if (s->sg_dma != NULL) {
+ if (s->sg_handle != IVTV_DMA_UNMAPPED) {
+ pci_unmap_single(s->itv->dev, s->sg_handle,
+ sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+ s->sg_handle = IVTV_DMA_UNMAPPED;
}
- kfree(s->SGarray);
- kfree(s->PIOarray);
- s->PIOarray = NULL;
- s->SGarray = NULL;
- s->SG_length = 0;
+ 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
index 2ed8d548255d..7cfc0c9ab050 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -19,6 +19,9 @@
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 1
@@ -79,13 +82,15 @@ 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->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ pci_dma_sync_single_for_cpu(s->itv->dev, 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->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ pci_dma_sync_single_for_device(s->itv->dev, s->sg_handle,
+ sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
}
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-video.c b/drivers/media/video/ivtv/ivtv-routing.c
index 5858b197d510..398bd33033ed 100644
--- a/drivers/media/video/ivtv/ivtv-video.c
+++ b/drivers/media/video/ivtv/ivtv-routing.c
@@ -1,6 +1,7 @@
/*
- saa7127 interface functions
- Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl>
+ 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
@@ -18,73 +19,46 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-video.h"
#include "ivtv-i2c.h"
-#include "ivtv-gpio.h"
#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "ivtv-routing.h"
+
+#include <media/msp3400.h>
#include <media/upd64031a.h>
#include <media/upd64083.h>
-void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3,
- u8 vps4, u8 vps5)
+/* Selects the audio input and output according to the current
+ settings. */
+void ivtv_audio_set_io(struct ivtv *itv)
{
- 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[4] = vps1;
- data.data[10] = vps2;
- data.data[11] = vps3;
- data.data[12] = vps4;
- data.data[13] = vps5;
- ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
-}
+ struct v4l2_routing route;
+ u32 audio_input;
+ int mux_input;
-void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4)
-{
- 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] = cc1;
- data.data[1] = cc2;
- ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
- data.field = 1;
- data.line = (mode & 2) ? 21 : 0;
- data.data[0] = cc3;
- data.data[1] = cc4;
- ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
-}
+ /* Determine which input to use */
+ if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+ audio_input = itv->card->radio_input.audio_input;
+ mux_input = itv->card->radio_input.muxer_input;
+ } else {
+ audio_input = itv->card->audio_inputs[itv->audio_input].audio_input;
+ mux_input = itv->card->audio_inputs[itv->audio_input].muxer_input;
+ }
-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 & V4L2_STD_625_50) && !enabled) {
- enabled = 1;
- mode = 0x08; /* 4x3 full format */
+ /* handle muxer chips */
+ route.input = mux_input;
+ route.output = 0;
+ ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+
+ route.input = audio_input;
+ if (itv->card->hw_audio & IVTV_HW_MSP34XX) {
+ route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
}
- 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_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
+ ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route);
}
+/* Selects the video input and output according to the current
+ settings. */
void ivtv_video_set_io(struct ivtv *itv)
{
struct v4l2_routing route;
diff --git a/drivers/media/video/ivtv/ivtv-audio.h b/drivers/media/video/ivtv/ivtv-routing.h
index 9c42846d8124..c72a9731ca01 100644
--- a/drivers/media/video/ivtv/ivtv-audio.h
+++ b/drivers/media/video/ivtv/ivtv-routing.h
@@ -1,5 +1,5 @@
/*
- Audio-related ivtv functions.
+ 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>
@@ -18,6 +18,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-int ivtv_audio_set_io(struct ivtv *itv);
-void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route);
-void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq);
+#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
index 6af88ae9295f..fd135985e70f 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -35,16 +35,13 @@
#include "ivtv-driver.h"
#include "ivtv-fileops.h"
-#include "ivtv-i2c.h"
#include "ivtv-queue.h"
#include "ivtv-mailbox.h"
-#include "ivtv-audio.h"
-#include "ivtv-video.h"
-#include "ivtv-vbi.h"
#include "ivtv-ioctl.h"
#include "ivtv-irq.h"
-#include "ivtv-streams.h"
+#include "ivtv-yuv.h"
#include "ivtv-cards.h"
+#include "ivtv-streams.h"
static struct file_operations ivtv_v4l2_enc_fops = {
.owner = THIS_MODULE,
@@ -66,6 +63,13 @@ static struct file_operations ivtv_v4l2_dec_fops = {
.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;
@@ -75,7 +79,7 @@ static struct {
struct file_operations *fops;
} ivtv_stream_info[] = {
{ /* IVTV_ENC_STREAM_TYPE_MPG */
- "encoder MPEG",
+ "encoder MPG",
VFL_TYPE_GRABBER, 0,
PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
&ivtv_v4l2_enc_fops
@@ -93,7 +97,7 @@ static struct {
&ivtv_v4l2_enc_fops
},
{ /* IVTV_ENC_STREAM_TYPE_PCM */
- "encoder PCM audio",
+ "encoder PCM",
VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE,
&ivtv_v4l2_enc_fops
@@ -105,7 +109,7 @@ static struct {
&ivtv_v4l2_enc_fops
},
{ /* IVTV_DEC_STREAM_TYPE_MPG */
- "decoder MPEG",
+ "decoder MPG",
VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
&ivtv_v4l2_dec_fops
@@ -150,11 +154,11 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
s->dma = ivtv_stream_info[type].dma;
s->buf_size = itv->stream_buf_size[type];
if (s->buf_size)
- s->buffers = itv->options.megabytes[type] * 1024 * 1024 / 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->id = -1;
- s->SG_handle = IVTV_DMA_UNMAPPED;
+ s->sg_handle = IVTV_DMA_UNMAPPED;
ivtv_queue_init(&s->q_free);
ivtv_queue_init(&s->q_full);
ivtv_queue_init(&s->q_dma);
@@ -192,7 +196,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
/* User explicitly selected 0 buffers for these streams, so don't
create them. */
if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE &&
- itv->options.megabytes[type] == 0) {
+ itv->options.kilobytes[type] == 0) {
IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
return 0;
}
@@ -238,18 +242,18 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
switch (vfl_type) {
case VFL_TYPE_GRABBER:
- IVTV_INFO("Registered device video%d for %s (%d MB)\n",
- s->v4l2dev->minor, s->name, itv->options.megabytes[type]);
+ IVTV_INFO("Registered device video%d for %s (%d kB)\n",
+ s->v4l2dev->minor, s->name, itv->options.kilobytes[type]);
break;
case VFL_TYPE_RADIO:
IVTV_INFO("Registered device radio%d for %s\n",
s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
break;
case VFL_TYPE_VBI:
- if (itv->options.megabytes[type])
- IVTV_INFO("Registered device vbi%d for %s (%d MB)\n",
+ if (itv->options.kilobytes[type])
+ IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN,
- s->name, itv->options.megabytes[type]);
+ s->name, itv->options.kilobytes[type]);
else
IVTV_INFO("Registered device vbi%d for %s\n",
s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
@@ -314,28 +318,9 @@ static void ivtv_vbi_setup(struct ivtv *itv)
int lines;
int i;
- /* If Embed then streamtype must be Program */
- /* TODO: should we really do this? */
- if (0 && !raw && itv->vbi.insert_mpeg) {
- itv->params.stream_type = 0;
-
- /* assign stream type */
- ivtv_vapi(itv, CX2341X_ENC_SET_STREAM_TYPE, 1, itv->params.stream_type);
- }
-
/* Reset VBI */
ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
- if (itv->is_60hz) {
- itv->vbi.count = 12;
- itv->vbi.start[0] = 10;
- itv->vbi.start[1] = 273;
- } else { /* PAL/SECAM */
- itv->vbi.count = 18;
- itv->vbi.start[0] = 6;
- itv->vbi.start[1] = 318;
- }
-
/* setup VBI registers */
itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
@@ -409,8 +394,8 @@ static void ivtv_vbi_setup(struct ivtv *itv)
if (!itv->vbi.fpi)
itv->vbi.fpi = 1;
- IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d lines 0x%08x\n",
- itv->vbi.enc_start, data[1], itv->vbi.fpi, itv->digitizer);
+ 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. */
@@ -499,6 +484,8 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
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
@@ -524,7 +511,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, itv->digitizer, itv->digitizer);
+ 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) {
@@ -559,9 +553,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
clear_bit(IVTV_F_I_EOS, &itv->i_flags);
/* Initialize Digitizer for Capture */
+ itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0);
+ ivtv_msleep_timeout(300, 1);
ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
- ivtv_sleep_timeout(HZ / 10, 0);
+ itv->video_dec_func(itv, VIDIOC_STREAMON, 0);
}
/* begin_capture */
@@ -597,10 +592,6 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
- /* disable VBI signals, if the MPEG stream contains VBI data,
- then that data will be processed automatically for you. */
- ivtv_disable_vbi(itv);
-
/* 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);
@@ -633,7 +624,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
}
if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
itv->params.width, itv->params.height, itv->params.audio_properties)) {
- IVTV_DEBUG_WARN("COULDN'T INITIALIZE DECODER SOURCE\n");
+ IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
}
return 0;
}
@@ -674,10 +665,10 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
/* Zero out decoder counters */
- writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[0]);
- writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[1]);
- writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[2]);
- writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[3]);
+ 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]);
@@ -718,9 +709,7 @@ 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;
- unsigned long then;
int stopmode;
- u32 data[CX2341X_MBOX_MAX_DATA];
if (s->v4l2dev == NULL)
return -EINVAL;
@@ -762,32 +751,20 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
/* 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);
- /* only run these if we're shutting down the last cap */
- if (atomic_read(&itv->capturing) - 1 == 0) {
- /* 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);
- }
- }
-
- then = jiffies;
-
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;
- then = jiffies;
- add_wait_queue(&itv->cap_w, &wait);
+ 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) && jiffies < then + 2 * HZ) {
- schedule_timeout(HZ / 100);
+ while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
+ jiffies < then + msecs_to_jiffies (2000)) {
+ schedule_timeout(msecs_to_jiffies(10));
}
/* To convert jiffies to ms, we must multiply by 1000
@@ -806,33 +783,12 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&itv->cap_w, &wait);
+ remove_wait_queue(&itv->eos_waitq, &wait);
+ set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
}
- then = jiffies;
- /* Make sure DMA is complete */
- add_wait_queue(&s->waitq, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- do {
- /* check if DMA is pending */
- if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */
- (read_reg(IVTV_REG_DMASTATUS) & 0x02)) {
- /* Check for last DMA */
- ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0);
-
- if (data[0] == 1) {
- IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]);
- break;
- }
- } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) {
- break;
- }
-
- ivtv_sleep_timeout(HZ / 100, 1);
- } while (then + HZ * 2 > jiffies);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&s->waitq, &wait);
+ /* Handle any pending interrupts */
+ ivtv_msleep_timeout(100, 1);
}
atomic_dec(&itv->capturing);
@@ -849,6 +805,15 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
/* 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);
+ }
wake_up(&s->waitq);
@@ -887,7 +852,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
break;
tmp = data[3];
}
- if (ivtv_sleep_timeout(HZ/10, 1))
+ if (ivtv_msleep_timeout(100, 1))
break;
}
}
@@ -897,16 +862,12 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
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);
- if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
- /* disable VBI on TV-out */
- ivtv_disable_vbi(itv);
- }
-
/* decrement decoding */
atomic_dec(&itv->decoding);
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h
index 8597b75384a7..8f5f5b1c7c89 100644
--- a/drivers/media/video/ivtv/ivtv-streams.h
+++ b/drivers/media/video/ivtv/ivtv-streams.h
@@ -18,6 +18,9 @@
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);
void ivtv_streams_cleanup(struct ivtv *itv);
@@ -29,3 +32,5 @@ 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
index bd642e1aafc3..c4626d1cdf41 100644
--- a/drivers/media/video/ivtv/ivtv-udma.c
+++ b/drivers/media/video/ivtv/ivtv-udma.c
@@ -21,7 +21,6 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-streams.h"
#include "ivtv-udma.h"
void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size)
@@ -38,19 +37,37 @@ void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long
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++) {
- if (i == dma_page->page_count - 1) {
- dma->SGlist[map_offset].length = dma_page->tail;
+ unsigned int len = (i == dma_page->page_count - 1) ?
+ dma_page->tail : PAGE_SIZE - offset;
+
+ dma->SGlist[map_offset].length = len;
+ dma->SGlist[map_offset].offset = 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], KM_BOUNCE_READ) + offset;
+ memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
+ kunmap_atomic(src, KM_BOUNCE_READ);
+ local_irq_restore(flags);
+ dma->SGlist[map_offset].page = dma->bouncemap[map_offset];
}
else {
- dma->SGlist[map_offset].length = PAGE_SIZE - offset;
+ dma->SGlist[map_offset].page = dma->map[map_offset];
}
- dma->SGlist[map_offset].offset = offset;
- dma->SGlist[map_offset].page = dma->map[map_offset];
offset = 0;
map_offset++;
}
@@ -89,7 +106,7 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
{
struct ivtv_dma_page_info user_dma;
struct ivtv_user_dma *dma = &itv->udma;
- int err;
+ int i, err;
IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr);
@@ -123,7 +140,13 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
dma->page_count = user_dma.page_count;
/* Fill SG List with new values */
- ivtv_udma_fill_sg_list(dma, &user_dma, 0);
+ 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->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
@@ -166,6 +189,8 @@ void ivtv_udma_unmap(struct ivtv *itv)
void ivtv_udma_free(struct ivtv *itv)
{
+ int i;
+
/* Unmap SG Array */
if (itv->udma.SG_handle) {
pci_unmap_single(itv->dev, itv->udma.SG_handle,
@@ -176,6 +201,11 @@ void ivtv_udma_free(struct ivtv *itv)
if (itv->udma.SG_length) {
pci_unmap_sg(itv->dev, 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)
diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h
index e131bccedec0..df727e23be0a 100644
--- a/drivers/media/video/ivtv/ivtv-udma.h
+++ b/drivers/media/video/ivtv/ivtv-udma.h
@@ -18,6 +18,9 @@
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);
@@ -41,3 +44,5 @@ static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv)
pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, 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
index 3ba46e07ea1f..c151bcf5519a 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -18,10 +18,69 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-video.h"
-#include "ivtv-vbi.h"
+#include "ivtv-i2c.h"
#include "ivtv-ioctl.h"
#include "ivtv-queue.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_saa7127(itv, VIDIOC_INT_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_saa7127(itv, VIDIOC_INT_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_saa7127(itv, VIDIOC_INT_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 & 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_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
+}
static int odd_parity(u8 c)
{
@@ -32,62 +91,50 @@ static int odd_parity(u8 c)
return c & 1;
}
-static void passthrough_vbi_data(struct ivtv *itv, int cnt)
+void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt)
{
- int wss = 0;
- u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 };
- u8 vps[13];
+ struct vbi_info *vi = &itv->vbi;
+ struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
int found_cc = 0;
- int found_wss = 0;
- int found_vps = 0;
- int cc_pos = itv->vbi.cc_pos;
- int i;
+ size_t i;
for (i = 0; i < cnt; i++) {
- struct v4l2_sliced_vbi_data *d = itv->vbi.sliced_dec_data + i;
+ const struct v4l2_sliced_vbi_data *d = sliced + i;
if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
- found_cc = 1;
if (d->field) {
- cc[2] = d->data[0];
- cc[3] = d->data[1];
+ cc.even[0] = d->data[0];
+ cc.even[1] = d->data[1];
} else {
- cc[0] = d->data[0];
- cc[1] = d->data[1];
+ 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) {
- memcpy(vps, d->data, sizeof(vps));
- found_vps = 1;
+ 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) {
- wss = d->data[0] | d->data[1] << 8;
- found_wss = 1;
- }
- }
+ int wss = d->data[0] | d->data[1] << 8;
- if (itv->vbi.wss_found != found_wss || itv->vbi.wss != wss) {
- itv->vbi.wss = wss;
- itv->vbi.wss_found = found_wss;
- set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
- }
-
- if (found_vps || itv->vbi.vps_found) {
- itv->vbi.vps[0] = vps[2];
- itv->vbi.vps[1] = vps[8];
- itv->vbi.vps[2] = vps[9];
- itv->vbi.vps[3] = vps[10];
- itv->vbi.vps[4] = vps[11];
- itv->vbi.vps_found = found_vps;
- set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
+ if (vi->wss_payload != wss) {
+ vi->wss_payload = wss;
+ set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
+ }
+ }
}
-
- if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) {
- itv->vbi.cc_data_odd[cc_pos] = cc[0];
- itv->vbi.cc_data_odd[cc_pos + 1] = cc[1];
- itv->vbi.cc_data_even[cc_pos] = cc[2];
- itv->vbi.cc_data_even[cc_pos + 1] = cc[3];
- itv->vbi.cc_pos = cc_pos + 2;
+ if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) {
+ vi->cc_payload[vi->cc_payload_idx++] = cc;
set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
}
}
@@ -163,8 +210,8 @@ static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
linemask[1] = 0xf;
p += 4;
} else {
- /* unknown VBI data stream */
- return 0;
+ /* unknown VBI data, convert to empty VBI frame */
+ linemask[0] = linemask[1] = 0;
}
for (i = 0; i < 36; i++) {
int err = 0;
@@ -211,78 +258,6 @@ static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
return line * sizeof(itv->vbi.sliced_dec_data[0]);
}
-ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count)
-{
- /* Should be a __user pointer, but sparse doesn't parse this bit correctly. */
- const struct v4l2_sliced_vbi_data *p = (const struct v4l2_sliced_vbi_data *)ubuf;
- u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 };
- int found_cc = 0;
- int cc_pos = itv->vbi.cc_pos;
-
- if (itv->vbi.service_set_out == 0)
- return -EPERM;
-
- while (count >= sizeof(struct v4l2_sliced_vbi_data)) {
- switch (p->id) {
- case V4L2_SLICED_CAPTION_525:
- if (p->id == V4L2_SLICED_CAPTION_525 &&
- p->line == 21 &&
- (itv->vbi.service_set_out &
- V4L2_SLICED_CAPTION_525) == 0) {
- break;
- }
- found_cc = 1;
- if (p->field) {
- cc[2] = p->data[0];
- cc[3] = p->data[1];
- } else {
- cc[0] = p->data[0];
- cc[1] = p->data[1];
- }
- break;
-
- case V4L2_SLICED_VPS:
- if (p->line == 16 && p->field == 0 &&
- (itv->vbi.service_set_out & V4L2_SLICED_VPS)) {
- itv->vbi.vps[0] = p->data[2];
- itv->vbi.vps[1] = p->data[8];
- itv->vbi.vps[2] = p->data[9];
- itv->vbi.vps[3] = p->data[10];
- itv->vbi.vps[4] = p->data[11];
- itv->vbi.vps_found = 1;
- set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
- }
- break;
-
- case V4L2_SLICED_WSS_625:
- if (p->line == 23 && p->field == 0 &&
- (itv->vbi.service_set_out & V4L2_SLICED_WSS_625)) {
- /* No lock needed for WSS */
- itv->vbi.wss = p->data[0] | (p->data[1] << 8);
- itv->vbi.wss_found = 1;
- set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
- }
- break;
-
- default:
- break;
- }
- count -= sizeof(*p);
- p++;
- }
-
- if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) {
- itv->vbi.cc_data_odd[cc_pos] = cc[0];
- itv->vbi.cc_data_odd[cc_pos + 1] = cc[1];
- itv->vbi.cc_data_even[cc_pos] = cc[2];
- itv->vbi.cc_data_even[cc_pos + 1] = cc[3];
- itv->vbi.cc_pos = cc_pos + 2;
- set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
- }
-
- return (const char __user *)p - ubuf;
-}
-
/* Compress raw VBI format, removes leading SAV codes and surplus space after the
field.
Returns new compressed size. */
@@ -431,108 +406,95 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
buf->bytesused = cnt;
- passthrough_vbi_data(itv, cnt / sizeof(itv->vbi.sliced_dec_data[0]));
+ ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
+ cnt / sizeof(itv->vbi.sliced_dec_data[0]));
return;
}
}
-void ivtv_disable_vbi(struct ivtv *itv)
+void ivtv_disable_cc(struct ivtv *itv)
{
- clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
- clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
+ struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+
clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
- ivtv_set_wss(itv, 0, 0);
- ivtv_set_cc(itv, 0, 0, 0, 0, 0);
- ivtv_set_vps(itv, 0, 0, 0, 0, 0, 0);
- itv->vbi.vps_found = itv->vbi.wss_found = 0;
- itv->vbi.wss = 0;
- itv->vbi.cc_pos = 0;
+ 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) {
- /* Note: currently only the saa7115 is used in a PVR350,
- so these commands are for now saa7115 specific. */
if (itv->is_50hz) {
data.id = V4L2_SLICED_WSS_625;
data.field = 0;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
ivtv_set_wss(itv, 1, data.data[0] & 0xf);
- itv->vbi.wss_no_update = 0;
- } else if (itv->vbi.wss_no_update == 4) {
+ vi->wss_missing_cnt = 0;
+ } else if (vi->wss_missing_cnt == 4) {
ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */
} else {
- itv->vbi.wss_no_update++;
+ vi->wss_missing_cnt++;
}
}
else {
- u8 c1 = 0, c2 = 0, c3 = 0, c4 = 0;
int mode = 0;
data.id = V4L2_SLICED_CAPTION_525;
data.field = 0;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
mode |= 1;
- c1 = data.data[0];
- c2 = data.data[1];
+ cc.odd[0] = data.data[0];
+ cc.odd[1] = data.data[1];
}
data.field = 1;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
mode |= 2;
- c3 = data.data[0];
- c4 = data.data[1];
+ cc.even[0] = data.data[0];
+ cc.even[1] = data.data[1];
}
if (mode) {
- itv->vbi.cc_no_update = 0;
- ivtv_set_cc(itv, mode, c1, c2, c3, c4);
- } else if (itv->vbi.cc_no_update == 4) {
- ivtv_set_cc(itv, 0, 0, 0, 0, 0);
+ 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 {
- itv->vbi.cc_no_update++;
+ vi->cc_missing_cnt++;
}
}
return;
}
if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
- /* Lock */
- ivtv_set_wss(itv, itv->vbi.wss_found, itv->vbi.wss & 0xf);
+ ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
}
- if (test_and_clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
- if (itv->vbi.cc_pos == 0) {
- ivtv_set_cc(itv, 3, 0x80, 0x80, 0x80, 0x80);
+ 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 (itv->vbi.cc_pos) {
- u8 cc_odd0 = itv->vbi.cc_data_odd[0];
- u8 cc_odd1 = itv->vbi.cc_data_odd[1];
- u8 cc_even0 = itv->vbi.cc_data_even[0];
- u8 cc_even1 = itv->vbi.cc_data_even[1];
-
- memcpy(itv->vbi.cc_data_odd, itv->vbi.cc_data_odd + 2, sizeof(itv->vbi.cc_data_odd) - 2);
- memcpy(itv->vbi.cc_data_even, itv->vbi.cc_data_even + 2, sizeof(itv->vbi.cc_data_even) - 2);
- itv->vbi.cc_pos -= 2;
- if (itv->vbi.cc_pos && cc_odd0 == 0x80 && cc_odd1 == 0x80)
+ 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;
- /* Send to Saa7127 */
- ivtv_set_cc(itv, 3, cc_odd0, cc_odd1, cc_even0, cc_even1);
- if (itv->vbi.cc_pos == 0)
- set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+ ivtv_set_cc(itv, 3, &cc);
break;
}
}
if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
- /* Lock */
- ivtv_set_vps(itv, itv->vbi.vps_found,
- itv->vbi.vps[0], itv->vbi.vps[1],
- itv->vbi.vps[2], itv->vbi.vps[3], itv->vbi.vps[4]);
+ ivtv_set_vps(itv, 1);
}
}
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
index ec211b49702c..970567b9194d 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.h
+++ b/drivers/media/video/ivtv/ivtv-vbi.h
@@ -17,10 +17,15 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count);
+#ifndef IVTV_VBI_H
+#define IVTV_VBI_H
+
+void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *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_vbi(struct ivtv *itv);
+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
index 85530a3cd369..d050de2a7229 100644
--- a/drivers/media/video/ivtv/ivtv-version.h
+++ b/drivers/media/video/ivtv/ivtv-version.h
@@ -17,10 +17,15 @@
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_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 0
+#define IVTV_DRIVER_VERSION_MINOR 1
#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
#define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
+
+#endif
diff --git a/drivers/media/video/ivtv/ivtv-video.h b/drivers/media/video/ivtv/ivtv-video.h
deleted file mode 100644
index c8ade5d3c413..000000000000
--- a/drivers/media/video/ivtv/ivtv-video.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- saa7127 interface 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
- */
-
-void ivtv_set_wss(struct ivtv *itv, int enabled, int mode);
-void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4);
-void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3,
- u8 vps4, u8 vps5);
-void ivtv_video_set_io(struct ivtv *itv);
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index bcea09542e5a..e2288f224ab6 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -19,11 +19,16 @@
*/
#include "ivtv-driver.h"
-#include "ivtv-queue.h"
#include "ivtv-udma.h"
-#include "ivtv-irq.h"
#include "ivtv-yuv.h"
+const u32 yuv_offset[4] = {
+ IVTV_YUV_BUFFER_OFFSET,
+ IVTV_YUV_BUFFER_OFFSET_1,
+ IVTV_YUV_BUFFER_OFFSET_2,
+ IVTV_YUV_BUFFER_OFFSET_3
+};
+
static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
struct ivtv_dma_frame *args)
{
@@ -37,7 +42,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
int y_decode_height, uv_decode_height, y_size;
int frame = atomic_read(&itv->yuv_info.next_fill_frame);
- y_buffer_offset = IVTV_DEC_MEM_START + yuv_offset[frame];
+ 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 = args->src.height + args->src.top;
@@ -83,7 +88,14 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
}
/* Fill & map SG List */
- ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0));
+ 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->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
/* Fill SG Array with new values */
@@ -94,7 +106,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
if (itv->yuv_info.blanking_dmaptr) {
dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr);
- dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DEC_MEM_START + yuv_offset[frame]);
+ dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
dma->SG_length++;
}
}
@@ -612,7 +624,6 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi
itv->yuv_info.v_filter_2 = v_filter_2;
}
- itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced;
}
/* Modify the supplied coordinate information to fit the visible osd area */
@@ -799,6 +810,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo
(itv->yuv_info.old_frame_info.src_y != window->src_y) ||
(itv->yuv_info.old_frame_info.pan_y != window->pan_y) ||
(itv->yuv_info.old_frame_info.vis_h != window->vis_h) ||
+ (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) ||
(itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
(itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
@@ -898,8 +910,21 @@ static void ivtv_yuv_init (struct ivtv *itv)
itv->yuv_info.decode_height = 480;
/* If no visible size set, assume full size */
- if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
- if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
+ if (!itv->yuv_info.osd_vis_w)
+ itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
+
+ if (!itv->yuv_info.osd_vis_h) {
+ itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
+ } else {
+ /* If output video standard has changed, requested height may
+ not be legal */
+ if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) {
+ IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
+ itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset,
+ itv->yuv_info.decode_height);
+ itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
+ }
+ }
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL);
@@ -927,6 +952,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
int rc = 0;
int got_sig = 0;
int frame, next_fill_frame, last_fill_frame;
+ int register_update = 0;
IVTV_DEBUG_INFO("yuv_prep_frame\n");
@@ -940,6 +966,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
/* Buffers are full - Overwrite the last frame */
next_fill_frame = frame;
frame = (frame - 1) & 3;
+ register_update = itv->yuv_info.new_frame_info[frame].update;
}
/* Take a snapshot of the yuv coordinate information */
@@ -955,6 +982,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
itv->yuv_info.new_frame_info[frame].tru_w = args->src_width;
itv->yuv_info.new_frame_info[frame].tru_h = args->src_height;
+ /* Snapshot field order */
+ itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field;
+
/* Are we going to offset the Y plane */
if (args->src.height + args->src.top < 512-16)
itv->yuv_info.new_frame_info[frame].offset_y = 1;
@@ -970,6 +1000,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
itv->yuv_info.new_frame_info[frame].update = 0;
itv->yuv_info.new_frame_info[frame].interlaced_y = 0;
itv->yuv_info.new_frame_info[frame].interlaced_uv = 0;
+ itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode;
if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame],
sizeof (itv->yuv_info.new_frame_info[frame]))) {
@@ -978,6 +1009,14 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
}
+ itv->yuv_info.new_frame_info[frame].update |= register_update;
+
+ /* Should this frame be delayed ? */
+ if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3])
+ itv->yuv_info.field_delay[frame] = 1;
+ else
+ itv->yuv_info.field_delay[frame] = 0;
+
/* DMA the frame */
mutex_lock(&itv->udma.lock);
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h
index 88972d3f77c4..f7215eeca018 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/drivers/media/video/ivtv/ivtv-yuv.h
@@ -18,7 +18,28 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef IVTV_YUV_H
+#define IVTV_YUV_H
+
+/* Buffers on hardware offsets */
+#define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */
+#define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */
+#define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */
+#define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */
+#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
+
+extern const u32 yuv_offset[4];
+
int ivtv_yuv_filter_check(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
new file mode 100644
index 000000000000..9684048fe56c
--- /dev/null
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -0,0 +1,1190 @@
+/*
+ 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>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "ivtv-driver.h"
+#include "ivtv-udma.h"
+#include "ivtv-mailbox.h"
+
+/* card parameters */
+static int ivtvfb_card_id = -1;
+static int ivtvfb_debug = 0;
+static int osd_laced;
+static int osd_compat;
+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_compat, 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)");
+
+MODULE_PARM_DESC(osd_compat,
+ "Compatibility mode - Display size is locked (use for old X drivers)\n"
+ "\t\t\t0=off\n"
+ "\t\t\t1=on\n"
+ "\t\t\tdefault off");
+
+/* 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->num , ## 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->num , ## args)
+#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args)
+#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## 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
+
+ /* Current osd mode */
+ int osd_mode;
+
+ /* 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;
+};
+
+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;
+
+ 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_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 ret = 0;
+ 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 (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) {
+ /* 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 ret;
+}
+
+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 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;
+
+ vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
+ FB_VBLANK_HAVE_VSYNC;
+ trace = read_reg(0x028c0) >> 16;
+ if (itv->is_50hz && trace > 312) trace -= 312;
+ else if (itv->is_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");
+ }
+
+ /* Change osd mode if needed.
+ Although rare, things can go wrong. The extra mode
+ change seems to help... */
+ if (osd_mode != -1 && osd_mode != oi->osd_mode) {
+ ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
+ ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
+ oi->osd_mode = 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);
+
+ /* Force update of yuv registers */
+ itv->yuv_info.yuv_forced_update = 1;
+
+ 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));
+ strcpy(fix->id, "cx23415 TV out");
+ 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_50hz) {
+ pixclock = 84316;
+ hlimit = 776;
+ vlimit = 591;
+ osd_height_limit = 576;
+ }
+ else {
+ pixclock = 83926;
+ hlimit = 776;
+ vlimit = 495;
+ osd_height_limit = 480;
+ }
+
+ /* Check the bits per pixel */
+ if (osd_compat) {
+ if (var->bits_per_pixel != 32) {
+ IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
+ return -EINVAL;
+ }
+ }
+
+ 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 (osd_compat) {
+ if (var->xres != oi->ivtvfb_defined.xres ||
+ var->yres != oi->ivtvfb_defined.yres ||
+ var->xres_virtual != oi->ivtvfb_defined.xres_virtual ||
+ var->yres_virtual != oi->ivtvfb_defined.yres_virtual) {
+ IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d (virtual %dx%d)\n",
+ var->xres, var->yres, var->xres_virtual, var->yres_virtual);
+ return -EINVAL;
+ }
+ }
+ else {
+ 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_50hz ? 577 : 481)) {
+ var->upper_margin = 1 + (((itv->is_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;
+
+ 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;
+
+ osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*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;
+ 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);
+ 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);
+ 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);
+ break;
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+ break;
+ }
+ return 0;
+}
+
+static struct fb_ops ivtvfb_ops = {
+ .owner = THIS_MODULE,
+ .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,
+};
+
+/* 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_compat) osd_depth = 32;
+ 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;
+
+ /* Invalidate current osd mode to force a mode switch later */
+ oi->osd_mode = -1;
+
+ /* 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;
+
+ if (osd_xres)
+ start_window.width = osd_xres;
+ else
+ start_window.width = osd_compat ? 720: 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_50hz ? 576 : 480;
+
+ if (osd_yres > max_height)
+ osd_yres = max_height;
+
+ if (osd_yres)
+ start_window.height = osd_yres;
+ else
+ start_window.height = osd_compat ? max_height : (itv->is_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);
+
+ if (!oi->ivtvfb_info.pseudo_palette) {
+ IVTVFB_ERR("abort, unable to alloc pseudo pallete\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);
+
+ ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
+
+ /* 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);
+ if (itv->osd_info == 0) {
+ IVTVFB_ERR("Failed to allocate memory for osd_info\n");
+ return -ENOMEM;
+ }
+
+ /* Find & setup the OSD buffer */
+ if ((rc = ivtvfb_init_io(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);
+
+ /* Note if we're running in compatibility mode */
+ if (osd_compat)
+ IVTVFB_INFO("Running in compatibility mode. Display resize & mode change disabled\n");
+
+ /* Allocate DMA */
+ ivtv_udma_alloc(itv);
+ return 0;
+
+}
+
+static int __init ivtvfb_init(void)
+{
+ struct ivtv *itv;
+ int i, registered = 0;
+
+ 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;
+ }
+
+ /* Locate & initialise all cards supporting an OSD. */
+ for (i = 0; i < ivtv_cards_active; i++) {
+ if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)
+ continue;
+ itv = ivtv_cards[i];
+ if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ if (ivtvfb_init_card(itv) == 0) {
+ IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
+ registered++;
+ }
+ }
+ }
+ if (!registered) {
+ printk(KERN_ERR "ivtvfb: no cards found");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void ivtvfb_cleanup(void)
+{
+ struct ivtv *itv;
+ int i;
+
+ printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
+
+ for (i = 0; i < ivtv_cards_active; i++) {
+ itv = ivtv_cards[i];
+ if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
+ IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
+ ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
+ unregister_framebuffer(&itv->osd_info->ivtvfb_info);
+ ivtvfb_release_buffers(itv);
+ itv->osd_video_pbase = 0;
+ }
+ }
+}
+
+module_init(ivtvfb_init);
+module_exit(ivtvfb_cleanup);
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 3bb7d6634862..c0c87e06259b 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -157,8 +157,7 @@ static int msp_read(struct i2c_client *client, int dev, int addr)
break;
v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
}
if (err == 3) {
v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
@@ -197,8 +196,7 @@ static int msp_write(struct i2c_client *client, int dev, int addr, int val)
break;
v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
+ schedule_timeout_interruptible(msecs_to_jiffies(10));
}
if (err == 3) {
v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
@@ -246,17 +244,17 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val)
* ----------------------------------------------------------------------- */
static int scarts[3][9] = {
- /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */
+ /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */
/* SCART DSP Input select */
- { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 },
+ { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 },
/* SCART1 Output select */
- { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
+ { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
/* SCART2 Output select */
- { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
+ { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
};
static char *scart_names[] = {
- "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
+ "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
};
void msp_set_scart(struct i2c_client *client, int in, int out)
@@ -814,10 +812,10 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
int msp_product, msp_prod_hi, msp_prod_lo;
int msp_rom;
- client = kmalloc(sizeof(*client), GFP_KERNEL);
- if (client == NULL)
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client)
return -ENOMEM;
- memset(client, 0, sizeof(*client));
+
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver;
@@ -829,14 +827,14 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
return 0;
}
- state = kmalloc(sizeof(*state), GFP_KERNEL);
- if (state == NULL) {
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state) {
kfree(client);
return -ENOMEM;
}
+
i2c_set_clientdata(client, state);
- memset(state, 0, sizeof(*state));
state->v4l2_std = V4L2_STD_NTSC;
state->audmode = V4L2_TUNER_MODE_STEREO;
state->volume = 58880; /* 0db gain */
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index c7c9f3f8715c..f49d1f4c40db 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -1,13 +1,20 @@
/*
- *
* i2c tv tuner chip device driver
* controls microtune tuners, mt2032 + mt2050 at the moment.
+ *
+ * This "mt20xx" module was split apart from the original "tuner" module.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
-#include <linux/moduleparam.h>
-#include <media/tuner.h>
+#include "tuner-i2c.h"
+#include "mt20xx.h"
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+#define PREFIX "mt20xx "
/* ---------------------------------------------------------------------- */
@@ -20,9 +27,6 @@ module_param(tv_antenna, int, 0644);
static unsigned int radio_antenna = 0;
module_param(radio_antenna, int, 0644);
-/* from tuner-core.c */
-extern int tuner_debug;
-
/* ---------------------------------------------------------------------- */
#define MT2032 0x04
@@ -37,11 +41,35 @@ static char *microtune_part[] = {
[ MT2050 ] = "MT2050",
};
+struct microtune_priv {
+ struct tuner_i2c_props i2c_props;
+
+ unsigned int xogc;
+ //unsigned int radio_if2;
+
+ u32 frequency;
+};
+
+static int microtune_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct microtune_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
// IsSpurInBand()?
-static int mt2032_spurcheck(struct i2c_client *c,
+static int mt2032_spurcheck(struct dvb_frontend *fe,
int f1, int f2, int spectrum_from,int spectrum_to)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
int n1=1,n2,f;
f1=f1/1000; //scale to kHz to avoid 32bit overflows
@@ -69,7 +97,7 @@ static int mt2032_spurcheck(struct i2c_client *c,
return 1;
}
-static int mt2032_compute_freq(struct i2c_client *c,
+static int mt2032_compute_freq(struct dvb_frontend *fe,
unsigned int rfin,
unsigned int if1, unsigned int if2,
unsigned int spectrum_from,
@@ -78,7 +106,7 @@ static int mt2032_compute_freq(struct i2c_client *c,
int *ret_sel,
unsigned int xogc) //all in Hz
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
@@ -128,7 +156,7 @@ static int mt2032_compute_freq(struct i2c_client *c,
return(-1);
}
- mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to);
+ mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to);
// should recalculate lo1 (one step up/down)
// set up MT2032 register map for transfer over i2c
@@ -152,16 +180,16 @@ static int mt2032_compute_freq(struct i2c_client *c,
return 0;
}
-static int mt2032_check_lo_lock(struct i2c_client *c)
+static int mt2032_check_lo_lock(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
int try,lock=0;
unsigned char buf[2];
for(try=0;try<10;try++) {
buf[0]=0x0e;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
lock=buf[0] &0x06;
@@ -174,15 +202,15 @@ static int mt2032_check_lo_lock(struct i2c_client *c)
return lock;
}
-static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
int tad1;
buf[0]=0x0f;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
tad1=buf[0]&0x07;
@@ -205,57 +233,57 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
buf[0]=0x0f;
buf[1]=sel;
- i2c_master_send(c,buf,2);
- lock=mt2032_check_lo_lock(c);
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+ lock=mt2032_check_lo_lock(fe);
return lock;
}
-static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
+static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
unsigned int if1, unsigned int if2,
unsigned int from, unsigned int to)
{
unsigned char buf[21];
int lint_try,ret,sel,lock=0;
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
rfin,if1,if2,from,to);
buf[0]=0;
- ret=i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,21);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
buf[0]=0;
- ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+ ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
if (ret<0)
return;
// send only the relevant registers per Rev. 1.2
buf[0]=0;
- ret=i2c_master_send(c,buf,4);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
buf[5]=5;
- ret=i2c_master_send(c,buf+5,4);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
buf[11]=11;
- ret=i2c_master_send(c,buf+11,3);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
if(ret!=3)
tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
// wait for PLLs to lock (per manual), retry LINT if not.
for(lint_try=0; lint_try<2; lint_try++) {
- lock=mt2032_check_lo_lock(c);
+ lock=mt2032_check_lo_lock(fe);
if(optimize_vco)
- lock=mt2032_optimize_vco(c,sel,lock);
+ lock=mt2032_optimize_vco(fe,sel,lock);
if(lock==6) break;
tuner_dbg("mt2032: re-init PLLs by LINT\n");
buf[0]=7;
- buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
- i2c_master_send(c,buf,2);
+ buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
mdelay(10);
- buf[1]=8+t->xogc;
- i2c_master_send(c,buf,2);
+ buf[1]=8+priv->xogc;
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
}
if (lock!=6)
@@ -263,19 +291,19 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
buf[0]=2;
buf[1]=0x20; // LOGC for optimal phase noise
- ret=i2c_master_send(c,buf,2);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
if (ret!=2)
tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
}
-static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
+static int mt2032_set_tv_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
int if2,from,to;
// signal bandwidth and picture carrier
- if (t->std & V4L2_STD_525_60) {
+ if (params->std & V4L2_STD_525_60) {
// NTSC
from = 40750*1000;
to = 46750*1000;
@@ -287,24 +315,64 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
if2 = 38900*1000;
}
- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+ mt2032_set_if_freq(fe, params->frequency*62500,
1090*1000*1000, if2, from, to);
+
+ return 0;
}
-static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
+static int mt2032_set_radio_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
- int if2 = t->radio_if2;
+ struct microtune_priv *priv = fe->tuner_priv;
+ int if2;
+
+ if (params->std & V4L2_STD_525_60) {
+ tuner_dbg("pinnacle ntsc\n");
+ if2 = 41300 * 1000;
+ } else {
+ tuner_dbg("pinnacle pal\n");
+ if2 = 33300 * 1000;
+ }
// per Manual for FM tuning: first if center freq. 1085 MHz
- mt2032_set_if_freq(c, freq * 1000 / 16,
- 1085*1000*1000,if2,if2,if2);
+ mt2032_set_if_freq(fe, params->frequency * 125 / 2,
+ 1085*1000*1000,if2,if2,if2);
+
+ return 0;
+}
+
+static int mt2032_set_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+{
+ struct microtune_priv *priv = fe->tuner_priv;
+ int ret = -EINVAL;
+
+ switch (params->mode) {
+ case V4L2_TUNER_RADIO:
+ ret = mt2032_set_radio_freq(fe, params);
+ priv->frequency = params->frequency * 125 / 2;
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ case V4L2_TUNER_DIGITAL_TV:
+ ret = mt2032_set_tv_freq(fe, params);
+ priv->frequency = params->frequency * 62500;
+ break;
+ }
+
+ return ret;
}
+static struct dvb_tuner_ops mt2032_tuner_ops = {
+ .set_analog_params = mt2032_set_params,
+ .release = microtune_release,
+ .get_frequency = microtune_get_frequency,
+};
+
// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
-static int mt2032_init(struct i2c_client *c)
+static int mt2032_init(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[21];
int ret,xogc,xok=0;
@@ -313,7 +381,7 @@ static int mt2032_init(struct i2c_client *c)
buf[2]=0xff;
buf[3]=0x0f;
buf[4]=0x1f;
- ret=i2c_master_send(c,buf+1,4);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
buf[5]=6; // Index register 6
buf[6]=0xe4;
@@ -321,11 +389,11 @@ static int mt2032_init(struct i2c_client *c)
buf[8]=0xc3;
buf[9]=0x4e;
buf[10]=0xec;
- ret=i2c_master_send(c,buf+5,6);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
buf[12]=13; // Index register 13
buf[13]=0x32;
- ret=i2c_master_send(c,buf+12,2);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
// Adjust XOGC (register 7), wait for XOK
xogc=7;
@@ -333,8 +401,8 @@ static int mt2032_init(struct i2c_client *c)
tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
mdelay(10);
buf[0]=0x0e;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
xok=buf[0]&0x01;
tuner_dbg("mt2032: xok = 0x%02x\n",xok);
if (xok == 1) break;
@@ -347,32 +415,32 @@ static int mt2032_init(struct i2c_client *c)
}
buf[0]=0x07;
buf[1]=0x88 + xogc;
- ret=i2c_master_send(c,buf,2);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
if (ret!=2)
tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
} while (xok != 1 );
- t->xogc=xogc;
+ priv->xogc=xogc;
+
+ memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
- t->set_tv_freq = mt2032_set_tv_freq;
- t->set_radio_freq = mt2032_set_radio_freq;
return(1);
}
-static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
+static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
{
- struct tuner *t = i2c_get_clientdata(c);
- unsigned char buf[2];
- int ret;
-
- buf[0] = 6;
- buf[1] = antenna ? 0x11 : 0x10;
- ret=i2c_master_send(c,buf,2);
- tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
+ struct microtune_priv *priv = fe->tuner_priv;
+ unsigned char buf[2];
+ int ret;
+
+ buf[0] = 6;
+ buf[1] = antenna ? 0x11 : 0x10;
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
+ tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
}
-static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
+static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
unsigned int if1=1218*1000*1000;
unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
int ret;
@@ -404,7 +472,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned
div2a=(lo2/8)-1;
div2b=lo2-(div2a+1)*8;
- if (tuner_debug > 1) {
+ if (debug > 1) {
tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
num1,num2,div1a,div1b,div2a,div2b);
@@ -420,7 +488,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned
buf[5]=div2a;
if(num2!=0) buf[5]=buf[5]|0x40;
- if (tuner_debug > 1) {
+ if (debug > 1) {
int i;
tuner_dbg("bufs is: ");
for(i=0;i<6;i++)
@@ -428,87 +496,131 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned
printk("\n");
}
- ret=i2c_master_send(c,buf,6);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
if (ret!=6)
tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
}
-static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
+static int mt2050_set_tv_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
unsigned int if2;
- if (t->std & V4L2_STD_525_60) {
+ if (params->std & V4L2_STD_525_60) {
// NTSC
if2 = 45750*1000;
} else {
// PAL
if2 = 38900*1000;
}
- if (V4L2_TUNER_DIGITAL_TV == t->mode) {
+ if (V4L2_TUNER_DIGITAL_TV == params->mode) {
// DVB (pinnacle 300i)
if2 = 36150*1000;
}
- mt2050_set_if_freq(c, freq*62500, if2);
- mt2050_set_antenna(c, tv_antenna);
+ mt2050_set_if_freq(fe, params->frequency*62500, if2);
+ mt2050_set_antenna(fe, tv_antenna);
+
+ return 0;
+}
+
+static int mt2050_set_radio_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+{
+ struct microtune_priv *priv = fe->tuner_priv;
+ int if2;
+
+ if (params->std & V4L2_STD_525_60) {
+ tuner_dbg("pinnacle ntsc\n");
+ if2 = 41300 * 1000;
+ } else {
+ tuner_dbg("pinnacle pal\n");
+ if2 = 33300 * 1000;
+ }
+
+ mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
+ mt2050_set_antenna(fe, radio_antenna);
+
+ return 0;
}
-static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
+static int mt2050_set_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
- int if2 = t->radio_if2;
+ struct microtune_priv *priv = fe->tuner_priv;
+ int ret = -EINVAL;
+
+ switch (params->mode) {
+ case V4L2_TUNER_RADIO:
+ ret = mt2050_set_radio_freq(fe, params);
+ priv->frequency = params->frequency * 125 / 2;
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ case V4L2_TUNER_DIGITAL_TV:
+ ret = mt2050_set_tv_freq(fe, params);
+ priv->frequency = params->frequency * 62500;
+ break;
+ }
- mt2050_set_if_freq(c, freq * 1000 / 16, if2);
- mt2050_set_antenna(c, radio_antenna);
+ return ret;
}
-static int mt2050_init(struct i2c_client *c)
+static struct dvb_tuner_ops mt2050_tuner_ops = {
+ .set_analog_params = mt2050_set_params,
+ .release = microtune_release,
+ .get_frequency = microtune_get_frequency,
+};
+
+static int mt2050_init(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = fe->tuner_priv;
unsigned char buf[2];
int ret;
buf[0]=6;
buf[1]=0x10;
- ret=i2c_master_send(c,buf,2); // power
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
buf[0]=0x0f;
buf[1]=0x0f;
- ret=i2c_master_send(c,buf,2); // m1lo
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
buf[0]=0x0d;
- ret=i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
+ ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
tuner_dbg("mt2050: sro is %x\n",buf[0]);
- t->set_tv_freq = mt2050_set_tv_freq;
- t->set_radio_freq = mt2050_set_radio_freq;
+
+ memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
+
return 0;
}
-int microtune_init(struct i2c_client *c)
+struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct microtune_priv *priv = NULL;
char *name;
unsigned char buf[21];
int company_code;
+ priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+ fe->tuner_priv = priv;
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
+
+ //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
+
memset(buf,0,sizeof(buf));
- t->set_tv_freq = NULL;
- t->set_radio_freq = NULL;
- t->standby = NULL;
- if (t->std & V4L2_STD_525_60) {
- tuner_dbg("pinnacle ntsc\n");
- t->radio_if2 = 41300 * 1000;
- } else {
- tuner_dbg("pinnacle pal\n");
- t->radio_if2 = 33300 * 1000;
- }
+
name = "unknown";
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,21);
- if (tuner_debug) {
+ tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
+ tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
+ if (debug) {
int i;
tuner_dbg("MT20xx hexdump:");
for(i=0;i<21;i++) {
@@ -527,10 +639,10 @@ int microtune_init(struct i2c_client *c)
name = microtune_part[buf[0x13]];
switch (buf[0x13]) {
case MT2032:
- mt2032_init(c);
+ mt2032_init(fe);
break;
case MT2050:
- mt2050_init(c);
+ mt2050_init(fe);
break;
default:
tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
@@ -538,11 +650,18 @@ int microtune_init(struct i2c_client *c)
return 0;
}
- strlcpy(c->name, name, sizeof(c->name));
+ strlcpy(fe->ops.tuner_ops.info.name, name,
+ sizeof(fe->ops.tuner_ops.info.name));
tuner_info("microtune %s found, OK\n",name);
- return 0;
+ return fe;
}
+EXPORT_SYMBOL_GPL(microtune_attach);
+
+MODULE_DESCRIPTION("Microtune tuner driver");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h
new file mode 100644
index 000000000000..5e9c825d2e91
--- /dev/null
+++ b/drivers/media/video/mt20xx.h
@@ -0,0 +1,37 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __MT20XX_H__
+#define __MT20XX_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE))
+extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr);
+#else
+static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif
+
+#endif /* __MT20XX_H__ */
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 152cc6b3e152..98ad3092a079 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -153,7 +153,6 @@ static int mxb_probe(struct saa7146_dev* dev)
{
struct mxb* mxb = NULL;
struct i2c_client *client;
- struct list_head *item;
int result;
if ((result = request_module("saa7111")) < 0) {
@@ -196,8 +195,7 @@ static int mxb_probe(struct saa7146_dev* dev)
}
/* loop through all i2c-devices on the bus and look who is there */
- list_for_each(item,&mxb->i2c_adapter.clients) {
- client = list_entry(item, struct i2c_client, list);
+ list_for_each_entry(client, &mxb->i2c_adapter.clients, list) {
if( I2C_ADDR_TEA6420_1 == client->addr )
mxb->tea6420_1 = client;
if( I2C_ADDR_TEA6420_2 == client->addr )
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index e5edff1059a2..9eb2562347a8 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -5554,41 +5554,46 @@ error:
* sysfs
***************************************************************************/
-static inline struct usb_ov511 *cd_to_ov(struct class_device *cd)
+static inline struct usb_ov511 *cd_to_ov(struct device *cd)
{
struct video_device *vdev = to_video_device(cd);
return video_get_drvdata(vdev);
}
-static ssize_t show_custom_id(struct class_device *cd, char *buf)
+static ssize_t show_custom_id(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%d\n", ov->customid);
}
-static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL);
+static DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL);
-static ssize_t show_model(struct class_device *cd, char *buf)
+static ssize_t show_model(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", ov->desc);
}
-static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
-static ssize_t show_bridge(struct class_device *cd, char *buf)
+static ssize_t show_bridge(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge));
}
-static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL);
+static DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL);
-static ssize_t show_sensor(struct class_device *cd, char *buf)
+static ssize_t show_sensor(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor));
}
-static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL);
+static DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL);
-static ssize_t show_brightness(struct class_device *cd, char *buf)
+static ssize_t show_brightness(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
unsigned short x;
@@ -5598,9 +5603,10 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
sensor_get_brightness(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
}
-static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
+static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
-static ssize_t show_saturation(struct class_device *cd, char *buf)
+static ssize_t show_saturation(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
unsigned short x;
@@ -5610,9 +5616,10 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
sensor_get_saturation(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
}
-static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
+static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
-static ssize_t show_contrast(struct class_device *cd, char *buf)
+static ssize_t show_contrast(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
unsigned short x;
@@ -5622,9 +5629,10 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
sensor_get_contrast(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
}
-static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
+static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
-static ssize_t show_hue(struct class_device *cd, char *buf)
+static ssize_t show_hue(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
unsigned short x;
@@ -5634,9 +5642,10 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
sensor_get_hue(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
}
-static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
+static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
-static ssize_t show_exposure(struct class_device *cd, char *buf)
+static ssize_t show_exposure(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
unsigned char exp = 0;
@@ -5646,49 +5655,49 @@ static ssize_t show_exposure(struct class_device *cd, char *buf)
sensor_get_exposure(ov, &exp);
return sprintf(buf, "%d\n", exp >> 8);
}
-static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
+static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
static int ov_create_sysfs(struct video_device *vdev)
{
int rc;
- rc = video_device_create_file(vdev, &class_device_attr_custom_id);
+ rc = video_device_create_file(vdev, &dev_attr_custom_id);
if (rc) goto err;
- rc = video_device_create_file(vdev, &class_device_attr_model);
+ rc = video_device_create_file(vdev, &dev_attr_model);
if (rc) goto err_id;
- rc = video_device_create_file(vdev, &class_device_attr_bridge);
+ rc = video_device_create_file(vdev, &dev_attr_bridge);
if (rc) goto err_model;
- rc = video_device_create_file(vdev, &class_device_attr_sensor);
+ rc = video_device_create_file(vdev, &dev_attr_sensor);
if (rc) goto err_bridge;
- rc = video_device_create_file(vdev, &class_device_attr_brightness);
+ rc = video_device_create_file(vdev, &dev_attr_brightness);
if (rc) goto err_sensor;
- rc = video_device_create_file(vdev, &class_device_attr_saturation);
+ rc = video_device_create_file(vdev, &dev_attr_saturation);
if (rc) goto err_bright;
- rc = video_device_create_file(vdev, &class_device_attr_contrast);
+ rc = video_device_create_file(vdev, &dev_attr_contrast);
if (rc) goto err_sat;
- rc = video_device_create_file(vdev, &class_device_attr_hue);
+ rc = video_device_create_file(vdev, &dev_attr_hue);
if (rc) goto err_contrast;
- rc = video_device_create_file(vdev, &class_device_attr_exposure);
+ rc = video_device_create_file(vdev, &dev_attr_exposure);
if (rc) goto err_hue;
return 0;
err_hue:
- video_device_remove_file(vdev, &class_device_attr_hue);
+ video_device_remove_file(vdev, &dev_attr_hue);
err_contrast:
- video_device_remove_file(vdev, &class_device_attr_contrast);
+ video_device_remove_file(vdev, &dev_attr_contrast);
err_sat:
- video_device_remove_file(vdev, &class_device_attr_saturation);
+ video_device_remove_file(vdev, &dev_attr_saturation);
err_bright:
- video_device_remove_file(vdev, &class_device_attr_brightness);
+ video_device_remove_file(vdev, &dev_attr_brightness);
err_sensor:
- video_device_remove_file(vdev, &class_device_attr_sensor);
+ video_device_remove_file(vdev, &dev_attr_sensor);
err_bridge:
- video_device_remove_file(vdev, &class_device_attr_bridge);
+ video_device_remove_file(vdev, &dev_attr_bridge);
err_model:
- video_device_remove_file(vdev, &class_device_attr_model);
+ video_device_remove_file(vdev, &dev_attr_model);
err_id:
- video_device_remove_file(vdev, &class_device_attr_custom_id);
+ video_device_remove_file(vdev, &dev_attr_custom_id);
err:
return rc;
}
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 3ceb8a6249dd..2bc6bdc9c1f2 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -12,7 +12,6 @@
*/
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/videodev.h>
@@ -416,7 +415,10 @@ static int ov7670_read(struct i2c_client *c, unsigned char reg,
static int ov7670_write(struct i2c_client *c, unsigned char reg,
unsigned char value)
{
- return i2c_smbus_write_byte_data(c, reg, value);
+ int ret = i2c_smbus_write_byte_data(c, reg, value);
+ if (reg == REG_COM7 && (value & COM7_RESET))
+ msleep(2); /* Wait for reset to run */
+ return ret;
}
@@ -617,7 +619,7 @@ static struct ov7670_win_size {
},
};
-#define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0]))
+#define N_WIN_SIZES (ARRAY_SIZE(ov7670_win_sizes))
/*
@@ -1183,7 +1185,7 @@ static struct ov7670_control {
.query = ov7670_q_hflip,
},
};
-#define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0]))
+#define N_CONTROLS (ARRAY_SIZE(ov7670_controls))
static struct ov7670_control *ov7670_find_control(__u32 id)
{
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 3fe9fa04cd84..8063e33f1c85 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include "ovcamchip_priv.h"
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 1455a8f4e930..0ef73d9d5848 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -353,9 +353,8 @@ static int planb_prepare_open(struct planb *pb)
* PLANB_DUMMY)*sizeof(struct dbdma_cmd)
+(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8
+MAX_GBUFFERS*sizeof(unsigned int);
- if ((pb->priv_space = kmalloc (size, GFP_KERNEL)) == 0)
+ if ((pb->priv_space = kzalloc (size, GFP_KERNEL)) == 0)
return -ENOMEM;
- memset ((void *) pb->priv_space, 0, size);
pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *)
DBDMA_ALIGN (pb->priv_space);
pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size;
@@ -845,21 +844,21 @@ cmd_tab_mask_end:
/*********************************/
static int palette2fmt[] = {
- 0,
- PLANB_GRAY,
- 0,
- 0,
- 0,
- PLANB_COLOUR32,
- PLANB_COLOUR15,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
+ 0,
+ PLANB_GRAY,
+ 0,
+ 0,
+ 0,
+ PLANB_COLOUR32,
+ PLANB_COLOUR15,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
#define PLANB_PALETTE_MAX 15
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
index 6bbed88d7867..22719ba861ac 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -33,8 +33,10 @@ static void pvr2_context_destroy(struct pvr2_context *mp)
{
if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
- flush_workqueue(mp->workqueue);
- destroy_workqueue(mp->workqueue);
+ if (mp->workqueue) {
+ flush_workqueue(mp->workqueue);
+ destroy_workqueue(mp->workqueue);
+ }
kfree(mp);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
index d95a8588e4f8..da6441b88f31 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debug.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h
@@ -26,32 +26,33 @@ extern int pvrusb2_debug;
/* These are listed in *rough* order of decreasing usefulness and
increasing noise level. */
-#define PVR2_TRACE_INFO (1 << 0) // Normal messages
-#define PVR2_TRACE_ERROR_LEGS (1 << 1) // error messages
-#define PVR2_TRACE_TOLERANCE (1 << 2) // track tolerance-affected errors
-#define PVR2_TRACE_TRAP (1 << 3) // Trap & report misbehavior from app
-#define PVR2_TRACE_INIT (1 << 4) // misc initialization steps
-#define PVR2_TRACE_START_STOP (1 << 5) // Streaming start / stop
-#define PVR2_TRACE_CTL (1 << 6) // commit of control changes
-#define PVR2_TRACE_DEBUG (1 << 7) // Temporary debug code
-#define PVR2_TRACE_EEPROM (1 << 8) // eeprom parsing / report
-#define PVR2_TRACE_STRUCT (1 << 9) // internal struct creation
-#define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close
-#define PVR2_TRACE_CREG (1 << 11) // Main critical region entry / exit
-#define PVR2_TRACE_SYSFS (1 << 12) // Sysfs driven I/O
-#define PVR2_TRACE_FIRMWARE (1 << 13) // firmware upload actions
-#define PVR2_TRACE_CHIPS (1 << 14) // chip broadcast operation
-#define PVR2_TRACE_I2C (1 << 15) // I2C related stuff
-#define PVR2_TRACE_I2C_CMD (1 << 16) // Software commands to I2C modules
-#define PVR2_TRACE_I2C_CORE (1 << 17) // I2C core debugging
-#define PVR2_TRACE_I2C_TRAF (1 << 18) // I2C traffic through the adapter
-#define PVR2_TRACE_V4LIOCTL (1 << 19) // v4l ioctl details
-#define PVR2_TRACE_ENCODER (1 << 20) // mpeg2 encoder operation
-#define PVR2_TRACE_BUF_POOL (1 << 21) // Track buffer pool management
-#define PVR2_TRACE_BUF_FLOW (1 << 22) // Track buffer flow in system
-#define PVR2_TRACE_DATA_FLOW (1 << 23) // Track data flow
-#define PVR2_TRACE_DEBUGIFC (1 << 24) // Debug interface actions
-#define PVR2_TRACE_GPIO (1 << 25) // GPIO state bit changes
+#define PVR2_TRACE_INFO (1 << 0) /* Normal messages */
+#define PVR2_TRACE_ERROR_LEGS (1 << 1) /* error messages */
+#define PVR2_TRACE_TOLERANCE (1 << 2) /* track tolerance-affected errors */
+#define PVR2_TRACE_TRAP (1 << 3) /* Trap & report app misbehavior */
+#define PVR2_TRACE_STD (1 << 4) /* Log video standard stuff */
+#define PVR2_TRACE_INIT (1 << 5) /* misc initialization steps */
+#define PVR2_TRACE_START_STOP (1 << 6) /* Streaming start / stop */
+#define PVR2_TRACE_CTL (1 << 7) /* commit of control changes */
+#define PVR2_TRACE_DEBUG (1 << 8) /* Temporary debug code */
+#define PVR2_TRACE_EEPROM (1 << 9) /* eeprom parsing / report */
+#define PVR2_TRACE_STRUCT (1 << 10) /* internal struct creation */
+#define PVR2_TRACE_OPEN_CLOSE (1 << 11) /* application open / close */
+#define PVR2_TRACE_CREG (1 << 12) /* Main critical region entry / exit */
+#define PVR2_TRACE_SYSFS (1 << 13) /* Sysfs driven I/O */
+#define PVR2_TRACE_FIRMWARE (1 << 14) /* firmware upload actions */
+#define PVR2_TRACE_CHIPS (1 << 15) /* chip broadcast operation */
+#define PVR2_TRACE_I2C (1 << 16) /* I2C related stuff */
+#define PVR2_TRACE_I2C_CMD (1 << 17) /* Software commands to I2C modules */
+#define PVR2_TRACE_I2C_CORE (1 << 18) /* I2C core debugging */
+#define PVR2_TRACE_I2C_TRAF (1 << 19) /* I2C traffic through the adapter */
+#define PVR2_TRACE_V4LIOCTL (1 << 20) /* v4l ioctl details */
+#define PVR2_TRACE_ENCODER (1 << 21) /* mpeg2 encoder operation */
+#define PVR2_TRACE_BUF_POOL (1 << 22) /* Track buffer pool management */
+#define PVR2_TRACE_BUF_FLOW (1 << 23) /* Track buffer flow in system */
+#define PVR2_TRACE_DATA_FLOW (1 << 24) /* Track data flow */
+#define PVR2_TRACE_DEBUGIFC (1 << 25) /* Debug interface actions */
+#define PVR2_TRACE_GPIO (1 << 26) /* GPIO state bit changes */
#endif /* __PVRUSB2_HDW_INTERNAL_H */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index e9da9bb8f8de..6f135f4a2497 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -397,10 +397,22 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
count -= scnt; buf += scnt;
if (!wptr) return -EINVAL;
if (debugifc_match_keyword(wptr,wlen,"fetch")) {
- pvr2_hdw_cpufw_set_enabled(hdw,!0);
+ scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+ if (scnt && wptr) {
+ count -= scnt; buf += scnt;
+ if (debugifc_match_keyword(wptr,wlen,"prom")) {
+ pvr2_hdw_cpufw_set_enabled(hdw,!0,!0);
+ } else if (debugifc_match_keyword(wptr,wlen,
+ "ram")) {
+ pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
+ } else {
+ return -EINVAL;
+ }
+ }
+ pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
return 0;
} else if (debugifc_match_keyword(wptr,wlen,"done")) {
- pvr2_hdw_cpufw_set_enabled(hdw,0);
+ pvr2_hdw_cpufw_set_enabled(hdw,0,0);
return 0;
} else {
return -EINVAL;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index ce66ab8ff2d8..985d9ae7f5ee 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -238,6 +238,7 @@ struct pvr2_hdw {
// CPU firmware info (used to help find / save firmware data)
char *fw_buffer;
unsigned int fw_size;
+ int fw_cpu_flag; /* True if we are dealing with the CPU */
// Which subsystem pieces have been enabled / configured
unsigned long subsys_enabled_mask;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 1311891e7ee3..27b12b4b5c88 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -492,7 +492,7 @@ static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
cs.controls = &c1;
cs.count = 1;
c1.id = cptr->info->v4l_id;
- ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+ ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs,
VIDIOC_G_EXT_CTRLS);
if (ret) return ret;
*vp = c1.value;
@@ -510,7 +510,7 @@ static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
cs.count = 1;
c1.id = cptr->info->v4l_id;
c1.value = v;
- ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+ ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs,
VIDIOC_S_EXT_CTRLS);
if (ret) return ret;
cptr->hdw->enc_stale = !0;
@@ -1143,6 +1143,13 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
fw_files_24xxx, ARRAY_SIZE(fw_files_24xxx)
},
};
+
+ if ((hdw->hdw_type >= ARRAY_SIZE(fw_file_defs)) ||
+ (!fw_file_defs[hdw->hdw_type].lst)) {
+ hdw->fw1_state = FW1_STATE_OK;
+ return 0;
+ }
+
hdw->fw1_state = FW1_STATE_FAILED; // default result
trace_firmware("pvr2_upload_firmware1");
@@ -1224,6 +1231,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
CX2341X_FIRM_ENC_FILENAME,
};
+ if ((hdw->hdw_type != PVR2_HDW_TYPE_29XXX) &&
+ (hdw->hdw_type != PVR2_HDW_TYPE_24XXX)) {
+ return 0;
+ }
+
trace_firmware("pvr2_upload_firmware2");
ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
@@ -1682,6 +1694,44 @@ static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
return result == 0;
}
+struct pvr2_std_hack {
+ v4l2_std_id pat; /* Pattern to match */
+ v4l2_std_id msk; /* Which bits we care about */
+ v4l2_std_id std; /* What additional standards or default to set */
+};
+
+/* This data structure labels specific combinations of standards from
+ tveeprom that we'll try to recognize. If we recognize one, then assume
+ a specified default standard to use. This is here because tveeprom only
+ tells us about available standards not the intended default standard (if
+ any) for the device in question. We guess the default based on what has
+ been reported as available. Note that this is only for guessing a
+ default - which can always be overridden explicitly - and if the user
+ has otherwise named a default then that default will always be used in
+ place of this table. */
+const static struct pvr2_std_hack std_eeprom_maps[] = {
+ { /* PAL(B/G) */
+ .pat = V4L2_STD_B|V4L2_STD_GH,
+ .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
+ },
+ { /* NTSC(M) */
+ .pat = V4L2_STD_MN,
+ .std = V4L2_STD_NTSC_M,
+ },
+ { /* PAL(I) */
+ .pat = V4L2_STD_PAL_I,
+ .std = V4L2_STD_PAL_I,
+ },
+ { /* SECAM(L/L') */
+ .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+ .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+ },
+ { /* PAL(D/D1/K) */
+ .pat = V4L2_STD_DK,
+ .std = V4L2_STD_PAL_D/V4L2_STD_PAL_D1|V4L2_STD_PAL_K,
+ },
+};
+
static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
{
char buf[40];
@@ -1691,7 +1741,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
std1 = get_default_standard(hdw);
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
- pvr2_trace(PVR2_TRACE_INIT,
+ pvr2_trace(PVR2_TRACE_STD,
"Supported video standard(s) reported by eeprom: %.*s",
bcnt,buf);
@@ -1700,7 +1750,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
std2 = std1 & ~hdw->std_mask_avail;
if (std2) {
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
- pvr2_trace(PVR2_TRACE_INIT,
+ pvr2_trace(PVR2_TRACE_STD,
"Expanding supported video standards"
" to include: %.*s",
bcnt,buf);
@@ -1711,7 +1761,7 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
if (std1) {
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
- pvr2_trace(PVR2_TRACE_INIT,
+ pvr2_trace(PVR2_TRACE_STD,
"Initial video standard forced to %.*s",
bcnt,buf);
hdw->std_mask_cur = std1;
@@ -1720,12 +1770,33 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
return;
}
+ {
+ unsigned int idx;
+ for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) {
+ if (std_eeprom_maps[idx].msk ?
+ ((std_eeprom_maps[idx].pat ^
+ hdw->std_mask_eeprom) &
+ std_eeprom_maps[idx].msk) :
+ (std_eeprom_maps[idx].pat !=
+ hdw->std_mask_eeprom)) continue;
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),
+ std_eeprom_maps[idx].std);
+ pvr2_trace(PVR2_TRACE_STD,
+ "Initial video standard guessed as %.*s",
+ bcnt,buf);
+ hdw->std_mask_cur = std_eeprom_maps[idx].std;
+ hdw->std_dirty = !0;
+ pvr2_hdw_internal_find_stdenum(hdw);
+ return;
+ }
+ }
+
if (hdw->std_enum_cnt > 1) {
// Autoselect the first listed standard
hdw->std_enum_cur = 1;
hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id;
hdw->std_dirty = !0;
- pvr2_trace(PVR2_TRACE_INIT,
+ pvr2_trace(PVR2_TRACE_STD,
"Initial video standard auto-selected to %s",
hdw->std_defs[hdw->std_enum_cur-1].name);
return;
@@ -1742,29 +1813,35 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
unsigned int idx;
struct pvr2_ctrl *cptr;
int reloadFl = 0;
- if (!reloadFl) {
- reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
- == 0);
- if (reloadFl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "USB endpoint config looks strange"
- "; possibly firmware needs to be loaded");
+ if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) ||
+ (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
+ if (!reloadFl) {
+ reloadFl =
+ (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
+ == 0);
+ if (reloadFl) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "USB endpoint config looks strange"
+ "; possibly firmware needs to be"
+ " loaded");
+ }
}
- }
- if (!reloadFl) {
- reloadFl = !pvr2_hdw_check_firmware(hdw);
- if (reloadFl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Check for FX2 firmware failed"
- "; possibly firmware needs to be loaded");
+ if (!reloadFl) {
+ reloadFl = !pvr2_hdw_check_firmware(hdw);
+ if (reloadFl) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Check for FX2 firmware failed"
+ "; possibly firmware needs to be"
+ " loaded");
+ }
}
- }
- if (reloadFl) {
- if (pvr2_upload_firmware1(hdw) != 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failure uploading firmware1");
+ if (reloadFl) {
+ if (pvr2_upload_firmware1(hdw) != 0) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Failure uploading firmware1");
+ }
+ return;
}
- return;
}
hdw->fw1_state = FW1_STATE_OK;
@@ -1773,17 +1850,25 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
}
if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) {
- request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]);
+ if (hdw->hdw_type < ARRAY_SIZE(pvr2_client_lists)) {
+ for (idx = 0;
+ idx < pvr2_client_lists[hdw->hdw_type].cnt;
+ idx++) {
+ request_module(
+ pvr2_client_lists[hdw->hdw_type].lst[idx]);
+ }
}
- pvr2_hdw_cmd_powerup(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
+ if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) ||
+ (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) {
+ pvr2_hdw_cmd_powerup(hdw);
+ if (!pvr2_hdw_dev_ok(hdw)) return;
- if (pvr2_upload_firmware2(hdw)){
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!");
- pvr2_hdw_render_useless(hdw);
- return;
+ if (pvr2_upload_firmware2(hdw)){
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!");
+ pvr2_hdw_render_useless(hdw);
+ return;
+ }
}
// This step MUST happen after the earlier powerup step.
@@ -2172,6 +2257,7 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
/* Destroy hardware interaction structure */
void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
{
+ if (!hdw) return;
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
if (hdw->fw_buffer) {
kfree(hdw->fw_buffer);
@@ -2478,7 +2564,7 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
cs.count = 1;
c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
c1.value = hdw->srate_val;
- cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS);
+ cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
}
/* Scan i2c core at this point - before we clear all the dirty
@@ -2604,7 +2690,85 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
} while (0); LOCK_GIVE(hdw->big_lock);
}
-void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
+
+/* Grab EEPROM contents, needed for direct method. */
+#define EEPROM_SIZE 8192
+#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
+static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw)
+{
+ struct i2c_msg msg[2];
+ u8 *eeprom;
+ u8 iadd[2];
+ u8 addr;
+ u16 eepromSize;
+ unsigned int offs;
+ int ret;
+ int mode16 = 0;
+ unsigned pcnt,tcnt;
+ eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
+ if (!eeprom) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Failed to allocate memory"
+ " required to read eeprom");
+ return NULL;
+ }
+
+ trace_eeprom("Value for eeprom addr from controller was 0x%x",
+ hdw->eeprom_addr);
+ addr = hdw->eeprom_addr;
+ /* Seems that if the high bit is set, then the *real* eeprom
+ address is shifted right now bit position (noticed this in
+ newer PVR USB2 hardware) */
+ if (addr & 0x80) addr >>= 1;
+
+ /* FX2 documentation states that a 16bit-addressed eeprom is
+ expected if the I2C address is an odd number (yeah, this is
+ strange but it's what they do) */
+ mode16 = (addr & 1);
+ eepromSize = (mode16 ? EEPROM_SIZE : 256);
+ trace_eeprom("Examining %d byte eeprom at location 0x%x"
+ " using %d bit addressing",eepromSize,addr,
+ mode16 ? 16 : 8);
+
+ msg[0].addr = addr;
+ msg[0].flags = 0;
+ msg[0].len = mode16 ? 2 : 1;
+ msg[0].buf = iadd;
+ msg[1].addr = addr;
+ msg[1].flags = I2C_M_RD;
+
+ /* We have to do the actual eeprom data fetch ourselves, because
+ (1) we're only fetching part of the eeprom, and (2) if we were
+ getting the whole thing our I2C driver can't grab it in one
+ pass - which is what tveeprom is otherwise going to attempt */
+ memset(eeprom,0,EEPROM_SIZE);
+ for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
+ pcnt = 16;
+ if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
+ offs = tcnt + (eepromSize - EEPROM_SIZE);
+ if (mode16) {
+ iadd[0] = offs >> 8;
+ iadd[1] = offs;
+ } else {
+ iadd[0] = offs;
+ }
+ msg[1].len = pcnt;
+ msg[1].buf = eeprom+tcnt;
+ if ((ret = i2c_transfer(&hdw->i2c_adap,
+ msg,ARRAY_SIZE(msg))) != 2) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "eeprom fetch set offs err=%d",ret);
+ kfree(eeprom);
+ return NULL;
+ }
+ }
+ return eeprom;
+}
+
+
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw,
+ int prom_flag,
+ int enable_flag)
{
int ret;
u16 address;
@@ -2618,37 +2782,59 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
kfree(hdw->fw_buffer);
hdw->fw_buffer = NULL;
hdw->fw_size = 0;
- /* Now release the CPU. It will disconnect and
- reconnect later. */
- pvr2_hdw_cpureset_assert(hdw,0);
+ if (hdw->fw_cpu_flag) {
+ /* Now release the CPU. It will disconnect
+ and reconnect later. */
+ pvr2_hdw_cpureset_assert(hdw,0);
+ }
break;
}
- pvr2_trace(PVR2_TRACE_FIRMWARE,
- "Preparing to suck out CPU firmware");
- hdw->fw_size = 0x2000;
- hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
- if (!hdw->fw_buffer) {
- hdw->fw_size = 0;
- break;
- }
+ hdw->fw_cpu_flag = (prom_flag == 0);
+ if (hdw->fw_cpu_flag) {
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "Preparing to suck out CPU firmware");
+ hdw->fw_size = 0x2000;
+ hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
+ if (!hdw->fw_buffer) {
+ hdw->fw_size = 0;
+ break;
+ }
- /* We have to hold the CPU during firmware upload. */
- pvr2_hdw_cpureset_assert(hdw,1);
+ /* We have to hold the CPU during firmware upload. */
+ pvr2_hdw_cpureset_assert(hdw,1);
- /* download the firmware from address 0000-1fff in 2048
- (=0x800) bytes chunk. */
+ /* download the firmware from address 0000-1fff in 2048
+ (=0x800) bytes chunk. */
- pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware");
- pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
- for(address = 0; address < hdw->fw_size; address += 0x800) {
- ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0,
- address,0,
- hdw->fw_buffer+address,0x800,HZ);
- if (ret < 0) break;
- }
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "Grabbing CPU firmware");
+ pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
+ for(address = 0; address < hdw->fw_size;
+ address += 0x800) {
+ ret = usb_control_msg(hdw->usb_dev,pipe,
+ 0xa0,0xc0,
+ address,0,
+ hdw->fw_buffer+address,
+ 0x800,HZ);
+ if (ret < 0) break;
+ }
- pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware");
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "Done grabbing CPU firmware");
+ } else {
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "Sucking down EEPROM contents");
+ hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw);
+ if (!hdw->fw_buffer) {
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "EEPROM content suck failed.");
+ break;
+ }
+ hdw->fw_size = EEPROM_SIZE;
+ pvr2_trace(PVR2_TRACE_FIRMWARE,
+ "Done sucking down EEPROM contents");
+ }
} while (0); LOCK_GIVE(hdw->big_lock);
}
@@ -3272,7 +3458,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
int setFl,u64 *val_ptr)
{
#ifdef CONFIG_VIDEO_ADV_DEBUG
- struct list_head *item;
struct pvr2_i2c_client *cp;
struct v4l2_register req;
int stat = 0;
@@ -3285,8 +3470,7 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
req.reg = reg_id;
if (setFl) req.val = *val_ptr;
mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
+ list_for_each_entry(cp, &hdw->i2c_clients, list) {
if (!v4l2_chip_match_i2c_client(
cp->client,
req.match_type, req.match_chip)) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 4dba8d006324..e2f9d5e4cb65 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -197,11 +197,13 @@ void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *);
-/* Enable / disable retrieval of CPU firmware. This must be enabled before
- pvr2_hdw_cpufw_get() will function. Note that doing this may prevent
- the device from running (and leaving this mode may imply a device
- reset). */
-void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, int enable_flag);
+/* Enable / disable retrieval of CPU firmware or prom contents. This must
+ be enabled before pvr2_hdw_cpufw_get() will function. Note that doing
+ this may prevent the device from running (and leaving this mode may
+ imply a device reset). */
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *,
+ int prom_flag,
+ int enable_flag);
/* Return true if we're in a mode for retrieval CPU firmware */
int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 6786d3c0c98b..898c9d2e4cdf 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -389,10 +389,6 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
ret = -EINVAL;
goto done;
}
- if ((msgs[0].flags & I2C_M_NOSTART)) {
- trace_i2c("i2c refusing I2C_M_NOSTART");
- goto done;
- }
if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
funcp = hdw->i2c_func[msgs[0].addr];
}
@@ -494,14 +490,12 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
cnt = msgs[idx].len;
printk(KERN_INFO
"pvrusb2 i2c xfer %u/%u:"
- " addr=0x%x len=%d %s%s",
+ " addr=0x%x len=%d %s",
idx+1,num,
msgs[idx].addr,
cnt,
(msgs[idx].flags & I2C_M_RD ?
- "read" : "write"),
- (msgs[idx].flags & I2C_M_NOSTART ?
- " nostart" : ""));
+ "read" : "write"));
if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
if (cnt > 8) cnt = 8;
printk(" [");
@@ -534,7 +528,7 @@ static int pvr2_i2c_control(struct i2c_adapter *adapter,
static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA;
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
}
static int pvr2_i2c_core_singleton(struct i2c_client *cp,
@@ -576,15 +570,13 @@ int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
{
- struct list_head *item,*nc;
- struct pvr2_i2c_client *cp;
+ struct pvr2_i2c_client *cp, *ncp;
int stat = -EINVAL;
if (!hdw) return stat;
mutex_lock(&hdw->i2c_list_lock);
- list_for_each_safe(item,nc,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
+ list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
if (!cp->recv_enable) continue;
mutex_unlock(&hdw->i2c_list_lock);
stat = pvr2_i2c_client_cmd(cp,cmd,arg);
@@ -608,13 +600,11 @@ static int handler_check(struct pvr2_i2c_client *cp)
void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
{
- struct list_head *item;
struct pvr2_i2c_client *cp;
mutex_lock(&hdw->i2c_list_lock); do {
struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
memset(vtp,0,sizeof(*vtp));
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
+ list_for_each_entry(cp, &hdw->i2c_clients, list) {
if (!cp->detected_flag) continue;
if (!cp->status_poll) continue;
cp->status_poll(cp);
@@ -636,8 +626,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
{
unsigned long msk;
unsigned int idx;
- struct list_head *item,*nc;
- struct pvr2_i2c_client *cp;
+ struct pvr2_i2c_client *cp, *ncp;
if (!hdw->i2c_linked) return;
if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
@@ -655,9 +644,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
buf = kmalloc(BUFSIZE,GFP_KERNEL);
pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,
- list);
+ list_for_each_entry(cp, &hdw->i2c_clients, list) {
if (!cp->detected_flag) {
cp->ctl_mask = 0;
pvr2_i2c_probe(hdw,cp);
@@ -693,9 +680,7 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
"i2c: PEND_STALE (0x%lx)",
hdw->i2c_stale_mask);
hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,
- list);
+ list_for_each_entry(cp, &hdw->i2c_clients, list) {
m2 = hdw->i2c_stale_mask;
m2 &= cp->ctl_mask;
m2 &= ~cp->pend_mask;
@@ -716,9 +701,8 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
and update each one. */
pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
- list_for_each_safe(item,nc,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,
- list);
+ list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients,
+ list) {
if (!cp->handler) continue;
if (!cp->handler->func_table->update) continue;
pvr2_trace(PVR2_TRACE_I2C_CORE,
@@ -750,10 +734,8 @@ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
if (!(pm & msk)) continue;
pm &= ~msk;
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,
- struct pvr2_i2c_client,
- list);
+ list_for_each_entry(cp, &hdw->i2c_clients,
+ list) {
if (cp->pend_mask & msk) {
cp->pend_mask &= ~msk;
cp->recv_enable = !0;
@@ -777,7 +759,6 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
unsigned long msk,sm,pm;
unsigned int idx;
const struct pvr2_i2c_op *opf;
- struct list_head *item;
struct pvr2_i2c_client *cp;
unsigned int pt = 0;
@@ -796,11 +777,9 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
}
if (sm) pt |= PVR2_I2C_PEND_STALE;
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
- if (!handler_check(cp)) continue;
- pt |= PVR2_I2C_PEND_CLIENT;
- }
+ list_for_each_entry(cp, &hdw->i2c_clients, list)
+ if (handler_check(cp))
+ pt |= PVR2_I2C_PEND_CLIENT;
if (pt) {
mutex_lock(&hdw->i2c_list_lock); do {
@@ -888,12 +867,10 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
char *buf,unsigned int maxlen)
{
unsigned int ccnt,bcnt;
- struct list_head *item;
struct pvr2_i2c_client *cp;
ccnt = 0;
mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
+ list_for_each_entry(cp, &hdw->i2c_clients, list) {
bcnt = pvr2_i2c_client_describe(
cp,
(PVR2_I2C_DETAIL_HANDLER|
@@ -931,13 +908,11 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client)
static int pvr2_i2c_detach_inform(struct i2c_client *client)
{
struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
- struct pvr2_i2c_client *cp;
- struct list_head *item,*nc;
+ struct pvr2_i2c_client *cp, *ncp;
unsigned long amask = 0;
int foundfl = 0;
mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each_safe(item,nc,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
+ list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
if (cp->client == client) {
trace_i2c("pvr2_i2c_detach"
" [client=%s @ 0x%x ctxt=%p]",
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index 9ea41c6699bb..ca9e2789c8ca 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -24,7 +24,6 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
@@ -42,6 +41,7 @@
#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
PVR2_TRACE_INFO| \
+ PVR2_TRACE_STD| \
PVR2_TRACE_TOLERANCE| \
PVR2_TRACE_TRAP| \
0)
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
index 81de26ba41d9..63e55bb59fcb 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-std.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -298,7 +298,7 @@ static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
std->id = id;
bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
std->name[bcnt] = 0;
- pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s",
+ pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s",
std->index,std->name);
return !0;
}
@@ -320,11 +320,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
v4l2_std_id idmsk,cmsk,fmsk;
struct v4l2_standard *stddefs;
- if (pvrusb2_debug & PVR2_TRACE_INIT) {
+ if (pvrusb2_debug & PVR2_TRACE_STD) {
char buf[50];
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
pvr2_trace(
- PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)",
+ PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
(int)id,bcnt,buf);
}
@@ -355,7 +355,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
bcnt,buf);
}
- pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)",
+ pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)",
std_cnt);
if (!std_cnt) return NULL; // paranoia
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 7ab79baa1c8c..2ee3c3049e8f 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -33,16 +33,16 @@
struct pvr2_sysfs {
struct pvr2_channel channel;
- struct class_device *class_dev;
+ struct device *class_dev;
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
struct pvr2_sysfs_debugifc *debugifc;
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
struct pvr2_sysfs_ctl_item *item_first;
struct pvr2_sysfs_ctl_item *item_last;
- struct class_device_attribute attr_v4l_minor_number;
- struct class_device_attribute attr_v4l_radio_minor_number;
- struct class_device_attribute attr_unit_number;
- struct class_device_attribute attr_bus_info;
+ struct device_attribute attr_v4l_minor_number;
+ struct device_attribute attr_v4l_radio_minor_number;
+ struct device_attribute attr_unit_number;
+ struct device_attribute attr_bus_info;
int v4l_minor_number_created_ok;
int v4l_radio_minor_number_created_ok;
int unit_number_created_ok;
@@ -51,22 +51,22 @@ struct pvr2_sysfs {
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
struct pvr2_sysfs_debugifc {
- struct class_device_attribute attr_debugcmd;
- struct class_device_attribute attr_debuginfo;
+ struct device_attribute attr_debugcmd;
+ struct device_attribute attr_debuginfo;
int debugcmd_created_ok;
int debuginfo_created_ok;
};
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
struct pvr2_sysfs_ctl_item {
- struct class_device_attribute attr_name;
- struct class_device_attribute attr_type;
- struct class_device_attribute attr_min;
- struct class_device_attribute attr_max;
- struct class_device_attribute attr_enum;
- struct class_device_attribute attr_bits;
- struct class_device_attribute attr_val;
- struct class_device_attribute attr_custom;
+ struct device_attribute attr_name;
+ struct device_attribute attr_type;
+ struct device_attribute attr_min;
+ struct device_attribute attr_max;
+ struct device_attribute attr_enum;
+ struct device_attribute attr_bits;
+ struct device_attribute attr_val;
+ struct device_attribute attr_custom;
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *chptr;
struct pvr2_sysfs_ctl_item *item_next;
@@ -80,13 +80,13 @@ struct pvr2_sysfs_class {
struct class class;
};
-static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_name(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
const char *name;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -99,14 +99,14 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
return scnprintf(buf,PAGE_SIZE,"%s\n",name);
}
-static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_type(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
const char *name;
enum pvr2_ctl_type tp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -126,13 +126,13 @@ static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
return scnprintf(buf,PAGE_SIZE,"%s\n",name);
}
-static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_min(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
long val;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -143,13 +143,13 @@ static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
}
-static ssize_t show_max(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_max(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
long val;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -160,14 +160,14 @@ static ssize_t show_max(int id,struct class_device *class_dev,char *buf)
return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
}
-static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_val_norm(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
int val,ret;
unsigned int cnt = 0;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -184,14 +184,14 @@ static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf)
return cnt+1;
}
-static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_val_custom(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
int val,ret;
unsigned int cnt = 0;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -208,14 +208,14 @@ static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf)
return cnt+1;
}
-static ssize_t show_enum(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_enum(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
long val;
unsigned int bcnt,ccnt,ecnt;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -233,14 +233,14 @@ static ssize_t show_enum(int id,struct class_device *class_dev,char *buf)
return bcnt;
}
-static ssize_t show_bits(int id,struct class_device *class_dev,char *buf)
+static ssize_t show_bits(int id,struct device *class_dev,char *buf)
{
struct pvr2_ctrl *cptr;
struct pvr2_sysfs *sfp;
int valid_bits,msk;
unsigned int bcnt,ccnt;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (!cptr) return -EINVAL;
@@ -278,23 +278,23 @@ static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
return ret;
}
-static ssize_t store_val_norm(int id,struct class_device *class_dev,
+static ssize_t store_val_norm(int id,struct device *class_dev,
const char *buf,size_t count)
{
struct pvr2_sysfs *sfp;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
ret = store_val_any(id,0,sfp,buf,count);
if (!ret) ret = count;
return ret;
}
-static ssize_t store_val_custom(int id,struct class_device *class_dev,
+static ssize_t store_val_custom(int id,struct device *class_dev,
const char *buf,size_t count)
{
struct pvr2_sysfs *sfp;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
ret = store_val_any(id,1,sfp,buf,count);
if (!ret) ret = count;
return ret;
@@ -304,7 +304,7 @@ static ssize_t store_val_custom(int id,struct class_device *class_dev,
Mike Isely <isely@pobox.com> 30-April-2005
This next batch of horrible preprocessor hackery is needed because the
- kernel's class_device_attribute mechanism fails to pass the actual
+ kernel's device_attribute mechanism fails to pass the actual
attribute through to the show / store functions, which means we have no
way to package up any attribute-specific parameters, like for example the
control id. So we work around this brain-damage by encoding the control
@@ -314,11 +314,13 @@ static ssize_t store_val_custom(int id,struct class_device *class_dev,
*/
#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
-static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \
+static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
+struct device_attribute *attr, char *buf) \
{ return sf_name(ctl_id,class_dev,buf); }
#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
-static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \
+static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
+struct device_attribute *attr, const char *buf, size_t count) \
{ return sf_name(ctl_id,class_dev,buf,count); }
#define CREATE_BATCH(ctl_id) \
@@ -395,17 +397,27 @@ CREATE_BATCH(58)
CREATE_BATCH(59)
struct pvr2_sysfs_func_set {
- ssize_t (*show_name)(struct class_device *,char *);
- ssize_t (*show_type)(struct class_device *,char *);
- ssize_t (*show_min)(struct class_device *,char *);
- ssize_t (*show_max)(struct class_device *,char *);
- ssize_t (*show_enum)(struct class_device *,char *);
- ssize_t (*show_bits)(struct class_device *,char *);
- ssize_t (*show_val_norm)(struct class_device *,char *);
- ssize_t (*store_val_norm)(struct class_device *,
+ ssize_t (*show_name)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_type)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_min)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_max)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_enum)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_bits)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*show_val_norm)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*store_val_norm)(struct device *,
+ struct device_attribute *attr,
const char *,size_t);
- ssize_t (*show_val_custom)(struct class_device *,char *);
- ssize_t (*store_val_custom)(struct class_device *,
+ ssize_t (*show_val_custom)(struct device *,
+ struct device_attribute *attr, char *);
+ ssize_t (*store_val_custom)(struct device *,
+ struct device_attribute *attr,
const char *,size_t);
};
@@ -597,9 +609,12 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
}
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-static ssize_t debuginfo_show(struct class_device *,char *);
-static ssize_t debugcmd_show(struct class_device *,char *);
-static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
+static ssize_t debuginfo_show(struct device *, struct device_attribute *,
+ char *);
+static ssize_t debugcmd_show(struct device *, struct device_attribute *,
+ char *);
+static ssize_t debugcmd_store(struct device *, struct device_attribute *,
+ const char *, size_t count);
static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
{
@@ -616,16 +631,16 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
dip->attr_debuginfo.attr.mode = S_IRUGO;
dip->attr_debuginfo.show = debuginfo_show;
sfp->debugifc = dip;
- ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+ ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
dip->debugcmd_created_ok = !0;
}
- ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
dip->debuginfo_created_ok = !0;
@@ -637,11 +652,11 @@ static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
{
if (!sfp->debugifc) return;
if (sfp->debugifc->debuginfo_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->debugifc->attr_debuginfo);
}
if (sfp->debugifc->debugcmd_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->debugifc->attr_debugcmd);
}
kfree(sfp->debugifc);
@@ -683,7 +698,7 @@ static void pvr2_sysfs_class_release(struct class *class)
}
-static void pvr2_sysfs_release(struct class_device *class_dev)
+static void pvr2_sysfs_release(struct device *class_dev)
{
pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
kfree(class_dev);
@@ -698,32 +713,33 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
pvr2_sysfs_tear_down_controls(sfp);
if (sfp->bus_info_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->attr_bus_info);
}
if (sfp->v4l_minor_number_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->attr_v4l_minor_number);
}
if (sfp->v4l_radio_minor_number_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->attr_v4l_radio_minor_number);
}
if (sfp->unit_number_created_ok) {
- class_device_remove_file(sfp->class_dev,
+ device_remove_file(sfp->class_dev,
&sfp->attr_unit_number);
}
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
- sfp->class_dev->class_data = NULL;
- class_device_unregister(sfp->class_dev);
+ sfp->class_dev->driver_data = NULL;
+ device_unregister(sfp->class_dev);
sfp->class_dev = NULL;
}
-static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
+static ssize_t v4l_minor_number_show(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -731,21 +747,23 @@ static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
}
-static ssize_t bus_info_show(struct class_device *class_dev,char *buf)
+static ssize_t bus_info_show(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%s\n",
pvr2_hdw_get_bus_info(sfp->channel.hdw));
}
-static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev,
+static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
+ struct device_attribute *attr,
char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -753,10 +771,11 @@ static ssize_t v4l_radio_minor_number_show(struct class_device *class_dev,
}
-static ssize_t unit_number_show(struct class_device *class_dev,char *buf)
+static ssize_t unit_number_show(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
return scnprintf(buf,PAGE_SIZE,"%d\n",
pvr2_hdw_get_unit_number(sfp->channel.hdw));
@@ -767,7 +786,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
struct pvr2_sysfs_class *class_ptr)
{
struct usb_device *usb_dev;
- struct class_device *class_dev;
+ struct device *class_dev;
int ret;
usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
@@ -779,23 +798,23 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
class_dev->class = &class_ptr->class;
if (pvr2_hdw_get_sn(sfp->channel.hdw)) {
- snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu",
+ snprintf(class_dev->bus_id, BUS_ID_SIZE, "sn-%lu",
pvr2_hdw_get_sn(sfp->channel.hdw));
} else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) {
- snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c",
+ snprintf(class_dev->bus_id, BUS_ID_SIZE, "unit-%c",
pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a');
} else {
kfree(class_dev);
return;
}
- class_dev->dev = &usb_dev->dev;
+ class_dev->parent = &usb_dev->dev;
sfp->class_dev = class_dev;
- class_dev->class_data = sfp;
- ret = class_device_register(class_dev);
+ class_dev->driver_data = sfp;
+ ret = device_register(class_dev);
if (ret) {
- printk(KERN_ERR "%s: class_device_register failed\n",
+ printk(KERN_ERR "%s: device_register failed\n",
__FUNCTION__);
kfree(class_dev);
return;
@@ -805,10 +824,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
sfp->attr_v4l_minor_number.store = NULL;
- ret = class_device_create_file(sfp->class_dev,
+ ret = device_create_file(sfp->class_dev,
&sfp->attr_v4l_minor_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
sfp->v4l_minor_number_created_ok = !0;
@@ -818,10 +837,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
sfp->attr_v4l_radio_minor_number.store = NULL;
- ret = class_device_create_file(sfp->class_dev,
+ ret = device_create_file(sfp->class_dev,
&sfp->attr_v4l_radio_minor_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
sfp->v4l_radio_minor_number_created_ok = !0;
@@ -831,9 +850,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_unit_number.attr.mode = S_IRUGO;
sfp->attr_unit_number.show = unit_number_show;
sfp->attr_unit_number.store = NULL;
- ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
sfp->unit_number_created_ok = !0;
@@ -843,10 +862,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_bus_info.attr.mode = S_IRUGO;
sfp->attr_bus_info.show = bus_info_show;
sfp->attr_bus_info.store = NULL;
- ret = class_device_create_file(sfp->class_dev,
+ ret = device_create_file(sfp->class_dev,
&sfp->attr_bus_info);
if (ret < 0) {
- printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ printk(KERN_WARNING "%s: device_create_file error: %d\n",
__FUNCTION__, ret);
} else {
sfp->bus_info_created_ok = !0;
@@ -886,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
}
-static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp,
- int numenvp,char *buf,int size)
+static int pvr2_sysfs_hotplug(struct device *d,
+ struct kobj_uevent_env *env)
{
/* Even though we don't do anything here, we still need this function
because sysfs will still try to call it. */
@@ -902,8 +921,8 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
clp->class.name = "pvrusb2";
clp->class.class_release = pvr2_sysfs_class_release;
- clp->class.release = pvr2_sysfs_release;
- clp->class.uevent = pvr2_sysfs_hotplug;
+ clp->class.dev_release = pvr2_sysfs_release;
+ clp->class.dev_uevent = pvr2_sysfs_hotplug;
if (class_register(&clp->class)) {
pvr2_sysfs_trace(
"Registration failed for pvr2_sysfs_class id=%p",clp);
@@ -921,32 +940,35 @@ void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-static ssize_t debuginfo_show(struct class_device *class_dev,char *buf)
+static ssize_t debuginfo_show(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
pvr2_hdw_trigger_module_log(sfp->channel.hdw);
return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
}
-static ssize_t debugcmd_show(struct class_device *class_dev,char *buf)
+static ssize_t debugcmd_show(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pvr2_sysfs *sfp;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
}
-static ssize_t debugcmd_store(struct class_device *class_dev,
- const char *buf,size_t count)
+static ssize_t debugcmd_store(struct device *class_dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct pvr2_sysfs *sfp;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->class_data;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
if (!sfp) return -EINVAL;
ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 338ced7188f2..ea53316d2111 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -1648,7 +1648,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ARG_OUT(cmd)
break;
}
- /*
+ /*
case VIDIOCPWCGVIDTABLE:
{
ARG_DEF(struct pwc_table_init_buffer, table);
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 085332a503de..0b67d4ec0318 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -64,7 +64,6 @@
#include <linux/vmalloc.h>
#include <linux/version.h>
#include <asm/io.h>
-#include <linux/moduleparam.h>
#include "pwc.h"
#include "pwc-kiara.h"
@@ -127,9 +126,9 @@ static struct usb_driver pwc_driver = {
static int default_size = PSZ_QCIF;
static int default_fps = 10;
static int default_fbufs = 3; /* Default number of frame buffers */
- int pwc_mbufs = 2; /* Default number of mmap() buffers */
+ int pwc_mbufs = 2; /* Default number of mmap() buffers */
#ifdef CONFIG_USB_PWC_DEBUG
- int pwc_trace = PWC_DEBUG_LEVEL;
+ int pwc_trace = PWC_DEBUG_LEVEL;
#endif
static int power_save = 0;
static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
@@ -908,31 +907,49 @@ int pwc_isoc_init(struct pwc_device *pdev)
return 0;
}
-void pwc_isoc_cleanup(struct pwc_device *pdev)
+static void pwc_iso_stop(struct pwc_device *pdev)
{
int i;
- PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
- if (pdev == NULL)
- return;
- if (pdev->iso_init == 0)
- return;
-
/* Unlinking ISOC buffers one by one */
for (i = 0; i < MAX_ISO_BUFS; i++) {
struct urb *urb;
urb = pdev->sbuf[i].urb;
if (urb != 0) {
- if (pdev->iso_init) {
- PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
- usb_kill_urb(urb);
- }
+ PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
+ usb_kill_urb(urb);
+ }
+ }
+}
+
+static void pwc_iso_free(struct pwc_device *pdev)
+{
+ int i;
+
+ /* Freeing ISOC buffers one by one */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ struct urb *urb;
+
+ urb = pdev->sbuf[i].urb;
+ if (urb != 0) {
PWC_DEBUG_MEMORY("Freeing URB\n");
usb_free_urb(urb);
pdev->sbuf[i].urb = NULL;
}
}
+}
+
+void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+ PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
+ if (pdev == NULL)
+ return;
+ if (pdev->iso_init == 0)
+ return;
+
+ pwc_iso_stop(pdev);
+ pwc_iso_free(pdev);
/* Stop camera, but only if we are sure the camera is still there (unplug
is signalled by EPIPE)
@@ -979,20 +996,22 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
/*********
* sysfs
*********/
-static struct pwc_device *cd_to_pwc(struct class_device *cd)
+static struct pwc_device *cd_to_pwc(struct device *cd)
{
struct video_device *vdev = to_video_device(cd);
return video_get_drvdata(vdev);
}
-static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf)
+static ssize_t show_pan_tilt(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pwc_device *pdev = cd_to_pwc(class_dev);
return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
}
-static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
- size_t count)
+static ssize_t store_pan_tilt(struct device *class_dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct pwc_device *pdev = cd_to_pwc(class_dev);
int pan, tilt;
@@ -1008,10 +1027,11 @@ static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
return ret;
return strlen(buf);
}
-static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
- store_pan_tilt);
+static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
+ store_pan_tilt);
-static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf)
+static ssize_t show_snapshot_button_status(struct device *class_dev,
+ struct device_attribute *attr, char *buf)
{
struct pwc_device *pdev = cd_to_pwc(class_dev);
int status = pdev->snapshot_button_status;
@@ -1019,26 +1039,26 @@ static ssize_t show_snapshot_button_status(struct class_device *class_dev, char
return sprintf(buf, "%d\n", status);
}
-static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
- NULL);
+static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
+ NULL);
static int pwc_create_sysfs_files(struct video_device *vdev)
{
struct pwc_device *pdev = video_get_drvdata(vdev);
int rc;
- rc = video_device_create_file(vdev, &class_device_attr_button);
+ rc = video_device_create_file(vdev, &dev_attr_button);
if (rc)
goto err;
if (pdev->features & FEATURE_MOTOR_PANTILT) {
- rc = video_device_create_file(vdev,&class_device_attr_pan_tilt);
+ rc = video_device_create_file(vdev, &dev_attr_pan_tilt);
if (rc) goto err_button;
}
return 0;
err_button:
- video_device_remove_file(vdev, &class_device_attr_button);
+ video_device_remove_file(vdev, &dev_attr_button);
err:
return rc;
}
@@ -1047,8 +1067,8 @@ static void pwc_remove_sysfs_files(struct video_device *vdev)
{
struct pwc_device *pdev = video_get_drvdata(vdev);
if (pdev->features & FEATURE_MOTOR_PANTILT)
- video_device_remove_file(vdev, &class_device_attr_pan_tilt);
- video_device_remove_file(vdev, &class_device_attr_button);
+ video_device_remove_file(vdev, &dev_attr_pan_tilt);
+ video_device_remove_file(vdev, &dev_attr_button);
}
#ifdef CONFIG_USB_PWC_DEBUG
@@ -1099,7 +1119,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
return -EBUSY;
}
- down(&pdev->modlock);
+ mutex_lock(&pdev->modlock);
if (!pdev->usb_init) {
PWC_DEBUG_OPEN("Doing first time initialization.\n");
pdev->usb_init = 1;
@@ -1131,7 +1151,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
if (i < 0) {
PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
pwc_free_buffers(pdev);
- up(&pdev->modlock);
+ mutex_unlock(&pdev->modlock);
return i;
}
@@ -1172,7 +1192,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
if (i) {
PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
pwc_free_buffers(pdev);
- up(&pdev->modlock);
+ mutex_unlock(&pdev->modlock);
return i;
}
@@ -1181,7 +1201,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
pwc_isoc_cleanup(pdev);
pwc_free_buffers(pdev);
- up(&pdev->modlock);
+ mutex_unlock(&pdev->modlock);
return i;
}
@@ -1191,20 +1211,28 @@ static int pwc_video_open(struct inode *inode, struct file *file)
pdev->vopen++;
file->private_data = vdev;
- up(&pdev->modlock);
+ mutex_unlock(&pdev->modlock);
PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
return 0;
}
+
+static void pwc_cleanup(struct pwc_device *pdev)
+{
+ pwc_remove_sysfs_files(pdev->vdev);
+ video_unregister_device(pdev->vdev);
+}
+
/* Note that all cleanup is done in the reverse order as in _open */
static int pwc_video_close(struct inode *inode, struct file *file)
{
struct video_device *vdev = file->private_data;
struct pwc_device *pdev;
- int i;
+ int i, hint;
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
+ lock_kernel();
pdev = (struct pwc_device *)vdev->priv;
if (pdev->vopen == 0)
PWC_DEBUG_MODULE("video_close() called on closed device?\n");
@@ -1225,7 +1253,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
pwc_free_buffers(pdev);
/* Turn off LEDS and power down camera, but only when not unplugged */
- if (pdev->error_status != EPIPE) {
+ if (!pdev->unplugged) {
/* Turn LEDs off */
if (pwc_set_leds(pdev, 0, 0) < 0)
PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
@@ -1234,9 +1262,19 @@ static int pwc_video_close(struct inode *inode, struct file *file)
if (i < 0)
PWC_ERROR("Failed to power down camera (%d)\n", i);
}
+ pdev->vopen--;
+ PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+ } else {
+ pwc_cleanup(pdev);
+ /* Free memory (don't set pdev to 0 just yet) */
+ kfree(pdev);
+ /* search device_hint[] table if we occupy a slot, by any chance */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+ if (device_hint[hint].pdev == pdev)
+ device_hint[hint].pdev = NULL;
}
- pdev->vopen--;
- PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+ unlock_kernel();
+
return 0;
}
@@ -1259,7 +1297,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
struct pwc_device *pdev;
int noblock = file->f_flags & O_NONBLOCK;
DECLARE_WAITQUEUE(wait, current);
- int bytes_to_read;
+ int bytes_to_read, rv = 0;
void *image_buffer_addr;
PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
@@ -1269,8 +1307,12 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
pdev = vdev->priv;
if (pdev == NULL)
return -EFAULT;
- if (pdev->error_status)
- return -pdev->error_status; /* Something happened, report what. */
+
+ mutex_lock(&pdev->modlock);
+ if (pdev->error_status) {
+ rv = -pdev->error_status; /* Something happened, report what. */
+ goto err_out;
+ }
/* In case we're doing partial reads, we don't have to wait for a frame */
if (pdev->image_read_pos == 0) {
@@ -1281,17 +1323,20 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
if (pdev->error_status) {
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
- return -pdev->error_status ;
+ rv = -pdev->error_status ;
+ goto err_out;
}
if (noblock) {
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
- return -EWOULDBLOCK;
+ rv = -EWOULDBLOCK;
+ goto err_out;
}
if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
- return -ERESTARTSYS;
+ rv = -ERESTARTSYS;
+ goto err_out;
}
schedule();
set_current_state(TASK_INTERRUPTIBLE);
@@ -1300,8 +1345,10 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
set_current_state(TASK_RUNNING);
/* Decompress and release frame */
- if (pwc_handle_frame(pdev))
- return -EFAULT;
+ if (pwc_handle_frame(pdev)) {
+ rv = -EFAULT;
+ goto err_out;
+ }
}
PWC_DEBUG_READ("Copying data to user space.\n");
@@ -1316,14 +1363,20 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
image_buffer_addr = pdev->image_data;
image_buffer_addr += pdev->images[pdev->fill_image].offset;
image_buffer_addr += pdev->image_read_pos;
- if (copy_to_user(buf, image_buffer_addr, count))
- return -EFAULT;
+ if (copy_to_user(buf, image_buffer_addr, count)) {
+ rv = -EFAULT;
+ goto err_out;
+ }
pdev->image_read_pos += count;
if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
pdev->image_read_pos = 0;
pwc_next_image(pdev);
}
+ mutex_unlock(&pdev->modlock);
return count;
+err_out:
+ mutex_unlock(&pdev->modlock);
+ return rv;
}
static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
@@ -1349,7 +1402,20 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
static int pwc_video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+ int r = -ENODEV;
+
+ if (!vdev)
+ goto out;
+ pdev = vdev->priv;
+
+ mutex_lock(&pdev->modlock);
+ if (!pdev->unplugged)
+ r = video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+ mutex_unlock(&pdev->modlock);
+out:
+ return r;
}
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1685,7 +1751,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->angle_range.tilt_max = 2500;
}
- init_MUTEX(&pdev->modlock);
+ mutex_init(&pdev->modlock);
spin_lock_init(&pdev->ptrlock);
pdev->udev = udev;
@@ -1791,26 +1857,28 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
/* Alert waiting processes */
wake_up_interruptible(&pdev->frameq);
/* Wait until device is closed */
- while (pdev->vopen)
- schedule();
- /* Device is now closed, so we can safely unregister it */
- PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
- pwc_remove_sysfs_files(pdev->vdev);
- video_unregister_device(pdev->vdev);
-
- /* Free memory (don't set pdev to 0 just yet) */
- kfree(pdev);
+ if(pdev->vopen) {
+ mutex_lock(&pdev->modlock);
+ pdev->unplugged = 1;
+ mutex_unlock(&pdev->modlock);
+ pwc_iso_stop(pdev);
+ } else {
+ /* Device is closed, so we can safely unregister it */
+ PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
+ pwc_cleanup(pdev);
+ /* Free memory (don't set pdev to 0 just yet) */
+ kfree(pdev);
disconnect_out:
- /* search device_hint[] table if we occupy a slot, by any chance */
- for (hint = 0; hint < MAX_DEV_HINTS; hint++)
- if (device_hint[hint].pdev == pdev)
- device_hint[hint].pdev = NULL;
+ /* search device_hint[] table if we occupy a slot, by any chance */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+ if (device_hint[hint].pdev == pdev)
+ device_hint[hint].pdev = NULL;
+ }
unlock_kernel();
}
-
/* *grunt* We have to do atoi ourselves :-( */
static int pwc_atoi(const char *s)
{
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index acbb9312960a..8e8e5b27e77e 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -31,7 +31,7 @@
#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/errno.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
@@ -193,6 +193,7 @@ struct pwc_device
char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */
+ char unplugged;
int cmd_len;
unsigned char cmd_buf[13];
@@ -244,7 +245,7 @@ struct pwc_device
int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */
int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */
- struct semaphore modlock; /* to prevent races in video_open(), etc */
+ struct mutex modlock; /* to prevent races in video_open(), etc */
spinlock_t ptrlock; /* for manipulating the buffer pointers */
/*** motorized pan/tilt feature */
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index f2a2f34cd626..17f1e2e9a66b 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -86,9 +86,9 @@ static const int disp_modes[8][3] =
-#define PAGE_WAIT (300*HZ/1000) /* Time between requesting page and */
+#define PAGE_WAIT msecs_to_jiffies(300) /* Time between requesting page and */
/* checking status bits */
-#define PGBUF_EXPIRE (15*HZ) /* Time to wait before retransmitting */
+#define PGBUF_EXPIRE msecs_to_jiffies(15000) /* Time to wait before retransmitting */
/* page regardless of infobits */
typedef struct {
u8 pgbuf[VTX_VIRTUALSIZE]; /* Page-buffer */
@@ -115,8 +115,8 @@ struct saa5249_device
#define CCTWR 34 /* I²C write/read-address of vtx-chip */
#define CCTRD 35
#define NOACK_REPEAT 10 /* Retry access this many times on failure */
-#define CLEAR_DELAY (HZ/20) /* Time required to clear a page */
-#define READY_TIMEOUT (30*HZ/1000) /* Time to wait for ready signal of I²C-bus interface */
+#define CLEAR_DELAY msecs_to_jiffies(50) /* Time required to clear a page */
+#define READY_TIMEOUT msecs_to_jiffies(30) /* Time to wait for ready signal of I2C-bus interface */
#define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */
#define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 92eabf88a09b..72e344a12c79 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -406,6 +406,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
kfree(s);
return -ENOMEM;
}
+ spin_lock_init(&s->lock);
s->client = client_template;
s->block_count = 0;
s->wr_index = 0;
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 676b9970eb2e..061134a7ba9f 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -208,7 +208,7 @@ determine_norm (struct i2c_client *client)
saa7110_write_block(client, initseq, sizeof(initseq));
saa7110_selmux(client, decoder->input);
prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/4);
+ schedule_timeout(msecs_to_jiffies(250));
finish_wait(&decoder->wq, &wait);
status = saa7110_read(client);
if (status & 0x40) {
@@ -249,7 +249,7 @@ determine_norm (struct i2c_client *client)
//saa7110_write(client,0x2E,0x9A);
prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/4);
+ schedule_timeout(msecs_to_jiffies(250));
finish_wait(&decoder->wq, &wait);
status = saa7110_read(client);
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index c1a392e47170..7ae2d646d000 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -37,23 +37,23 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_decoder.h>
MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(s) (s)->name
-#include <linux/video_decoder.h>
static int debug = 0;
module_param(debug, int, 0644);
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 87c3144ec7fc..677df51de1a9 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -35,28 +35,26 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/major.h>
-
#include <linux/slab.h>
-
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_decoder.h>
MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(x) (x)->name
-#include <linux/video_decoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 9f986930490f..e35ef321ec71 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -332,11 +332,11 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (!enable)
return 0;
- state->vps_data[0] = data->data[4];
- state->vps_data[1] = data->data[10];
- state->vps_data[2] = data->data[11];
- state->vps_data[3] = data->data[12];
- state->vps_data[4] = data->data[13];
+ state->vps_data[0] = data->data[2];
+ state->vps_data[1] = data->data[8];
+ state->vps_data[2] = data->data[9];
+ state->vps_data[3] = data->data[10];
+ state->vps_data[4] = data->data[11];
v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
state->vps_data[0], state->vps_data[1],
state->vps_data[2], state->vps_data[3],
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 309dca368f4a..d6d8d660196d 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -1,7 +1,7 @@
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
depends on VIDEO_DEV && PCI && I2C
- select VIDEO_BUF
+ select VIDEOBUF_DMA_SG
select VIDEO_IR
select VIDEO_TUNER
select CRC32
@@ -38,9 +38,9 @@ config VIDEO_SAA7134_OSS
config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
- select VIDEO_BUF_DVB
+ select VIDEOBUF_DVB
select FW_LOADER
- select DVB_PLL
+ 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
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index ffb0f647a86d..c6f7279669c1 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
#include <linux/module.h>
#include <sound/driver.h>
#include <sound/core.h>
@@ -75,7 +74,8 @@ typedef struct snd_card_saa7134 {
struct saa7134_dev *dev;
unsigned long iobase;
- int irq;
+ s16 irq;
+ u16 mute_was_on;
spinlock_t lock;
} snd_card_saa7134_t;
@@ -312,7 +312,7 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
dev->dmasound.blksize = 0;
dev->dmasound.bufsize = 0;
- return 0;
+ return 0;
}
@@ -589,8 +589,10 @@ 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;
- dev->ctl_mute = 1;
- saa7134_tvaudio_setmute(dev);
+ if (saa7134->mute_was_on) {
+ dev->ctl_mute = 1;
+ saa7134_tvaudio_setmute(dev);
+ }
return 0;
}
@@ -637,8 +639,11 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
runtime->private_free = snd_card_saa7134_runtime_free;
runtime->hw = snd_card_saa7134_capture;
- dev->ctl_mute = 0;
- saa7134_tvaudio_setmute(dev);
+ if (dev->ctl_mute != 0) {
+ saa7134->mute_was_on = 1;
+ dev->ctl_mute = 0;
+ saa7134_tvaudio_setmute(dev);
+ }
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 50f15adfa7c8..a4c192fb4e41 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -32,6 +32,7 @@ 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";
@@ -400,7 +401,7 @@ struct saa7134_board saa7134_boards[] = {
.inputs = {{
.name = name_tv,
.vmux = 1,
- .amux = LINE2,
+ .amux = TV,
.tv = 1,
.gpio = 0x20000,
},{
@@ -1535,20 +1536,15 @@ struct saa7134_board saa7134_boards[] = {
.tv = 1,
.gpio = 0x00,
},{
- .name = name_comp1,
- .vmux = 0,
- .amux = LINE2,
- .gpio = 0x00,
- },{
- .name = name_comp2,
+ .name = name_comp,
.vmux = 3,
- .amux = LINE2,
- .gpio = 0x00,
+ .amux = LINE1,
+ .gpio = 0x02,
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE2,
- .gpio = 0x00,
+ .amux = LINE1,
+ .gpio = 0x02,
}},
.radio = {
.name = name_radio,
@@ -2771,6 +2767,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 1 << 21,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -2781,13 +2778,18 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 3,
.amux = LINE1,
},{
- .name = name_svideo,
+ .name = name_comp2,
.vmux = 0,
.amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
}},
.radio = {
.name = name_radio,
- .amux = LINE1,
+ .amux = TV,
+ .gpio = 0x0200000,
},
},
[SAA7134_BOARD_KWORLD_DVBT_210] = {
@@ -2820,7 +2822,7 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_KWORLD_ATSC110] = {
- .name = "Kworld ATSC110",
+ .name = "Kworld ATSC110/115",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_TUV1236D,
.radio_type = UNSET,
@@ -2896,7 +2898,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_addr = ADDR_UNSET,
},
[SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
- .name = "LifeView FlyDVB-T 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,
@@ -3502,6 +3504,54 @@ struct saa7134_board saa7134_boards[] = {
.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,
+ }},
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -4034,6 +4084,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.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_SAA7134,
.subvendor = 0x1461,
.subdevice = 0x7360,
@@ -4219,6 +4275,24 @@ struct pci_device_id saa7134_pci_tbl[] = {
.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_SAA7133,
+ .subvendor = 0x4e42,
+ .subdevice = 0x3502,
+ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -4330,6 +4404,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_A16AR:
case SAA7134_BOARD_ENCORE_ENLTV:
case SAA7134_BOARD_ENCORE_ENLTV_FM:
+ case SAA7134_BOARD_10MOONSTVMASTER3:
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
@@ -4525,6 +4600,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_PHILIPS_TIGER:
case SAA7134_BOARD_PHILIPS_TIGER_S:
+ case SAA7134_BOARD_AVERMEDIA_SUPER_007:
{
u8 data[] = { 0x3c, 0x33, 0x60};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 25f84701a8e8..1a4a24471f20 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -32,6 +31,7 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/dma-mapping.h>
+#include <linux/pm.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -237,9 +237,10 @@ int saa7134_buffer_startpage(struct saa7134_buf *buf)
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 += buf->vb.dma.sglist[0].offset;
+ base += dma->sglist[0].offset;
return base;
}
@@ -287,11 +288,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
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(&buf->vb,0,0);
- videobuf_dma_unmap(q, &buf->vb.dma);
- videobuf_dma_free(&buf->vb.dma);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
buf->vb.state = STATE_NEEDS_INIT;
}
@@ -391,6 +393,32 @@ void saa7134_buffer_timeout(unsigned long data)
spin_unlock_irqrestore(&dev->slock,flags);
}
+/* resends a current buffer in queue after resume */
+
+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;
+}
+
/* ------------------------------------------------------------------ */
int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -401,6 +429,9 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
assert_spin_locked(&dev->slock);
+ if (dev->inresume)
+ return 0;
+
/* video capture -- dma 0 + video task A */
if (dev->video_q.curr) {
task |= 0x01;
@@ -560,8 +591,10 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
print_irqstatus(dev,loop,report,status);
- if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */)
- saa7134_irq_video_intl(dev);
+ 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)
@@ -646,6 +679,39 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
/* ------------------------------------------------------------------ */
/* 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");
@@ -662,44 +728,16 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa7134_ts_init1(dev);
saa7134_input_init1(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);
+ saa7134_hw_enable1(dev);
return 0;
}
/* late init (with i2c + irq) */
-static int saa7134_hwinit2(struct saa7134_dev *dev)
+static int saa7134_hw_enable2(struct saa7134_dev *dev)
{
- unsigned int irq2_mask;
- dprintk("hwinit2\n");
- saa7134_video_init2(dev);
- saa7134_tvaudio_init2(dev);
+ unsigned int irq2_mask;
/* enable IRQ's */
irq2_mask =
@@ -725,6 +763,20 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
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)
{
@@ -838,7 +890,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
struct saa7134_dev *dev;
- struct list_head *item;
struct saa7134_mpeg_ops *mops;
int err;
@@ -1020,15 +1071,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
saa7134_devcount++;
mutex_lock(&devlist_lock);
- list_for_each(item,&mops_list) {
- mops = list_entry(item, struct saa7134_mpeg_ops, next);
+ list_for_each_entry(mops, &mops_list, next)
mpeg_ops_attach(mops, dev);
- }
list_add_tail(&dev->devlist,&saa7134_devlist);
mutex_unlock(&devlist_lock);
/* check for signal */
- saa7134_irq_video_intl(dev);
+ saa7134_irq_video_signalchange(dev);
if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
saa7134_dmasound_init(dev);
@@ -1057,7 +1106,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
{
struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
- struct list_head *item;
struct saa7134_mpeg_ops *mops;
/* Release DMA sound modules if present */
@@ -1086,10 +1134,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
/* unregister */
mutex_lock(&devlist_lock);
list_del(&dev->devlist);
- list_for_each(item,&mops_list) {
- mops = list_entry(item, struct saa7134_mpeg_ops, next);
+ list_for_each_entry(mops, &mops_list, next)
mpeg_ops_detach(mops, dev);
- }
mutex_unlock(&devlist_lock);
saa7134_devcount--;
@@ -1117,18 +1163,79 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
kfree(dev);
}
+static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
+{
+
+ struct saa7134_dev *dev = pci_get_drvdata(pci_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);
+
+ pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+ pci_save_state(pci_dev);
+
+ return 0;
+}
+
+static int saa7134_resume(struct pci_dev *pci_dev)
+{
+
+ struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+ unsigned int flags;
+
+ pci_restore_state(pci_dev);
+ pci_set_power_state(pci_dev, PCI_D0);
+
+ /* Do things that are done in saa7134_initdev ,
+ except of initializing memory structures.*/
+
+ dev->inresume = 1;
+ saa7134_board_init1(dev);
+
+ if (saa7134_boards[dev->board].video_out)
+ saa7134_videoport_init(dev);
+
+ if (card_has_mpeg(dev))
+ saa7134_ts_init_hw(dev);
+
+ saa7134_hw_enable1(dev);
+ saa7134_set_decoder(dev);
+ saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+ saa7134_board_init2(dev);
+ saa7134_hw_enable2(dev);
+
+ saa7134_tvaudio_setmute(dev);
+ saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
+ saa7134_enable_i2s(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);
+
+ /* start DMA now*/
+ dev->inresume = 0;
+ saa7134_set_dmabits(dev);
+ spin_unlock_irqrestore(&dev->slock, flags);
+
+ return 0;
+}
+
/* ----------------------------------------------------------- */
int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
{
- struct list_head *item;
struct saa7134_dev *dev;
mutex_lock(&devlist_lock);
- list_for_each(item,&saa7134_devlist) {
- dev = list_entry(item, struct saa7134_dev, devlist);
+ list_for_each_entry(dev, &saa7134_devlist, devlist)
mpeg_ops_attach(ops, dev);
- }
list_add_tail(&ops->next,&mops_list);
mutex_unlock(&devlist_lock);
return 0;
@@ -1136,15 +1243,12 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
{
- struct list_head *item;
struct saa7134_dev *dev;
mutex_lock(&devlist_lock);
list_del(&ops->next);
- list_for_each(item,&saa7134_devlist) {
- dev = list_entry(item, struct saa7134_dev, devlist);
+ list_for_each_entry(dev, &saa7134_devlist, devlist)
mpeg_ops_detach(ops, dev);
- }
mutex_unlock(&devlist_lock);
}
@@ -1158,6 +1262,8 @@ static struct pci_driver saa7134_pci_driver = {
.id_table = saa7134_pci_tbl,
.probe = saa7134_initdev,
.remove = __devexit_p(saa7134_finidev),
+ .suspend = saa7134_suspend,
+ .resume = saa7134_resume
};
static int saa7134_init(void)
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index e0eec80088c7..38d87332cc5d 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -175,18 +175,6 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
return mt352_pinnacle_init(fe);
}
-static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
-{
- if (buf_len < 5)
- return -EINVAL;
-
- pllbuf[0] = 0x61;
- dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1,
- params->frequency,
- params->u.ofdm.bandwidth);
- return 5;
-}
-
static struct mt352_config pinnacle_300i = {
.demod_address = 0x3c >> 1,
.adc_clock = 20333,
@@ -444,135 +432,6 @@ static struct tda1004x_config philips_europa_config = {
/* ------------------------------------------------------------------ */
-static int philips_fmd1216_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;
- /* this message is to set up ATC and ALC */
- static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
- struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
-
- 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 int philips_fmd1216_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;
- /* this message actually turns the tuner back to analog mode */
- u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 };
- struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
- msleep(1);
- fmd1216_init[2] = 0x86;
- fmd1216_init[3] = 0x54;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
- msleep(1);
- return 0;
-}
-
-static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
-{
- 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;
- int divider = 0;
- u8 band, mode, cp;
-
- /* determine charge pump */
- tuner_frequency = params->frequency + 36130000;
- if (tuner_frequency < 87000000)
- return -EINVAL;
- /* low band */
- else if (tuner_frequency < 180000000) {
- band = 1;
- mode = 7;
- cp = 0;
- } else if (tuner_frequency < 195000000) {
- band = 1;
- mode = 6;
- cp = 1;
- /* mid band */
- } else if (tuner_frequency < 366000000) {
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
- band = 10;
- } else {
- band = 2;
- }
- mode = 7;
- cp = 0;
- } else if (tuner_frequency < 478000000) {
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
- band = 10;
- } else {
- band = 2;
- }
- mode = 6;
- cp = 1;
- /* high band */
- } else if (tuner_frequency < 662000000) {
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
- band = 12;
- } else {
- band = 4;
- }
- mode = 7;
- cp = 0;
- } else if (tuner_frequency < 840000000) {
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
- band = 12;
- } else {
- band = 4;
- }
- mode = 6;
- cp = 1;
- } else {
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
- band = 12;
- } else {
- band = 4;
- }
- mode = 7;
- cp = 1;
-
- }
- /* calculate divisor */
- /* ((36166000 + Finput) / 166666) rounded! */
- divider = (tuner_frequency + 83333) / 166667;
-
- /* setup tuner buffer */
- tuner_buf[0] = (divider >> 8) & 0x7f;
- tuner_buf[1] = divider & 0xff;
- tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4;
- tuner_buf[3] = 0x40 | 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;
- }
- return 0;
-}
-
static struct tda1004x_config medion_cardbus = {
.demod_address = 0x08,
.invert = 1,
@@ -708,6 +567,7 @@ static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config
}
/* ------------------------------------------------------------------ */
+
static struct tda1004x_config tda827x_lifeview_config = {
.demod_address = 0x08,
.invert = 1,
@@ -887,6 +747,7 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
.antenna_switch= 2,
.request_firmware = philips_tda1004x_request_firmware
};
+
static struct tda1004x_config kworld_dvb_t_210_config = {
.demod_address = 0x08,
.invert = 1,
@@ -901,6 +762,22 @@ static struct tda1004x_config kworld_dvb_t_210_config = {
.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,
+ .tuner_config = 0,
+ .antenna_switch= 1,
+ .request_firmware = philips_tda1004x_request_firmware
+};
+
/* ------------------------------------------------------------------
* special case: this card uses saa713x GPIO22 for the mode switch
*/
@@ -958,18 +835,8 @@ static struct nxt200x_config avertvhda180 = {
.demod_address = 0x0a,
};
-static int nxt200x_set_pll_input(u8 *buf, int input)
-{
- if (input)
- buf[3] |= 0x08;
- else
- buf[3] &= ~0x08;
- return 0;
-}
-
static struct nxt200x_config kworldatsc110 = {
.demod_address = 0x0a,
- .set_pll_input = nxt200x_set_pll_input,
};
/* ==================================================================
@@ -983,7 +850,7 @@ static int dvb_init(struct saa7134_dev *dev)
dev->ts.nr_bufs = 32;
dev->ts.nr_packets = 32*4;
dev->dvb.name = dev->name;
- videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+ videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
@@ -1005,7 +872,8 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
&dev->i2c_adap);
if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ NULL, DVB_PLL_PHILIPS_TD1316);
}
break;
case SAA7134_BOARD_MD7134:
@@ -1013,9 +881,8 @@ static int dvb_init(struct saa7134_dev *dev)
&medion_cardbus,
&dev->i2c_adap);
if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
- dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+ &dev->i2c_adap, DVB_PLL_FMD1216ME);
}
break;
case SAA7134_BOARD_PHILIPS_TOUGH:
@@ -1113,7 +980,7 @@ static int dvb_init(struct saa7134_dev *dev)
&dev->i2c_adap);
if (dev->dvb.frontend) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_tdhu2);
+ NULL, DVB_PLL_TDHU2);
}
break;
case SAA7134_BOARD_KWORLD_ATSC110:
@@ -1121,7 +988,7 @@ static int dvb_init(struct saa7134_dev *dev)
&dev->i2c_adap);
if (dev->dvb.frontend) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, &dvb_pll_tuv1236d);
+ NULL, DVB_PLL_TUV1236D);
}
break;
case SAA7134_BOARD_FLYDVBS_LR300:
@@ -1144,9 +1011,9 @@ static int dvb_init(struct saa7134_dev *dev)
if (dev->dvb.frontend) {
dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
- dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
- dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
- dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+ &dev->i2c_adap, DVB_PLL_FMD1216ME);
}
break;
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
@@ -1173,6 +1040,9 @@ static int dvb_init(struct saa7134_dev *dev)
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config);
break;
+ case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+ configure_tda827x_fe(dev, &avermedia_super_007_config);
+ break;
default:
wprintk("Huh? unknown DVB card?\n");
break;
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index f521603482ca..34ca874dd7fe 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -20,7 +20,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -77,17 +76,14 @@ static int ts_init_encoder(struct saa7134_dev* dev)
static int ts_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct saa7134_dev *h,*dev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev;
int err;
- list_for_each(list,&saa7134_devlist) {
- h = list_entry(list, struct saa7134_dev, devlist);
- if (h->empress_dev && h->empress_dev->minor == minor)
- dev = h;
- }
- if (NULL == dev)
- return -ENODEV;
+ list_for_each_entry(dev, &saa7134_devlist, devlist)
+ if (dev->empress_dev && dev->empress_dev->minor == minor)
+ goto found;
+ return -ENODEV;
+ found:
dprintk("open minor=%d\n",minor);
err = -EBUSY;
@@ -96,6 +92,10 @@ static int ts_open(struct inode *inode, struct file *file)
if (dev->empress_users)
goto done_up;
+ /* Unmute audio */
+ saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
+ saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
+
dev->empress_users++;
file->private_data = dev;
err = 0;
@@ -121,6 +121,10 @@ static int ts_release(struct inode *inode, struct file *file)
/* stop the encoder */
ts_reset_encoder(dev);
+ /* Mute audio */
+ saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
+ saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
+
mutex_unlock(&dev->empress_tsq.lock);
return 0;
}
@@ -393,7 +397,7 @@ static int empress_init(struct saa7134_dev *dev)
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
dev->name,dev->empress_dev->minor & 0x1f);
- videobuf_queue_init(&dev->empress_tsq, &saa7134_ts_qops,
+ videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 1cb8c709ca90..cc87f5855a21 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index c0de37e3f5c6..80d2644f765a 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -19,7 +19,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -153,21 +152,18 @@ void saa7134_input_irq(struct saa7134_dev *dev)
static void saa7134_input_timer(unsigned long data)
{
- struct saa7134_dev *dev = (struct saa7134_dev*)data;
+ struct saa7134_dev *dev = (struct saa7134_dev *)data;
struct card_ir *ir = dev->remote;
- unsigned long timeout;
build_key(dev);
- timeout = jiffies + (ir->polling * HZ / 1000);
- mod_timer(&ir->timer, timeout);
+ mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
{
if (ir->polling) {
- init_timer(&ir->timer);
- ir->timer.function = saa7134_input_timer;
- ir->timer.data = (unsigned long)dev;
+ setup_timer(&ir->timer, saa7134_input_timer,
+ (unsigned long)dev);
ir->timer.expires = jiffies + HZ;
add_timer(&ir->timer);
} else if (ir->rc5_gpio) {
@@ -314,6 +310,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keycode = 0x003F00;
mask_keyup = 0x040000;
break;
+ case SAA7134_BOARD_FLYDVBS_LR300:
case SAA7134_BOARD_FLYDVBT_LR301:
case SAA7134_BOARD_FLYDVBTDUO:
ir_codes = ir_codes_flydvb;
@@ -333,6 +330,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keyup = 0x040000;
polling = 50; // ms
break;
+ case SAA7134_BOARD_10MOONSTVMASTER3:
+ ir_codes = ir_codes_encore_enltv;
+ mask_keycode = 0x5f80000;
+ mask_keyup = 0x8000000;
+ polling = 50; //ms
+ break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
@@ -374,7 +377,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
input_dev->id.vendor = dev->pci->vendor;
input_dev->id.product = dev->pci->device;
}
- input_dev->cdev.dev = &dev->pci->dev;
+ input_dev->dev.parent = &dev->pci->dev;
dev->remote = ir;
saa7134_ir_start(dev, ir);
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 72444f039e3d..aedf04653e0e 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -25,7 +25,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -240,17 +239,14 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
static int dsp_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct saa7134_dev *h,*dev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev;
int err;
- list_for_each(list,&saa7134_devlist) {
- h = list_entry(list, struct saa7134_dev, devlist);
- if (h->dmasound.minor_dsp == minor)
- dev = h;
- }
- if (NULL == dev)
- return -ENODEV;
+ list_for_each_entry(dev, &saa7134_devlist, devlist)
+ if (dev->dmasound.minor_dsp == minor)
+ goto found;
+ return -ENODEV;
+ found:
mutex_lock(&dev->dmasound.lock);
err = -EBUSY;
@@ -681,19 +677,14 @@ mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
static int mixer_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct saa7134_dev *h,*dev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev;
- list_for_each(list,&saa7134_devlist) {
- h = list_entry(list, struct saa7134_dev, devlist);
- if (h->dmasound.minor_mixer == minor)
- dev = h;
- }
- if (NULL == dev)
- return -ENODEV;
-
- file->private_data = dev;
- return 0;
+ list_for_each_entry(dev, &saa7134_devlist, devlist)
+ if (dev->dmasound.minor_mixer == minor) {
+ file->private_data = dev;
+ return 0;
+ }
+ return -ENODEV;
}
static int mixer_release(struct inode *inode, struct file *file)
@@ -1023,18 +1014,14 @@ static int saa7134_oss_init(void)
static void saa7134_oss_exit(void)
{
- struct saa7134_dev *dev = NULL;
- struct list_head *list;
-
- list_for_each(list,&saa7134_devlist) {
- dev = list_entry(list, struct saa7134_dev, devlist);
+ struct saa7134_dev *dev;
+ list_for_each_entry(dev, &saa7134_devlist, devlist) {
/* Device isn't registered by OSS, probably ALSA's */
if (!dev->dmasound.minor_dsp)
continue;
oss_device_exit(dev);
-
}
saa7134_dmasound_init = NULL;
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 60a90a2617ae..4b63ad3e8466 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -93,6 +92,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
}
if (STATE_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;
@@ -102,8 +103,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
- buf->vb.dma.sglist,
- buf->vb.dma.sglen,
+ dma->sglist,
+ dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
@@ -176,6 +177,22 @@ 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, 0xec);
+ 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 */
@@ -199,12 +216,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev)
saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
/* init TS hw */
- saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */
- saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */
- 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));
- saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
+ saa7134_ts_init_hw(dev);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 30395d6b5f14..1b9e39a5ea47 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -23,8 +23,8 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/div64.h>
@@ -231,7 +231,7 @@ static void mute_input_7134(struct saa7134_dev *dev)
}
if (dev->hw_mute == mute &&
- dev->hw_input == in) {
+ dev->hw_input == in && !dev->inresume) {
dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
mute,in->name);
return;
@@ -341,10 +341,8 @@ static void tvaudio_setmode(struct saa7134_dev *dev,
static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(&dev->thread.wq, &wait);
- if (dev->thread.scan1 == dev->thread.scan2 && !dev->thread.shutdown) {
+ if (dev->thread.scan1 == dev->thread.scan2 &&
+ !kthread_should_stop()) {
if (timeout < 0) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
@@ -353,7 +351,6 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
(msecs_to_jiffies(timeout));
}
}
- remove_wait_queue(&dev->thread.wq, &wait);
return dev->thread.scan1 != dev->thread.scan2;
}
@@ -505,11 +502,10 @@ static int tvaudio_thread(void *data)
unsigned int i, audio, nscan;
int max1,max2,carrier,rx,mode,lastmode,default_carrier;
- daemonize("%s", dev->name);
allow_signal(SIGTERM);
for (;;) {
tvaudio_sleep(dev,-1);
- if (dev->thread.shutdown || signal_pending(current))
+ if (kthread_should_stop() || signal_pending(current))
goto done;
restart:
@@ -618,7 +614,7 @@ static int tvaudio_thread(void *data)
for (;;) {
if (tvaudio_sleep(dev,5000))
goto restart;
- if (dev->thread.shutdown || signal_pending(current))
+ if (kthread_should_stop() || signal_pending(current))
break;
if (UNSET == dev->thread.mode) {
rx = tvaudio_getstereo(dev,&tvaudio[i]);
@@ -634,7 +630,6 @@ static int tvaudio_thread(void *data)
}
done:
- complete_and_exit(&dev->thread.exit, 0);
return 0;
}
@@ -782,7 +777,6 @@ static int tvaudio_thread_ddep(void *data)
struct saa7134_dev *dev = data;
u32 value, norms, clock;
- daemonize("%s", dev->name);
allow_signal(SIGTERM);
clock = saa7134_boards[dev->board].audio_clock;
@@ -796,7 +790,7 @@ static int tvaudio_thread_ddep(void *data)
for (;;) {
tvaudio_sleep(dev,-1);
- if (dev->thread.shutdown || signal_pending(current))
+ if (kthread_should_stop() || signal_pending(current))
goto done;
restart:
@@ -876,14 +870,13 @@ static int tvaudio_thread_ddep(void *data)
}
done:
- complete_and_exit(&dev->thread.exit, 0);
return 0;
}
/* ------------------------------------------------------------------ */
/* common stuff + external entry points */
-static void saa7134_enable_i2s(struct saa7134_dev *dev)
+void saa7134_enable_i2s(struct saa7134_dev *dev)
{
int i2s_format;
@@ -973,7 +966,6 @@ int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
int saa7134_tvaudio_init2(struct saa7134_dev *dev)
{
- DECLARE_MUTEX_LOCKED(sem);
int (*my_thread)(void *data) = NULL;
switch (dev->pci->device) {
@@ -986,15 +978,15 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
break;
}
- dev->thread.pid = -1;
+ dev->thread.thread = NULL;
if (my_thread) {
/* start tvaudio thread */
- init_waitqueue_head(&dev->thread.wq);
- init_completion(&dev->thread.exit);
- dev->thread.pid = kernel_thread(my_thread,dev,0);
- if (dev->thread.pid < 0)
+ 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_tvaudio_do_scan(dev);
}
@@ -1005,11 +997,9 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
int saa7134_tvaudio_fini(struct saa7134_dev *dev)
{
/* shutdown tvaudio thread */
- if (dev->thread.pid > 0) {
- dev->thread.shutdown = 1;
- wake_up_interruptible(&dev->thread.wq);
- wait_for_completion(&dev->thread.exit);
- }
+ if (dev->thread.thread)
+ kthread_stop(dev->thread.thread);
+
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */
return 0;
}
@@ -1020,10 +1010,10 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
dprintk("sound IF not in use, skipping scan\n");
dev->automute = 0;
saa7134_tvaudio_setmute(dev);
- } else if (dev->thread.pid >= 0) {
+ } else if (dev->thread.thread) {
dev->thread.mode = UNSET;
dev->thread.scan2++;
- wake_up_interruptible(&dev->thread.wq);
+ wake_up_process(dev->thread.thread);
} else {
dev->automute = 0;
saa7134_tvaudio_setmute(dev);
@@ -1040,4 +1030,3 @@ EXPORT_SYMBOL(saa7134_tvaudio_setmute);
* c-basic-offset: 8
* End:
*/
-
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index f38366a470fa..81a2aedeff5c 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -138,6 +137,8 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7134_dma_free(q,buf);
if (STATE_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;
@@ -147,8 +148,8 @@ static int buffer_prepare(struct videobuf_queue *q,
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
- buf->vb.dma.sglist,
- buf->vb.dma.sglen,
+ dma->sglist,
+ dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 9985ded20950..471b92793c12 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sort.h>
@@ -41,7 +40,7 @@
static unsigned int video_debug = 0;
static unsigned int gbuffers = 8;
-static unsigned int noninterlaced = 1;
+static unsigned int noninterlaced = 0;
static unsigned int gbufsize = 720*576*4;
static unsigned int gbufsize_max = 720*576*4;
static char secam[] = "--";
@@ -541,22 +540,12 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
/* ------------------------------------------------------------------ */
-static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
+void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
{
- int luma_control,sync_control,mux;
dprintk("set tv norm = %s\n",norm->name);
dev->tvnorm = norm;
- 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 cropping */
dev->crop_bounds.left = norm->h_start;
dev->crop_defrect.left = norm->h_start;
@@ -571,6 +560,40 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
dev->crop_current = dev->crop_defrect;
+ saa7134_set_decoder(dev);
+
+ if (card_in(dev, dev->ctl_input).tv) {
+ if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
+ && ((card(dev).tuner_config == 1)
+ || (card(dev).tuner_config == 2)))
+ saa7134_set_gpio(dev, 22, 5);
+ saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &norm->id);
+ }
+}
+
+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));
+}
+
+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);
@@ -585,9 +608,13 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
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_contrast);
- saa_writeb(SAA7134_DEC_CHROMA_SATURATION, dev->ctl_saturation);
+ 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);
@@ -601,23 +628,6 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_MISC_VGATE_MSB, norm->vgate_misc);
saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40);
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
-
- /* only tell the tuner if this is a tv input */
- if (card_in(dev,dev->ctl_input).tv) {
- if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
- && ((card(dev).tuner_config == 1)
- || (card(dev).tuner_config == 2)))
- saa7134_set_gpio(dev, 22, 5);
- saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
- }
-}
-
-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 set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1038,6 +1048,8 @@ static int buffer_prepare(struct videobuf_queue *q,
}
if (STATE_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;
@@ -1049,8 +1061,8 @@ static int buffer_prepare(struct videobuf_queue *q,
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
- buf->vb.dma.sglist,
- buf->vb.dma.sglen,
+ dma->sglist,
+ dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
@@ -1273,26 +1285,24 @@ static int saa7134_resource(struct saa7134_fh *fh)
static int video_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct saa7134_dev *h,*dev = NULL;
+ struct saa7134_dev *dev;
struct saa7134_fh *fh;
- struct list_head *list;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int radio = 0;
- list_for_each(list,&saa7134_devlist) {
- h = list_entry(list, struct saa7134_dev, devlist);
- if (h->video_dev && (h->video_dev->minor == minor))
- dev = h;
- if (h->radio_dev && (h->radio_dev->minor == minor)) {
+ list_for_each_entry(dev, &saa7134_devlist, devlist) {
+ if (dev->video_dev && (dev->video_dev->minor == minor))
+ goto found;
+ if (dev->radio_dev && (dev->radio_dev->minor == minor)) {
radio = 1;
- dev = h;
+ goto found;
}
- if (h->vbi_dev && (h->vbi_dev->minor == minor)) {
+ if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) {
type = V4L2_BUF_TYPE_VBI_CAPTURE;
- dev = h;
+ goto found;
}
}
- if (NULL == dev)
- return -ENODEV;
+ return -ENODEV;
+ found:
dprintk("open minor=%d radio=%d type=%s\n",minor,radio,
v4l2_type_names[type]);
@@ -1310,13 +1320,13 @@ static int video_open(struct inode *inode, struct file *file)
fh->height = 576;
v4l2_prio_open(&dev->prio,&fh->prio);
- videobuf_queue_init(&fh->cap, &video_qops,
+ videobuf_queue_pci_init(&fh->cap, &video_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct saa7134_buf),
fh);
- videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops,
+ videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
@@ -1833,7 +1843,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (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
@@ -2138,29 +2152,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGMBUF:
- {
- struct video_mbuf *mbuf = arg;
- struct videobuf_queue *q;
- struct v4l2_requestbuffers req;
- unsigned int i;
-
- q = saa7134_queue(fh);
- memset(&req,0,sizeof(req));
- req.type = q->type;
- req.count = gbuffers;
- req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(q,&req);
- if (err < 0)
- return err;
- memset(mbuf,0,sizeof(*mbuf));
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return 0;
- }
+ return videobuf_cgmbuf(saa7134_queue(fh), arg, gbuffers);
#endif
case VIDIOC_REQBUFS:
return videobuf_reqbufs(saa7134_queue(fh),arg);
@@ -2412,34 +2404,40 @@ int saa7134_video_init1(struct saa7134_dev *dev)
dev->video_q.timeout.data = (unsigned long)(&dev->video_q);
dev->video_q.dev = dev;
- if (saa7134_boards[dev->board].video_out) {
- /* 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;
- 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_CTRL3, video_out[vo][3]);
- 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]);
- }
+ 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;
+ 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_CTRL3, video_out[vo][3]);
+ 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]);
return 0;
}
@@ -2454,7 +2452,7 @@ int saa7134_video_init2(struct saa7134_dev *dev)
return 0;
}
-void saa7134_irq_video_intl(struct saa7134_dev *dev)
+void saa7134_irq_video_signalchange(struct saa7134_dev *dev)
{
static const char *st[] = {
"(no signal)", "NTSC", "PAL", "SECAM" };
@@ -2466,24 +2464,28 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev)
(st1 & 0x40) ? "not locked" : "locked",
(st2 & 0x40) ? "no" : "yes",
st[st1 & 0x03]);
- dev->nosignal = (st1 & 0x40) || (st2 & 0x40);
+ 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);
- saa_setb(SAA7134_SYNC_CTRL, 0x20);
} else {
/* wake up tvaudio audio carrier scan thread */
saa7134_tvaudio_do_scan(dev);
- if (!noninterlaced)
- saa_clearb(SAA7134_SYNC_CTRL, 0x20);
}
+
+ 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;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 15623b27ad2e..28ec6804bd5d 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -37,12 +37,12 @@
#include <media/tuner.h>
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
-#include <media/video-buf.h>
+#include <media/videobuf-dma-sg.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
-#include <media/video-buf-dvb.h>
+#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
+#include <media/videobuf-dvb.h>
#endif
#define UNSET (-1U)
@@ -238,6 +238,8 @@ struct saa7134_format {
#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_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -313,7 +315,7 @@ struct saa7134_board {
#define INTERLACE_ON 1
#define INTERLACE_OFF 2
-#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */
+#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
struct saa7134_dev;
struct saa7134_dma;
@@ -327,10 +329,7 @@ struct saa7134_pgtable {
/* tvaudio thread status */
struct saa7134_thread {
- pid_t pid;
- struct completion exit;
- wait_queue_head_t wq;
- unsigned int shutdown;
+ struct task_struct *thread;
unsigned int scan1;
unsigned int scan2;
unsigned int mode;
@@ -525,6 +524,7 @@ struct saa7134_dev {
unsigned int hw_mute;
int last_carrier;
int nosignal;
+ unsigned int inresume;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
@@ -538,7 +538,7 @@ struct saa7134_dev {
struct work_struct empress_workqueue;
int empress_started;
-#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE)
+#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
/* SAA7134_MPEG_DVB only */
struct videobuf_dvb dvb;
int (*original_demod_sleep)(struct dvb_frontend* fe);
@@ -595,6 +595,9 @@ 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_buffer_requeue(struct saa7134_dev *dev,
+ struct saa7134_dmaqueue *q);
+
int saa7134_set_dmabits(struct saa7134_dev *dev);
extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
@@ -627,12 +630,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev,
extern struct video_device saa7134_video_template;
extern struct video_device saa7134_radio_template;
+void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm);
+int saa7134_videoport_init(struct saa7134_dev *dev);
+void saa7134_set_decoder(struct saa7134_dev *dev);
+
int saa7134_common_ioctl(struct saa7134_dev *dev,
unsigned int cmd, void *arg);
int saa7134_video_init1(struct saa7134_dev *dev);
int saa7134_video_init2(struct saa7134_dev *dev);
-void saa7134_irq_video_intl(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);
@@ -650,6 +657,8 @@ 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);
+
/* ----------------------------------------------------------- */
/* saa7134-vbi.c */
@@ -678,6 +687,8 @@ int saa7134_tvaudio_do_scan(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 */
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 339592e7722d..66cc92c0ea66 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -34,23 +34,23 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
-#include <linux/types.h>
+#include <asm/uaccess.h>
#include <linux/videodev.h>
-#include <asm/uaccess.h>
+#include <linux/video_encoder.h>
MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
-#include <linux/i2c.h>
#define I2C_NAME(s) (s)->name
-#include <linux/video_encoder.h>
static int debug = 0;
module_param(debug, int, 0);
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index 8615a6081a5d..b4018cce3285 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -130,7 +130,7 @@ static int saa7191_write_reg(struct i2c_client *client, u8 reg,
/* the first byte of data must be the first subaddress number (register) */
static int saa7191_write_block(struct i2c_client *client,
- u8 length, u8 *data)
+ u8 length, const u8 *data)
{
int i;
int ret;
@@ -592,7 +592,7 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
if (err)
goto out_free_decoder;
- err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq);
+ err = saa7191_write_block(client, sizeof(initseq), initseq);
if (err) {
printk(KERN_ERR "SAA7191 initialization failed\n");
goto out_detach_client;
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 11fcb49f5b99..2e3c3de793a7 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/stddef.h>
+#include <linux/kref.h>
#include "sn9c102_config.h"
#include "sn9c102_sensor.h"
@@ -94,7 +95,7 @@ struct sn9c102_module_param {
};
static DEFINE_MUTEX(sn9c102_sysfs_lock);
-static DECLARE_RWSEM(sn9c102_disconnect);
+static DECLARE_RWSEM(sn9c102_dev_lock);
struct sn9c102_device {
struct video_device* v4ldev;
@@ -122,12 +123,14 @@ struct sn9c102_device {
struct sn9c102_module_param module_param;
+ struct kref kref;
enum sn9c102_dev_state state;
u8 users;
- struct mutex dev_mutex, fileop_mutex;
+ struct completion probe;
+ struct mutex open_mutex, fileop_mutex;
spinlock_t queue_lock;
- wait_queue_head_t open, wait_frame, wait_stream;
+ wait_queue_head_t wait_open, wait_frame, wait_stream;
};
/*****************************************************************************/
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 74a204f8ebc8..6991e06f7651 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/device.h>
@@ -48,8 +47,8 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.44"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44)
+#define SN9C102_MODULE_VERSION "1:1.47"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)
/*****************************************************************************/
@@ -64,9 +63,10 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE);
static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
module_param_array(video_nr, short, NULL, 0444);
MODULE_PARM_DESC(video_nr,
- "\n<-1|n[,...]> Specify V4L2 minor mode number."
- "\n -1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
+ " <-1|n[,...]>"
+ "\nSpecify V4L2 minor mode number."
+ "\n-1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
"\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
" cameras this way."
"\nFor example:"
@@ -79,13 +79,14 @@ static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
SN9C102_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
- "\n<0|1[,...]> Force the application to unmap previously"
+ " <0|1[,...]>"
+ "\nForce the application to unmap previously"
"\nmapped buffer memory before calling any VIDIOC_S_CROP or"
"\nVIDIOC_S_FMT ioctl's. Not all the applications support"
"\nthis feature. This parameter is specific for each"
"\ndetected camera."
- "\n 0 = do not force memory unmapping"
- "\n 1 = force memory unmapping (save memory)"
+ "\n0 = do not force memory unmapping"
+ "\n1 = force memory unmapping (save memory)"
"\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
"\n");
@@ -93,7 +94,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
SN9C102_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout,
- "\n<0|n[,...]> Timeout for a video frame in seconds before"
+ " <0|n[,...]>"
+ "\nTimeout for a video frame in seconds before"
"\nreturning an I/O error; 0 for infinity."
"\nThis parameter is specific for each detected camera."
"\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
@@ -103,7 +105,8 @@ MODULE_PARM_DESC(frame_timeout,
static unsigned short debug = SN9C102_DEBUG_LEVEL;
module_param(debug, ushort, 0644);
MODULE_PARM_DESC(debug,
- "\n<n> Debugging information level, from 0 to 3:"
+ " <n>"
+ "\nDebugging information level, from 0 to 3:"
"\n0 = none (use carefully)"
"\n1 = critical errors"
"\n2 = significant informations"
@@ -1026,7 +1029,8 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
NOTE 2: buffers are PAGE_SIZE long
*/
-static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
+static ssize_t sn9c102_show_reg(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct sn9c102_device* cam;
ssize_t count;
@@ -1050,7 +1054,8 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
static ssize_t
-sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_reg(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct sn9c102_device* cam;
u16 index;
@@ -1083,7 +1088,8 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
+static ssize_t sn9c102_show_val(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct sn9c102_device* cam;
ssize_t count;
@@ -1115,7 +1121,8 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
static ssize_t
-sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_val(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct sn9c102_device* cam;
u16 value;
@@ -1154,7 +1161,8 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
+static ssize_t sn9c102_show_i2c_reg(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct sn9c102_device* cam;
ssize_t count;
@@ -1180,7 +1188,8 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
static ssize_t
-sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct sn9c102_device* cam;
u16 index;
@@ -1213,7 +1222,8 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
}
-static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
+static ssize_t sn9c102_show_i2c_val(struct device* cd,
+ struct device_attribute *attr, char* buf)
{
struct sn9c102_device* cam;
ssize_t count;
@@ -1250,7 +1260,8 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
static ssize_t
-sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct sn9c102_device* cam;
u16 value;
@@ -1295,7 +1306,8 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
static ssize_t
-sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_green(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
struct sn9c102_device* cam;
enum sn9c102_bridge bridge;
@@ -1326,16 +1338,16 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
case BRIDGE_SN9C102:
if (value > 0x0f)
return -EINVAL;
- if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)
- res = sn9c102_store_val(cd, buf, len);
+ if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0)
+ res = sn9c102_store_val(cd, attr, buf, len);
break;
case BRIDGE_SN9C103:
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
if (value > 0x7f)
return -EINVAL;
- if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0)
- res = sn9c102_store_val(cd, buf, len);
+ if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0)
+ res = sn9c102_store_val(cd, attr, buf, len);
break;
}
@@ -1344,7 +1356,8 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
static ssize_t
-sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_blue(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
ssize_t res = 0;
u16 value;
@@ -1354,15 +1367,16 @@ sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
if (!count || value > 0x7f)
return -EINVAL;
- if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0)
- res = sn9c102_store_val(cd, buf, len);
+ if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0)
+ res = sn9c102_store_val(cd, attr, buf, len);
return res;
}
static ssize_t
-sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
+sn9c102_store_red(struct device* cd, struct device_attribute *attr,
+ const char* buf, size_t len)
{
ssize_t res = 0;
u16 value;
@@ -1372,14 +1386,16 @@ sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
if (!count || value > 0x7f)
return -EINVAL;
- if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0)
- res = sn9c102_store_val(cd, buf, len);
+ if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0)
+ res = sn9c102_store_val(cd, attr, buf, len);
return res;
}
-static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
+static ssize_t sn9c102_show_frame_header(struct device* cd,
+ struct device_attribute *attr,
+ char* buf)
{
struct sn9c102_device* cam;
ssize_t count;
@@ -1398,72 +1414,63 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
}
-static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
- sn9c102_show_reg, sn9c102_store_reg);
-static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
- sn9c102_show_val, sn9c102_store_val);
-static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
-static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
-static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
-static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
-static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
- sn9c102_show_frame_header, NULL);
+static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
+static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
+static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
+ sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
+static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
+ sn9c102_show_i2c_val, sn9c102_store_i2c_val);
+static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
+static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
+static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
+static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
static int sn9c102_create_sysfs(struct sn9c102_device* cam)
{
- struct class_device *classdev = &(cam->v4ldev->class_dev);
+ struct device *classdev = &(cam->v4ldev->class_dev);
int err = 0;
- if ((err = class_device_create_file(classdev, &class_device_attr_reg)))
+ if ((err = device_create_file(classdev, &dev_attr_reg)))
goto err_out;
- if ((err = class_device_create_file(classdev, &class_device_attr_val)))
+ if ((err = device_create_file(classdev, &dev_attr_val)))
goto err_reg;
- if ((err = class_device_create_file(classdev,
- &class_device_attr_frame_header)))
+ if ((err = device_create_file(classdev, &dev_attr_frame_header)))
goto err_val;
if (cam->sensor.sysfs_ops) {
- if ((err = class_device_create_file(classdev,
- &class_device_attr_i2c_reg)))
+ if ((err = device_create_file(classdev, &dev_attr_i2c_reg)))
goto err_frame_header;
- if ((err = class_device_create_file(classdev,
- &class_device_attr_i2c_val)))
+ if ((err = device_create_file(classdev, &dev_attr_i2c_val)))
goto err_i2c_reg;
}
if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
- if ((err = class_device_create_file(classdev,
- &class_device_attr_green)))
+ if ((err = device_create_file(classdev, &dev_attr_green)))
goto err_i2c_val;
} else {
- if ((err = class_device_create_file(classdev,
- &class_device_attr_blue)))
+ if ((err = device_create_file(classdev, &dev_attr_blue)))
goto err_i2c_val;
- if ((err = class_device_create_file(classdev,
- &class_device_attr_red)))
+ if ((err = device_create_file(classdev, &dev_attr_red)))
goto err_blue;
}
return 0;
err_blue:
- class_device_remove_file(classdev, &class_device_attr_blue);
+ device_remove_file(classdev, &dev_attr_blue);
err_i2c_val:
if (cam->sensor.sysfs_ops)
- class_device_remove_file(classdev, &class_device_attr_i2c_val);
+ device_remove_file(classdev, &dev_attr_i2c_val);
err_i2c_reg:
if (cam->sensor.sysfs_ops)
- class_device_remove_file(classdev, &class_device_attr_i2c_reg);
+ device_remove_file(classdev, &dev_attr_i2c_reg);
err_frame_header:
- class_device_remove_file(classdev, &class_device_attr_frame_header);
+ device_remove_file(classdev, &dev_attr_frame_header);
err_val:
- class_device_remove_file(classdev, &class_device_attr_val);
+ device_remove_file(classdev, &dev_attr_val);
err_reg:
- class_device_remove_file(classdev, &class_device_attr_reg);
+ device_remove_file(classdev, &dev_attr_reg);
err_out:
return err;
}
@@ -1616,7 +1623,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
int err = 0;
if (!(cam->state & DEV_INITIALIZED)) {
- init_waitqueue_head(&cam->open);
+ mutex_init(&cam->open_mutex);
+ init_waitqueue_head(&cam->wait_open);
qctrl = s->qctrl;
rect = &(s->cropcap.defrect);
} else { /* use current values */
@@ -1706,21 +1714,27 @@ static int sn9c102_init(struct sn9c102_device* cam)
return 0;
}
+/*****************************************************************************/
-static void sn9c102_release_resources(struct sn9c102_device* cam)
+static void sn9c102_release_resources(struct kref *kref)
{
+ struct sn9c102_device *cam;
+
mutex_lock(&sn9c102_sysfs_lock);
+ cam = container_of(kref, struct sn9c102_device, kref);
+
DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
+ usb_put_dev(cam->usbdev);
+ kfree(cam->control_buffer);
+ kfree(cam);
mutex_unlock(&sn9c102_sysfs_lock);
- kfree(cam->control_buffer);
}
-/*****************************************************************************/
static int sn9c102_open(struct inode* inode, struct file* filp)
{
@@ -1728,43 +1742,78 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
int err = 0;
/*
- This is the only safe way to prevent race conditions with
- disconnect
+ A read_trylock() in open() is the only safe way to prevent race
+ conditions with disconnect(), one close() and multiple (not
+ necessarily simultaneous) attempts to open(). For example, it
+ prevents from waiting for a second access, while the device
+ structure is being deallocated, after a possible disconnect() and
+ during a following close() holding the write lock: given that, after
+ this deallocation, no access will be possible anymore, using the
+ non-trylock version would have let open() gain the access to the
+ device structure improperly.
+ For this reason the lock must also not be per-device.
*/
- if (!down_read_trylock(&sn9c102_disconnect))
+ if (!down_read_trylock(&sn9c102_dev_lock))
return -ERESTARTSYS;
cam = video_get_drvdata(video_devdata(filp));
- if (mutex_lock_interruptible(&cam->dev_mutex)) {
- up_read(&sn9c102_disconnect);
+ if (wait_for_completion_interruptible(&cam->probe)) {
+ up_read(&sn9c102_dev_lock);
+ return -ERESTARTSYS;
+ }
+
+ kref_get(&cam->kref);
+
+ /*
+ Make sure to isolate all the simultaneous opens.
+ */
+ if (mutex_lock_interruptible(&cam->open_mutex)) {
+ kref_put(&cam->kref, sn9c102_release_resources);
+ up_read(&sn9c102_dev_lock);
return -ERESTARTSYS;
}
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ err = -ENODEV;
+ goto out;
+ }
+
if (cam->users) {
- DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ DBG(2, "Device /dev/video%d is already in use",
+ cam->v4ldev->minor);
DBG(3, "Simultaneous opens are not supported");
+ /*
+ open() must follow the open flags and should block
+ eventually while the device is in use.
+ */
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
err = -EWOULDBLOCK;
goto out;
}
- mutex_unlock(&cam->dev_mutex);
- err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
+ DBG(2, "A blocking open() has been requested. Wait for the "
+ "device to be released...");
+ up_read(&sn9c102_dev_lock);
+ /*
+ We will not release the "open_mutex" lock, so that only one
+ process can be in the wait queue below. This way the process
+ will be sleeping while holding the lock, without loosing its
+ priority after any wake_up().
+ */
+ err = wait_event_interruptible_exclusive(cam->wait_open,
+ (cam->state & DEV_DISCONNECTED)
|| !cam->users);
- if (err) {
- up_read(&sn9c102_disconnect);
- return err;
- }
+ down_read(&sn9c102_dev_lock);
+ if (err)
+ goto out;
if (cam->state & DEV_DISCONNECTED) {
- up_read(&sn9c102_disconnect);
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
- mutex_lock(&cam->dev_mutex);
}
-
if (cam->state & DEV_MISCONFIGURED) {
err = sn9c102_init(cam);
if (err) {
@@ -1789,36 +1838,33 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
out:
- mutex_unlock(&cam->dev_mutex);
- up_read(&sn9c102_disconnect);
+ mutex_unlock(&cam->open_mutex);
+ if (err)
+ kref_put(&cam->kref, sn9c102_release_resources);
+
+ up_read(&sn9c102_dev_lock);
return err;
}
static int sn9c102_release(struct inode* inode, struct file* filp)
{
- struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_device* cam;
- mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
+ down_write(&sn9c102_dev_lock);
- sn9c102_stop_transfer(cam);
+ cam = video_get_drvdata(video_devdata(filp));
+ sn9c102_stop_transfer(cam);
sn9c102_release_buffers(cam);
-
- if (cam->state & DEV_DISCONNECTED) {
- sn9c102_release_resources(cam);
- usb_put_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
- kfree(cam);
- return 0;
- }
-
cam->users--;
- wake_up_interruptible_nr(&cam->open, 1);
+ wake_up_interruptible_nr(&cam->wait_open, 1);
DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
- mutex_unlock(&cam->dev_mutex);
+ kref_put(&cam->kref, sn9c102_release_resources);
+
+ up_write(&sn9c102_dev_lock);
return 0;
}
@@ -2085,7 +2131,6 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
vma->vm_ops = &sn9c102_vm_ops;
vma->vm_private_data = &cam->frame[i];
-
sn9c102_vm_open(vma);
mutex_unlock(&cam->fileop_mutex);
@@ -3215,8 +3260,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- mutex_init(&cam->dev_mutex);
-
r = sn9c102_read_reg(cam, 0x00);
if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
DBG(1, "Sorry, this is not a SN9C1xx-based camera "
@@ -3282,7 +3325,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->release = video_device_release;
video_set_drvdata(cam->v4ldev, cam);
- mutex_lock(&cam->dev_mutex);
+ init_completion(&cam->probe);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]);
@@ -3292,7 +3335,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(1, "Free /dev/videoX node not found");
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
goto fail;
}
@@ -3318,8 +3361,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
#endif
usb_set_intfdata(intf, cam);
+ kref_init(&cam->kref);
+ usb_get_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
return 0;
@@ -3336,40 +3381,31 @@ fail:
static void sn9c102_usb_disconnect(struct usb_interface* intf)
{
- struct sn9c102_device* cam = usb_get_intfdata(intf);
-
- if (!cam)
- return;
+ struct sn9c102_device* cam;
- down_write(&sn9c102_disconnect);
+ down_write(&sn9c102_dev_lock);
- mutex_lock(&cam->dev_mutex);
+ cam = usb_get_intfdata(intf);
DBG(2, "Disconnecting %s...", cam->v4ldev->name);
- wake_up_interruptible_all(&cam->open);
-
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
- "memory deallocation are deferred on close.",
+ "memory deallocation are deferred.",
cam->v4ldev->minor);
cam->state |= DEV_MISCONFIGURED;
sn9c102_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
wake_up_interruptible(&cam->wait_frame);
wake_up(&cam->wait_stream);
- usb_get_dev(cam->usbdev);
- } else {
+ } else
cam->state |= DEV_DISCONNECTED;
- sn9c102_release_resources(cam);
- }
- mutex_unlock(&cam->dev_mutex);
+ wake_up_interruptible_all(&cam->wait_open);
- if (!cam->users)
- kfree(cam);
+ kref_put(&cam->kref, sn9c102_release_resources);
- up_write(&sn9c102_disconnect);
+ up_write(&sn9c102_dev_lock);
}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index e6832347894f..e4856fd77982 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -104,6 +104,145 @@ static int ov7630_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x74, 0x21);
err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
+ {0x1a, 0x04}, {0x03, 0x10},
+ {0x0a, 0x14}, {0xe2, 0x17},
+ {0x0b, 0x18}, {0x00, 0x19},
+ {0x1d, 0x1a}, {0x10, 0x1b},
+ {0x02, 0x1c}, {0x03, 0x1d},
+ {0x0f, 0x1e}, {0x0c, 0x1f},
+ {0x00, 0x20}, {0x24, 0x21},
+ {0x3b, 0x22}, {0x47, 0x23},
+ {0x60, 0x24}, {0x71, 0x25},
+ {0x80, 0x26}, {0x8f, 0x27},
+ {0x9d, 0x28}, {0xaa, 0x29},
+ {0xb8, 0x2a}, {0xc4, 0x2b},
+ {0xd1, 0x2c}, {0xdd, 0x2d},
+ {0xe8, 0x2e}, {0xf4, 0x2f},
+ {0xff, 0x30}, {0x00, 0x3f},
+ {0xc7, 0x40}, {0x01, 0x41},
+ {0x44, 0x42}, {0x00, 0x43},
+ {0x44, 0x44}, {0x00, 0x45},
+ {0x44, 0x46}, {0x00, 0x47},
+ {0xc7, 0x48}, {0x01, 0x49},
+ {0xc7, 0x4a}, {0x01, 0x4b},
+ {0xc7, 0x4c}, {0x01, 0x4d},
+ {0x44, 0x4e}, {0x00, 0x4f},
+ {0x44, 0x50}, {0x00, 0x51},
+ {0x44, 0x52}, {0x00, 0x53},
+ {0xc7, 0x54}, {0x01, 0x55},
+ {0xc7, 0x56}, {0x01, 0x57},
+ {0xc7, 0x58}, {0x01, 0x59},
+ {0x44, 0x5a}, {0x00, 0x5b},
+ {0x44, 0x5c}, {0x00, 0x5d},
+ {0x44, 0x5e}, {0x00, 0x5f},
+ {0xc7, 0x60}, {0x01, 0x61},
+ {0xc7, 0x62}, {0x01, 0x63},
+ {0xc7, 0x64}, {0x01, 0x65},
+ {0x44, 0x66}, {0x00, 0x67},
+ {0x44, 0x68}, {0x00, 0x69},
+ {0x44, 0x6a}, {0x00, 0x6b},
+ {0xc7, 0x6c}, {0x01, 0x6d},
+ {0xc7, 0x6e}, {0x01, 0x6f},
+ {0xc7, 0x70}, {0x01, 0x71},
+ {0x44, 0x72}, {0x00, 0x73},
+ {0x44, 0x74}, {0x00, 0x75},
+ {0x44, 0x76}, {0x00, 0x77},
+ {0xc7, 0x78}, {0x01, 0x79},
+ {0xc7, 0x7a}, {0x01, 0x7b},
+ {0xc7, 0x7c}, {0x01, 0x7d},
+ {0x44, 0x7e}, {0x00, 0x7f},
+ {0x17, 0x84}, {0x00, 0x85},
+ {0x2e, 0x86}, {0x00, 0x87},
+ {0x09, 0x88}, {0x00, 0x89},
+ {0xe8, 0x8a}, {0x0f, 0x8b},
+ {0xda, 0x8c}, {0x0f, 0x8d},
+ {0x40, 0x8e}, {0x00, 0x8f},
+ {0x37, 0x90}, {0x00, 0x91},
+ {0xcf, 0x92}, {0x0f, 0x93},
+ {0xfa, 0x94}, {0x0f, 0x95},
+ {0x00, 0x96}, {0x00, 0x97},
+ {0x00, 0x98}, {0x66, 0x99},
+ {0x00, 0x9a}, {0x40, 0x9b},
+ {0x20, 0x9c}, {0x00, 0x9d},
+ {0x00, 0x9e}, {0x00, 0x9f},
+ {0x2d, 0xc0}, {0x2d, 0xc1},
+ {0x3a, 0xc2}, {0x00, 0xc3},
+ {0x04, 0xc4}, {0x3f, 0xc5},
+ {0x00, 0xc6}, {0x00, 0xc7},
+ {0x50, 0xc8}, {0x3c, 0xc9},
+ {0x28, 0xca}, {0xd8, 0xcb},
+ {0x14, 0xcc}, {0xec, 0xcd},
+ {0x32, 0xce}, {0xdd, 0xcf},
+ {0x32, 0xd0}, {0xdd, 0xd1},
+ {0x6a, 0xd2}, {0x50, 0xd3},
+ {0x60, 0xd4}, {0x00, 0xd5},
+ {0x00, 0xd6});
+
+ err += sn9c102_i2c_write(cam, 0x12, 0x80);
+ err += sn9c102_i2c_write(cam, 0x12, 0x48);
+ err += sn9c102_i2c_write(cam, 0x01, 0x80);
+ err += sn9c102_i2c_write(cam, 0x02, 0x80);
+ err += sn9c102_i2c_write(cam, 0x03, 0x80);
+ err += sn9c102_i2c_write(cam, 0x04, 0x10);
+ err += sn9c102_i2c_write(cam, 0x05, 0x20);
+ err += sn9c102_i2c_write(cam, 0x06, 0x80);
+ err += sn9c102_i2c_write(cam, 0x11, 0x00);
+ err += sn9c102_i2c_write(cam, 0x0c, 0x20);
+ err += sn9c102_i2c_write(cam, 0x0d, 0x20);
+ err += sn9c102_i2c_write(cam, 0x15, 0x80);
+ err += sn9c102_i2c_write(cam, 0x16, 0x03);
+ err += sn9c102_i2c_write(cam, 0x17, 0x1b);
+ err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+ err += sn9c102_i2c_write(cam, 0x19, 0x05);
+ err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+ err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+ err += sn9c102_i2c_write(cam, 0x21, 0x1b);
+ err += sn9c102_i2c_write(cam, 0x22, 0x00);
+ err += sn9c102_i2c_write(cam, 0x23, 0xde);
+ err += sn9c102_i2c_write(cam, 0x24, 0x10);
+ err += sn9c102_i2c_write(cam, 0x25, 0x8a);
+ err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+ err += sn9c102_i2c_write(cam, 0x27, 0xca);
+ err += sn9c102_i2c_write(cam, 0x28, 0xa2);
+ err += sn9c102_i2c_write(cam, 0x29, 0x74);
+ err += sn9c102_i2c_write(cam, 0x2a, 0x88);
+ err += sn9c102_i2c_write(cam, 0x2b, 0x34);
+ err += sn9c102_i2c_write(cam, 0x2c, 0x88);
+ err += sn9c102_i2c_write(cam, 0x2e, 0x00);
+ err += sn9c102_i2c_write(cam, 0x2f, 0x00);
+ err += sn9c102_i2c_write(cam, 0x30, 0x00);
+ err += sn9c102_i2c_write(cam, 0x32, 0xc2);
+ err += sn9c102_i2c_write(cam, 0x33, 0x08);
+ err += sn9c102_i2c_write(cam, 0x4c, 0x40);
+ err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
+ err += sn9c102_i2c_write(cam, 0x60, 0x05);
+ err += sn9c102_i2c_write(cam, 0x61, 0x40);
+ err += sn9c102_i2c_write(cam, 0x62, 0x12);
+ err += sn9c102_i2c_write(cam, 0x63, 0x57);
+ err += sn9c102_i2c_write(cam, 0x64, 0x73);
+ err += sn9c102_i2c_write(cam, 0x65, 0x00);
+ err += sn9c102_i2c_write(cam, 0x66, 0x55);
+ err += sn9c102_i2c_write(cam, 0x67, 0x01);
+ err += sn9c102_i2c_write(cam, 0x68, 0xac);
+ err += sn9c102_i2c_write(cam, 0x69, 0x38);
+ err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
+ err += sn9c102_i2c_write(cam, 0x70, 0x01);
+ err += sn9c102_i2c_write(cam, 0x71, 0x00);
+ err += sn9c102_i2c_write(cam, 0x72, 0x10);
+ err += sn9c102_i2c_write(cam, 0x73, 0x50);
+ err += sn9c102_i2c_write(cam, 0x74, 0x20);
+ err += sn9c102_i2c_write(cam, 0x76, 0x01);
+ err += sn9c102_i2c_write(cam, 0x77, 0xf3);
+ err += sn9c102_i2c_write(cam, 0x78, 0x90);
+ err += sn9c102_i2c_write(cam, 0x79, 0x98);
+ err += sn9c102_i2c_write(cam, 0x7a, 0x98);
+ err += sn9c102_i2c_write(cam, 0x7b, 0x00);
+ err += sn9c102_i2c_write(cam, 0x7c, 0x38);
+ err += sn9c102_i2c_write(cam, 0x7d, 0xff);
+ break;
default:
break;
}
@@ -115,6 +254,7 @@ static int ov7630_init(struct sn9c102_device* cam)
static int ov7630_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
+ enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
int err = 0;
switch (ctrl->id) {
@@ -123,13 +263,20 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam,
return -EIO;
break;
case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_pread_reg(cam, 0x07);
+ if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+ ctrl->value = sn9c102_pread_reg(cam, 0x05);
+ else
+ ctrl->value = sn9c102_pread_reg(cam, 0x07);
break;
case V4L2_CID_BLUE_BALANCE:
ctrl->value = sn9c102_pread_reg(cam, 0x06);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_pread_reg(cam, 0x05);
+ if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+ ctrl->value = sn9c102_pread_reg(cam, 0x07);
+ else
+ ctrl->value = sn9c102_pread_reg(cam, 0x05);
+ break;
break;
case V4L2_CID_GAIN:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
@@ -177,6 +324,7 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam,
static int ov7630_set_ctrl(struct sn9c102_device* cam,
const struct v4l2_control* ctrl)
{
+ enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
int err = 0;
switch (ctrl->id) {
@@ -184,13 +332,19 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
break;
case V4L2_CID_RED_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+ if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+ err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+ else
+ err += sn9c102_write_reg(cam, ctrl->value, 0x07);
break;
case V4L2_CID_BLUE_BALANCE:
err += sn9c102_write_reg(cam, ctrl->value, 0x06);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+ if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+ err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+ else
+ err += sn9c102_write_reg(cam, ctrl->value, 0x05);
break;
case V4L2_CID_GAIN:
err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
@@ -227,8 +381,21 @@ static int ov7630_set_crop(struct sn9c102_device* cam,
{
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+ u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C101:
+ case BRIDGE_SN9C102:
+ case BRIDGE_SN9C103:
+ h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
+ break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
+ break;
+ default:
+ break;
+ }
err += sn9c102_write_reg(cam, h_start, 0x12);
err += sn9c102_write_reg(cam, v_start, 0x13);
@@ -242,10 +409,28 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
{
int err = 0;
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x20, 0x19);
- else
- err += sn9c102_write_reg(cam, 0x50, 0x19);
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C101:
+ case BRIDGE_SN9C102:
+ case BRIDGE_SN9C103:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
+ err += sn9c102_write_reg(cam, 0x50, 0x19);
+ else
+ err += sn9c102_write_reg(cam, 0x20, 0x19);
+ break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+ err += sn9c102_write_reg(cam, 0xe5, 0x17);
+ err += sn9c102_i2c_write(cam, 0x11, 0x04);
+ } else {
+ err += sn9c102_write_reg(cam, 0xe2, 0x17);
+ err += sn9c102_i2c_write(cam, 0x11, 0x02);
+ }
+ break;
+ default:
+ break;
+ }
return err;
}
@@ -254,7 +439,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
static const struct sn9c102_sensor ov7630 = {
.name = "OV7630",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
+ BRIDGE_SN9C105 | BRIDGE_SN9C120,
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
@@ -417,6 +603,12 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
err += sn9c102_write_const_regs(cam, {0x01, 0x01},
{0x00, 0x01});
break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+ {0x29, 0x01}, {0x74, 0x02},
+ {0x0e, 0x01}, {0x44, 0x01});
+ break;
default:
break;
}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
index 4b6474048a72..8aae416ba8ec 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -41,65 +41,65 @@ static int ov7660_init(struct sn9c102_device* cam)
{0xbb, 0x2a}, {0xc7, 0x2b},
{0xd3, 0x2c}, {0xde, 0x2d},
{0xea, 0x2e}, {0xf4, 0x2f},
- {0xff, 0x30}, {0x00, 0x3F},
- {0xC7, 0x40}, {0x01, 0x41},
+ {0xff, 0x30}, {0x00, 0x3f},
+ {0xc7, 0x40}, {0x01, 0x41},
{0x44, 0x42}, {0x00, 0x43},
{0x44, 0x44}, {0x00, 0x45},
{0x44, 0x46}, {0x00, 0x47},
- {0xC7, 0x48}, {0x01, 0x49},
- {0xC7, 0x4A}, {0x01, 0x4B},
- {0xC7, 0x4C}, {0x01, 0x4D},
- {0x44, 0x4E}, {0x00, 0x4F},
+ {0xc7, 0x48}, {0x01, 0x49},
+ {0xc7, 0x4a}, {0x01, 0x4b},
+ {0xc7, 0x4c}, {0x01, 0x4d},
+ {0x44, 0x4e}, {0x00, 0x4f},
{0x44, 0x50}, {0x00, 0x51},
{0x44, 0x52}, {0x00, 0x53},
- {0xC7, 0x54}, {0x01, 0x55},
- {0xC7, 0x56}, {0x01, 0x57},
- {0xC7, 0x58}, {0x01, 0x59},
- {0x44, 0x5A}, {0x00, 0x5B},
- {0x44, 0x5C}, {0x00, 0x5D},
- {0x44, 0x5E}, {0x00, 0x5F},
- {0xC7, 0x60}, {0x01, 0x61},
- {0xC7, 0x62}, {0x01, 0x63},
- {0xC7, 0x64}, {0x01, 0x65},
+ {0xc7, 0x54}, {0x01, 0x55},
+ {0xc7, 0x56}, {0x01, 0x57},
+ {0xc7, 0x58}, {0x01, 0x59},
+ {0x44, 0x5a}, {0x00, 0x5b},
+ {0x44, 0x5c}, {0x00, 0x5d},
+ {0x44, 0x5e}, {0x00, 0x5f},
+ {0xc7, 0x60}, {0x01, 0x61},
+ {0xc7, 0x62}, {0x01, 0x63},
+ {0xc7, 0x64}, {0x01, 0x65},
{0x44, 0x66}, {0x00, 0x67},
{0x44, 0x68}, {0x00, 0x69},
- {0x44, 0x6A}, {0x00, 0x6B},
- {0xC7, 0x6C}, {0x01, 0x6D},
- {0xC7, 0x6E}, {0x01, 0x6F},
- {0xC7, 0x70}, {0x01, 0x71},
+ {0x44, 0x6a}, {0x00, 0x6b},
+ {0xc7, 0x6c}, {0x01, 0x6d},
+ {0xc7, 0x6e}, {0x01, 0x6f},
+ {0xc7, 0x70}, {0x01, 0x71},
{0x44, 0x72}, {0x00, 0x73},
{0x44, 0x74}, {0x00, 0x75},
{0x44, 0x76}, {0x00, 0x77},
- {0xC7, 0x78}, {0x01, 0x79},
- {0xC7, 0x7A}, {0x01, 0x7B},
- {0xC7, 0x7C}, {0x01, 0x7D},
- {0x44, 0x7E}, {0x00, 0x7F},
+ {0xc7, 0x78}, {0x01, 0x79},
+ {0xc7, 0x7a}, {0x01, 0x7b},
+ {0xc7, 0x7c}, {0x01, 0x7d},
+ {0x44, 0x7e}, {0x00, 0x7f},
{0x14, 0x84}, {0x00, 0x85},
{0x27, 0x86}, {0x00, 0x87},
{0x07, 0x88}, {0x00, 0x89},
- {0xEC, 0x8A}, {0x0f, 0x8B},
- {0xD8, 0x8C}, {0x0f, 0x8D},
- {0x3D, 0x8E}, {0x00, 0x8F},
- {0x3D, 0x90}, {0x00, 0x91},
- {0xCD, 0x92}, {0x0f, 0x93},
+ {0xec, 0x8a}, {0x0f, 0x8b},
+ {0xd8, 0x8c}, {0x0f, 0x8d},
+ {0x3d, 0x8e}, {0x00, 0x8f},
+ {0x3d, 0x90}, {0x00, 0x91},
+ {0xcd, 0x92}, {0x0f, 0x93},
{0xf7, 0x94}, {0x0f, 0x95},
- {0x0C, 0x96}, {0x00, 0x97},
+ {0x0c, 0x96}, {0x00, 0x97},
{0x00, 0x98}, {0x66, 0x99},
- {0x05, 0x9A}, {0x00, 0x9B},
- {0x04, 0x9C}, {0x00, 0x9D},
- {0x08, 0x9E}, {0x00, 0x9F},
- {0x2D, 0xC0}, {0x2D, 0xC1},
- {0x3A, 0xC2}, {0x05, 0xC3},
- {0x04, 0xC4}, {0x3F, 0xC5},
- {0x00, 0xC6}, {0x00, 0xC7},
- {0x50, 0xC8}, {0x3C, 0xC9},
- {0x28, 0xCA}, {0xD8, 0xCB},
- {0x14, 0xCC}, {0xEC, 0xCD},
- {0x32, 0xCE}, {0xDD, 0xCF},
- {0x32, 0xD0}, {0xDD, 0xD1},
- {0x6A, 0xD2}, {0x50, 0xD3},
- {0x00, 0xD4}, {0x00, 0xD5},
- {0x00, 0xD6});
+ {0x05, 0x9a}, {0x00, 0x9b},
+ {0x04, 0x9c}, {0x00, 0x9d},
+ {0x08, 0x9e}, {0x00, 0x9f},
+ {0x2d, 0xc0}, {0x2d, 0xc1},
+ {0x3a, 0xc2}, {0x05, 0xc3},
+ {0x04, 0xc4}, {0x3f, 0xc5},
+ {0x00, 0xc6}, {0x00, 0xc7},
+ {0x50, 0xc8}, {0x3C, 0xc9},
+ {0x28, 0xca}, {0xd8, 0xcb},
+ {0x14, 0xcc}, {0xec, 0xcd},
+ {0x32, 0xce}, {0xdd, 0xcf},
+ {0x32, 0xd0}, {0xdd, 0xd1},
+ {0x6a, 0xd2}, {0x50, 0xd3},
+ {0x00, 0xd4}, {0x00, 0xd5},
+ {0x00, 0xd6});
err += sn9c102_i2c_write(cam, 0x12, 0x80);
err += sn9c102_i2c_write(cam, 0x11, 0x09);
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 3e736be5de84..eb220461ac77 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1321,7 +1321,7 @@ static int saa_ioctl(struct inode *inode, struct file *file,
u32 format;
if (copy_from_user(&p, arg, sizeof(p)))
return -EFAULT;
- if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
+ if (p.palette < ARRAY_SIZE(palette2fmt)) {
format = palette2fmt[p.palette];
saa->win.color_fmt = format;
saawrite(format | 0x60,
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index bf3aa8d2d57e..9e009a7ab863 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -499,13 +499,14 @@ exit:
* sysfs
***************************************************************************/
#define stv680_file(name, variable, field) \
-static ssize_t show_##name(struct class_device *class_dev, char *buf) \
+static ssize_t show_##name(struct device *class_dev, \
+ struct device_attribute *attr, char *buf) \
{ \
struct video_device *vdev = to_video_device(class_dev); \
struct usb_stv *stv = video_get_drvdata(vdev); \
return sprintf(buf, field, stv->variable); \
} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
stv680_file(model, camera_name, "%s\n");
stv680_file(in_use, user, "%d\n");
@@ -520,53 +521,53 @@ static int stv680_create_sysfs_files(struct video_device *vdev)
{
int rc;
- rc = video_device_create_file(vdev, &class_device_attr_model);
+ rc = video_device_create_file(vdev, &dev_attr_model);
if (rc) goto err;
- rc = video_device_create_file(vdev, &class_device_attr_in_use);
+ rc = video_device_create_file(vdev, &dev_attr_in_use);
if (rc) goto err_model;
- rc = video_device_create_file(vdev, &class_device_attr_streaming);
+ rc = video_device_create_file(vdev, &dev_attr_streaming);
if (rc) goto err_inuse;
- rc = video_device_create_file(vdev, &class_device_attr_palette);
+ rc = video_device_create_file(vdev, &dev_attr_palette);
if (rc) goto err_stream;
- rc = video_device_create_file(vdev, &class_device_attr_frames_total);
+ rc = video_device_create_file(vdev, &dev_attr_frames_total);
if (rc) goto err_pal;
- rc = video_device_create_file(vdev, &class_device_attr_frames_read);
+ rc = video_device_create_file(vdev, &dev_attr_frames_read);
if (rc) goto err_framtot;
- rc = video_device_create_file(vdev, &class_device_attr_packets_dropped);
+ rc = video_device_create_file(vdev, &dev_attr_packets_dropped);
if (rc) goto err_framread;
- rc = video_device_create_file(vdev, &class_device_attr_decoding_errors);
+ rc = video_device_create_file(vdev, &dev_attr_decoding_errors);
if (rc) goto err_dropped;
return 0;
err_dropped:
- video_device_remove_file(vdev, &class_device_attr_packets_dropped);
+ video_device_remove_file(vdev, &dev_attr_packets_dropped);
err_framread:
- video_device_remove_file(vdev, &class_device_attr_frames_read);
+ video_device_remove_file(vdev, &dev_attr_frames_read);
err_framtot:
- video_device_remove_file(vdev, &class_device_attr_frames_total);
+ video_device_remove_file(vdev, &dev_attr_frames_total);
err_pal:
- video_device_remove_file(vdev, &class_device_attr_palette);
+ video_device_remove_file(vdev, &dev_attr_palette);
err_stream:
- video_device_remove_file(vdev, &class_device_attr_streaming);
+ video_device_remove_file(vdev, &dev_attr_streaming);
err_inuse:
- video_device_remove_file(vdev, &class_device_attr_in_use);
+ video_device_remove_file(vdev, &dev_attr_in_use);
err_model:
- video_device_remove_file(vdev, &class_device_attr_model);
+ video_device_remove_file(vdev, &dev_attr_model);
err:
return rc;
}
static void stv680_remove_sysfs_files(struct video_device *vdev)
{
- video_device_remove_file(vdev, &class_device_attr_model);
- video_device_remove_file(vdev, &class_device_attr_in_use);
- video_device_remove_file(vdev, &class_device_attr_streaming);
- video_device_remove_file(vdev, &class_device_attr_palette);
- video_device_remove_file(vdev, &class_device_attr_frames_total);
- video_device_remove_file(vdev, &class_device_attr_frames_read);
- video_device_remove_file(vdev, &class_device_attr_packets_dropped);
- video_device_remove_file(vdev, &class_device_attr_decoding_errors);
+ video_device_remove_file(vdev, &dev_attr_model);
+ video_device_remove_file(vdev, &dev_attr_in_use);
+ video_device_remove_file(vdev, &dev_attr_streaming);
+ video_device_remove_file(vdev, &dev_attr_palette);
+ video_device_remove_file(vdev, &dev_attr_frames_total);
+ video_device_remove_file(vdev, &dev_attr_frames_read);
+ video_device_remove_file(vdev, &dev_attr_packets_dropped);
+ video_device_remove_file(vdev, &dev_attr_decoding_errors);
}
/********************************************************************
@@ -715,8 +716,11 @@ static int stv680_start_stream (struct usb_stv *stv680)
stv680_video_irq, stv680);
stv680->urb[i] = urb;
err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
- if (err)
- PDEBUG (0, "STV(e): urb burned down in start stream");
+ if (err) {
+ PDEBUG (0, "STV(e): urb burned down with err "
+ "%d in start stream %d", err, i);
+ goto nomem_err;
+ }
} /* i STV680_NUMSBUF */
stv680->framecount = 0;
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
new file mode 100644
index 000000000000..41cd6a0b0485
--- /dev/null
+++ b/drivers/media/video/tcm825x.c
@@ -0,0 +1,928 @@
+/*
+ * drivers/media/video/tcm825x.c
+ *
+ * TCM825X camera sensor driver.
+ *
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * Based on code from David Cohen <david.cohen@indt.org.br>
+ *
+ * This driver was based on ov9640 sensor driver from MontaVista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/i2c.h>
+#include <media/v4l2-int-device.h>
+
+#include "tcm825x.h"
+
+/*
+ * The sensor has two fps modes: the lower one just gives half the fps
+ * at the same xclk than the high one.
+ */
+#define MAX_FPS 30
+#define MIN_FPS 8
+#define MAX_HALF_FPS (MAX_FPS / 2)
+#define HIGH_FPS_MODE_LOWER_LIMIT 14
+#define DEFAULT_FPS MAX_HALF_FPS
+
+struct tcm825x_sensor {
+ const struct tcm825x_platform_data *platform_data;
+ struct v4l2_int_device *v4l2_int_device;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+};
+
+/* list of image formats supported by TCM825X sensor */
+const static struct v4l2_fmtdesc tcm825x_formats[] = {
+ {
+ .description = "YUYV (YUV 4:2:2), packed",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ }, {
+ /* Note: V4L2 defines RGB565 as:
+ *
+ * Byte 0 Byte 1
+ * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3
+ *
+ * We interpret RGB565 as:
+ *
+ * Byte 0 Byte 1
+ * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3
+ */
+ .description = "RGB565, le",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ },
+};
+
+#define TCM825X_NUM_CAPTURE_FORMATS ARRAY_SIZE(tcm825x_formats)
+
+/*
+ * TCM825X register configuration for all combinations of pixel format and
+ * image size
+ */
+const static struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ };
+const static struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ };
+const static struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ };
+const static struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ };
+const static struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ };
+const static struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ };
+
+const static struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT };
+const static struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT };
+
+/* Our own specific controls */
+#define V4L2_CID_ALC V4L2_CID_PRIVATE_BASE
+#define V4L2_CID_H_EDGE_EN V4L2_CID_PRIVATE_BASE + 1
+#define V4L2_CID_V_EDGE_EN V4L2_CID_PRIVATE_BASE + 2
+#define V4L2_CID_LENS V4L2_CID_PRIVATE_BASE + 3
+#define V4L2_CID_MAX_EXPOSURE_TIME V4L2_CID_PRIVATE_BASE + 4
+#define V4L2_CID_LAST_PRIV V4L2_CID_MAX_EXPOSURE_TIME
+
+/* Video controls */
+static struct vcontrol {
+ struct v4l2_queryctrl qc;
+ u16 reg;
+ u16 start_bit;
+} video_control[] = {
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+ .maximum = 63,
+ .step = 1,
+ },
+ .reg = TCM825X_AG,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ },
+ .reg = TCM825X_MRG,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ },
+ .reg = TCM825X_MBG,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto White Balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 0,
+ },
+ .reg = TCM825X_AWBSW,
+ .start_bit = 7,
+ },
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Time",
+ .minimum = 0,
+ .maximum = 0x1fff,
+ .step = 1,
+ },
+ .reg = TCM825X_ESRSPD_U,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Image",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 0,
+ },
+ .reg = TCM825X_H_INV,
+ .start_bit = 6,
+ },
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 0,
+ },
+ .reg = TCM825X_V_INV,
+ .start_bit = 7,
+ },
+ /* Private controls */
+ {
+ {
+ .id = V4L2_CID_ALC,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Luminance Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 0,
+ },
+ .reg = TCM825X_ALCSW,
+ .start_bit = 7,
+ },
+ {
+ {
+ .id = V4L2_CID_H_EDGE_EN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Horizontal Edge Enhancement",
+ .minimum = 0,
+ .maximum = 0xff,
+ .step = 1,
+ },
+ .reg = TCM825X_HDTG,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_V_EDGE_EN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Vertical Edge Enhancement",
+ .minimum = 0,
+ .maximum = 0xff,
+ .step = 1,
+ },
+ .reg = TCM825X_VDTG,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_LENS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Lens Shading Compensation",
+ .minimum = 0,
+ .maximum = 0x3f,
+ .step = 1,
+ },
+ .reg = TCM825X_LENS,
+ .start_bit = 0,
+ },
+ {
+ {
+ .id = V4L2_CID_MAX_EXPOSURE_TIME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Maximum Exposure Time",
+ .minimum = 0,
+ .maximum = 0x3,
+ .step = 1,
+ },
+ .reg = TCM825X_ESRLIM,
+ .start_bit = 5,
+ },
+};
+
+
+const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
+{ &subqcif, &qqvga, &qcif, &qvga, &cif, &vga };
+
+const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
+{ &yuv422, &rgb565 };
+
+/*
+ * Read a value from a register in an TCM825X sensor device. The value is
+ * returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_read_reg(struct i2c_client *client, int reg)
+{
+ int err;
+ struct i2c_msg msg[2];
+ u8 reg_buf, data_buf = 0;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &reg_buf;
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = &data_buf;
+
+ reg_buf = reg;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (err < 0)
+ return err;
+ return data_buf;
+}
+
+/*
+ * Write a value to a register in an TCM825X sensor device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg->addr = client->addr;
+ msg->flags = 0;
+ msg->len = 2;
+ msg->buf = data;
+ data[0] = reg;
+ data[1] = val;
+ err = i2c_transfer(client->adapter, msg, 1);
+ if (err >= 0)
+ return 0;
+ return err;
+}
+
+static int __tcm825x_write_reg_mask(struct i2c_client *client,
+ u8 reg, u8 val, u8 mask)
+{
+ int rc;
+
+ /* need to do read - modify - write */
+ rc = tcm825x_read_reg(client, reg);
+ if (rc < 0)
+ return rc;
+
+ rc &= (~mask); /* Clear the masked bits */
+ val &= mask; /* Enforce mask on value */
+ val |= rc;
+
+ /* write the new value to the register */
+ rc = tcm825x_write_reg(client, reg, val);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+#define tcm825x_write_reg_mask(client, regmask, val) \
+ __tcm825x_write_reg_mask(client, TCM825X_ADDR((regmask)), val, \
+ TCM825X_MASK((regmask)))
+
+
+/*
+ * Initialize a list of TCM825X registers.
+ * The list of registers is terminated by the pair of values
+ * { TCM825X_REG_TERM, TCM825X_VAL_TERM }.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_write_default_regs(struct i2c_client *client,
+ const struct tcm825x_reg *reglist)
+{
+ int err;
+ const struct tcm825x_reg *next = reglist;
+
+ while (!((next->reg == TCM825X_REG_TERM)
+ && (next->val == TCM825X_VAL_TERM))) {
+ err = tcm825x_write_reg(client, next->reg, next->val);
+ if (err) {
+ dev_err(&client->dev, "register writing failed\n");
+ return err;
+ }
+ next++;
+ }
+
+ return 0;
+}
+
+static struct vcontrol *find_vctrl(int id)
+{
+ int i;
+
+ if (id < V4L2_CID_BASE)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(video_control); i++)
+ if (video_control[i].qc.id == id)
+ return &video_control[i];
+
+ return NULL;
+}
+
+/*
+ * Find the best match for a requested image capture size. The best match
+ * is chosen as the nearest match that has the same number or fewer pixels
+ * as the requested size, or the smallest image size if the requested size
+ * has fewer pixels than the smallest image.
+ */
+static enum image_size tcm825x_find_size(struct v4l2_int_device *s,
+ unsigned int width,
+ unsigned int height)
+{
+ enum image_size isize;
+ unsigned long pixels = width * height;
+ struct tcm825x_sensor *sensor = s->priv;
+
+ for (isize = subQCIF; isize < VGA; isize++) {
+ if (tcm825x_sizes[isize + 1].height
+ * tcm825x_sizes[isize + 1].width > pixels) {
+ dev_dbg(&sensor->i2c_client->dev, "size %d\n", isize);
+
+ return isize;
+ }
+ }
+
+ dev_dbg(&sensor->i2c_client->dev, "format default VGA\n");
+
+ return VGA;
+}
+
+/*
+ * Configure the TCM825X for current image size, pixel format, and
+ * frame period. fper is the frame period (in seconds) expressed as a
+ * fraction. Returns zero if successful, or non-zero otherwise. The
+ * actual frame period is returned in fper.
+ */
+static int tcm825x_configure(struct v4l2_int_device *s)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct v4l2_pix_format *pix = &sensor->pix;
+ enum image_size isize = tcm825x_find_size(s, pix->width, pix->height);
+ struct v4l2_fract *fper = &sensor->timeperframe;
+ enum pixel_format pfmt;
+ int err;
+ u32 tgt_fps;
+ u8 val;
+
+ /* common register initialization */
+ err = tcm825x_write_default_regs(
+ sensor->i2c_client, sensor->platform_data->default_regs());
+ if (err)
+ return err;
+
+ /* configure image size */
+ val = tcm825x_siz_reg[isize]->val;
+ dev_dbg(&sensor->i2c_client->dev,
+ "configuring image size %d\n", isize);
+ err = tcm825x_write_reg_mask(sensor->i2c_client,
+ tcm825x_siz_reg[isize]->reg, val);
+ if (err)
+ return err;
+
+ /* configure pixel format */
+ switch (pix->pixelformat) {
+ default:
+ case V4L2_PIX_FMT_RGB565:
+ pfmt = RGB565;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ pfmt = YUV422;
+ break;
+ }
+
+ dev_dbg(&sensor->i2c_client->dev,
+ "configuring pixel format %d\n", pfmt);
+ val = tcm825x_fmt_reg[pfmt]->val;
+
+ err = tcm825x_write_reg_mask(sensor->i2c_client,
+ tcm825x_fmt_reg[pfmt]->reg, val);
+ if (err)
+ return err;
+
+ /*
+ * For frame rate < 15, the FPS reg (addr 0x02, bit 7) must be
+ * set. Frame rate will be halved from the normal.
+ */
+ tgt_fps = fper->denominator / fper->numerator;
+ if (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) {
+ val = tcm825x_read_reg(sensor->i2c_client, 0x02);
+ val |= 0x80;
+ tcm825x_write_reg(sensor->i2c_client, 0x02, val);
+ }
+
+ return 0;
+}
+
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+ struct v4l2_queryctrl *qc)
+{
+ struct vcontrol *control;
+
+ control = find_vctrl(qc->id);
+
+ if (control == NULL)
+ return -EINVAL;
+
+ *qc = control->qc;
+
+ return 0;
+}
+
+static int ioctl_g_ctrl(struct v4l2_int_device *s,
+ struct v4l2_control *vc)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct i2c_client *client = sensor->i2c_client;
+ int val, r;
+ struct vcontrol *lvc;
+
+ /* exposure time is special, spread accross 2 registers */
+ if (vc->id == V4L2_CID_EXPOSURE) {
+ int val_lower, val_upper;
+
+ val_upper = tcm825x_read_reg(client,
+ TCM825X_ADDR(TCM825X_ESRSPD_U));
+ if (val_upper < 0)
+ return val_upper;
+ val_lower = tcm825x_read_reg(client,
+ TCM825X_ADDR(TCM825X_ESRSPD_L));
+ if (val_lower < 0)
+ return val_lower;
+
+ vc->value = ((val_upper & 0x1f) << 8) | (val_lower);
+ return 0;
+ }
+
+ lvc = find_vctrl(vc->id);
+ if (lvc == NULL)
+ return -EINVAL;
+
+ r = tcm825x_read_reg(client, TCM825X_ADDR(lvc->reg));
+ if (r < 0)
+ return r;
+ val = r & TCM825X_MASK(lvc->reg);
+ val >>= lvc->start_bit;
+
+ if (val < 0)
+ return val;
+
+ vc->value = val;
+ return 0;
+}
+
+static int ioctl_s_ctrl(struct v4l2_int_device *s,
+ struct v4l2_control *vc)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct i2c_client *client = sensor->i2c_client;
+ struct vcontrol *lvc;
+ int val = vc->value;
+
+ /* exposure time is special, spread accross 2 registers */
+ if (vc->id == V4L2_CID_EXPOSURE) {
+ int val_lower, val_upper;
+ val_lower = val & TCM825X_MASK(TCM825X_ESRSPD_L);
+ val_upper = (val >> 8) & TCM825X_MASK(TCM825X_ESRSPD_U);
+
+ if (tcm825x_write_reg_mask(client,
+ TCM825X_ESRSPD_U, val_upper))
+ return -EIO;
+
+ if (tcm825x_write_reg_mask(client,
+ TCM825X_ESRSPD_L, val_lower))
+ return -EIO;
+
+ return 0;
+ }
+
+ lvc = find_vctrl(vc->id);
+ if (lvc == NULL)
+ return -EINVAL;
+
+ val = val << lvc->start_bit;
+ if (tcm825x_write_reg_mask(client, lvc->reg, val))
+ return -EIO;
+
+ return 0;
+}
+
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_fmtdesc *fmt)
+{
+ int index = fmt->index;
+
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (index >= TCM825X_NUM_CAPTURE_FORMATS)
+ return -EINVAL;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ fmt->flags = tcm825x_formats[index].flags;
+ strlcpy(fmt->description, tcm825x_formats[index].description,
+ sizeof(fmt->description));
+ fmt->pixelformat = tcm825x_formats[index].pixelformat;
+
+ return 0;
+}
+
+static int ioctl_try_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_format *f)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ enum image_size isize;
+ int ifmt;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ isize = tcm825x_find_size(s, pix->width, pix->height);
+ dev_dbg(&sensor->i2c_client->dev, "isize = %d num_capture = %lu\n",
+ isize, (unsigned long)TCM825X_NUM_CAPTURE_FORMATS);
+
+ pix->width = tcm825x_sizes[isize].width;
+ pix->height = tcm825x_sizes[isize].height;
+
+ for (ifmt = 0; ifmt < TCM825X_NUM_CAPTURE_FORMATS; ifmt++)
+ if (pix->pixelformat == tcm825x_formats[ifmt].pixelformat)
+ break;
+
+ if (ifmt == TCM825X_NUM_CAPTURE_FORMATS)
+ ifmt = 0; /* Default = YUV 4:2:2 */
+
+ pix->pixelformat = tcm825x_formats[ifmt].pixelformat;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = pix->width * TCM825X_BYTES_PER_PIXEL;
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->priv = 0;
+ dev_dbg(&sensor->i2c_client->dev, "format = 0x%08x\n",
+ pix->pixelformat);
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_UYVY:
+ default:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ break;
+ }
+
+ return 0;
+}
+
+static int ioctl_s_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_format *f)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ int rval;
+
+ rval = ioctl_try_fmt_cap(s, f);
+ if (rval)
+ return rval;
+
+ rval = tcm825x_configure(s);
+
+ sensor->pix = *pix;
+
+ return rval;
+}
+
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s,
+ struct v4l2_format *f)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+
+ f->fmt.pix = sensor->pix;
+
+ return 0;
+}
+
+static int ioctl_g_parm(struct v4l2_int_device *s,
+ struct v4l2_streamparm *a)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ cparm->capability = V4L2_CAP_TIMEPERFRAME;
+ cparm->timeperframe = sensor->timeperframe;
+
+ return 0;
+}
+
+static int ioctl_s_parm(struct v4l2_int_device *s,
+ struct v4l2_streamparm *a)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+ u32 tgt_fps; /* target frames per secound */
+ int rval;
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if ((timeperframe->numerator == 0)
+ || (timeperframe->denominator == 0)) {
+ timeperframe->denominator = DEFAULT_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ tgt_fps = timeperframe->denominator / timeperframe->numerator;
+
+ if (tgt_fps > MAX_FPS) {
+ timeperframe->denominator = MAX_FPS;
+ timeperframe->numerator = 1;
+ } else if (tgt_fps < MIN_FPS) {
+ timeperframe->denominator = MIN_FPS;
+ timeperframe->numerator = 1;
+ }
+
+ sensor->timeperframe = *timeperframe;
+
+ rval = tcm825x_configure(s);
+
+ return rval;
+}
+
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+
+ return sensor->platform_data->power_set(on);
+}
+
+/*
+ * Given the image capture format in pix, the nominal frame period in
+ * timeperframe, calculate the required xclk frequency.
+ *
+ * TCM825X input frequency characteristics are:
+ * Minimum 11.9 MHz, Typical 24.57 MHz and maximum 25/27 MHz
+ */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ struct v4l2_fract *timeperframe = &sensor->timeperframe;
+ u32 tgt_xclk; /* target xclk */
+ u32 tgt_fps; /* target frames per secound */
+ int rval;
+
+ rval = sensor->platform_data->ifparm(p);
+ if (rval)
+ return rval;
+
+ tgt_fps = timeperframe->denominator / timeperframe->numerator;
+
+ tgt_xclk = (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) ?
+ (2457 * tgt_fps) / MAX_HALF_FPS :
+ (2457 * tgt_fps) / MAX_FPS;
+ tgt_xclk *= 10000;
+
+ tgt_xclk = min(tgt_xclk, (u32)TCM825X_XCLK_MAX);
+ tgt_xclk = max(tgt_xclk, (u32)TCM825X_XCLK_MIN);
+
+ p->u.bt656.clock_curr = tgt_xclk;
+
+ return 0;
+}
+
+static int ioctl_g_needs_reset(struct v4l2_int_device *s, void *buf)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+
+ return sensor->platform_data->needs_reset(s, buf, &sensor->pix);
+}
+
+static int ioctl_reset(struct v4l2_int_device *s)
+{
+ return -EBUSY;
+}
+
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ return tcm825x_configure(s);
+}
+
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+ return 0;
+}
+
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ struct tcm825x_sensor *sensor = s->priv;
+ int r;
+
+ r = tcm825x_read_reg(sensor->i2c_client, 0x01);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ dev_err(&sensor->i2c_client->dev, "device not detected\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static struct v4l2_int_ioctl_desc tcm825x_ioctl_desc[] = {
+ { vidioc_int_dev_init_num,
+ (v4l2_int_ioctl_func *)ioctl_dev_init },
+ { vidioc_int_dev_exit_num,
+ (v4l2_int_ioctl_func *)ioctl_dev_exit },
+ { vidioc_int_s_power_num,
+ (v4l2_int_ioctl_func *)ioctl_s_power },
+ { vidioc_int_g_ifparm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+ { vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset },
+ { vidioc_int_reset_num,
+ (v4l2_int_ioctl_func *)ioctl_reset },
+ { vidioc_int_init_num,
+ (v4l2_int_ioctl_func *)ioctl_init },
+ { vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+ { vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap },
+ { vidioc_int_g_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+ { vidioc_int_s_fmt_cap_num,
+ (v4l2_int_ioctl_func *)ioctl_s_fmt_cap },
+ { vidioc_int_g_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_g_parm },
+ { vidioc_int_s_parm_num,
+ (v4l2_int_ioctl_func *)ioctl_s_parm },
+ { vidioc_int_queryctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_queryctrl },
+ { vidioc_int_g_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+ { vidioc_int_s_ctrl_num,
+ (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+};
+
+static struct v4l2_int_slave tcm825x_slave = {
+ .ioctls = tcm825x_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(tcm825x_ioctl_desc),
+};
+
+static struct tcm825x_sensor tcm825x;
+
+static struct v4l2_int_device tcm825x_int_device = {
+ .module = THIS_MODULE,
+ .name = TCM825X_NAME,
+ .priv = &tcm825x,
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &tcm825x_slave,
+ },
+};
+
+static int tcm825x_probe(struct i2c_client *client)
+{
+ struct tcm825x_sensor *sensor = &tcm825x;
+ int rval;
+
+ if (i2c_get_clientdata(client))
+ return -EBUSY;
+
+ sensor->platform_data = client->dev.platform_data;
+
+ if (sensor->platform_data == NULL
+ && !sensor->platform_data->is_okay())
+ return -ENODEV;
+
+ sensor->v4l2_int_device = &tcm825x_int_device;
+
+ sensor->i2c_client = client;
+ i2c_set_clientdata(client, sensor);
+
+ /* Make the default capture format QVGA RGB565 */
+ sensor->pix.width = tcm825x_sizes[QVGA].width;
+ sensor->pix.height = tcm825x_sizes[QVGA].height;
+ sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
+
+ rval = v4l2_int_device_register(sensor->v4l2_int_device);
+ if (rval)
+ i2c_set_clientdata(client, NULL);
+
+ return rval;
+}
+
+static int __exit tcm825x_remove(struct i2c_client *client)
+{
+ struct tcm825x_sensor *sensor = i2c_get_clientdata(client);
+
+ if (!client->adapter)
+ return -ENODEV; /* our client isn't attached */
+
+ v4l2_int_device_unregister(sensor->v4l2_int_device);
+ i2c_set_clientdata(client, NULL);
+
+ return 0;
+}
+
+static struct i2c_driver tcm825x_i2c_driver = {
+ .driver = {
+ .name = TCM825X_NAME,
+ },
+ .probe = tcm825x_probe,
+ .remove = __exit_p(tcm825x_remove),
+};
+
+static struct tcm825x_sensor tcm825x = {
+ .timeperframe = {
+ .numerator = 1,
+ .denominator = DEFAULT_FPS,
+ },
+};
+
+static int __init tcm825x_init(void)
+{
+ int rval;
+
+ rval = i2c_add_driver(&tcm825x_i2c_driver);
+ if (rval)
+ printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
+ __FUNCTION__);
+
+ return rval;
+}
+
+static void __exit tcm825x_exit(void)
+{
+ i2c_del_driver(&tcm825x_i2c_driver);
+}
+
+/*
+ * FIXME: Menelaus isn't ready (?) at module_init stage, so use
+ * late_initcall for now.
+ */
+late_initcall(tcm825x_init);
+module_exit(tcm825x_exit);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("TCM825x camera sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tcm825x.h b/drivers/media/video/tcm825x.h
new file mode 100644
index 000000000000..966765b66b3a
--- /dev/null
+++ b/drivers/media/video/tcm825x.h
@@ -0,0 +1,199 @@
+/*
+ * drivers/media/video/tcm825x.h
+ *
+ * Register definitions for the TCM825X CameraChip.
+ *
+ * Author: David Cohen (david.cohen@indt.org.br)
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * This file was based on ov9640.h from MontaVista
+ */
+
+#ifndef TCM825X_H
+#define TCM825X_H
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-int-device.h>
+
+#define TCM825X_NAME "tcm825x"
+
+#define TCM825X_MASK(x) x & 0x00ff
+#define TCM825X_ADDR(x) (x & 0xff00) >> 8
+
+/* The TCM825X I2C sensor chip has a fixed slave address of 0x3d. */
+#define TCM825X_I2C_ADDR 0x3d
+
+/*
+ * define register offsets for the TCM825X sensor chip
+ * OFFSET(8 bits) + MASK(8 bits)
+ * MASK bit 4 and 3 are used when the register uses more than one address
+ */
+#define TCM825X_FPS 0x0280
+#define TCM825X_ACF 0x0240
+#define TCM825X_DOUTBUF 0x020C
+#define TCM825X_DCLKP 0x0202
+#define TCM825X_ACFDET 0x0201
+#define TCM825X_DOUTSW 0x0380
+#define TCM825X_DATAHZ 0x0340
+#define TCM825X_PICSIZ 0x033c
+#define TCM825X_PICFMT 0x0302
+#define TCM825X_V_INV 0x0480
+#define TCM825X_H_INV 0x0440
+#define TCM825X_ESRLSW 0x0430
+#define TCM825X_V_LENGTH 0x040F
+#define TCM825X_ALCSW 0x0580
+#define TCM825X_ESRLIM 0x0560
+#define TCM825X_ESRSPD_U 0x051F
+#define TCM825X_ESRSPD_L 0x06FF
+#define TCM825X_AG 0x07FF
+#define TCM825X_ESRSPD2 0x06FF
+#define TCM825X_ALCMODE 0x0830
+#define TCM825X_ALCH 0x080F
+#define TCM825X_ALCL 0x09FF
+#define TCM825X_AWBSW 0x0A80
+#define TCM825X_MRG 0x0BFF
+#define TCM825X_MBG 0x0CFF
+#define TCM825X_GAMSW 0x0D80
+#define TCM825X_HDTG 0x0EFF
+#define TCM825X_VDTG 0x0FFF
+#define TCM825X_HDTCORE 0x10F0
+#define TCM825X_VDTCORE 0x100F
+#define TCM825X_CONT 0x11FF
+#define TCM825X_BRIGHT 0x12FF
+#define TCM825X_VHUE 0x137F
+#define TCM825X_UHUE 0x147F
+#define TCM825X_VGAIN 0x153F
+#define TCM825X_UGAIN 0x163F
+#define TCM825X_UVCORE 0x170F
+#define TCM825X_SATU 0x187F
+#define TCM825X_MHMODE 0x1980
+#define TCM825X_MHLPFSEL 0x1940
+#define TCM825X_YMODE 0x1930
+#define TCM825X_MIXHG 0x1907
+#define TCM825X_LENS 0x1A3F
+#define TCM825X_AGLIM 0x1BE0
+#define TCM825X_LENSRPOL 0x1B10
+#define TCM825X_LENSRGAIN 0x1B0F
+#define TCM825X_ES100S 0x1CFF
+#define TCM825X_ES120S 0x1DFF
+#define TCM825X_DMASK 0x1EC0
+#define TCM825X_CODESW 0x1E20
+#define TCM825X_CODESEL 0x1E10
+#define TCM825X_TESPIC 0x1E04
+#define TCM825X_PICSEL 0x1E03
+#define TCM825X_HNUM 0x20FF
+#define TCM825X_VOUTPH 0x287F
+#define TCM825X_ESROUT 0x327F
+#define TCM825X_ESROUT2 0x33FF
+#define TCM825X_AGOUT 0x34FF
+#define TCM825X_DGOUT 0x353F
+#define TCM825X_AGSLOW1 0x39C0
+#define TCM825X_FLLSMODE 0x3930
+#define TCM825X_FLLSLIM 0x390F
+#define TCM825X_DETSEL 0x3AF0
+#define TCM825X_ACDETNC 0x3A0F
+#define TCM825X_AGSLOW2 0x3BC0
+#define TCM825X_DG 0x3B3F
+#define TCM825X_REJHLEV 0x3CFF
+#define TCM825X_ALCLOCK 0x3D80
+#define TCM825X_FPSLNKSW 0x3D40
+#define TCM825X_ALCSPD 0x3D30
+#define TCM825X_REJH 0x3D03
+#define TCM825X_SHESRSW 0x3E80
+#define TCM825X_ESLIMSEL 0x3E40
+#define TCM825X_SHESRSPD 0x3E30
+#define TCM825X_ELSTEP 0x3E0C
+#define TCM825X_ELSTART 0x3E03
+#define TCM825X_AGMIN 0x3FFF
+#define TCM825X_PREGRG 0x423F
+#define TCM825X_PREGBG 0x433F
+#define TCM825X_PRERG 0x443F
+#define TCM825X_PREBG 0x453F
+#define TCM825X_MSKBR 0x477F
+#define TCM825X_MSKGR 0x487F
+#define TCM825X_MSKRB 0x497F
+#define TCM825X_MSKGB 0x4A7F
+#define TCM825X_MSKRG 0x4B7F
+#define TCM825X_MSKBG 0x4C7F
+#define TCM825X_HDTCSW 0x4D80
+#define TCM825X_VDTCSW 0x4D40
+#define TCM825X_DTCYL 0x4D3F
+#define TCM825X_HDTPSW 0x4E80
+#define TCM825X_VDTPSW 0x4E40
+#define TCM825X_DTCGAIN 0x4E3F
+#define TCM825X_DTLLIMSW 0x4F10
+#define TCM825X_DTLYLIM 0x4F0F
+#define TCM825X_YLCUTLMSK 0x5080
+#define TCM825X_YLCUTL 0x503F
+#define TCM825X_YLCUTHMSK 0x5180
+#define TCM825X_YLCUTH 0x513F
+#define TCM825X_UVSKNC 0x527F
+#define TCM825X_UVLJ 0x537F
+#define TCM825X_WBGMIN 0x54FF
+#define TCM825X_WBGMAX 0x55FF
+#define TCM825X_WBSPDUP 0x5603
+#define TCM825X_ALLAREA 0x5820
+#define TCM825X_WBLOCK 0x5810
+#define TCM825X_WB2SP 0x580F
+#define TCM825X_KIZUSW 0x5920
+#define TCM825X_PBRSW 0x5910
+#define TCM825X_ABCSW 0x5903
+#define TCM825X_PBDLV 0x5AFF
+#define TCM825X_PBC1LV 0x5BFF
+
+#define TCM825X_NUM_REGS (TCM825X_ADDR(TCM825X_PBC1LV) + 1)
+
+#define TCM825X_BYTES_PER_PIXEL 2
+
+#define TCM825X_REG_TERM 0xff /* terminating list entry for reg */
+#define TCM825X_VAL_TERM 0xff /* terminating list entry for val */
+
+/* define a structure for tcm825x register initialization values */
+struct tcm825x_reg {
+ u8 val;
+ u16 reg;
+};
+
+enum image_size { subQCIF = 0, QQVGA, QCIF, QVGA, CIF, VGA };
+enum pixel_format { YUV422 = 0, RGB565 };
+#define NUM_IMAGE_SIZES 6
+#define NUM_PIXEL_FORMATS 2
+
+#define TCM825X_XCLK_MIN 11900000
+#define TCM825X_XCLK_MAX 25000000
+
+struct capture_size {
+ unsigned long width;
+ unsigned long height;
+};
+
+struct tcm825x_platform_data {
+ /* Is the sensor usable? Doesn't yet mean it's there, but you
+ * can try! */
+ int (*is_okay)(void);
+ /* Set power state, zero is off, non-zero is on. */
+ int (*power_set)(int power);
+ /* Default registers written after power-on or reset. */
+ const struct tcm825x_reg *(*default_regs)(void);
+ int (*needs_reset)(struct v4l2_int_device *s, void *buf,
+ struct v4l2_pix_format *fmt);
+ int (*ifparm)(struct v4l2_ifparm *p);
+};
+
+/* Array of image sizes supported by TCM825X. These must be ordered from
+ * smallest image size to largest.
+ */
+const static struct capture_size tcm825x_sizes[] = {
+ { 128, 96 }, /* subQCIF */
+ { 160, 120 }, /* QQVGA */
+ { 176, 144 }, /* QCIF */
+ { 320, 240 }, /* QVGA */
+ { 352, 288 }, /* CIF */
+ { 640, 480 }, /* VGA */
+};
+
+#endif /* ifndef TCM825X_H */
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 1a1bef0e9c3d..0e5cf459d3ed 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -16,12 +16,38 @@
You 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.
+
+ This "tda8290" module was split apart from the original "tuner" module.
*/
#include <linux/i2c.h>
-#include <linux/videodev.h>
#include <linux/delay.h>
-#include <media/tuner.h>
+#include <linux/videodev.h>
+#include "tuner-i2c.h"
+#include "tda8290.h"
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+#define PREFIX "tda8290 "
+
+/* ---------------------------------------------------------------------- */
+
+struct tda8290_priv {
+ struct tuner_i2c_props i2c_props;
+
+ unsigned char tda8290_easy_mode;
+ unsigned char tda827x_lpsel;
+ unsigned char tda827x_addr;
+ unsigned char tda827x_ver;
+ unsigned int sgIF;
+
+ u32 frequency;
+
+ unsigned int *lna_cfg;
+ int (*tuner_callback) (void *dev, int command,int arg);
+};
/* ---------------------------------------------------------------------- */
@@ -69,19 +95,21 @@ static struct tda827x_data tda827x_analog[] = {
{ .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */
};
-static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
+static void tda827x_set_analog_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
unsigned char tuner_reg[8];
unsigned char reg2[2];
u32 N;
int i;
- struct tuner *t = i2c_get_clientdata(c);
- struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0};
+ struct tda8290_priv *priv = fe->tuner_priv;
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0};
+ unsigned int freq = params->frequency;
- if (t->mode == V4L2_TUNER_RADIO)
+ if (params->mode == V4L2_TUNER_RADIO)
freq = freq / 1000;
- N = freq + ifc;
+ N = freq + priv->sgIF;
i = 0;
while (tda827x_analog[i].lomax < N) {
if(tda827x_analog[i + 1].lomax == 0)
@@ -95,7 +123,7 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
tuner_reg[1] = (unsigned char)(N>>8);
tuner_reg[2] = (unsigned char) N;
tuner_reg[3] = 0x40;
- tuner_reg[4] = 0x52 + (t->tda827x_lpsel << 5);
+ tuner_reg[4] = 0x52 + (priv->tda827x_lpsel << 5);
tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) +
(tda827x_analog[i].bs <<3) + tda827x_analog[i].bp;
tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4);
@@ -103,53 +131,53 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
msg.buf = tuner_reg;
msg.len = 8;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msg.buf= reg2;
msg.len = 2;
reg2[0] = 0x80;
reg2[1] = 0;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
reg2[0] = 0x60;
reg2[1] = 0xbf;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 0x80;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msleep(1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 4;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msleep(1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4];
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msleep(550);
reg2[0] = 0x30;
reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
reg2[0] = 0x60;
reg2[1] = 0x3f;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
reg2[0] = 0x80;
reg2[1] = 0x08; // Vsync en
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
}
-static void tda827x_agcf(struct i2c_client *c)
+static void tda827x_agcf(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char data[] = {0x80, 0x0c};
- struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data,
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data,
.flags = 0, .len = 2};
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
}
/* ---------------------------------------------------------------------- */
@@ -192,57 +220,64 @@ static struct tda827xa_data tda827xa_analog[] = {
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */
};
-static void tda827xa_lna_gain(struct i2c_client *c, int high)
+static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char buf[] = {0x22, 0x01};
int arg;
- struct i2c_msg msg = {.addr = c->addr, .flags = 0, .buf = buf, .len = sizeof(buf)};
- if (t->config) {
+ struct i2c_msg msg = {.addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = sizeof(buf)};
+
+ if ((priv->lna_cfg == NULL) || (priv->tuner_callback == NULL))
+ return;
+
+ if (*priv->lna_cfg) {
if (high)
tuner_dbg("setting LNA to high gain\n");
else
tuner_dbg("setting LNA to low gain\n");
}
- switch (t->config) {
+ switch (*priv->lna_cfg) {
case 0: /* no LNA */
break;
case 1: /* switch is GPIO 0 of tda8290 */
case 2:
/* turn Vsync on */
- if (t->std & V4L2_STD_MN)
+ if (params->std & V4L2_STD_MN)
arg = 1;
else
arg = 0;
- if (t->tuner_callback)
- t->tuner_callback(c->adapter->algo_data, 1, arg);
+ if (priv->tuner_callback)
+ priv->tuner_callback(priv->i2c_props.adap->algo_data, 1, arg);
buf[1] = high ? 0 : 1;
- if (t->config == 2)
+ if (*priv->lna_cfg == 2)
buf[1] = high ? 1 : 0;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
break;
case 3: /* switch with GPIO of saa713x */
- if (t->tuner_callback)
- t->tuner_callback(c->adapter->algo_data, 0, high);
+ if (priv->tuner_callback)
+ priv->tuner_callback(priv->i2c_props.adap->algo_data, 0, high);
break;
}
}
-static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
+static void tda827xa_set_analog_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
unsigned char tuner_reg[11];
u32 N;
int i;
- struct tuner *t = i2c_get_clientdata(c);
- struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0, .buf = tuner_reg};
+ struct tda8290_priv *priv = fe->tuner_priv;
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg};
+ unsigned int freq = params->frequency;
- tda827xa_lna_gain( c, 1);
+ tda827xa_lna_gain(fe, 1, params);
msleep(10);
- if (t->mode == V4L2_TUNER_RADIO)
+ if (params->mode == V4L2_TUNER_RADIO)
freq = freq / 1000;
- N = freq + ifc;
+ N = freq + priv->sgIF;
i = 0;
while (tda827xa_analog[i].lomax < N) {
if(tda827xa_analog[i + 1].lomax == 0)
@@ -265,90 +300,141 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
tuner_reg[9] = 0x20;
tuner_reg[10] = 0x00;
msg.len = 11;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0x90;
tuner_reg[1] = 0xff;
tuner_reg[2] = 0xe0;
tuner_reg[3] = 0;
- tuner_reg[4] = 0x99 + (t->tda827x_lpsel << 1);
+ tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1);
msg.len = 5;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0xa0;
tuner_reg[1] = 0xc0;
msg.len = 2;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0x30;
tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msg.flags = I2C_M_RD;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msg.flags = 0;
tuner_reg[1] >>= 4;
tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]);
if (tuner_reg[1] < 1)
- tda827xa_lna_gain( c, 0);
+ tda827xa_lna_gain(fe, 0, params);
msleep(100);
tuner_reg[0] = 0x60;
tuner_reg[1] = 0x3c;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
msleep(163);
tuner_reg[0] = 0x50;
tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0x80;
tuner_reg[1] = 0x28;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0xb0;
tuner_reg[1] = 0x01;
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
tuner_reg[0] = 0xc0;
- tuner_reg[1] = 0x19 + (t->tda827x_lpsel << 1);
- i2c_transfer(c->adapter, &msg, 1);
+ tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
}
-static void tda827xa_agcf(struct i2c_client *c)
+static void tda827xa_agcf(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char data[] = {0x80, 0x2c};
- struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data,
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data,
.flags = 0, .len = 2};
- i2c_transfer(c->adapter, &msg, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
}
/*---------------------------------------------------------------------*/
-static void tda8290_i2c_bridge(struct i2c_client *c, int close)
+static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
{
+ struct tda8290_priv *priv = fe->tuner_priv;
+
unsigned char enable[2] = { 0x21, 0xC0 };
unsigned char disable[2] = { 0x21, 0x00 };
unsigned char *msg;
if(close) {
msg = enable;
- i2c_master_send(c, msg, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
/* let the bridge stabilize */
msleep(20);
} else {
msg = disable;
- i2c_master_send(c, msg, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
}
}
/*---------------------------------------------------------------------*/
-static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
+static void set_audio(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+{
+ struct tda8290_priv *priv = fe->tuner_priv;
+ char* mode;
+
+ priv->tda827x_lpsel = 0;
+ if (params->std & V4L2_STD_MN) {
+ priv->sgIF = 92;
+ priv->tda8290_easy_mode = 0x01;
+ priv->tda827x_lpsel = 1;
+ mode = "MN";
+ } else if (params->std & V4L2_STD_B) {
+ priv->sgIF = 108;
+ priv->tda8290_easy_mode = 0x02;
+ mode = "B";
+ } else if (params->std & V4L2_STD_GH) {
+ priv->sgIF = 124;
+ priv->tda8290_easy_mode = 0x04;
+ mode = "GH";
+ } else if (params->std & V4L2_STD_PAL_I) {
+ priv->sgIF = 124;
+ priv->tda8290_easy_mode = 0x08;
+ mode = "I";
+ } else if (params->std & V4L2_STD_DK) {
+ priv->sgIF = 124;
+ priv->tda8290_easy_mode = 0x10;
+ mode = "DK";
+ } else if (params->std & V4L2_STD_SECAM_L) {
+ priv->sgIF = 124;
+ priv->tda8290_easy_mode = 0x20;
+ mode = "L";
+ } else if (params->std & V4L2_STD_SECAM_LC) {
+ priv->sgIF = 20;
+ priv->tda8290_easy_mode = 0x40;
+ mode = "LC";
+ } else {
+ priv->sgIF = 124;
+ priv->tda8290_easy_mode = 0x10;
+ mode = "xx";
+ }
+
+ if (params->mode == V4L2_TUNER_RADIO)
+ priv->sgIF = 88; /* if frequency is 5.5 MHz */
+
+ tuner_dbg("setting tda8290 to system %s\n", mode);
+}
+
+static int tda8290_set_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char soft_reset[] = { 0x00, 0x00 };
- unsigned char easy_mode[] = { 0x01, t->tda8290_easy_mode };
+ unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode };
unsigned char expert_mode[] = { 0x01, 0x80 };
unsigned char agc_out_on[] = { 0x02, 0x00 };
unsigned char gainset_off[] = { 0x28, 0x14 };
@@ -369,35 +455,38 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
pll_stat;
int i;
- tuner_dbg("tda827xa config is 0x%02x\n", t->config);
- i2c_master_send(c, easy_mode, 2);
- i2c_master_send(c, agc_out_on, 2);
- i2c_master_send(c, soft_reset, 2);
+ set_audio(fe, params);
+
+ if (priv->lna_cfg)
+ tuner_dbg("tda827xa config is 0x%02x\n", *priv->lna_cfg);
+ tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
msleep(1);
- expert_mode[1] = t->tda8290_easy_mode + 0x80;
- i2c_master_send(c, expert_mode, 2);
- i2c_master_send(c, gainset_off, 2);
- i2c_master_send(c, if_agc_spd, 2);
- if (t->tda8290_easy_mode & 0x60)
- i2c_master_send(c, adc_head_9, 2);
+ expert_mode[1] = priv->tda8290_easy_mode + 0x80;
+ tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
+ if (priv->tda8290_easy_mode & 0x60)
+ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
else
- i2c_master_send(c, adc_head_6, 2);
- i2c_master_send(c, pll_bw_nom, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
- tda8290_i2c_bridge(c, 1);
- if (t->tda827x_ver != 0)
- tda827xa_tune(c, ifc, freq);
+ tda8290_i2c_bridge(fe, 1);
+ if (priv->tda827x_ver != 0)
+ tda827xa_set_analog_params(fe, params);
else
- tda827x_tune(c, ifc, freq);
+ tda827x_set_analog_params(fe, params);
for (i = 0; i < 3; i++) {
- i2c_master_send(c, &addr_pll_stat, 1);
- i2c_master_recv(c, &pll_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
if (pll_stat & 0x80) {
- i2c_master_send(c, &addr_adc_sat, 1);
- i2c_master_recv(c, &adc_sat, 1);
- i2c_master_send(c, &addr_agc_stat, 1);
- i2c_master_recv(c, &agc_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
break;
} else {
@@ -409,188 +498,205 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
agc_stat, adc_sat, pll_stat & 0x80);
- i2c_master_send(c, gainset_2, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
msleep(100);
- i2c_master_send(c, &addr_agc_stat, 1);
- i2c_master_recv(c, &agc_stat, 1);
- i2c_master_send(c, &addr_pll_stat, 1);
- i2c_master_recv(c, &pll_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
if ((agc_stat > 115) || !(pll_stat & 0x80)) {
tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
agc_stat, pll_stat & 0x80);
- if (t->tda827x_ver != 0)
- tda827xa_agcf(c);
+ if (priv->tda827x_ver != 0)
+ tda827xa_agcf(fe);
else
- tda827x_agcf(c);
+ tda827x_agcf(fe);
msleep(100);
- i2c_master_send(c, &addr_agc_stat, 1);
- i2c_master_recv(c, &agc_stat, 1);
- i2c_master_send(c, &addr_pll_stat, 1);
- i2c_master_recv(c, &pll_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
if((agc_stat > 115) || !(pll_stat & 0x80)) {
tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
- i2c_master_send(c, adc_head_12, 2);
- i2c_master_send(c, pll_bw_low, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
msleep(100);
}
}
}
/* l/ l' deadlock? */
- if(t->tda8290_easy_mode & 0x60) {
- i2c_master_send(c, &addr_adc_sat, 1);
- i2c_master_recv(c, &adc_sat, 1);
- i2c_master_send(c, &addr_pll_stat, 1);
- i2c_master_recv(c, &pll_stat, 1);
+ if(priv->tda8290_easy_mode & 0x60) {
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
+ tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
+ tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
if ((adc_sat > 20) || !(pll_stat & 0x80)) {
tuner_dbg("trying to resolve SECAM L deadlock\n");
- i2c_master_send(c, agc_rst_on, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
msleep(40);
- i2c_master_send(c, agc_rst_off, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
}
}
- tda8290_i2c_bridge(c, 0);
- i2c_master_send(c, if_agc_set, 2);
+ tda8290_i2c_bridge(fe, 0);
+ tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
+
+ priv->frequency = (V4L2_TUNER_RADIO == params->mode) ?
+ params->frequency * 125 / 2 : params->frequency * 62500;
+
return 0;
}
/*---------------------------------------------------------------------*/
-static void set_audio(struct tuner *t)
+static int tda8290_has_signal(struct dvb_frontend *fe)
{
- char* mode;
+ struct tda8290_priv *priv = fe->tuner_priv;
+ int ret;
- t->tda827x_lpsel = 0;
- if (t->std & V4L2_STD_MN) {
- t->sgIF = 92;
- t->tda8290_easy_mode = 0x01;
- t->tda827x_lpsel = 1;
- mode = "MN";
- } else if (t->std & V4L2_STD_B) {
- t->sgIF = 108;
- t->tda8290_easy_mode = 0x02;
- mode = "B";
- } else if (t->std & V4L2_STD_GH) {
- t->sgIF = 124;
- t->tda8290_easy_mode = 0x04;
- mode = "GH";
- } else if (t->std & V4L2_STD_PAL_I) {
- t->sgIF = 124;
- t->tda8290_easy_mode = 0x08;
- mode = "I";
- } else if (t->std & V4L2_STD_DK) {
- t->sgIF = 124;
- t->tda8290_easy_mode = 0x10;
- mode = "DK";
- } else if (t->std & V4L2_STD_SECAM_L) {
- t->sgIF = 124;
- t->tda8290_easy_mode = 0x20;
- mode = "L";
- } else if (t->std & V4L2_STD_SECAM_LC) {
- t->sgIF = 20;
- t->tda8290_easy_mode = 0x40;
- mode = "LC";
- } else {
- t->sgIF = 124;
- t->tda8290_easy_mode = 0x10;
- mode = "xx";
- }
- tuner_dbg("setting tda8290 to system %s\n", mode);
-}
+ unsigned char i2c_get_afc[1] = { 0x1B };
+ unsigned char afc = 0;
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
+ /* for now, report based on afc status */
+ tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
+ tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
+
+ ret = (afc & 0x80) ? 65535 : 0;
- set_audio(t);
- tda8290_tune(c, t->sgIF, freq);
+ tuner_dbg("AFC status: %d\n", ret);
+
+ return ret;
}
-static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+static int tda8290_get_status(struct dvb_frontend *fe, u32 *status)
{
- /* if frequency is 5.5 MHz */
- tda8290_tune(c, 88, freq);
+ *status = 0;
+
+ if (tda8290_has_signal(fe))
+ *status = TUNER_STATUS_LOCKED;
+
+ return 0;
}
-static int has_signal(struct i2c_client *c)
+static int tda8290_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
{
- unsigned char i2c_get_afc[1] = { 0x1B };
- unsigned char afc = 0;
+ *strength = tda8290_has_signal(fe);
- i2c_master_send(c, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
- i2c_master_recv(c, &afc, 1);
- return (afc & 0x80)? 65535:0;
+ return 0;
}
/*---------------------------------------------------------------------*/
-static void standby(struct i2c_client *c)
+static int tda8290_standby(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char cb1[] = { 0x30, 0xD0 };
unsigned char tda8290_standby[] = { 0x00, 0x02 };
unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
- struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
- tda8290_i2c_bridge(c, 1);
- if (t->tda827x_ver != 0)
+ tda8290_i2c_bridge(fe, 1);
+ if (priv->tda827x_ver != 0)
cb1[1] = 0x90;
- i2c_transfer(c->adapter, &msg, 1);
- tda8290_i2c_bridge(c, 0);
- i2c_master_send(c, tda8290_agc_tri, 2);
- i2c_master_send(c, tda8290_standby, 2);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
+ tda8290_i2c_bridge(fe, 0);
+ tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
+
+ return 0;
}
-static void tda8290_init_if(struct i2c_client *c)
+static void tda8290_init_if(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
+
unsigned char set_VS[] = { 0x30, 0x6F };
unsigned char set_GP00_CF[] = { 0x20, 0x01 };
unsigned char set_GP01_CF[] = { 0x20, 0x0B };
- if ((t->config == 1) || (t->config == 2))
- i2c_master_send(c, set_GP00_CF, 2);
+ if ((priv->lna_cfg) &&
+ ((*priv->lna_cfg == 1) || (*priv->lna_cfg == 2)))
+ tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
else
- i2c_master_send(c, set_GP01_CF, 2);
- i2c_master_send(c, set_VS, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
}
-static void tda8290_init_tuner(struct i2c_client *c)
+static void tda8290_init_tuner(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tda8290_priv *priv = fe->tuner_priv;
unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
- struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0,
+ struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
.buf=tda8275_init, .len = 14};
- if (t->tda827x_ver != 0)
+ if (priv->tda827x_ver != 0)
msg.buf = tda8275a_init;
- tda8290_i2c_bridge(c, 1);
- i2c_transfer(c->adapter, &msg, 1);
- tda8290_i2c_bridge(c, 0);
+ tda8290_i2c_bridge(fe, 1);
+ i2c_transfer(priv->i2c_props.adap, &msg, 1);
+ tda8290_i2c_bridge(fe, 0);
}
/*---------------------------------------------------------------------*/
-int tda8290_init(struct i2c_client *c)
+static int tda8290_release(struct dvb_frontend *fe)
{
- struct tuner *t = i2c_get_clientdata(c);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int tda8290_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tda8290_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static struct dvb_tuner_ops tda8290_tuner_ops = {
+ .sleep = tda8290_standby,
+ .set_analog_params = tda8290_set_params,
+ .release = tda8290_release,
+ .get_frequency = tda8290_get_frequency,
+ .get_status = tda8290_get_status,
+ .get_rf_strength = tda8290_get_rf_strength,
+};
+
+struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr,
+ struct tda8290_config *cfg)
+{
+ struct tda8290_priv *priv = NULL;
u8 data;
int i, ret, tuners_found;
u32 tuner_addrs;
struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1};
- tda8290_i2c_bridge(c, 1);
+ priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+ fe->tuner_priv = priv;
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
+ if (cfg) {
+ priv->lna_cfg = cfg->lna_cfg;
+ priv->tuner_callback = cfg->tuner_callback;
+ }
+
+ tda8290_i2c_bridge(fe, 1);
/* probe for tuner chip */
tuners_found = 0;
tuner_addrs = 0;
for (i=0x60; i<= 0x63; i++) {
msg.addr = i;
- ret = i2c_transfer(c->adapter, &msg, 1);
+ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
if (ret == 1) {
tuners_found++;
tuner_addrs = (tuner_addrs << 8) + i;
@@ -600,11 +706,11 @@ int tda8290_init(struct i2c_client *c)
behind the bridge and we choose the highest address that doesn't
give a response now
*/
- tda8290_i2c_bridge(c, 0);
+ tda8290_i2c_bridge(fe, 0);
if(tuners_found > 1)
for (i = 0; i < tuners_found; i++) {
msg.addr = tuner_addrs & 0xff;
- ret = i2c_transfer(c->adapter, &msg, 1);
+ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
if(ret == 1)
tuner_addrs = tuner_addrs >> 8;
else
@@ -612,42 +718,53 @@ int tda8290_init(struct i2c_client *c)
}
if (tuner_addrs == 0) {
tuner_addrs = 0x61;
- tuner_info ("could not clearly identify tuner address, defaulting to %x\n",
+ tuner_info("could not clearly identify tuner address, defaulting to %x\n",
tuner_addrs);
} else {
tuner_addrs = tuner_addrs & 0xff;
- tuner_info ("setting tuner address to %x\n", tuner_addrs);
+ tuner_info("setting tuner address to %x\n", tuner_addrs);
}
- t->tda827x_addr = tuner_addrs;
+ priv->tda827x_addr = tuner_addrs;
msg.addr = tuner_addrs;
- tda8290_i2c_bridge(c, 1);
- ret = i2c_transfer(c->adapter, &msg, 1);
+ tda8290_i2c_bridge(fe, 1);
+ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
if( ret != 1)
- tuner_warn ("TDA827x access failed!\n");
+ tuner_warn("TDA827x access failed!\n");
+
+ memcpy(&fe->ops.tuner_ops, &tda8290_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
if ((data & 0x3c) == 0) {
- strlcpy(c->name, "tda8290+75", sizeof(c->name));
- t->tda827x_ver = 0;
+ strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75",
+ sizeof(fe->ops.tuner_ops.info.name));
+ fe->ops.tuner_ops.info.frequency_min = 55000000;
+ fe->ops.tuner_ops.info.frequency_max = 860000000;
+ fe->ops.tuner_ops.info.frequency_step = 250000;
+ priv->tda827x_ver = 0;
} else {
- strlcpy(c->name, "tda8290+75a", sizeof(c->name));
- t->tda827x_ver = 2;
+ strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75a",
+ sizeof(fe->ops.tuner_ops.info.name));
+ fe->ops.tuner_ops.info.frequency_min = 44000000;
+ fe->ops.tuner_ops.info.frequency_max = 906000000;
+ fe->ops.tuner_ops.info.frequency_step = 62500;
+ priv->tda827x_ver = 2;
}
- tuner_info("type set to %s\n", c->name);
- t->set_tv_freq = set_tv_freq;
- t->set_radio_freq = set_radio_freq;
- t->has_signal = has_signal;
- t->standby = standby;
- t->tda827x_lpsel = 0;
- t->mode = V4L2_TUNER_ANALOG_TV;
+ priv->tda827x_lpsel = 0;
- tda8290_init_tuner(c);
- tda8290_init_if(c);
- return 0;
+ tda8290_init_tuner(fe);
+ tda8290_init_if(fe);
+ return fe;
}
-int tda8290_probe(struct i2c_client *c)
+int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr)
{
+ struct tuner_i2c_props i2c_props = {
+ .adap = i2c_adap,
+ .addr = i2c_addr
+ };
+
unsigned char soft_reset[] = { 0x00, 0x00 };
unsigned char easy_mode_b[] = { 0x01, 0x02 };
unsigned char easy_mode_g[] = { 0x01, 0x04 };
@@ -655,23 +772,30 @@ int tda8290_probe(struct i2c_client *c)
unsigned char addr_dto_lsb = 0x07;
unsigned char data;
- i2c_master_send(c, easy_mode_b, 2);
- i2c_master_send(c, soft_reset, 2);
- i2c_master_send(c, &addr_dto_lsb, 1);
- i2c_master_recv(c, &data, 1);
+ tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
+ tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
+ tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
+ tuner_i2c_xfer_recv(&i2c_props, &data, 1);
if (data == 0) {
- i2c_master_send(c, easy_mode_g, 2);
- i2c_master_send(c, soft_reset, 2);
- i2c_master_send(c, &addr_dto_lsb, 1);
- i2c_master_recv(c, &data, 1);
+ tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
+ tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
+ tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
+ tuner_i2c_xfer_recv(&i2c_props, &data, 1);
if (data == 0x7b) {
return 0;
}
}
- i2c_master_send(c, restore_9886, 3);
+ tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
return -1;
}
+EXPORT_SYMBOL_GPL(tda8290_probe);
+EXPORT_SYMBOL_GPL(tda8290_attach);
+
+MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver");
+MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann");
+MODULE_LICENSE("GPL");
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h
new file mode 100644
index 000000000000..107b24b05aa1
--- /dev/null
+++ b/drivers/media/video/tda8290.h
@@ -0,0 +1,54 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __TDA8290_H__
+#define __TDA8290_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+struct tda8290_config
+{
+ unsigned int *lna_cfg;
+ int (*tuner_callback) (void *dev, int command,int arg);
+};
+
+#if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE))
+extern int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr);
+
+extern struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr,
+ struct tda8290_config *cfg);
+#else
+static inline int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+{
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+ __FUNCTION__);
+ return -EINVAL;
+}
+
+static inline struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr,
+ struct tda8290_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif
+
+#endif /* __TDA8290_H__ */
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index fde576f1101c..be5387f11afb 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -1,16 +1,15 @@
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/types.h>
-#include <linux/videodev.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/delay.h>
-
+#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
+#include "tuner-driver.h"
/* Chips:
@@ -29,6 +28,11 @@
printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \
i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+struct tda9887_priv {
+ struct tuner_i2c_props i2c_props;
+
+ unsigned char data[4];
+};
/* ---------------------------------------------------------------------- */
@@ -93,6 +97,8 @@ struct tvnorm {
#define cAudioIF_6_5 0x03 // bit e0:1
+#define cVideoIFMask 0x1c // bit e2:4
+/* Video IF selection in TV Mode (bit B3=0) */
#define cVideoIF_58_75 0x00 // bit e2:4
#define cVideoIF_45_75 0x04 // bit e2:4
#define cVideoIF_38_90 0x08 // bit e2:4
@@ -102,6 +108,13 @@ struct tvnorm {
#define cRadioIF_45_75 0x18 // bit e2:4
#define cRadioIF_38_90 0x1C // bit e2:4
+/* IF1 selection in Radio Mode (bit B3=1) */
+#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
+#define cRadioIF_41_30 0x04 // bit e2,4
+
+/* Output of AFC pin in radio mode when bit E7=1 */
+#define cRadioAGC_SIF 0x00 // bit e3
+#define cRadioAGC_FM 0x08 // bit e3
#define cTunerGainNormal 0x00 // bit e5
#define cTunerGainLow 0x20 // bit e5
@@ -483,9 +496,13 @@ static int tda9887_set_config(struct tuner *t, char *buf)
if (t->tda9887_config & TDA9887_GATING_18)
buf[3] &= ~cGating_36;
- if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
- radio_stereo.e &= ~cTunerGainLow;
- radio_mono.e &= ~cTunerGainLow;
+ if (t->mode == V4L2_TUNER_RADIO) {
+ if (t->tda9887_config & TDA9887_RIF_41_3) {
+ buf[3] &= ~cVideoIFMask;
+ buf[3] |= cRadioIF_41_30;
+ }
+ if (t->tda9887_config & TDA9887_GAIN_NORMAL)
+ buf[3] &= ~cTunerGainLow;
}
return 0;
@@ -495,23 +512,24 @@ static int tda9887_set_config(struct tuner *t, char *buf)
static int tda9887_status(struct tuner *t)
{
+ struct tda9887_priv *priv = t->priv;
unsigned char buf[1];
int rc;
memset(buf,0,sizeof(buf));
- if (1 != (rc = i2c_master_recv(&t->i2c,buf,1)))
+ if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc);
dump_read_message(t, buf);
return 0;
}
-static void tda9887_configure(struct i2c_client *client)
+static void tda9887_configure(struct tuner *t)
{
- struct tuner *t = i2c_get_clientdata(client);
+ struct tda9887_priv *priv = t->priv;
int rc;
- memset(t->tda9887_data,0,sizeof(t->tda9887_data));
- tda9887_set_tvnorm(t,t->tda9887_data);
+ memset(priv->data,0,sizeof(priv->data));
+ tda9887_set_tvnorm(t,priv->data);
/* A note on the port settings:
These settings tend to depend on the specifics of the board.
@@ -526,22 +544,22 @@ static void tda9887_configure(struct i2c_client *client)
the ports should be set to active (0), but, again, that may
differ depending on the precise hardware configuration.
*/
- t->tda9887_data[1] |= cOutputPort1Inactive;
- t->tda9887_data[1] |= cOutputPort2Inactive;
+ priv->data[1] |= cOutputPort1Inactive;
+ priv->data[1] |= cOutputPort2Inactive;
- tda9887_set_config(t,t->tda9887_data);
- tda9887_set_insmod(t,t->tda9887_data);
+ tda9887_set_config(t,priv->data);
+ tda9887_set_insmod(t,priv->data);
if (t->mode == T_STANDBY) {
- t->tda9887_data[1] |= cForcedMuteAudioON;
+ priv->data[1] |= cForcedMuteAudioON;
}
tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
- t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]);
+ priv->data[1],priv->data[2],priv->data[3]);
if (tuner_debug > 1)
- dump_write_message(t, t->tda9887_data);
+ dump_write_message(t, priv->data);
- if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4)))
+ if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc);
if (tuner_debug > 2) {
@@ -552,15 +570,15 @@ static void tda9887_configure(struct i2c_client *client)
/* ---------------------------------------------------------------------- */
-static void tda9887_tuner_status(struct i2c_client *client)
+static void tda9887_tuner_status(struct tuner *t)
{
- struct tuner *t = i2c_get_clientdata(client);
- tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]);
+ struct tda9887_priv *priv = t->priv;
+ tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]);
}
-static int tda9887_get_afc(struct i2c_client *client)
+static int tda9887_get_afc(struct tuner *t)
{
- struct tuner *t = i2c_get_clientdata(client);
+ struct tda9887_priv *priv = t->priv;
static int AFC_BITS_2_kHz[] = {
-12500, -37500, -62500, -97500,
-112500, -137500, -162500, -187500,
@@ -570,36 +588,55 @@ static int tda9887_get_afc(struct i2c_client *client)
int afc=0;
__u8 reg = 0;
- if (1 == i2c_master_recv(&t->i2c,&reg,1))
+ if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
return afc;
}
-static void tda9887_standby(struct i2c_client *client)
+static void tda9887_standby(struct tuner *t)
{
- tda9887_configure(client);
+ tda9887_configure(t);
}
-static void tda9887_set_freq(struct i2c_client *client, unsigned int freq)
+static void tda9887_set_freq(struct tuner *t, unsigned int freq)
{
- tda9887_configure(client);
+ tda9887_configure(t);
}
-int tda9887_tuner_init(struct i2c_client *c)
+static void tda9887_release(struct tuner *t)
{
- struct tuner *t = i2c_get_clientdata(c);
+ kfree(t->priv);
+ t->priv = NULL;
+}
+
+static struct tuner_operations tda9887_tuner_ops = {
+ .set_tv_freq = tda9887_set_freq,
+ .set_radio_freq = tda9887_set_freq,
+ .standby = tda9887_standby,
+ .tuner_status = tda9887_tuner_status,
+ .get_afc = tda9887_get_afc,
+ .release = tda9887_release,
+};
+
+int tda9887_tuner_init(struct tuner *t)
+{
+ struct tda9887_priv *priv = NULL;
+
+ priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+ t->priv = priv;
+
+ priv->i2c_props.addr = t->i2c.addr;
+ priv->i2c_props.adap = t->i2c.adapter;
- strlcpy(c->name, "tda9887", sizeof(c->name));
+ strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name));
tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr,
t->i2c.driver->driver.name);
- t->set_tv_freq = tda9887_set_freq;
- t->set_radio_freq = tda9887_set_freq;
- t->standby = tda9887_standby;
- t->tuner_status = tda9887_tuner_status;
- t->get_afc = tda9887_get_afc;
+ memcpy(&t->ops, &tda9887_tuner_ops, sizeof(struct tuner_operations));
return 0;
}
diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c
new file mode 100644
index 000000000000..2150222a3860
--- /dev/null
+++ b/drivers/media/video/tea5761.c
@@ -0,0 +1,320 @@
+/*
+ * For Philips TEA5761 FM Chip
+ * I2C address is allways 0x20 (0x10 at 7-bit mode).
+ *
+ * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNUv2 General Public License
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev.h>
+#include <media/tuner.h>
+#include "tuner-i2c.h"
+#include "tea5761.h"
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+#define PREFIX "tea5761 "
+
+struct tea5761_priv {
+ struct tuner_i2c_props i2c_props;
+
+ u32 frequency;
+};
+
+/*****************************************************************************/
+
+/***************************
+ * TEA5761HN I2C registers *
+ ***************************/
+
+/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */
+
+ /* first byte for reading */
+#define TEA5761_INTREG_IFFLAG 0x10
+#define TEA5761_INTREG_LEVFLAG 0x8
+#define TEA5761_INTREG_FRRFLAG 0x2
+#define TEA5761_INTREG_BLFLAG 0x1
+
+ /* second byte for reading / byte for writing */
+#define TEA5761_INTREG_IFMSK 0x10
+#define TEA5761_INTREG_LEVMSK 0x8
+#define TEA5761_INTREG_FRMSK 0x2
+#define TEA5761_INTREG_BLMSK 0x1
+
+/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
+
+ /* First byte */
+#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */
+#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */
+
+ /* Bits 0-5 for divider MSB */
+
+ /* Second byte */
+ /* Bits 0-7 for divider LSB */
+
+/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */
+
+ /* first byte */
+
+#define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */
+#define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */
+#define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */
+#define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */
+#define TEA5761_TNCTRL_AFM 0x04
+#define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */
+#define TEA5761_TNCTRL_SNC 0x01
+
+ /* second byte */
+
+#define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */
+#define TEA5761_TNCTRL_SSL_1 0x40
+#define TEA5761_TNCTRL_SSL_0 0x20
+#define TEA5761_TNCTRL_HLSI 0x10
+#define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */
+#define TEA5761_TNCTRL_SWP 0x04
+#define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */
+#define TEA5761_TNCTRL_AHLSI 0x01
+
+/* FRQCHECK - Read: bytes 6 and 7 */
+ /* First byte */
+
+ /* Bits 0-5 for divider MSB */
+
+ /* Second byte */
+ /* Bits 0-7 for divider LSB */
+
+/* TUNCHECK - Read: bytes 8 and 9 */
+
+ /* First byte */
+#define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */
+#define TEA5761_TUNCHECK_TUNTO 0x01
+
+ /* Second byte */
+#define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */
+#define TEA5761_TUNCHECK_LD 0x08
+#define TEA5761_TUNCHECK_STEREO 0x04
+
+/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */
+
+ /* All zero = no test mode */
+
+/* MANID - Read: bytes 12 and 13 */
+
+ /* First byte - should be 0x10 */
+#define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */
+#define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */
+
+ /* Second byte - Should be 0x2b */
+
+#define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */
+#define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */
+
+/* Chip ID - Read: bytes 14 and 15 */
+
+ /* First byte - should be 0x57 */
+
+ /* Second byte - should be 0x61 */
+
+/*****************************************************************************/
+
+#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */
+static void tea5761_status_dump(unsigned char *buffer)
+{
+ unsigned int div, frq;
+
+ div = ((buffer[2] & 0x3f) << 8) | buffer[3];
+
+ frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */
+
+ printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+ frq / 1000, frq % 1000, div);
+}
+
+/* Freq should be specifyed at 62.5 Hz */
+static int set_radio_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+{
+ struct tea5761_priv *priv = fe->tuner_priv;
+ unsigned int frq = params->frequency;
+ unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
+ unsigned div;
+ int rc;
+
+ tuner_dbg("radio freq counter %d\n", frq);
+
+ if (params->mode == T_STANDBY) {
+ tuner_dbg("TEA5761 set to standby mode\n");
+ buffer[5] |= TEA5761_TNCTRL_MU;
+ } else {
+ buffer[4] |= TEA5761_TNCTRL_PUPD_0;
+ }
+
+
+ if (params->audmode == V4L2_TUNER_MODE_MONO) {
+ tuner_dbg("TEA5761 set to mono\n");
+ buffer[5] |= TEA5761_TNCTRL_MST;
+ } else {
+ tuner_dbg("TEA5761 set to stereo\n");
+ }
+
+ div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15;
+ buffer[1] = (div >> 8) & 0x3f;
+ buffer[2] = div & 0xff;
+
+ if (debug)
+ tea5761_status_dump(buffer);
+
+ if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7)))
+ tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+
+ priv->frequency = frq * 125 / 2;
+
+ return 0;
+}
+
+static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
+{
+ struct tea5761_priv *priv = fe->tuner_priv;
+ int rc;
+
+ memset(buffer, 0, 16);
+ if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) {
+ tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer)
+{
+ struct tea5761_priv *priv = fe->tuner_priv;
+
+ int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4));
+
+ tuner_dbg("Signal strength: %d\n", signal);
+
+ return signal;
+}
+
+static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer)
+{
+ struct tea5761_priv *priv = fe->tuner_priv;
+
+ int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO;
+
+ tuner_dbg("Radio ST GET = %02x\n", stereo);
+
+ return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+}
+
+static int tea5761_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ unsigned char buffer[16];
+
+ *status = 0;
+
+ if (0 == tea5761_read_status(fe, buffer)) {
+ if (tea5761_signal(fe, buffer))
+ *status = TUNER_STATUS_LOCKED;
+ if (tea5761_stereo(fe, buffer))
+ *status |= TUNER_STATUS_STEREO;
+ }
+
+ return 0;
+}
+
+static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ unsigned char buffer[16];
+
+ *strength = 0;
+
+ if (0 == tea5761_read_status(fe, buffer))
+ *strength = tea5761_signal(fe, buffer);
+
+ return 0;
+}
+
+int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+{
+ unsigned char buffer[16];
+ int rc;
+ struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
+
+ if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
+ printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
+ return EINVAL;
+ }
+
+ if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
+ printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
+ return EINVAL;
+ }
+ printk(KERN_WARNING "TEA5761 detected.\n");
+ return 0;
+}
+
+static int tea5761_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tea5761_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static struct dvb_tuner_ops tea5761_tuner_ops = {
+ .info = {
+ .name = "tea5761", // Philips TEA5761HN FM Radio
+ },
+ .set_analog_params = set_radio_freq,
+ .release = tea5761_release,
+ .get_frequency = tea5761_get_frequency,
+ .get_status = tea5761_get_status,
+ .get_rf_strength = tea5761_get_rf_strength,
+};
+
+struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ struct tea5761_priv *priv = NULL;
+
+ if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
+ return NULL;
+
+ priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+ fe->tuner_priv = priv;
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
+
+ memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio");
+
+ return fe;
+}
+
+
+EXPORT_SYMBOL_GPL(tea5761_attach);
+EXPORT_SYMBOL_GPL(tea5761_autodetection);
+
+MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h
new file mode 100644
index 000000000000..73a03b427843
--- /dev/null
+++ b/drivers/media/video/tea5761.h
@@ -0,0 +1,47 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __TEA5761_H__
+#define __TEA5761_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
+
+extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr);
+#else
+static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+ __FUNCTION__);
+ return -EINVAL;
+}
+
+static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif
+
+#endif /* __TEA5761_H__ */
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index d1c41781ccc4..71df419df7bc 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -11,14 +11,22 @@
*/
#include <linux/i2c.h>
-#include <linux/videodev.h>
#include <linux/delay.h>
-#include <media/tuner.h>
+#include <linux/videodev.h>
+#include "tuner-i2c.h"
+#include "tea5767.h"
-#define PREFIX "TEA5767 "
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
-/* from tuner-core.c */
-extern int tuner_debug;
+#define PREFIX "tea5767 "
+
+struct tea5767_priv {
+ struct tuner_i2c_props i2c_props;
+
+ u32 frequency;
+};
/*****************************************************************************/
@@ -129,13 +137,6 @@ enum tea5767_xtal_freq {
/*****************************************************************************/
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
-
- tuner_warn("This tuner doesn't support TV freq.\n");
-}
-
static void tea5767_status_dump(unsigned char *buffer)
{
unsigned int div, frq;
@@ -190,14 +191,16 @@ static void tea5767_status_dump(unsigned char *buffer)
}
/* Freq should be specifyed at 62.5 Hz */
-static void set_radio_freq(struct i2c_client *c, unsigned int frq)
+static int set_radio_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tea5767_priv *priv = fe->tuner_priv;
+ unsigned int frq = params->frequency;
unsigned char buffer[5];
unsigned div;
int rc;
- tuner_dbg (PREFIX "radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
+ tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
/* Rounds freq to next decimal value - for 62.5 KHz step */
/* frq = 20*(frq/16)+radio_frq[frq%16]; */
@@ -207,7 +210,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
buffer[4] = 0;
- if (t->audmode == V4L2_TUNER_MODE_MONO) {
+ if (params->audmode == V4L2_TUNER_MODE_MONO) {
tuner_dbg("TEA5767 set to mono\n");
buffer[2] |= TEA5767_MONO;
} else {
@@ -217,26 +220,26 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
/* Should be replaced */
switch (TEA5767_HIGH_LO_32768) {
case TEA5767_HIGH_LO_13MHz:
- tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
+ tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[4] |= TEA5767_PLLREF_ENABLE;
div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_13MHz:
- tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
+ tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
buffer[4] |= TEA5767_PLLREF_ENABLE;
div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_32768:
- tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
+ tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
buffer[3] |= TEA5767_XTAL_32768;
/* const 700=4000*175 Khz - to adjust freq to right value */
div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
break;
case TEA5767_HIGH_LO_32768:
default:
- tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n");
+ tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[3] |= TEA5767_XTAL_32768;
@@ -246,51 +249,89 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
buffer[0] = (div >> 8) & 0x3f;
buffer[1] = div & 0xff;
- if (5 != (rc = i2c_master_send(c, buffer, 5)))
+ if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
- if (tuner_debug) {
- if (5 != (rc = i2c_master_recv(c, buffer, 5)))
+ if (debug) {
+ if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
else
tea5767_status_dump(buffer);
}
+
+ priv->frequency = frq * 125 / 2;
+
+ return 0;
}
-static int tea5767_signal(struct i2c_client *c)
+static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
{
- unsigned char buffer[5];
+ struct tea5767_priv *priv = fe->tuner_priv;
int rc;
- struct tuner *t = i2c_get_clientdata(c);
- memset(buffer, 0, sizeof(buffer));
- if (5 != (rc = i2c_master_recv(c, buffer, 5)))
+ memset(buffer, 0, 5);
+ if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+ return -EREMOTEIO;
+ }
- return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
+ return 0;
+}
+
+static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
+{
+ struct tea5767_priv *priv = fe->tuner_priv;
+
+ int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
+
+ tuner_dbg("Signal strength: %d\n", signal);
+
+ return signal;
}
-static int tea5767_stereo(struct i2c_client *c)
+static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
+{
+ struct tea5767_priv *priv = fe->tuner_priv;
+
+ int stereo = buffer[2] & TEA5767_STEREO_MASK;
+
+ tuner_dbg("Radio ST GET = %02x\n", stereo);
+
+ return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
+}
+
+static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
{
unsigned char buffer[5];
- int rc;
- struct tuner *t = i2c_get_clientdata(c);
- memset(buffer, 0, sizeof(buffer));
- if (5 != (rc = i2c_master_recv(c, buffer, 5)))
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+ *status = 0;
+
+ if (0 == tea5767_read_status(fe, buffer)) {
+ if (tea5767_signal(fe, buffer))
+ *status = TUNER_STATUS_LOCKED;
+ if (tea5767_stereo(fe, buffer))
+ *status |= TUNER_STATUS_STEREO;
+ }
+
+ return 0;
+}
+
+static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ unsigned char buffer[5];
- rc = buffer[2] & TEA5767_STEREO_MASK;
+ *strength = 0;
- tuner_dbg("TEA5767 radio ST GET = %02x\n", rc);
+ if (0 == tea5767_read_status(fe, buffer))
+ *strength = tea5767_signal(fe, buffer);
- return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0);
+ return 0;
}
-static void tea5767_standby(struct i2c_client *c)
+static int tea5767_standby(struct dvb_frontend *fe)
{
unsigned char buffer[5];
- struct tuner *t = i2c_get_clientdata(c);
+ struct tea5767_priv *priv = fe->tuner_priv;
unsigned div, rc;
div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
@@ -301,25 +342,27 @@ static void tea5767_standby(struct i2c_client *c)
TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
buffer[4] = 0;
- if (5 != (rc = i2c_master_send(c, buffer, 5)))
+ if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+
+ return 0;
}
-int tea5767_autodetection(struct i2c_client *c)
+int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
{
+ struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int rc;
- struct tuner *t = i2c_get_clientdata(c);
- if ((rc = i2c_master_recv(c, buffer, 7))< 5) {
- tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
+ if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
+ printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
return EINVAL;
}
/* If all bytes are the same then it's a TV tuner and not a tea5767 */
if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
- tuner_warn("All bytes are equal. It is not a TEA5767\n");
+ printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
return EINVAL;
}
@@ -329,32 +372,74 @@ int tea5767_autodetection(struct i2c_client *c)
* Byte 5: bit 7:0 : == 0
*/
if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
- tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
+ printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
return EINVAL;
}
/* It seems that tea5767 returns 0xff after the 5th byte */
if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
- tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
+ printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
return EINVAL;
}
- tuner_warn("TEA5767 detected.\n");
+ printk(KERN_WARNING "TEA5767 detected.\n");
+ return 0;
+}
+
+static int tea5767_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tea5767_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
return 0;
}
-int tea5767_tuner_init(struct i2c_client *c)
+static struct dvb_tuner_ops tea5767_tuner_ops = {
+ .info = {
+ .name = "tea5767", // Philips TEA5767HN FM Radio
+ },
+
+ .set_analog_params = set_radio_freq,
+ .sleep = tea5767_standby,
+ .release = tea5767_release,
+ .get_frequency = tea5767_get_frequency,
+ .get_status = tea5767_get_status,
+ .get_rf_strength = tea5767_get_rf_strength,
+};
+
+struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tea5767_priv *priv = NULL;
+
+ priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+ fe->tuner_priv = priv;
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
- tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
- strlcpy(c->name, "tea5767", sizeof(c->name));
+ memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
- t->set_tv_freq = set_tv_freq;
- t->set_radio_freq = set_radio_freq;
- t->has_signal = tea5767_signal;
- t->is_stereo = tea5767_stereo;
- t->standby = tea5767_standby;
+ tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
- return (0);
+ return fe;
}
+
+
+EXPORT_SYMBOL_GPL(tea5767_attach);
+EXPORT_SYMBOL_GPL(tea5767_autodetection);
+
+MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h
new file mode 100644
index 000000000000..5d78281adcc2
--- /dev/null
+++ b/drivers/media/video/tea5767.h
@@ -0,0 +1,47 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __TEA5767_H__
+#define __TEA5767_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
+extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
+
+extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr);
+#else
+static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+ __FUNCTION__);
+ return -EINVAL;
+}
+
+static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif
+
+#endif /* __TEA5767_H__ */
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 505591a7abe9..94843086cda9 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -5,7 +5,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
@@ -15,16 +14,25 @@
#include <linux/poll.h>
#include <linux/i2c.h>
#include <linux/types.h>
-#include <linux/videodev.h>
#include <linux/init.h>
-
+#include <linux/videodev.h>
#include <media/tuner.h>
+#include <media/tuner-types.h>
#include <media/v4l2-common.h>
+#include "tuner-driver.h"
+#include "mt20xx.h"
+#include "tda8290.h"
+#include "tea5761.h"
+#include "tea5767.h"
+#include "tuner-simple.h"
#define UNSET (-1U)
/* standard i2c insmod options */
static unsigned short normal_i2c[] = {
+#ifdef CONFIG_TUNER_TEA5761
+ 0x10,
+#endif
0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
@@ -68,6 +76,51 @@ static struct i2c_client client_template;
/* ---------------------------------------------------------------------- */
+static void fe_set_freq(struct tuner *t, unsigned int freq)
+{
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+
+ struct analog_parameters params = {
+ .frequency = freq,
+ .mode = t->mode,
+ .audmode = t->audmode,
+ .std = t->std
+ };
+
+ if (NULL == fe_tuner_ops->set_analog_params) {
+ tuner_warn("Tuner frontend module has no way to set freq\n");
+ return;
+ }
+ fe_tuner_ops->set_analog_params(&t->fe, &params);
+}
+
+static void fe_release(struct tuner *t)
+{
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+
+ if (fe_tuner_ops->release)
+ fe_tuner_ops->release(&t->fe);
+}
+
+static void fe_standby(struct tuner *t)
+{
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+
+ if (fe_tuner_ops->sleep)
+ fe_tuner_ops->sleep(&t->fe);
+}
+
+static int fe_has_signal(struct tuner *t)
+{
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+ u16 strength;
+
+ if (fe_tuner_ops->get_rf_strength)
+ fe_tuner_ops->get_rf_strength(&t->fe, &strength);
+
+ return strength;
+}
+
/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
static void set_tv_freq(struct i2c_client *c, unsigned int freq)
{
@@ -77,7 +130,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->set_tv_freq) {
+ if (NULL == t->ops.set_tv_freq) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
@@ -92,7 +145,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
else
freq = tv_range[1] * 16;
}
- t->set_tv_freq(c, freq);
+ t->ops.set_tv_freq(t, freq);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -103,7 +156,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->set_radio_freq) {
+ if (NULL == t->ops.set_radio_freq) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
@@ -119,7 +172,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
freq = radio_range[1] * 16000;
}
- t->set_radio_freq(c, freq);
+ t->ops.set_radio_freq(t, freq);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -143,11 +196,51 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
}
}
+static void tuner_i2c_address_check(struct tuner *t)
+{
+ if ((t->type == UNSET || t->type == TUNER_ABSENT) ||
+ ((t->i2c.addr < 0x64) || (t->i2c.addr > 0x6f)))
+ return;
+
+ tuner_warn("====================== WARNING! ======================\n");
+ tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
+ tuner_warn("will soon be dropped. This message indicates that your\n");
+ tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n",
+ t->i2c.name, t->i2c.addr);
+ tuner_warn("To ensure continued support for your device, please\n");
+ tuner_warn("send a copy of this message, along with full dmesg\n");
+ tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
+ tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
+ tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
+ t->i2c.adapter->name, t->i2c.addr, t->type,
+ tuners[t->type].name);
+ tuner_warn("====================== WARNING! ======================\n");
+}
+
+static void attach_tda8290(struct tuner *t)
+{
+ struct tda8290_config cfg = {
+ .lna_cfg = &t->config,
+ .tuner_callback = t->tuner_callback
+ };
+ tda8290_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg);
+}
+
+static void attach_simple_tuner(struct tuner *t)
+{
+ struct simple_tuner_config cfg = {
+ .type = t->type,
+ .tun = &tuners[t->type]
+ };
+ simple_tuner_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg);
+}
+
static void set_type(struct i2c_client *c, unsigned int type,
unsigned int new_mode_mask, unsigned int new_config,
int (*tuner_callback) (void *dev, int command,int arg))
{
struct tuner *t = i2c_get_clientdata(c);
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
unsigned char buffer[4];
if (type == UNSET || type == TUNER_ABSENT) {
@@ -174,21 +267,41 @@ static void set_type(struct i2c_client *c, unsigned int type,
return;
}
+ /* discard private data, in case set_type() was previously called */
+ if (t->ops.release)
+ t->ops.release(t);
+ else {
+ kfree(t->priv);
+ t->priv = NULL;
+ }
+
switch (t->type) {
case TUNER_MT2032:
- microtune_init(c);
+ microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr);
break;
case TUNER_PHILIPS_TDA8290:
- tda8290_init(c);
+ {
+ attach_tda8290(t);
break;
+ }
case TUNER_TEA5767:
- if (tea5767_tuner_init(c) == EINVAL) {
+ if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) {
t->type = TUNER_ABSENT;
t->mode_mask = T_UNINITIALIZED;
return;
}
t->mode_mask = T_RADIO;
break;
+#ifdef CONFIG_TUNER_TEA5761
+ case TUNER_TEA5761:
+ if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) {
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+ return;
+ }
+ t->mode_mask = T_RADIO;
+ break;
+#endif
case TUNER_PHILIPS_FMD1216ME_MK3:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
@@ -199,7 +312,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[2] = 0x86;
buffer[3] = 0x54;
i2c_master_send(c, buffer, 4);
- default_tuner_init(c);
+ attach_simple_tuner(t);
break;
case TUNER_PHILIPS_TD1316:
buffer[0] = 0x0b;
@@ -207,16 +320,28 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[2] = 0x86;
buffer[3] = 0xa4;
i2c_master_send(c,buffer,4);
- default_tuner_init(c);
+ attach_simple_tuner(t);
break;
case TUNER_TDA9887:
- tda9887_tuner_init(c);
+ tda9887_tuner_init(t);
break;
default:
- default_tuner_init(c);
+ attach_simple_tuner(t);
break;
}
+ if (fe_tuner_ops->set_analog_params) {
+ strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name));
+
+ t->ops.set_tv_freq = fe_set_freq;
+ t->ops.set_radio_freq = fe_set_freq;
+ t->ops.standby = fe_standby;
+ t->ops.release = fe_release;
+ t->ops.has_signal = fe_has_signal;
+ }
+
+ tuner_info("type set to %s\n", t->i2c.name);
+
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
@@ -224,6 +349,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
+ tuner_i2c_address_check(t);
}
/*
@@ -384,10 +510,10 @@ static int tuner_fixup_std(struct tuner *t)
return 0;
}
-static void tuner_status(struct i2c_client *client)
+static void tuner_status(struct tuner *t)
{
- struct tuner *t = i2c_get_clientdata(client);
unsigned long freq, freq_fraction;
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
const char *p;
switch (t->mode) {
@@ -408,11 +534,20 @@ static void tuner_status(struct i2c_client *client)
tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
if (t->mode != V4L2_TUNER_RADIO)
return;
- if (t->has_signal) {
- tuner_info("Signal strength: %d\n", t->has_signal(client));
+ if (fe_tuner_ops->get_status) {
+ u32 tuner_status;
+
+ fe_tuner_ops->get_status(&t->fe, &tuner_status);
+ if (tuner_status & TUNER_STATUS_LOCKED)
+ tuner_info("Tuner is locked.\n");
+ if (tuner_status & TUNER_STATUS_STEREO)
+ tuner_info("Stereo: yes\n");
+ }
+ if (t->ops.has_signal) {
+ tuner_info("Signal strength: %d\n", t->ops.has_signal(t));
}
- if (t->is_stereo) {
- tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no");
+ if (t->ops.is_stereo) {
+ tuner_info("Stereo: %s\n", t->ops.is_stereo(t) ? "yes" : "no");
}
}
@@ -437,10 +572,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
memcpy(&t->i2c, &client_template, sizeof(struct i2c_client));
i2c_set_clientdata(&t->i2c, t);
t->type = UNSET;
- t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
t->audmode = V4L2_TUNER_MODE_STEREO;
t->mode_mask = T_UNINITIALIZED;
- t->tuner_status = tuner_status;
+ t->ops.tuner_status = tuner_status;
if (show_i2c) {
unsigned char buffer[16];
@@ -460,13 +594,26 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
/* autodetection code based on the i2c addr */
if (!no_autodetect) {
switch (addr) {
+#ifdef CONFIG_TUNER_TEA5761
+ case 0x10:
+ if (tea5761_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) {
+ t->type = TUNER_TEA5761;
+ t->mode_mask = T_RADIO;
+ t->mode = T_STANDBY;
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
+ default_mode_mask &= ~T_RADIO;
+
+ goto register_client;
+ }
+ break;
+#endif
case 0x42:
case 0x43:
case 0x4a:
case 0x4b:
/* If chip is not tda8290, don't register.
since it can be tda9887*/
- if (tda8290_probe(&t->i2c) == 0) {
+ if (tda8290_probe(t->i2c.adapter, t->i2c.addr) == 0) {
tuner_dbg("chip at addr %x is a tda8290\n", addr);
} else {
/* Default is being tda9887 */
@@ -477,7 +624,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
}
break;
case 0x60:
- if (tea5767_autodetection(&t->i2c) != EINVAL) {
+ if (tea5767_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) {
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
@@ -514,6 +661,28 @@ static int tuner_probe(struct i2c_adapter *adap)
normal_i2c[1] = I2C_CLIENT_END;
}
+ /* HACK: 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.
+ */
+ if ((adap->id == I2C_HW_B_CX2388x) ||
+ (adap->id == I2C_HW_B_CX23885)) {
+ unsigned int i = 0;
+
+ while (i < I2C_CLIENT_MAX_OPTS && ignore[i] != I2C_CLIENT_END)
+ i += 2;
+ if (i + 4 < I2C_CLIENT_MAX_OPTS) {
+ ignore[i+0] = adap->nr;
+ ignore[i+1] = 0x6b;
+ ignore[i+2] = adap->nr;
+ ignore[i+3] = 0x6f;
+ ignore[i+4] = I2C_CLIENT_END;
+ } else
+ printk(KERN_WARNING "tuner: "
+ "too many options specified "
+ "in i2c probe ignore list!\n");
+ }
+
default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
if (adap->class & I2C_CLASS_TV_ANALOG)
@@ -533,6 +702,11 @@ static int tuner_detach(struct i2c_client *client)
return err;
}
+ if (t->ops.release)
+ t->ops.release(t);
+ else {
+ kfree(t->priv);
+ }
kfree(t);
return 0;
}
@@ -553,8 +727,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
if (check_mode(t, cmd) == EINVAL) {
t->mode = T_STANDBY;
- if (t->standby)
- t->standby (client);
+ if (t->ops.standby)
+ t->ops.standby(t);
return EINVAL;
}
return 0;
@@ -576,6 +750,7 @@ static inline int check_v4l2(struct tuner *t)
static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct tuner *t = i2c_get_clientdata(client);
+ struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
if (tuner_debug>1)
v4l_i2c_print_ioctl(&(t->i2c),cmd);
@@ -602,8 +777,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
return 0;
t->mode = T_STANDBY;
- if (t->standby)
- t->standby (client);
+ if (t->ops.standby)
+ t->ops.standby(t);
break;
#ifdef CONFIG_VIDEO_V4L1
case VIDIOCSAUDIO:
@@ -662,16 +837,27 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
if (V4L2_TUNER_RADIO == t->mode) {
- if (t->has_signal)
- vt->signal = t->has_signal(client);
- if (t->is_stereo) {
- if (t->is_stereo(client))
- vt->flags |=
- VIDEO_TUNER_STEREO_ON;
+ if (fe_tuner_ops->get_status) {
+ u32 tuner_status;
+
+ fe_tuner_ops->get_status(&t->fe, &tuner_status);
+ if (tuner_status & TUNER_STATUS_STEREO)
+ vt->flags |= VIDEO_TUNER_STEREO_ON;
else
- vt->flags &=
- ~VIDEO_TUNER_STEREO_ON;
+ vt->flags &= ~VIDEO_TUNER_STEREO_ON;
+ } else {
+ if (t->ops.is_stereo) {
+ if (t->ops.is_stereo(t))
+ vt->flags |=
+ VIDEO_TUNER_STEREO_ON;
+ else
+ vt->flags &=
+ ~VIDEO_TUNER_STEREO_ON;
+ }
}
+ if (t->ops.has_signal)
+ vt->signal = t->ops.has_signal(t);
+
vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */
vt->rangelow = radio_range[0] * 16000;
@@ -693,9 +879,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (check_v4l2(t) == EINVAL)
return 0;
- if (V4L2_TUNER_RADIO == t->mode && t->is_stereo)
- va->mode = t->is_stereo(client)
- ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (fe_tuner_ops->get_status) {
+ u32 tuner_status;
+
+ fe_tuner_ops->get_status(&t->fe, &tuner_status);
+ va->mode = (tuner_status & TUNER_STATUS_STEREO)
+ ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ } else if (t->ops.is_stereo)
+ va->mode = t->ops.is_stereo(t)
+ ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ }
return 0;
}
#endif
@@ -746,6 +940,15 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
switch_v4l2();
f->type = t->mode;
+ if (fe_tuner_ops->get_frequency) {
+ u32 abs_freq;
+
+ fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
+ f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+ (abs_freq * 2 + 125/2) / 125 :
+ (abs_freq + 62500/2) / 62500;
+ break;
+ }
f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
t->radio_freq : t->tv_freq;
break;
@@ -759,8 +962,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2();
tuner->type = t->mode;
- if (t->get_afc)
- tuner->afc=t->get_afc(client);
+ if (t->ops.get_afc)
+ tuner->afc=t->ops.get_afc(t);
if (t->mode == V4L2_TUNER_ANALOG_TV)
tuner->capability |= V4L2_TUNER_CAP_NORM;
if (t->mode != V4L2_TUNER_RADIO) {
@@ -770,16 +973,22 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
/* radio mode */
- if (t->has_signal)
- tuner->signal = t->has_signal(client);
-
tuner->rxsubchans =
V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- if (t->is_stereo) {
- tuner->rxsubchans = t->is_stereo(client) ?
+ if (fe_tuner_ops->get_status) {
+ u32 tuner_status;
+
+ fe_tuner_ops->get_status(&t->fe, &tuner_status);
+ tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ?
V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
+ } else {
+ if (t->ops.is_stereo) {
+ tuner->rxsubchans = t->ops.is_stereo(t) ?
+ V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
+ }
}
-
+ if (t->ops.has_signal)
+ tuner->signal = t->ops.has_signal(t);
tuner->capability |=
V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
tuner->audmode = t->audmode;
@@ -804,8 +1013,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
}
case VIDIOC_LOG_STATUS:
- if (t->tuner_status)
- t->tuner_status(client);
+ if (t->ops.tuner_status)
+ t->ops.tuner_status(t);
break;
}
diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h
new file mode 100644
index 000000000000..28a10da76d12
--- /dev/null
+++ b/drivers/media/video/tuner-driver.h
@@ -0,0 +1,99 @@
+/*
+ tuner-driver.h - interface for different tuners
+
+ Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
+ minor modifications by Ralph Metzler (rjkm@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 __TUNER_DRIVER_H__
+#define __TUNER_DRIVER_H__
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include "tuner-i2c.h"
+#include "dvb_frontend.h"
+
+extern unsigned const int tuner_count;
+
+struct tuner;
+
+struct tuner_operations {
+ void (*set_tv_freq)(struct tuner *t, unsigned int freq);
+ void (*set_radio_freq)(struct tuner *t, unsigned int freq);
+ int (*has_signal)(struct tuner *t);
+ int (*is_stereo)(struct tuner *t);
+ int (*get_afc)(struct tuner *t);
+ void (*tuner_status)(struct tuner *t);
+ void (*standby)(struct tuner *t);
+ void (*release)(struct tuner *t);
+};
+
+struct tuner {
+ /* device */
+ struct i2c_client i2c;
+
+ unsigned int type; /* chip type */
+
+ unsigned int mode;
+ unsigned int mode_mask; /* Combination of allowable modes */
+
+ unsigned int tv_freq; /* keep track of the current settings */
+ unsigned int radio_freq;
+ unsigned int audmode;
+ v4l2_std_id std;
+
+ int using_v4l2;
+ void *priv;
+
+ struct dvb_frontend fe;
+
+ /* used by tda9887 */
+ unsigned int tda9887_config;
+
+ unsigned int config;
+ int (*tuner_callback) (void *dev, int command,int arg);
+
+ struct tuner_operations ops;
+};
+
+/* ------------------------------------------------------------------------ */
+
+extern int tda9887_tuner_init(struct tuner *t);
+
+/* ------------------------------------------------------------------------ */
+
+#define tuner_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+#define tuner_info(fmt, arg...) do {\
+ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+#define tuner_dbg(fmt, arg...) do {\
+ extern int tuner_debug; \
+ if (tuner_debug) \
+ printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+
+#endif /* __TUNER_DRIVER_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h
new file mode 100644
index 000000000000..159019ec3373
--- /dev/null
+++ b/drivers/media/video/tuner-i2c.h
@@ -0,0 +1,70 @@
+/*
+ tuner-i2c.h - i2c interface for different tuners
+
+ Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __TUNER_I2C_H__
+#define __TUNER_I2C_H__
+
+#include <linux/i2c.h>
+
+struct tuner_i2c_props {
+ u8 addr;
+ struct i2c_adapter *adap;
+};
+
+static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
+{
+ struct i2c_msg msg = { .addr = props->addr, .flags = 0,
+ .buf = buf, .len = len };
+ int ret = i2c_transfer(props->adap, &msg, 1);
+
+ return (ret == 1) ? len : ret;
+}
+
+static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
+{
+ struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
+ .buf = buf, .len = len };
+ int ret = i2c_transfer(props->adap, &msg, 1);
+
+ return (ret == 1) ? len : ret;
+}
+
+#ifndef __TUNER_DRIVER_H__
+#define tuner_warn(fmt, arg...) do {\
+ printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \
+ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0)
+#define tuner_info(fmt, arg...) do {\
+ printk(KERN_INFO PREFIX "%d-%04x: " fmt, \
+ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0)
+#define tuner_dbg(fmt, arg...) do {\
+ if ((debug)) \
+ printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \
+ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0)
+#endif /* __TUNER_DRIVER_H__ */
+
+#endif /* __TUNER_I2C_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index c40b92ce1fad..7b93d3b1f4c6 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,13 +1,23 @@
/*
- *
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
+ *
+ * This "tuner-simple" module was split apart from the original "tuner" module.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>
+#include <media/tuner-types.h>
+#include "tuner-i2c.h"
+#include "tuner-simple.h"
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+#define PREFIX "tuner-simple "
static int offset = 0;
module_param(offset, int, 0664);
@@ -54,9 +64,9 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
sound 2 33.16 - -
NICAM 33.05 33.05 39.80
*/
-#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
-#define PHILIPS_MF_SET_PAL_L 0x03 // France
-#define PHILIPS_MF_SET_PAL_L2 0x02 // L'
+#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
+#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */
+#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */
/* Control byte */
@@ -80,59 +90,102 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
#define TUNER_PLL_LOCKED 0x40
#define TUNER_STEREO_MK3 0x04
+struct tuner_simple_priv {
+ u16 last_div;
+ struct tuner_i2c_props i2c_props;
+
+ unsigned int type;
+ struct tunertype *tun;
+
+ u32 frequency;
+};
+
/* ---------------------------------------------------------------------- */
-static int tuner_getstatus(struct i2c_client *c)
+static int tuner_read_status(struct dvb_frontend *fe)
{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
unsigned char byte;
- if (1 != i2c_master_recv(c,&byte,1))
+ if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1))
return 0;
return byte;
}
-static int tuner_signal(struct i2c_client *c)
+static inline int tuner_signal(const int status)
{
- return (tuner_getstatus(c) & TUNER_SIGNAL) << 13;
+ return (status & TUNER_SIGNAL) << 13;
}
-static int tuner_stereo(struct i2c_client *c)
+static inline int tuner_stereo(const int type, const int status)
{
- int stereo, status;
- struct tuner *t = i2c_get_clientdata(c);
-
- status = tuner_getstatus (c);
-
- switch (t->type) {
+ switch (type) {
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FM1256_IH3:
case TUNER_LG_NTSC_TAPE:
- stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
- break;
+ return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
default:
- stereo = status & TUNER_STEREO;
+ return status & TUNER_STEREO;
}
+}
+
+static inline int tuner_islocked(const int status)
+{
+ return (status & TUNER_FL);
+}
+
+static inline int tuner_afcstatus(const int status)
+{
+ return (status & TUNER_AFC) - 2;
+}
+
+
+static int simple_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ int tuner_status = tuner_read_status(fe);
+
+ *status = 0;
+
+ if (tuner_islocked(tuner_status))
+ *status = TUNER_STATUS_LOCKED;
+ if (tuner_stereo(priv->type, tuner_status))
+ *status |= TUNER_STATUS_STEREO;
- return stereo;
+ tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
+
+ return 0;
}
+static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ int signal = tuner_signal(tuner_read_status(fe));
+
+ *strength = signal;
+
+ tuner_dbg("Signal strength: %d\n", signal);
+
+ return 0;
+}
/* ---------------------------------------------------------------------- */
-static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
+static int simple_set_tv_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tuner_simple_priv *priv = fe->tuner_priv;
u8 config, cb, tuneraddr;
u16 div;
struct tunertype *tun;
u8 buffer[4];
int rc, IFPCoff, i, j;
enum param_type desired_type;
- struct tuner_params *params;
+ struct tuner_params *t_params;
- tun = &tuners[t->type];
+ tun = priv->tun;
/* IFPCoff = Video Intermediate Frequency - Vif:
940 =16*58.75 NTSC/J (Japan)
@@ -146,14 +199,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
171.2=16*10.70 FM Radio (at set_radio_freq)
*/
- if (t->std == V4L2_STD_NTSC_M_JP) {
+ if (params->std == V4L2_STD_NTSC_M_JP) {
IFPCoff = 940;
desired_type = TUNER_PARAM_TYPE_NTSC;
- } else if ((t->std & V4L2_STD_MN) &&
- !(t->std & ~V4L2_STD_MN)) {
+ } else if ((params->std & V4L2_STD_MN) &&
+ !(params->std & ~V4L2_STD_MN)) {
IFPCoff = 732;
desired_type = TUNER_PARAM_TYPE_NTSC;
- } else if (t->std == V4L2_STD_SECAM_LC) {
+ } else if (params->std == V4L2_STD_SECAM_LC) {
IFPCoff = 543;
desired_type = TUNER_PARAM_TYPE_SECAM;
} else {
@@ -166,67 +219,67 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
continue;
break;
}
- /* use default tuner_params if desired_type not available */
+ /* use default tuner_t_params if desired_type not available */
if (desired_type != tun->params[j].type) {
- tuner_dbg("IFPCoff = %d: tuner_params undefined for tuner %d\n",
- IFPCoff,t->type);
+ tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n",
+ IFPCoff, priv->type);
j = 0;
}
- params = &tun->params[j];
+ t_params = &tun->params[j];
- for (i = 0; i < params->count; i++) {
- if (freq > params->ranges[i].limit)
+ for (i = 0; i < t_params->count; i++) {
+ if (params->frequency > t_params->ranges[i].limit)
continue;
break;
}
- if (i == params->count) {
+ if (i == t_params->count) {
tuner_dbg("TV frequency out of range (%d > %d)",
- freq, params->ranges[i - 1].limit);
- freq = params->ranges[--i].limit;
+ params->frequency, t_params->ranges[i - 1].limit);
+ params->frequency = t_params->ranges[--i].limit;
}
- config = params->ranges[i].config;
- cb = params->ranges[i].cb;
+ config = t_params->ranges[i].config;
+ cb = t_params->ranges[i].cb;
/* i == 0 -> VHF_LO
* i == 1 -> VHF_HI
* i == 2 -> UHF */
tuner_dbg("tv: param %d, range %d\n",j,i);
- div=freq + IFPCoff + offset;
+ div=params->frequency + IFPCoff + offset;
tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
- freq / 16, freq % 16 * 100 / 16,
+ params->frequency / 16, params->frequency % 16 * 100 / 16,
IFPCoff / 16, IFPCoff % 16 * 100 / 16,
offset / 16, offset % 16 * 100 / 16,
div);
/* tv norm specific stuff for multi-norm tuners */
- switch (t->type) {
+ switch (priv->type) {
case TUNER_PHILIPS_SECAM: // FI1216MF
/* 0x01 -> ??? no change ??? */
/* 0x02 -> PAL BDGHI / SECAM L */
/* 0x04 -> ??? PAL others / SECAM others ??? */
cb &= ~0x03;
- if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
- cb |= PHILIPS_MF_SET_PAL_L;
- else if (t->std & V4L2_STD_SECAM_LC)
- cb |= PHILIPS_MF_SET_PAL_L2;
+ if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
+ cb |= PHILIPS_MF_SET_STD_L;
+ else if (params->std & V4L2_STD_SECAM_LC)
+ cb |= PHILIPS_MF_SET_STD_LC;
else /* V4L2_STD_B|V4L2_STD_GH */
- cb |= PHILIPS_MF_SET_BG;
+ cb |= PHILIPS_MF_SET_STD_BG;
break;
case TUNER_TEMIC_4046FM5:
cb &= ~0x0f;
- if (t->std & V4L2_STD_PAL_BG) {
+ if (params->std & V4L2_STD_PAL_BG) {
cb |= TEMIC_SET_PAL_BG;
- } else if (t->std & V4L2_STD_PAL_I) {
+ } else if (params->std & V4L2_STD_PAL_I) {
cb |= TEMIC_SET_PAL_I;
- } else if (t->std & V4L2_STD_PAL_DK) {
+ } else if (params->std & V4L2_STD_PAL_DK) {
cb |= TEMIC_SET_PAL_DK;
- } else if (t->std & V4L2_STD_SECAM_L) {
+ } else if (params->std & V4L2_STD_SECAM_L) {
cb |= TEMIC_SET_PAL_L;
}
@@ -235,13 +288,13 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
case TUNER_PHILIPS_FQ1216ME:
cb &= ~0x0f;
- if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+ if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
cb |= PHILIPS_SET_PAL_BGDK;
- } else if (t->std & V4L2_STD_PAL_I) {
+ } else if (params->std & V4L2_STD_PAL_I) {
cb |= PHILIPS_SET_PAL_I;
- } else if (t->std & V4L2_STD_SECAM_L) {
+ } else if (params->std & V4L2_STD_SECAM_L) {
cb |= PHILIPS_SET_PAL_L;
}
@@ -253,7 +306,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
/* 0x02 -> NTSC antenna input 1 */
/* 0x03 -> NTSC antenna input 2 */
cb &= ~0x03;
- if (!(t->std & V4L2_STD_ATSC))
+ if (!(params->std & V4L2_STD_ATSC))
cb |= 2;
/* FIXME: input */
break;
@@ -273,23 +326,23 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = 0x17;
buffer[3] = 0x00;
cb &= ~0x40;
- if (t->std & V4L2_STD_ATSC) {
+ if (params->std & V4L2_STD_ATSC) {
cb |= 0x40;
buffer[1] = 0x04;
}
/* set to the correct mode (analog or digital) */
- tuneraddr = c->addr;
- c->addr = 0x0a;
- if (2 != (rc = i2c_master_send(c,&buffer[0],2)))
+ tuneraddr = priv->i2c_props.addr;
+ priv->i2c_props.addr = 0x0a;
+ if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))
tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
- if (2 != (rc = i2c_master_send(c,&buffer[2],2)))
+ if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))
tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
- c->addr = tuneraddr;
+ priv->i2c_props.addr = tuneraddr;
/* FIXME: input */
break;
}
- if (params->cb_first_if_lower_freq && div < t->last_div) {
+ if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
buffer[0] = config;
buffer[1] = cb;
buffer[2] = (div>>8) & 0x7f;
@@ -300,53 +353,53 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = config;
buffer[3] = cb;
}
- t->last_div = div;
- if (params->has_tda9887) {
+ priv->last_div = div;
+ if (t_params->has_tda9887) {
int config = 0;
- int is_secam_l = (t->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
- !(t->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
+ int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
+ !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
- if (t->std == V4L2_STD_SECAM_LC) {
- if (params->port1_active ^ params->port1_invert_for_secam_lc)
+ if (params->std == V4L2_STD_SECAM_LC) {
+ if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
config |= TDA9887_PORT1_ACTIVE;
- if (params->port2_active ^ params->port2_invert_for_secam_lc)
+ if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
config |= TDA9887_PORT2_ACTIVE;
}
else {
- if (params->port1_active)
+ if (t_params->port1_active)
config |= TDA9887_PORT1_ACTIVE;
- if (params->port2_active)
+ if (t_params->port2_active)
config |= TDA9887_PORT2_ACTIVE;
}
- if (params->intercarrier_mode)
+ if (t_params->intercarrier_mode)
config |= TDA9887_INTERCARRIER;
if (is_secam_l) {
- if (i == 0 && params->default_top_secam_low)
- config |= TDA9887_TOP(params->default_top_secam_low);
- else if (i == 1 && params->default_top_secam_mid)
- config |= TDA9887_TOP(params->default_top_secam_mid);
- else if (params->default_top_secam_high)
- config |= TDA9887_TOP(params->default_top_secam_high);
+ if (i == 0 && t_params->default_top_secam_low)
+ config |= TDA9887_TOP(t_params->default_top_secam_low);
+ else if (i == 1 && t_params->default_top_secam_mid)
+ config |= TDA9887_TOP(t_params->default_top_secam_mid);
+ else if (t_params->default_top_secam_high)
+ config |= TDA9887_TOP(t_params->default_top_secam_high);
}
else {
- if (i == 0 && params->default_top_low)
- config |= TDA9887_TOP(params->default_top_low);
- else if (i == 1 && params->default_top_mid)
- config |= TDA9887_TOP(params->default_top_mid);
- else if (params->default_top_high)
- config |= TDA9887_TOP(params->default_top_high);
+ if (i == 0 && t_params->default_top_low)
+ config |= TDA9887_TOP(t_params->default_top_low);
+ else if (i == 1 && t_params->default_top_mid)
+ config |= TDA9887_TOP(t_params->default_top_mid);
+ else if (t_params->default_top_high)
+ config |= TDA9887_TOP(t_params->default_top_high);
}
- if (params->default_pll_gating_18)
+ if (t_params->default_pll_gating_18)
config |= TDA9887_GATING_18;
- i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
+ i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config);
}
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
- if (4 != (rc = i2c_master_send(c,buffer,4)))
+ if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
- switch (t->type) {
+ switch (priv->type) {
case TUNER_LG_TDVS_H06XF:
/* Set the Auxiliary Byte. */
buffer[0] = buffer[2];
@@ -355,7 +408,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[1] = 0x20;
tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
- if (2 != (rc = i2c_master_send(c,buffer,2)))
+ if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))
tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
break;
case TUNER_MICROTUNE_4042FI5:
@@ -367,8 +420,8 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
/* Wait until the PLL locks */
for (;;) {
if (time_after(jiffies,timeout))
- return;
- if (1 != (rc = i2c_master_recv(c,&status_byte,1))) {
+ return 0;
+ if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {
tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
break;
}
@@ -386,68 +439,86 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
- if (4 != (rc = i2c_master_send(c,buffer,4)))
+ if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
break;
}
}
+ return 0;
}
-static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
+static int simple_set_radio_freq(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
struct tunertype *tun;
- struct tuner *t = i2c_get_clientdata(c);
+ struct tuner_simple_priv *priv = fe->tuner_priv;
u8 buffer[4];
u16 div;
int rc, j;
- enum param_type desired_type = TUNER_PARAM_TYPE_RADIO;
- struct tuner_params *params;
+ struct tuner_params *t_params;
+ unsigned int freq = params->frequency;
- tun = &tuners[t->type];
+ tun = priv->tun;
- for (j = 0; j < tun->count-1; j++) {
- if (desired_type != tun->params[j].type)
- continue;
+ for (j = tun->count-1; j > 0; j--)
+ if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
+ break;
+ /* default t_params (j=0) will be used if desired type wasn't found */
+ t_params = &tun->params[j];
+
+ /* Select Radio 1st IF used */
+ switch (t_params->radio_if) {
+ case 0: /* 10.7 MHz */
+ freq += (unsigned int)(10.7*16000);
+ break;
+ case 1: /* 33.3 MHz */
+ freq += (unsigned int)(33.3*16000);
break;
+ case 2: /* 41.3 MHz */
+ freq += (unsigned int)(41.3*16000);
+ break;
+ default:
+ tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);
+ return 0;
}
- /* use default tuner_params if desired_type not available */
- if (desired_type != tun->params[j].type)
- j = 0;
-
- div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
- params = &tun->params[j];
- buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
- switch (t->type) {
+ /* Bandswitch byte */
+ switch (priv->type) {
case TUNER_TENA_9533_DI:
case TUNER_YMEC_TVF_5533MF:
- tuner_dbg ("This tuner doesn't have FM. Most cards has a TEA5767 for FM\n");
- return;
+ tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
+ return 0;
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FMD1216ME_MK3:
case TUNER_LG_NTSC_TAPE:
+ case TUNER_PHILIPS_FM1256_IH3:
buffer[3] = 0x19;
break;
case TUNER_TNF_5335MF:
buffer[3] = 0x11;
break;
- case TUNER_PHILIPS_FM1256_IH3:
- div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
- buffer[3] = 0x19;
- break;
case TUNER_LG_PAL_FM:
buffer[3] = 0xa5;
break;
- case TUNER_MICROTUNE_4049FM5:
- div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
- buffer[3] = 0xa4;
+ case TUNER_THOMSON_DTT761X:
+ buffer[3] = 0x39;
break;
+ case TUNER_MICROTUNE_4049FM5:
default:
buffer[3] = 0xa4;
break;
}
- if (params->cb_first_if_lower_freq && div < t->last_div) {
+
+ buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
+ TUNER_RATIO_SELECT_50; /* 50 kHz step */
+
+ /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
+ freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
+ freq * (1/800) */
+ div = (freq + 400) / 800;
+
+ if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
buffer[0] = buffer[2];
buffer[1] = buffer[3];
buffer[2] = (div>>8) & 0x7f;
@@ -459,43 +530,108 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
- t->last_div = div;
+ priv->last_div = div;
- if (params->has_tda9887) {
+ if (t_params->has_tda9887) {
int config = 0;
- if (params->port1_active && !params->port1_fm_high_sensitivity)
+ if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)
config |= TDA9887_PORT1_ACTIVE;
- if (params->port2_active && !params->port2_fm_high_sensitivity)
+ if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)
config |= TDA9887_PORT2_ACTIVE;
- if (params->intercarrier_mode)
+ if (t_params->intercarrier_mode)
config |= TDA9887_INTERCARRIER;
-/* if (params->port1_set_for_fm_mono)
+/* if (t_params->port1_set_for_fm_mono)
config &= ~TDA9887_PORT1_ACTIVE;*/
- if (params->fm_gain_normal)
+ if (t_params->fm_gain_normal)
config |= TDA9887_GAIN_NORMAL;
- i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
+ if (t_params->radio_if == 2)
+ config |= TDA9887_RIF_41_3;
+ i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config);
}
- if (4 != (rc = i2c_master_send(c,buffer,4)))
+ if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+
+ return 0;
}
-int default_tuner_init(struct i2c_client *c)
+static int simple_set_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
- struct tuner *t = i2c_get_clientdata(c);
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ int ret = -EINVAL;
- tuner_info("type set to %d (%s)\n",
- t->type, tuners[t->type].name);
- strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
+ switch (params->mode) {
+ case V4L2_TUNER_RADIO:
+ ret = simple_set_radio_freq(fe, params);
+ priv->frequency = params->frequency * 125 / 2;
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ case V4L2_TUNER_DIGITAL_TV:
+ ret = simple_set_tv_freq(fe, params);
+ priv->frequency = params->frequency * 62500;
+ break;
+ }
- t->set_tv_freq = default_set_tv_freq;
- t->set_radio_freq = default_set_radio_freq;
- t->has_signal = tuner_signal;
- t->is_stereo = tuner_stereo;
- t->standby = NULL;
+ return ret;
+}
+
+static int simple_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
return 0;
}
+static struct dvb_tuner_ops simple_tuner_ops = {
+ .set_analog_params = simple_set_params,
+ .release = simple_release,
+ .get_frequency = simple_get_frequency,
+ .get_status = simple_get_status,
+ .get_rf_strength = simple_get_rf_strength,
+};
+
+struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct simple_tuner_config *cfg)
+{
+ struct tuner_simple_priv *priv = NULL;
+
+ priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+ fe->tuner_priv = priv;
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
+ priv->type = cfg->type;
+ priv->tun = cfg->tun;
+
+ memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+ tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);
+
+ strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));
+
+ return fe;
+}
+
+
+EXPORT_SYMBOL_GPL(simple_tuner_attach);
+
+MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h
new file mode 100644
index 000000000000..9089939a8c02
--- /dev/null
+++ b/drivers/media/video/tuner-simple.h
@@ -0,0 +1,46 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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 __TUNER_SIMPLE_H__
+#define __TUNER_SIMPLE_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+struct simple_tuner_config
+{
+ /* chip type */
+ unsigned int type;
+ struct tunertype *tun;
+};
+
+#if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
+extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct simple_tuner_config *cfg);
+#else
+static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct simple_tuner_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif
+
+#endif /* __TUNER_SIMPLE_H__ */
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index 74c3e6f96f1a..c6a7934bd5a6 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -594,19 +594,19 @@ static struct tuner_params tuner_philips_pal_mk_params[] = {
},
};
-/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */
+/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */
-static struct tuner_range tuner_philips_atsc_ranges[] = {
+static struct tuner_range tuner_philips_fcv1236d_ranges[] = {
{ 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
+ { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
{ 16 * 999.99 , 0x8e, 0x30, },
};
-static struct tuner_params tuner_philips_atsc_params[] = {
+static struct tuner_params tuner_philips_fcv1236d_params[] = {
{
.type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_atsc_ranges,
- .count = ARRAY_SIZE(tuner_philips_atsc_ranges),
+ .ranges = tuner_philips_fcv1236d_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fcv1236d_ranges),
},
};
@@ -652,6 +652,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
.port1_invert_for_secam_lc = 1,
.default_pll_gating_18 = 1,
.fm_gain_normal=1,
+ .radio_if = 1, /* 33.3 MHz */
},
};
@@ -670,6 +671,9 @@ static struct tuner_params tuner_panasonic_vp27_params[] = {
.count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
.has_tda9887 = 1,
.intercarrier_mode = 1,
+ .default_top_low = -3,
+ .default_top_mid = -3,
+ .default_top_high = -3,
},
};
@@ -730,6 +734,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
.type = TUNER_PARAM_TYPE_PAL,
.ranges = tuner_fm1236_mk3_ntsc_ranges,
.count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+ .radio_if = 1, /* 33.3 MHz */
},
};
@@ -856,6 +861,9 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
.type = TUNER_PARAM_TYPE_NTSC,
.ranges = tuner_thomson_dtt761x_ntsc_ranges,
.count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+ .has_tda9887 = 1,
+ .fm_gain_normal = 1,
+ .radio_if = 2, /* 41.3 MHz */
},
};
@@ -1296,9 +1304,9 @@ struct tunertype tuners[] = {
.count = ARRAY_SIZE(tuner_philips_pal_mk_params),
},
[TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
- .name = "Philips 1236D ATSC/NTSC dual in",
- .params = tuner_philips_atsc_params,
- .count = ARRAY_SIZE(tuner_philips_atsc_params),
+ .name = "Philips FCV1236D ATSC/NTSC dual in",
+ .params = tuner_philips_fcv1236d_params,
+ .count = ARRAY_SIZE(tuner_philips_fcv1236d_params),
},
[TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
.name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
@@ -1463,6 +1471,10 @@ struct tunertype tuners[] = {
.name = "Philips TDA988[5,6,7] IF PLL Demodulator",
/* see tda9887.c for details */
},
+ [TUNER_TEA5761] = { /* Philips RADIO */
+ .name = "Philips TEA5761 FM Radio",
+ /* see tea5767.c for details */
+ },
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 9da338dc4f3b..a19cdcc17ef7 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -15,7 +15,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -290,7 +289,7 @@ static int chip_thread(void *data)
desc->checkmode(chip);
/* schedule next check */
- mod_timer(&chip->wt, jiffies+2*HZ);
+ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
}
v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name);
@@ -1770,7 +1769,7 @@ static int chip_command(struct i2c_client *client,
desc->setmode(chip,VIDEO_SOUND_MONO);
if (chip->prevmode != VIDEO_SOUND_MONO)
chip->prevmode = -1; /* reset previous mode */
- mod_timer(&chip->wt, jiffies+2*HZ);
+ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
/* the thread will call checkmode() later */
}
break;
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index a1136da74ba8..4b2c4034f5b3 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -30,7 +30,6 @@
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -183,7 +182,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Silicon TDA8275C1 8290 FM"},
{ TUNER_ABSENT, "Thompson DTT757"},
/* 80-89 */
- { TUNER_ABSENT, "Philips FQ1216LME MK3"},
+ { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216LME MK3"},
{ TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"},
{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
@@ -490,7 +489,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
to indicate 4052 mux was removed in favor of using MSP
inputs directly. */
audioic = eeprom_data[i+2] & 0x7f;
- if (audioic < sizeof(audioIC)/sizeof(*audioIC))
+ if (audioic < ARRAY_SIZE(audioIC))
tvee->audio_processor = audioIC[audioic].id;
else
tvee->audio_processor = AUDIO_CHIP_UNKNOWN;
@@ -523,7 +522,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
to indicate 4052 mux was removed in favor of using MSP
inputs directly. */
audioic = eeprom_data[i+1] & 0x7f;
- if (audioic < sizeof(audioIC)/sizeof(*audioIC))
+ if (audioic < ARRAY_SIZE(audioIC))
tvee->audio_processor = audioIC[audioic].id;
else
tvee->audio_processor = AUDIO_CHIP_UNKNOWN;
@@ -678,7 +677,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
tveeprom_info("audio processor is unknown (no idx)\n");
tvee->audio_processor=AUDIO_CHIP_UNKNOWN;
} else {
- if (audioic < sizeof(audioIC)/sizeof(*audioIC))
+ if (audioic < ARRAY_SIZE(audioIC))
tveeprom_info("audio processor is %s (idx %d)\n",
audioIC[audioic].name,audioic);
else
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 3ae5a9cd2e28..9fa5b702e073 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -2,7 +2,6 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
@@ -238,13 +237,10 @@ static const struct file_operations tvmixer_fops = {
static int tvmixer_adapters(struct i2c_adapter *adap)
{
- struct list_head *item;
struct i2c_client *client;
- list_for_each(item,&adap->clients) {
- client = list_entry(item, struct i2c_client, list);
+ list_for_each_entry(client, &adap->clients, list)
tvmixer_clients(client);
- }
return 0;
}
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index d5ec05f56adf..e2f1c972754b 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -1006,7 +1006,7 @@ static int tvp5150_command(struct i2c_client *c,
{
struct v4l2_control *ctrl = arg;
u8 i, n;
- n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
+ n = ARRAY_SIZE(tvp5150_qctrl);
for (i = 0; i < n; i++)
if (ctrl->id == tvp5150_qctrl[i].id) {
if (ctrl->value <
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index abe214619092..491505d6fdee 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -236,7 +236,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
input_dev->name = "Konicawc snapshot button";
input_dev->phys = cam->input_physname;
usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &dev->dev;
+ input_dev->dev.parent = &dev->dev;
input_dev->evbit[0] = BIT(EV_KEY);
input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index ec0ff2247f06..dd1a6d6bbc9e 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -100,7 +100,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
input_dev->name = "QCM button";
input_dev->phys = cam->input_physname;
usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &dev->dev;
+ input_dev->dev.parent = &dev->dev;
input_dev->evbit[0] = BIT(EV_KEY);
input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
@@ -439,7 +439,7 @@ static int qcm_sensor_init(struct uvd *uvd)
int ret;
int i;
- for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) {
+ for (i=0; i < ARRAY_SIZE(regval_table) ; i++) {
CHECK_RET(ret, qcm_stv_setb(uvd->dev,
regval_table[i].reg,
regval_table[i].val));
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 982b115193f8..ff555129c82f 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -42,7 +42,6 @@
#include <linux/usb.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/proc_fs.h>
#include <linux/mutex.h>
#include "usbvideo.h"
@@ -417,11 +416,6 @@ struct vicam_camera {
u8 open_count;
u8 bulkEndpoint;
int needsDummyRead;
-
-#if defined(CONFIG_VIDEO_PROC_FS)
- struct proc_dir_entry *proc_dir;
-#endif
-
};
static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
@@ -1065,175 +1059,6 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-#if defined(CONFIG_VIDEO_PROC_FS)
-
-static struct proc_dir_entry *vicam_proc_root = NULL;
-
-static int vicam_read_helper(char *page, char **start, off_t off,
- int count, int *eof, int value)
-{
- char *out = page;
- int len;
-
- out += sprintf(out, "%d",value);
-
- len = out - page;
- len -= off;
- if (len < count) {
- *eof = 1;
- if (len <= 0)
- return 0;
- } else
- len = count;
-
- *start = page + off;
- return len;
-}
-
-static int vicam_read_proc_shutter(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return vicam_read_helper(page,start,off,count,eof,
- ((struct vicam_camera *)data)->shutter_speed);
-}
-
-static int vicam_read_proc_gain(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return vicam_read_helper(page,start,off,count,eof,
- ((struct vicam_camera *)data)->gain);
-}
-
-static int
-vicam_write_proc_shutter(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- u16 stmp;
- char kbuf[8];
- struct vicam_camera *cam = (struct vicam_camera *) data;
-
- if (count > 6)
- return -EINVAL;
-
- if (copy_from_user(kbuf, buffer, count))
- return -EFAULT;
-
- stmp = (u16) simple_strtoul(kbuf, NULL, 10);
- if (stmp < 4 || stmp > 32000)
- return -EINVAL;
-
- cam->shutter_speed = stmp;
-
- return count;
-}
-
-static int
-vicam_write_proc_gain(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- u16 gtmp;
- char kbuf[8];
-
- struct vicam_camera *cam = (struct vicam_camera *) data;
-
- if (count > 4)
- return -EINVAL;
-
- if (copy_from_user(kbuf, buffer, count))
- return -EFAULT;
-
- gtmp = (u16) simple_strtoul(kbuf, NULL, 10);
- if (gtmp > 255)
- return -EINVAL;
- cam->gain = gtmp;
-
- return count;
-}
-
-static void
-vicam_create_proc_root(void)
-{
- vicam_proc_root = proc_mkdir("video/vicam", NULL);
-
- if (vicam_proc_root)
- vicam_proc_root->owner = THIS_MODULE;
- else
- printk(KERN_ERR
- "could not create /proc entry for vicam!");
-}
-
-static void
-vicam_destroy_proc_root(void)
-{
- if (vicam_proc_root)
- remove_proc_entry("video/vicam", 0);
-}
-
-static void
-vicam_create_proc_entry(struct vicam_camera *cam)
-{
- char name[64];
- struct proc_dir_entry *ent;
-
- DBG(KERN_INFO "vicam: creating proc entry\n");
-
- if (!vicam_proc_root || !cam) {
- printk(KERN_INFO
- "vicam: could not create proc entry, %s pointer is null.\n",
- (!cam ? "camera" : "root"));
- return;
- }
-
- sprintf(name, "video%d", cam->vdev.minor);
-
- cam->proc_dir = proc_mkdir(name, vicam_proc_root);
-
- if ( !cam->proc_dir )
- return; // FIXME: We should probably return an error here
-
- ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
- cam->proc_dir);
- if (ent) {
- ent->data = cam;
- ent->read_proc = vicam_read_proc_shutter;
- ent->write_proc = vicam_write_proc_shutter;
- ent->size = 64;
- }
-
- ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
- cam->proc_dir);
- if (ent) {
- ent->data = cam;
- ent->read_proc = vicam_read_proc_gain;
- ent->write_proc = vicam_write_proc_gain;
- ent->size = 64;
- }
-}
-
-static void
-vicam_destroy_proc_entry(void *ptr)
-{
- struct vicam_camera *cam = (struct vicam_camera *) ptr;
- char name[16];
-
- if ( !cam->proc_dir )
- return;
-
- sprintf(name, "video%d", cam->vdev.minor);
- remove_proc_entry("shutter", cam->proc_dir);
- remove_proc_entry("gain", cam->proc_dir);
- remove_proc_entry(name,vicam_proc_root);
- cam->proc_dir = NULL;
-
-}
-
-#else
-static inline void vicam_create_proc_root(void) { }
-static inline void vicam_destroy_proc_root(void) { }
-static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }
-static inline void vicam_destroy_proc_entry(void *ptr) { }
-#endif
-
static const struct file_operations vicam_fops = {
.owner = THIS_MODULE,
.open = vicam_open,
@@ -1305,13 +1130,12 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
}
if ((cam =
- kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
+ kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
printk(KERN_WARNING
"could not allocate kernel memory for vicam_camera struct\n");
return -ENOMEM;
}
- memset(cam, 0, sizeof (struct vicam_camera));
cam->shutter_speed = 15;
@@ -1330,8 +1154,6 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
return -EIO;
}
- vicam_create_proc_entry(cam);
-
printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
usb_set_intfdata (intf, cam);
@@ -1363,8 +1185,6 @@ vicam_disconnect(struct usb_interface *intf)
cam->udev = NULL;
- vicam_destroy_proc_entry(cam);
-
/* the only thing left to do is synchronize with
* our close/release function on who should release
* the camera memory. if there are any users using the
@@ -1390,7 +1210,6 @@ usb_vicam_init(void)
{
int retval;
DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
- vicam_create_proc_root();
retval = usb_register(&vicam_driver);
if (retval)
printk(KERN_WARNING "usb_register failed!\n");
@@ -1404,7 +1223,6 @@ usb_vicam_exit(void)
"ViCam-based WebCam driver shutdown\n");
usb_deregister(&vicam_driver);
- vicam_destroy_proc_root();
}
module_init(usb_vicam_init);
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
index 51ab265d566a..f09eb102731b 100644
--- a/drivers/media/video/usbvision/usbvision-cards.c
+++ b/drivers/media/video/usbvision/usbvision-cards.c
@@ -79,7 +79,7 @@ struct usbvision_device_data_st usbvision_device_data[] = {
.Interface = -1,
.Codec = CODEC_SAA7113,
.VideoChannels = 2,
- .VideoNorm = V4L2_STD_PAL,
+ .VideoNorm = V4L2_STD_NTSC,
.AudioChannels = 1,
.Radio = 0,
.vbi = 1,
@@ -311,8 +311,8 @@ struct usbvision_device_data_st usbvision_device_data[] = {
.vbi = 1,
.Tuner = 1,
.TunerType = TUNER_PHILIPS_SECAM,
- .X_Offset = -1,
- .Y_Offset = -1,
+ .X_Offset = 0x80,
+ .Y_Offset = 0x16,
.ModelString = "Hauppauge WinTV USB (PAL/SECAM L)",
},
[HPG_WINTV_PAL_D_K] = {
@@ -586,7 +586,7 @@ struct usbvision_device_data_st usbvision_device_data[] = {
.Radio = 0,
.vbi = 1,
.Tuner = 1,
- .TunerType = TUNER_PHILIPS_PAL,
+ .TunerType = TUNER_LG_PAL_NEW_TAPC,
.X_Offset = 0,
.Y_Offset = 3,
.Dvi_yuv_override = 1,
@@ -1081,6 +1081,7 @@ struct usb_device_id usbvision_table [] = {
{ USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL },
{ USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM },
{ USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV },
+ { }, /* terminate list */
};
MODULE_DEVICE_TABLE (usb, usbvision_table);
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 7df071eb0a3b..c7d5f9ed22d7 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -45,7 +45,6 @@
#include <media/tuner.h>
#include <media/audiochip.h>
-#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#ifdef CONFIG_KMOD
@@ -1742,7 +1741,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma
format = ISOC_MODE_YUV420;
}
value[0] = 0x0A; //TODO: See the effect of the filter
- value[1] = format;
+ value[1] = format; // Sets the VO_MODE register which follows FILT_CONT
rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
USBVISION_OP_CODE,
USB_DIR_OUT | USB_TYPE_VENDOR |
@@ -1831,10 +1830,10 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
frameRate = FRAMERATE_MAX;
}
- if (usbvision->tvnorm->id & V4L2_STD_625_50) {
+ if (usbvision->tvnormId & V4L2_STD_625_50) {
frameDrop = frameRate * 32 / 25 - 1;
}
- else if (usbvision->tvnorm->id & V4L2_STD_525_60) {
+ else if (usbvision->tvnormId & V4L2_STD_525_60) {
frameDrop = frameRate * 32 / 30 - 1;
}
@@ -2067,7 +2066,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision)
}
- if (usbvision->tvnorm->id & V4L2_STD_PAL) {
+ if (usbvision->tvnormId & V4L2_STD_PAL) {
value[0] = 0xC0;
value[1] = 0x02; //0x02C0 -> 704 Input video line length
value[2] = 0x20;
@@ -2076,7 +2075,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision)
value[5] = 0x00; //0x0060 -> 96 Input video h offset
value[6] = 0x16;
value[7] = 0x00; //0x0016 -> 22 Input video v offset
- } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) {
+ } else if (usbvision->tvnormId & V4L2_STD_SECAM) {
value[0] = 0xC0;
value[1] = 0x02; //0x02C0 -> 704 Input video line length
value[2] = 0x20;
@@ -2537,7 +2536,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
{
- int mode[4];
+ /* inputs #0 and #3 are constant for every SAA711x. */
+ /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */
+ int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3};
int audio[]= {1, 0, 0, 0};
struct v4l2_routing route;
//channel 0 is TV with audiochannel 1 (tuner mono)
@@ -2547,10 +2548,6 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
usbvision->ctl_input = channel;
- route.input = SAA7115_COMPOSITE1;
- route.output = 0;
- call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
- call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
// set the new channel
// Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video
@@ -2558,28 +2555,27 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
switch (usbvision_device_data[usbvision->DevModel].Codec) {
case CODEC_SAA7113:
- if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module.
- mode[2] = 1;
+ mode[1] = SAA7115_COMPOSITE2;
+ if (SwitchSVideoInput) {
+ /* To handle problems with S-Video Input for
+ * some devices. Use SwitchSVideoInput
+ * parameter when loading the module.*/
+ mode[2] = SAA7115_COMPOSITE1;
}
else {
- mode[2] = 7;
- }
- if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
- mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices
- }
- else {
- mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices
+ mode[2] = SAA7115_SVIDEO1;
}
break;
case CODEC_SAA7111:
- mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111
- break;
default:
- mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes
+ /* modes for saa7111 */
+ mode[1] = SAA7115_COMPOSITE1;
+ mode[2] = SAA7115_SVIDEO1;
+ break;
}
route.input = mode[channel];
+ route.output = 0;
call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
- usbvision->channel = channel;
usbvision_set_audio(usbvision, audio[channel]);
return 0;
}
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 025be555194f..c66aef63916f 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -134,8 +134,6 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap,
addr = (msg->addr << 1);
if (flags & I2C_M_RD)
addr |= 1;
- if (flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
add[0] = addr;
if (flags & I2C_M_RD)
@@ -192,7 +190,7 @@ static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned
static u32 functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
}
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index aa3258bbb4af..e2f3c01cfa13 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -36,7 +36,8 @@
* - use submit_urb for all setup packets
* - Fix memory settings for nt1004. It is 4 times as big as the
* nt1003 memory.
- * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one?
+ * - Add audio on endpoint 3 for nt1004 chip.
+ * Seems impossible, needs a codec interface. Which one?
* - Clean up the driver.
* - optimization for performance.
* - Add Videotext capability (VBI). Working on it.....
@@ -67,7 +68,6 @@
#include <media/tuner.h>
#include <media/audiochip.h>
-#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#ifdef CONFIG_KMOD
@@ -77,7 +77,8 @@
#include "usbvision.h"
#include "usbvision-cards.h"
-#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>"
+#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>,\
+ Dwaine Garden <DwaineGarden@rogers.com>"
#define DRIVER_NAME "usbvision"
#define DRIVER_ALIAS "USBVision"
#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
@@ -85,20 +86,25 @@
#define USBVISION_DRIVER_VERSION_MAJOR 0
#define USBVISION_DRIVER_VERSION_MINOR 9
#define USBVISION_DRIVER_VERSION_PATCHLEVEL 9
-#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL)
-#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\
+USBVISION_DRIVER_VERSION_MINOR,\
+USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR)\
+ "." __stringify(USBVISION_DRIVER_VERSION_MINOR)\
+ "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
#define ENABLE_HEXDUMP 0 /* Enable if you need it */
#ifdef USBVISION_DEBUG
#define PDEBUG(level, fmt, args...) \
- if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+ if (video_debug & (level)) \
+ info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\
+ ## args)
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
#endif
-#define DBG_IOCTL 1<<0
#define DBG_IO 1<<1
#define DBG_PROBE 1<<2
#define DBG_MMAP 1<<3
@@ -108,7 +114,8 @@
#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++;
-static int usbvision_nr = 0; // sequential number of usbvision device
+/* sequential number of usbvision device */
+static int usbvision_nr = 0;
static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
{ 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" },
@@ -121,55 +128,32 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
{ 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
};
-/* supported tv norms */
-static struct usbvision_tvnorm tvnorms[] = {
- {
- .name = "PAL",
- .id = V4L2_STD_PAL,
- }, {
- .name = "NTSC",
- .id = V4L2_STD_NTSC,
- }, {
- .name = "SECAM",
- .id = V4L2_STD_SECAM,
- }, {
- .name = "PAL-M",
- .id = V4L2_STD_PAL_M,
- }
-};
-
-#define TVNORMS ARRAY_SIZE(tvnorms)
-
-// Function prototypes
+/* Function prototypes */
static void usbvision_release(struct usb_usbvision *usbvision);
-// Default initalization of device driver parameters
-static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint
-static int video_debug = 0; // Set the default Debug Mode of the device driver
-static int PowerOnAtOpen = 1; // Set the default device to power on at startup
-static int video_nr = -1; // Sequential Number of Video Device
-static int radio_nr = -1; // Sequential Number of Radio Device
-static int vbi_nr = -1; // Sequential Number of VBI Device
-
-// Grab parameters for the device driver
-
-#if defined(module_param) // Showing parameters under SYSFS
+/* Default initalization of device driver parameters */
+/* Set the default format for ISOC endpoint */
+static int isocMode = ISOC_MODE_COMPRESS;
+/* Set the default Debug Mode of the device driver */
+static int video_debug = 0;
+/* Set the default device to power on at startup */
+static int PowerOnAtOpen = 1;
+/* Sequential Number of Video Device */
+static int video_nr = -1;
+/* Sequential Number of Radio Device */
+static int radio_nr = -1;
+/* Sequential Number of VBI Device */
+static int vbi_nr = -1;
+
+/* Grab parameters for the device driver */
+
+/* Showing parameters under SYSFS */
module_param(isocMode, int, 0444);
module_param(video_debug, int, 0444);
module_param(PowerOnAtOpen, int, 0444);
module_param(video_nr, int, 0444);
module_param(radio_nr, int, 0444);
module_param(vbi_nr, int, 0444);
-#else // Old Style
-MODULE_PARAM(isocMode, "i");
-MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver
-MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive
-MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup
-MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently.
-MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...)
-MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...)
-MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...)
-#endif
MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)");
MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)");
@@ -187,39 +171,47 @@ MODULE_VERSION(USBVISION_VERSION_STRING);
MODULE_ALIAS(DRIVER_ALIAS);
-/****************************************************************************************/
-/* SYSFS Code - Copied from the stv680.c usb module. */
-/* Device information is located at /sys/class/video4linux/video0 */
-/* Device parameters information is located at /sys/module/usbvision */
-/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */
-/****************************************************************************************/
+/*****************************************************************************/
+/* SYSFS Code - Copied from the stv680.c usb module. */
+/* Device information is located at /sys/class/video4linux/video0 */
+/* Device parameters information is located at /sys/module/usbvision */
+/* Device USB Information is located at */
+/* /sys/bus/usb/drivers/USBVision Video Grabber */
+/*****************************************************************************/
#define YES_NO(x) ((x) ? "Yes" : "No")
-static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd)
+static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
return video_get_drvdata(vdev);
}
-static ssize_t show_version(struct class_device *cd, char *buf)
+static ssize_t show_version(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", USBVISION_VERSION_STRING);
}
-static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
-static ssize_t show_model(struct class_device *cd, char *buf)
+static ssize_t show_model(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
- return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString);
+ return sprintf(buf, "%s\n",
+ usbvision_device_data[usbvision->DevModel].ModelString);
}
-static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
-static ssize_t show_hue(struct class_device *cd, char *buf)
+static ssize_t show_hue(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_HUE;
@@ -228,11 +220,13 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
return sprintf(buf, "%d\n", ctrl.value);
}
-static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
+static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
-static ssize_t show_contrast(struct class_device *cd, char *buf)
+static ssize_t show_contrast(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_CONTRAST;
@@ -241,11 +235,13 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
return sprintf(buf, "%d\n", ctrl.value);
}
-static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
+static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
-static ssize_t show_brightness(struct class_device *cd, char *buf)
+static ssize_t show_brightness(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_BRIGHTNESS;
@@ -254,11 +250,13 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
return sprintf(buf, "%d\n", ctrl.value);
}
-static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
+static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
-static ssize_t show_saturation(struct class_device *cd, char *buf)
+static ssize_t show_saturation(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_SATURATION;
@@ -267,31 +265,39 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
return sprintf(buf, "%d\n", ctrl.value);
}
-static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
+static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
-static ssize_t show_streaming(struct class_device *cd, char *buf)
+static ssize_t show_streaming(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
- return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0));
+ return sprintf(buf, "%s\n",
+ YES_NO(usbvision->streaming==Stream_On?1:0));
}
-static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
+static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
-static ssize_t show_compression(struct class_device *cd, char *buf)
+static ssize_t show_compression(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
- return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
+ return sprintf(buf, "%s\n",
+ YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
}
-static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
+static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
-static ssize_t show_device_bridge(struct class_device *cd, char *buf)
+static ssize_t show_device_bridge(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
- struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct video_device *vdev =
+ container_of(cd, struct video_device, class_dev);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
return sprintf(buf, "%d\n", usbvision->bridgeType);
}
-static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
+static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
static void usbvision_create_sysfs(struct video_device *vdev)
{
@@ -299,40 +305,40 @@ static void usbvision_create_sysfs(struct video_device *vdev)
if (!vdev)
return;
do {
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_version);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_version);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_model);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_model);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_hue);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_hue);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_contrast);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_contrast);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_brightness);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_brightness);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_saturation);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_saturation);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_streaming);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_streaming);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_compression);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_compression);
if (res<0)
break;
- res=class_device_create_file(&vdev->class_dev,
- &class_device_attr_bridge);
+ res = device_create_file(&vdev->class_dev,
+ &dev_attr_bridge);
if (res>=0)
return;
} while (0);
@@ -343,24 +349,24 @@ static void usbvision_create_sysfs(struct video_device *vdev)
static void usbvision_remove_sysfs(struct video_device *vdev)
{
if (vdev) {
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_version);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_model);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_hue);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_contrast);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_brightness);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_saturation);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_streaming);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_compression);
- class_device_remove_file(&vdev->class_dev,
- &class_device_attr_bridge);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_version);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_model);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_hue);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_contrast);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_brightness);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_saturation);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_streaming);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_compression);
+ device_remove_file(&vdev->class_dev,
+ &dev_attr_bridge);
}
}
@@ -376,7 +382,8 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
static int usbvision_v4l2_open(struct inode *inode, struct file *file)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
int errCode = 0;
PDEBUG(DBG_IO, "open");
@@ -390,7 +397,8 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
/* Allocate memory for the scratch ring buffer */
errCode = usbvision_scratch_alloc(usbvision);
if (isocMode==ISOC_MODE_COMPRESS) {
- /* Allocate intermediate decompression buffers only if needed */
+ /* Allocate intermediate decompression buffers
+ only if needed */
errCode = usbvision_decompress_alloc(usbvision);
}
if (errCode) {
@@ -421,11 +429,10 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
if (!errCode) {
usbvision_begin_streaming(usbvision);
errCode = usbvision_init_isoc(usbvision);
- /* device needs to be initialized before isoc transfer */
+ /* device must be initialized before isoc transfer */
usbvision_muxsel(usbvision,0);
usbvision->user++;
- }
- else {
+ } else {
if (PowerOnAtOpen) {
usbvision_i2c_unregister(usbvision);
usbvision_power_off(usbvision);
@@ -456,7 +463,8 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
static int usbvision_v4l2_close(struct inode *inode, struct file *file)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
PDEBUG(DBG_IO, "close");
down(&usbvision->lock);
@@ -473,7 +481,8 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
usbvision->user--;
if (PowerOnAtOpen) {
- /* power off in a little while to avoid off/on every close/open short sequences */
+ /* power off in a little while
+ to avoid off/on every close/open short sequences */
usbvision_set_powerOffTimer(usbvision);
usbvision->initialized = 0;
}
@@ -498,583 +507,613 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
*/
-static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *priv,
+ struct v4l2_register *reg)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
-
- if (!USBVISION_IS_OPERATIONAL(usbvision))
- return -EFAULT;
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int errCode;
- switch (cmd) {
+ if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return -EINVAL;
+ /* NT100x has a 8-bit register space */
+ errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+ if (errCode < 0) {
+ err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
+ __FUNCTION__, errCode);
+ return errCode;
+ }
+ reg->val = errCode;
+ return 0;
+}
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- /* ioctls to allow direct acces to the NT100x registers */
- case VIDIOC_DBG_G_REGISTER:
- case VIDIOC_DBG_S_REGISTER:
- {
- struct v4l2_register *reg = arg;
- int errCode;
-
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- /* NT100x has a 8-bit register space */
- if (cmd == VIDIOC_DBG_G_REGISTER)
- errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
- else
- errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
- if (errCode < 0) {
- err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__,
- cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode);
- return errCode;
- }
- if (cmd == VIDIOC_DBG_S_REGISTER)
- reg->val = (u8)errCode;
+static int vidioc_s_register (struct file *file, void *priv,
+ struct v4l2_register *reg)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int errCode;
- PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X",
- cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S',
- (unsigned int)reg->reg, (unsigned int)reg->val);
- return 0;
- }
+ if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return -EINVAL;
+ /* NT100x has a 8-bit register space */
+ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+ if (errCode < 0) {
+ err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
+ __FUNCTION__, errCode);
+ return errCode;
+ }
+ return 0;
+}
#endif
- case VIDIOC_QUERYCAP:
- {
- struct v4l2_capability *vc=arg;
-
- memset(vc, 0, sizeof(*vc));
- strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
- strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
- sizeof(vc->card));
- strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
- sizeof(vc->bus_info));
- vc->version = USBVISION_DRIVER_VERSION;
- vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_AUDIO |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING |
- (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
- PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP");
- return 0;
- }
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *vi = arg;
- int chan;
-
- if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
- return -EINVAL;
- if (usbvision->have_tuner) {
- chan = vi->index;
- }
- else {
- chan = vi->index + 1; //skip Television string
- }
- switch(chan) {
- case 0:
- if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
- strcpy(vi->name, "White Video Input");
- }
- else {
- strcpy(vi->name, "Television");
- vi->type = V4L2_INPUT_TYPE_TUNER;
- vi->audioset = 1;
- vi->tuner = chan;
- vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM;
- }
- break;
- case 1:
- vi->type = V4L2_INPUT_TYPE_CAMERA;
- if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
- strcpy(vi->name, "Green Video Input");
- }
- else {
- strcpy(vi->name, "Composite Video Input");
- }
- vi->std = V4L2_STD_PAL;
- break;
- case 2:
- vi->type = V4L2_INPUT_TYPE_CAMERA;
- if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
- strcpy(vi->name, "Yellow Video Input");
- }
- else {
- strcpy(vi->name, "S-Video Input");
- }
- vi->std = V4L2_STD_PAL;
- break;
- case 3:
- vi->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(vi->name, "Red Video Input");
- vi->std = V4L2_STD_PAL;
- break;
- }
- PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x",
- vi->name, vi->index, vi->tuner,vi->type,(int)vi->std);
- return 0;
- }
- case VIDIOC_ENUMSTD:
- {
- struct v4l2_standard *e = arg;
- unsigned int i;
- int ret;
-
- i = e->index;
- if (i >= TVNORMS)
- return -EINVAL;
- ret = v4l2_video_std_construct(e, tvnorms[e->index].id,
- tvnorms[e->index].name);
- e->index = i;
- if (ret < 0)
- return ret;
- return 0;
+
+static int vidioc_querycap (struct file *file, void *priv,
+ struct v4l2_capability *vc)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+
+ strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+ strlcpy(vc->card,
+ usbvision_device_data[usbvision->DevModel].ModelString,
+ sizeof(vc->card));
+ strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+ sizeof(vc->bus_info));
+ vc->version = USBVISION_DRIVER_VERSION;
+ vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_AUDIO |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+ return 0;
+}
+
+static int vidioc_enum_input (struct file *file, void *priv,
+ struct v4l2_input *vi)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int chan;
+
+ if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
+ return -EINVAL;
+ if (usbvision->have_tuner) {
+ chan = vi->index;
+ } else {
+ chan = vi->index + 1; /*skip Television string*/
+ }
+ /* Determine the requested input characteristics
+ specific for each usbvision card model */
+ switch(chan) {
+ case 0:
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "White Video Input");
+ } else {
+ strcpy(vi->name, "Television");
+ vi->type = V4L2_INPUT_TYPE_TUNER;
+ vi->audioset = 1;
+ vi->tuner = chan;
+ vi->std = USBVISION_NORMS;
}
- case VIDIOC_G_INPUT:
- {
- int *input = arg;
- *input = usbvision->ctl_input;
- return 0;
+ break;
+ case 1:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "Green Video Input");
+ } else {
+ strcpy(vi->name, "Composite Video Input");
}
- case VIDIOC_S_INPUT:
- {
- int *input = arg;
- if ((*input >= usbvision->video_inputs) || (*input < 0) )
- return -EINVAL;
- usbvision->ctl_input = *input;
-
- down(&usbvision->lock);
- usbvision_muxsel(usbvision, usbvision->ctl_input);
- usbvision_set_input(usbvision);
- usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
- up(&usbvision->lock);
- return 0;
+ vi->std = V4L2_STD_PAL;
+ break;
+ case 2:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "Yellow Video Input");
+ } else {
+ strcpy(vi->name, "S-Video Input");
}
- case VIDIOC_G_STD:
- {
- v4l2_std_id *id = arg;
+ vi->std = V4L2_STD_PAL;
+ break;
+ case 3:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ strcpy(vi->name, "Red Video Input");
+ vi->std = V4L2_STD_PAL;
+ break;
+ }
+ return 0;
+}
- *id = usbvision->tvnorm->id;
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name);
- return 0;
- }
- case VIDIOC_S_STD:
- {
- v4l2_std_id *id = arg;
- unsigned int i;
-
- 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;
-
- down(&usbvision->lock);
- usbvision->tvnorm = &tvnorms[i];
-
- call_i2c_clients(usbvision, VIDIOC_S_STD,
- &usbvision->tvnorm->id);
+ *input = usbvision->ctl_input;
+ return 0;
+}
- up(&usbvision->lock);
+static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name);
- return 0;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *vt = arg;
-
- if (!usbvision->have_tuner || vt->index) // Only tuner 0
- return -EINVAL;
- strcpy(vt->name, "Television");
- /* Let clients fill in the remainder of this struct */
- call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
-
- PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc);
- return 0;
- }
- case VIDIOC_S_TUNER:
- {
- struct v4l2_tuner *vt = arg;
-
- // Only no or one tuner for now
- if (!usbvision->have_tuner || vt->index)
- return -EINVAL;
- /* let clients handle this */
- call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
-
- PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER");
- return 0;
- }
- case VIDIOC_G_FREQUENCY:
- {
- struct v4l2_frequency *freq = arg;
-
- freq->tuner = 0; // Only one tuner
- freq->type = V4L2_TUNER_ANALOG_TV;
- freq->frequency = usbvision->freq;
- PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
- return 0;
- }
- case VIDIOC_S_FREQUENCY:
- {
- struct v4l2_frequency *freq = arg;
-
- // Only no or one tuner for now
- if (!usbvision->have_tuner || freq->tuner)
- return -EINVAL;
-
- usbvision->freq = freq->frequency;
- call_i2c_clients(usbvision, cmd, freq);
- PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
- return 0;
- }
- case VIDIOC_G_AUDIO:
- {
- struct v4l2_audio *v = arg;
- memset(v,0, sizeof(v));
- strcpy(v->name, "TV");
- PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO");
- return 0;
- }
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *v = arg;
- if(v->index) {
- return -EINVAL;
- }
- PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO");
- return 0;
- }
- case VIDIOC_QUERYCTRL:
- {
- struct v4l2_queryctrl *ctrl = arg;
- int id=ctrl->id;
+ if ((input >= usbvision->video_inputs) || (input < 0) )
+ return -EINVAL;
- memset(ctrl,0,sizeof(*ctrl));
- ctrl->id=id;
+ down(&usbvision->lock);
+ usbvision_muxsel(usbvision, input);
+ usbvision_set_input(usbvision);
+ usbvision_set_output(usbvision,
+ usbvision->curwidth,
+ usbvision->curheight);
+ up(&usbvision->lock);
+ return 0;
+}
- call_i2c_clients(usbvision, cmd, arg);
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ usbvision->tvnormId=*id;
- if (ctrl->type)
- return 0;
- else
- return -EINVAL;
+ down(&usbvision->lock);
+ call_i2c_clients(usbvision, VIDIOC_S_STD,
+ &usbvision->tvnormId);
+ up(&usbvision->lock);
+ /* propagate the change to the decoder */
+ usbvision_muxsel(usbvision, usbvision->ctl_input);
- PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
- }
- case VIDIOC_G_CTRL:
- {
- struct v4l2_control *ctrl = arg;
- call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
- PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
- return 0;
- }
- case VIDIOC_S_CTRL:
- {
- struct v4l2_control *ctrl = arg;
+ return 0;
+}
- PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
- call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
- return 0;
- }
- case VIDIOC_REQBUFS:
- {
- struct v4l2_requestbuffers *vr = arg;
- int ret;
+static int vidioc_g_tuner (struct file *file, void *priv,
+ struct v4l2_tuner *vt)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+ if (!usbvision->have_tuner || vt->index) // Only tuner 0
+ return -EINVAL;
+ if(usbvision->radio) {
+ strcpy(vt->name, "Radio");
+ vt->type = V4L2_TUNER_RADIO;
+ } else {
+ strcpy(vt->name, "Television");
+ }
+ /* Let clients fill in the remainder of this struct */
+ call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
- // Check input validity : the user must do a VIDEO CAPTURE and MMAP method.
- if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
- (vr->memory != V4L2_MEMORY_MMAP))
- return -EINVAL;
+ return 0;
+}
- if(usbvision->streaming == Stream_On) {
- if ((ret = usbvision_stream_interrupt(usbvision)))
- return ret;
- }
+static int vidioc_s_tuner (struct file *file, void *priv,
+ struct v4l2_tuner *vt)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- usbvision_frames_free(usbvision);
- usbvision_empty_framequeues(usbvision);
- vr->count = usbvision_frames_alloc(usbvision,vr->count);
+ // Only no or one tuner for now
+ if (!usbvision->have_tuner || vt->index)
+ return -EINVAL;
+ /* let clients handle this */
+ call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
- usbvision->curFrame = NULL;
+ return 0;
+}
- PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count);
- return 0;
- }
- case VIDIOC_QUERYBUF:
- {
- struct v4l2_buffer *vb = arg;
- struct usbvision_frame *frame;
+static int vidioc_g_frequency (struct file *file, void *priv,
+ struct v4l2_frequency *freq)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called)
+ freq->tuner = 0; // Only one tuner
+ if(usbvision->radio) {
+ freq->type = V4L2_TUNER_RADIO;
+ } else {
+ freq->type = V4L2_TUNER_ANALOG_TV;
+ }
+ freq->frequency = usbvision->freq;
- if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
- return -EINVAL;
- }
- if(vb->index>=usbvision->num_frames) {
- return -EINVAL;
- }
- // Updating the corresponding frame state
- vb->flags = 0;
- frame = &usbvision->frame[vb->index];
- if(frame->grabstate >= FrameState_Ready)
- vb->flags |= V4L2_BUF_FLAG_QUEUED;
- if(frame->grabstate >= FrameState_Done)
- vb->flags |= V4L2_BUF_FLAG_DONE;
- if(frame->grabstate == FrameState_Unused)
- vb->flags |= V4L2_BUF_FLAG_MAPPED;
- vb->memory = V4L2_MEMORY_MMAP;
-
- vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size);
-
- vb->memory = V4L2_MEMORY_MMAP;
- vb->field = V4L2_FIELD_NONE;
- vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel;
- vb->timestamp = usbvision->frame[vb->index].timestamp;
- vb->sequence = usbvision->frame[vb->index].sequence;
- return 0;
- }
- case VIDIOC_QBUF:
- {
- struct v4l2_buffer *vb = arg;
- struct usbvision_frame *frame;
- unsigned long lock_flags;
-
- // FIXME : works only on VIDEO_CAPTURE MODE, MMAP.
- if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
- return -EINVAL;
- }
- if(vb->index>=usbvision->num_frames) {
- return -EINVAL;
- }
+ return 0;
+}
- frame = &usbvision->frame[vb->index];
+static int vidioc_s_frequency (struct file *file, void *priv,
+ struct v4l2_frequency *freq)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- if (frame->grabstate != FrameState_Unused) {
- return -EAGAIN;
- }
+ // Only no or one tuner for now
+ if (!usbvision->have_tuner || freq->tuner)
+ return -EINVAL;
- /* Mark it as ready and enqueue frame */
- frame->grabstate = FrameState_Ready;
- frame->scanstate = ScanState_Scanning;
- frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */
+ usbvision->freq = freq->frequency;
+ call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq);
- vb->flags &= ~V4L2_BUF_FLAG_DONE;
+ return 0;
+}
- /* set v4l2_format index */
- frame->v4l2_format = usbvision->palette;
+static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
- spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
- list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
- spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+ memset(a,0,sizeof(*a));
+ if(usbvision->radio) {
+ strcpy(a->name,"Radio");
+ } else {
+ strcpy(a->name, "TV");
+ }
- PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index);
- return 0;
- }
- case VIDIOC_DQBUF:
- {
- struct v4l2_buffer *vb = arg;
- int ret;
- struct usbvision_frame *f;
- unsigned long lock_flags;
-
- if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- if (list_empty(&(usbvision->outqueue))) {
- if (usbvision->streaming == Stream_Idle)
- return -EINVAL;
- ret = wait_event_interruptible
- (usbvision->wait_frame,
- !list_empty(&(usbvision->outqueue)));
- if (ret)
- return ret;
- }
+ return 0;
+}
- spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
- f = list_entry(usbvision->outqueue.next,
- struct usbvision_frame, frame);
- list_del(usbvision->outqueue.next);
- spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
-
- f->grabstate = FrameState_Unused;
-
- vb->memory = V4L2_MEMORY_MMAP;
- vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE;
- vb->index = f->index;
- vb->sequence = f->sequence;
- vb->timestamp = f->timestamp;
- vb->field = V4L2_FIELD_NONE;
- vb->bytesused = f->scanlength;
-
- return 0;
- }
- case VIDIOC_STREAMON:
- {
- int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+static int vidioc_s_audio (struct file *file, void *fh,
+ struct v4l2_audio *a)
+{
+ if(a->index) {
+ return -EINVAL;
+ }
- usbvision->streaming = Stream_On;
+ return 0;
+}
- call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+static int vidioc_queryctrl (struct file *file, void *priv,
+ struct v4l2_queryctrl *ctrl)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int id=ctrl->id;
- PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON");
+ memset(ctrl,0,sizeof(*ctrl));
+ ctrl->id=id;
- return 0;
- }
- case VIDIOC_STREAMOFF:
- {
- int *type = arg;
- int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- if(usbvision->streaming == Stream_On) {
- usbvision_stream_interrupt(usbvision);
- // Stop all video streamings
- call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
- }
- usbvision_empty_framequeues(usbvision);
+ call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl);
- PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF");
- return 0;
- }
- case VIDIOC_ENUM_FMT:
- {
- struct v4l2_fmtdesc *vfd = arg;
+ if (!ctrl->type)
+ return -EINVAL;
- if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
- return -EINVAL;
- }
- vfd->flags = 0;
- vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
- vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
- memset(vfd->reserved, 0, sizeof(vfd->reserved));
- return 0;
- }
- case VIDIOC_G_FMT:
- {
- struct v4l2_format *vf = arg;
-
- switch (vf->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- {
- vf->fmt.pix.width = usbvision->curwidth;
- vf->fmt.pix.height = usbvision->curheight;
- vf->fmt.pix.pixelformat = usbvision->palette.format;
- vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel;
- vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight;
- vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
- PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s",
- vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
- return 0;
- }
- default:
- PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type);
- return -EINVAL;
- }
- return 0;
- }
- case VIDIOC_TRY_FMT:
- case VIDIOC_S_FMT:
- {
- struct v4l2_format *vf = arg;
- int formatIdx,ret;
-
- switch(vf->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- {
- /* Find requested format in available ones */
- for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) {
- if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) {
- usbvision->palette = usbvision_v4l2_format[formatIdx];
- break;
- }
- }
- /* robustness */
- if(formatIdx == USBVISION_SUPPORTED_PALETTES) {
- return -EINVAL;
- }
- RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
- RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
-
- vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel;
- vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
-
- if(cmd == VIDIOC_TRY_FMT) {
- PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s",
- vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
- return 0;
- }
-
- /* stop io in case it is already in progress */
- if(usbvision->streaming == Stream_On) {
- if ((ret = usbvision_stream_interrupt(usbvision)))
- return ret;
- }
- usbvision_frames_free(usbvision);
- usbvision_empty_framequeues(usbvision);
-
- usbvision->curFrame = NULL;
-
- // by now we are committed to the new data...
- down(&usbvision->lock);
- usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
- up(&usbvision->lock);
-
- PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s",
- vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
- return 0;
- }
- default:
- return -EINVAL;
- }
- }
- default:
- return -ENOIOCTLCMD;
+ return 0;
+}
+
+static int vidioc_g_ctrl (struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+
+ return 0;
+}
+
+static int vidioc_s_ctrl (struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+
+ return 0;
+}
+
+static int vidioc_reqbufs (struct file *file,
+ void *priv, struct v4l2_requestbuffers *vr)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int ret;
+
+ RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+
+ /* Check input validity:
+ the user must do a VIDEO CAPTURE and MMAP method. */
+ if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+ (vr->memory != V4L2_MEMORY_MMAP))
+ return -EINVAL;
+
+ if(usbvision->streaming == Stream_On) {
+ if ((ret = usbvision_stream_interrupt(usbvision)))
+ return ret;
}
+
+ usbvision_frames_free(usbvision);
+ usbvision_empty_framequeues(usbvision);
+ vr->count = usbvision_frames_alloc(usbvision,vr->count);
+
+ usbvision->curFrame = NULL;
+
return 0;
}
-static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int vidioc_querybuf (struct file *file,
+ void *priv, struct v4l2_buffer *vb)
{
- return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl);
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usbvision_frame *frame;
+
+ /* FIXME : must control
+ that buffers are mapped (VIDIOC_REQBUFS has been called) */
+ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+ return -EINVAL;
+ }
+ if(vb->index>=usbvision->num_frames) {
+ return -EINVAL;
+ }
+ /* Updating the corresponding frame state */
+ vb->flags = 0;
+ frame = &usbvision->frame[vb->index];
+ if(frame->grabstate >= FrameState_Ready)
+ vb->flags |= V4L2_BUF_FLAG_QUEUED;
+ if(frame->grabstate >= FrameState_Done)
+ vb->flags |= V4L2_BUF_FLAG_DONE;
+ if(frame->grabstate == FrameState_Unused)
+ vb->flags |= V4L2_BUF_FLAG_MAPPED;
+ vb->memory = V4L2_MEMORY_MMAP;
+
+ vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size);
+
+ vb->memory = V4L2_MEMORY_MMAP;
+ vb->field = V4L2_FIELD_NONE;
+ vb->length = usbvision->curwidth*
+ usbvision->curheight*
+ usbvision->palette.bytes_per_pixel;
+ vb->timestamp = usbvision->frame[vb->index].timestamp;
+ vb->sequence = usbvision->frame[vb->index].sequence;
+ return 0;
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usbvision_frame *frame;
+ unsigned long lock_flags;
+
+ /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */
+ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+ return -EINVAL;
+ }
+ if(vb->index>=usbvision->num_frames) {
+ return -EINVAL;
+ }
+
+ frame = &usbvision->frame[vb->index];
+
+ if (frame->grabstate != FrameState_Unused) {
+ return -EAGAIN;
+ }
+
+ /* Mark it as ready and enqueue frame */
+ frame->grabstate = FrameState_Ready;
+ frame->scanstate = ScanState_Scanning;
+ frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */
+
+ vb->flags &= ~V4L2_BUF_FLAG_DONE;
+
+ /* set v4l2_format index */
+ frame->v4l2_format = usbvision->palette;
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ return 0;
}
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int ret;
+ struct usbvision_frame *f;
+ unsigned long lock_flags;
+
+ if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (list_empty(&(usbvision->outqueue))) {
+ if (usbvision->streaming == Stream_Idle)
+ return -EINVAL;
+ ret = wait_event_interruptible
+ (usbvision->wait_frame,
+ !list_empty(&(usbvision->outqueue)));
+ if (ret)
+ return ret;
+ }
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ f = list_entry(usbvision->outqueue.next,
+ struct usbvision_frame, frame);
+ list_del(usbvision->outqueue.next);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ f->grabstate = FrameState_Unused;
+
+ vb->memory = V4L2_MEMORY_MMAP;
+ vb->flags = V4L2_BUF_FLAG_MAPPED |
+ V4L2_BUF_FLAG_QUEUED |
+ V4L2_BUF_FLAG_DONE;
+ vb->index = f->index;
+ vb->sequence = f->sequence;
+ vb->timestamp = f->timestamp;
+ vb->field = V4L2_FIELD_NONE;
+ vb->bytesused = f->scanlength;
+
+ return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ usbvision->streaming = Stream_On;
+ call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+
+ return 0;
+}
+
+static int vidioc_streamoff(struct file *file,
+ void *priv, enum v4l2_buf_type type)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if(usbvision->streaming == Stream_On) {
+ usbvision_stream_interrupt(usbvision);
+ /* Stop all video streamings */
+ call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
+ }
+ usbvision_empty_framequeues(usbvision);
+
+ return 0;
+}
+
+static int vidioc_enum_fmt_cap (struct file *file, void *priv,
+ struct v4l2_fmtdesc *vfd)
+{
+ if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
+ return -EINVAL;
+ }
+ vfd->flags = 0;
+ vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
+ vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
+ memset(vfd->reserved, 0, sizeof(vfd->reserved));
+ return 0;
+}
+
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+ struct v4l2_format *vf)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ vf->fmt.pix.width = usbvision->curwidth;
+ vf->fmt.pix.height = usbvision->curheight;
+ vf->fmt.pix.pixelformat = usbvision->palette.format;
+ vf->fmt.pix.bytesperline =
+ usbvision->curwidth*usbvision->palette.bytes_per_pixel;
+ vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight;
+ vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
+
+ return 0;
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
+ struct v4l2_format *vf)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int formatIdx;
+
+ /* Find requested format in available ones */
+ for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) {
+ if(vf->fmt.pix.pixelformat ==
+ usbvision_v4l2_format[formatIdx].format) {
+ usbvision->palette = usbvision_v4l2_format[formatIdx];
+ break;
+ }
+ }
+ /* robustness */
+ if(formatIdx == USBVISION_SUPPORTED_PALETTES) {
+ return -EINVAL;
+ }
+ RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
+ RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
+
+ vf->fmt.pix.bytesperline = vf->fmt.pix.width*
+ usbvision->palette.bytes_per_pixel;
+ vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
+
+ return 0;
+}
+
+static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ struct v4l2_format *vf)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int ret;
+
+ if( 0 != (ret=vidioc_try_fmt_cap (file, priv, vf)) ) {
+ return ret;
+ }
+
+ /* stop io in case it is already in progress */
+ if(usbvision->streaming == Stream_On) {
+ if ((ret = usbvision_stream_interrupt(usbvision)))
+ return ret;
+ }
+ usbvision_frames_free(usbvision);
+ usbvision_empty_framequeues(usbvision);
+
+ usbvision->curFrame = NULL;
+
+ /* by now we are committed to the new data... */
+ down(&usbvision->lock);
+ usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
+ up(&usbvision->lock);
+
+ return 0;
+}
static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
int noblock = file->f_flags & O_NONBLOCK;
unsigned long lock_flags;
int ret,i;
struct usbvision_frame *frame;
- PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock);
+ PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__,
+ (unsigned long)count, noblock);
if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
return -EFAULT;
- /* This entry point is compatible with the mmap routines so that a user can do either
- VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */
+ /* This entry point is compatible with the mmap routines
+ so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF
+ to get frames or call read on the device. */
if(!usbvision->num_frames) {
- /* First, allocate some frames to work with if this has not been done with
- VIDIOC_REQBUF */
+ /* First, allocate some frames to work with
+ if this has not been done with VIDIOC_REQBUF */
usbvision_frames_free(usbvision);
usbvision_empty_framequeues(usbvision);
usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES);
@@ -1086,21 +1125,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
}
- /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
+ /* Then, enqueue as many frames as possible
+ (like a user of VIDIOC_QBUF would do) */
for(i=0;i<usbvision->num_frames;i++) {
frame = &usbvision->frame[i];
if(frame->grabstate == FrameState_Unused) {
/* Mark it as ready and enqueue frame */
frame->grabstate = FrameState_Ready;
frame->scanstate = ScanState_Scanning;
- frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */
+ /* Accumulated in usbvision_parse_data() */
+ frame->scanlength = 0;
/* set v4l2_format index */
frame->v4l2_format = usbvision->palette;
spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
list_add_tail(&frame->frame, &usbvision->inqueue);
- spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+ spin_unlock_irqrestore(&usbvision->queue_lock,
+ lock_flags);
}
}
@@ -1128,8 +1170,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
return 0;
}
- PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__,
- frame->index, frame->bytes_read, frame->scanlength);
+ PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
+ __FUNCTION__,
+ frame->index, frame->bytes_read, frame->scanlength);
/* copy bytes to user space; we allow for partials reads */
if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
@@ -1140,10 +1183,11 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
}
frame->bytes_read += count;
- PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__,
- (unsigned long)count, frame->bytes_read);
+ PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
+ __FUNCTION__,
+ (unsigned long)count, frame->bytes_read);
- // For now, forget the frame if it has not been read in one shot.
+ /* For now, forget the frame if it has not been read in one shot. */
/* if (frame->bytes_read >= frame->scanlength) {// All data has been read */
frame->bytes_read = 0;
@@ -1162,7 +1206,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
u32 i;
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
PDEBUG(DBG_MMAP, "mmap");
@@ -1180,11 +1225,13 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
}
for (i = 0; i < usbvision->num_frames; i++) {
- if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff)
+ if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) ==
+ vma->vm_pgoff)
break;
}
if (i == usbvision->num_frames) {
- PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range");
+ PDEBUG(DBG_MMAP,
+ "mmap: user supplied mapping address is out of range");
up(&usbvision->lock);
return -EINVAL;
}
@@ -1218,8 +1265,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
static int usbvision_radio_open(struct inode *inode, struct file *file)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
- struct v4l2_frequency freq;
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
int errCode = 0;
PDEBUG(DBG_IO, "%s:", __FUNCTION__);
@@ -1249,8 +1296,6 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
// If so far no errors then we shall start the radio
usbvision->radio = 1;
call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
- freq.frequency = 1517; //SWR3 @ 94.8MHz
- call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq);
usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
usbvision->user++;
}
@@ -1270,7 +1315,8 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
static int usbvision_radio_close(struct inode *inode, struct file *file)
{
struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct usb_usbvision *usbvision =
+ (struct usb_usbvision *) video_get_drvdata(dev);
int errCode = 0;
PDEBUG(DBG_IO, "");
@@ -1304,149 +1350,6 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
return errCode;
}
-static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
-{
- struct video_device *dev = video_devdata(file);
- struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
-
- if (!USBVISION_IS_OPERATIONAL(usbvision))
- return -EIO;
-
- switch (cmd) {
- case VIDIOC_QUERYCAP:
- {
- struct v4l2_capability *vc=arg;
-
- memset(vc, 0, sizeof(*vc));
- strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
- strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
- sizeof(vc->card));
- strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
- sizeof(vc->bus_info));
- vc->version = USBVISION_DRIVER_VERSION;
- vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
- PDEBUG(DBG_IO, "VIDIOC_QUERYCAP");
- return 0;
- }
- case VIDIOC_QUERYCTRL:
- {
- struct v4l2_queryctrl *ctrl = arg;
- int id=ctrl->id;
-
- memset(ctrl,0,sizeof(*ctrl));
- ctrl->id=id;
-
- call_i2c_clients(usbvision, cmd, arg);
- PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
-
- if (ctrl->type)
- return 0;
- else
- return -EINVAL;
-
- }
- case VIDIOC_G_CTRL:
- {
- struct v4l2_control *ctrl = arg;
-
- call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
- PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
- return 0;
- }
- case VIDIOC_S_CTRL:
- {
- struct v4l2_control *ctrl = arg;
-
- call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
- PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
- return 0;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *t = arg;
-
- if (t->index > 0)
- return -EINVAL;
-
- memset(t,0,sizeof(*t));
- strcpy(t->name, "Radio");
- t->type = V4L2_TUNER_RADIO;
-
- /* Let clients fill in the remainder of this struct */
- call_i2c_clients(usbvision,VIDIOC_G_TUNER,t);
- PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc);
- return 0;
- }
- case VIDIOC_S_TUNER:
- {
- struct v4l2_tuner *vt = arg;
-
- // Only no or one tuner for now
- if (!usbvision->have_tuner || vt->index)
- return -EINVAL;
- /* let clients handle this */
- call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
-
- PDEBUG(DBG_IO, "VIDIOC_S_TUNER");
- return 0;
- }
- case VIDIOC_G_AUDIO:
- {
- struct v4l2_audio *a = arg;
-
- memset(a,0,sizeof(*a));
- strcpy(a->name,"Radio");
- PDEBUG(DBG_IO, "VIDIOC_G_AUDIO");
- return 0;
- }
- case VIDIOC_S_AUDIO:
- case VIDIOC_S_INPUT:
- case VIDIOC_S_STD:
- return 0;
-
- case VIDIOC_G_FREQUENCY:
- {
- struct v4l2_frequency *f = arg;
-
- memset(f,0,sizeof(*f));
-
- f->type = V4L2_TUNER_RADIO;
- f->frequency = usbvision->freq;
- call_i2c_clients(usbvision, cmd, f);
- PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency);
-
- return 0;
- }
- case VIDIOC_S_FREQUENCY:
- {
- struct v4l2_frequency *f = arg;
-
- if (f->tuner != 0)
- return -EINVAL;
- usbvision->freq = f->frequency;
- call_i2c_clients(usbvision, cmd, f);
- PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency);
-
- return 0;
- }
- default:
- {
- PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd);
- return -ENOIOCTLCMD;
- }
- }
- return 0;
-}
-
-
-static int usbvision_radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl);
-}
-
-
/*
* Here comes the stuff for vbi on usbvision based devices
*
@@ -1454,21 +1357,21 @@ static int usbvision_radio_ioctl(struct inode *inode, struct file *file,
static int usbvision_vbi_open(struct inode *inode, struct file *file)
{
/* TODO */
- return -EINVAL;
+ return -ENODEV;
}
static int usbvision_vbi_close(struct inode *inode, struct file *file)
{
/* TODO */
- return -EINVAL;
+ return -ENODEV;
}
static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
/* TODO */
- return -EINVAL;
+ return -ENOIOCTLCMD;
}
static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
@@ -1489,8 +1392,10 @@ static const struct file_operations usbvision_fops = {
.release = usbvision_v4l2_close,
.read = usbvision_v4l2_read,
.mmap = usbvision_v4l2_mmap,
- .ioctl = usbvision_v4l2_ioctl,
+ .ioctl = video_ioctl2,
.llseek = no_llseek,
+/* .poll = video_poll, */
+ .compat_ioctl = v4l_compat_ioctl32,
};
static struct video_device usbvision_video_template = {
.owner = THIS_MODULE,
@@ -1500,6 +1405,39 @@ static struct video_device usbvision_video_template = {
.name = "usbvision-video",
.release = video_device_release,
.minor = -1,
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
+ .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
+ .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
+ .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+/* .vidiocgmbuf = vidiocgmbuf, */
+#endif
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+#endif
+ .tvnorms = USBVISION_NORMS,
+ .current_norm = V4L2_STD_PAL
};
@@ -1508,8 +1446,9 @@ static const struct file_operations usbvision_radio_fops = {
.owner = THIS_MODULE,
.open = usbvision_radio_open,
.release = usbvision_radio_close,
- .ioctl = usbvision_radio_ioctl,
+ .ioctl = video_ioctl2,
.llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
};
static struct video_device usbvision_radio_template=
@@ -1518,12 +1457,27 @@ static struct video_device usbvision_radio_template=
.type = VID_TYPE_TUNER,
.hardware = VID_HARDWARE_USBVISION,
.fops = &usbvision_radio_fops,
- .release = video_device_release,
.name = "usbvision-radio",
+ .release = video_device_release,
.minor = -1,
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+
+ .tvnorms = USBVISION_NORMS,
+ .current_norm = V4L2_STD_PAL
};
-
// vbi template
static const struct file_operations usbvision_vbi_fops = {
.owner = THIS_MODULE,
@@ -1531,6 +1485,7 @@ static const struct file_operations usbvision_vbi_fops = {
.release = usbvision_vbi_close,
.ioctl = usbvision_vbi_ioctl,
.llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
};
static struct video_device usbvision_vbi_template=
@@ -1574,11 +1529,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
{
// vbi Device:
if (usbvision->vbi) {
- PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f);
+ PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]",
+ usbvision->vbi->minor & 0x1f);
if (usbvision->vbi->minor != -1) {
video_unregister_device(usbvision->vbi);
- }
- else {
+ } else {
video_device_release(usbvision->vbi);
}
usbvision->vbi = NULL;
@@ -1586,11 +1541,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Radio Device:
if (usbvision->rdev) {
- PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f);
+ PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]",
+ usbvision->rdev->minor & 0x1f);
if (usbvision->rdev->minor != -1) {
video_unregister_device(usbvision->rdev);
- }
- else {
+ } else {
video_device_release(usbvision->rdev);
}
usbvision->rdev = NULL;
@@ -1598,11 +1553,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Video Device:
if (usbvision->vdev) {
- PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f);
+ PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]",
+ usbvision->vdev->minor & 0x1f);
if (usbvision->vdev->minor != -1) {
video_unregister_device(usbvision->vdev);
- }
- else {
+ } else {
video_device_release(usbvision->vdev);
}
usbvision->vdev = NULL;
@@ -1613,37 +1568,52 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
{
// Video Device:
- usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video");
+ usbvision->vdev = usbvision_vdev_init(usbvision,
+ &usbvision_video_template,
+ "USBVision Video");
if (usbvision->vdev == NULL) {
goto err_exit;
}
- if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) {
+ if (video_register_device(usbvision->vdev,
+ VFL_TYPE_GRABBER,
+ video_nr)<0) {
goto err_exit;
}
- printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f);
+ printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n",
+ usbvision->nr,usbvision->vdev->minor & 0x1f);
// Radio Device:
if (usbvision_device_data[usbvision->DevModel].Radio) {
// usbvision has radio
- usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio");
+ usbvision->rdev = usbvision_vdev_init(usbvision,
+ &usbvision_radio_template,
+ "USBVision Radio");
if (usbvision->rdev == NULL) {
goto err_exit;
}
- if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) {
+ if (video_register_device(usbvision->rdev,
+ VFL_TYPE_RADIO,
+ radio_nr)<0) {
goto err_exit;
}
- printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f);
+ printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n",
+ usbvision->nr, usbvision->rdev->minor & 0x1f);
}
// vbi Device:
if (usbvision_device_data[usbvision->DevModel].vbi) {
- usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI");
+ usbvision->vbi = usbvision_vdev_init(usbvision,
+ &usbvision_vbi_template,
+ "USBVision VBI");
if (usbvision->vdev == NULL) {
goto err_exit;
}
- if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) {
+ if (video_register_device(usbvision->vbi,
+ VFL_TYPE_VBI,
+ vbi_nr)<0) {
goto err_exit;
}
- printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f);
+ printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n",
+ usbvision->nr,usbvision->vbi->minor & 0x1f);
}
// all done
return 0;
@@ -1657,7 +1627,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
/*
* usbvision_alloc()
*
- * This code allocates the struct usb_usbvision. It is filled with default values.
+ * This code allocates the struct usb_usbvision.
+ * It is filled with default values.
*
* Returns NULL on error, a pointer to usb_usbvision else.
*
@@ -1666,7 +1637,8 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev)
{
struct usb_usbvision *usbvision;
- if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) {
+ if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) ==
+ NULL) {
goto err_exit;
}
@@ -1728,11 +1700,11 @@ static void usbvision_release(struct usb_usbvision *usbvision)
}
-/******************************** usb interface *****************************************/
+/*********************** usb interface **********************************/
static void usbvision_configure_video(struct usb_usbvision *usbvision)
{
- int model,i;
+ int model;
if (usbvision == NULL)
return;
@@ -1741,25 +1713,23 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) {
- usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2;
+ usbvision->Vin_Reg2_Preset =
+ usbvision_device_data[usbvision->DevModel].Vin_Reg2;
} else {
usbvision->Vin_Reg2_Preset = 0;
}
- for (i = 0; i < TVNORMS; i++)
- if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode)
- break;
- if (i == TVNORMS)
- i = 0;
- usbvision->tvnorm = &tvnorms[i]; /* set default norm */
+ usbvision->tvnormId = usbvision_device_data[model].VideoNorm;
usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
usbvision->ctl_input = 0;
/* This should be here to make i2c clients to be able to register */
- usbvision_audio_off(usbvision); //first switch off audio
+ /* first switch off audio */
+ usbvision_audio_off(usbvision);
if (!PowerOnAtOpen) {
- usbvision_power_on(usbvision); //and then power up the noisy tuner
+ /* and then power up the noisy tuner */
+ usbvision_power_on(usbvision);
usbvision_i2c_register(usbvision);
}
}
@@ -1796,18 +1766,22 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
if (usbvision_device_data[model].Interface >= 0) {
interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0];
- }
- else {
+ } else {
interface = &dev->actconfig->interface[ifnum]->altsetting[0];
}
endpoint = &interface->endpoint[1].desc;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) {
- err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum);
- err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes);
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ USB_ENDPOINT_XFER_ISOC) {
+ err("%s: interface %d. has non-ISO endpoint!",
+ __FUNCTION__, ifnum);
+ err("%s: Endpoint attributes %d",
+ __FUNCTION__, endpoint->bmAttributes);
return -ENODEV;
}
- if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
- err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum);
+ if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+ USB_DIR_OUT) {
+ err("%s: interface %d. has ISO OUT endpoint!",
+ __FUNCTION__, ifnum);
return -ENODEV;
}
@@ -1818,11 +1792,9 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
if (dev->descriptor.bNumConfigurations > 1) {
usbvision->bridgeType = BRIDGE_NT1004;
- }
- else if (model == DAZZLE_DVC_90_REV_1_SECAM) {
+ } else if (model == DAZZLE_DVC_90_REV_1_SECAM) {
usbvision->bridgeType = BRIDGE_NT1005;
- }
- else {
+ } else {
usbvision->bridgeType = BRIDGE_NT1003;
}
PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType);
@@ -1919,11 +1891,11 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
up(&usbvision->lock);
if (usbvision->user) {
- printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__);
+ printk(KERN_INFO "%s: In use, disconnect pending\n",
+ __FUNCTION__);
wake_up_interruptible(&usbvision->wait_frame);
wake_up_interruptible(&usbvision->wait_stream);
- }
- else {
+ } else {
usbvision_release(usbvision);
}
@@ -1950,7 +1922,6 @@ static int __init usbvision_init(void)
PDEBUG(DBG_PROBE, "");
- PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]");
PDEBUG(DBG_IO, "IO debugging is enabled [video]");
PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]");
PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]");
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index c759d00d7014..c5b6c501c869 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -221,6 +221,8 @@ enum {
#define I2C_USB_ADAP_MAX 16
+#define USBVISION_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_M)
+
/* ----------------------------------------------------------------- */
/* usbvision video structures */
/* ----------------------------------------------------------------- */
@@ -301,14 +303,6 @@ struct usbvision_frame_header {
__u16 frameHeight; /* 10 - 11 after endian correction*/
};
-/* tvnorms */
-struct usbvision_tvnorm {
- char *name;
- v4l2_std_id id;
- /* mode for saa7113h */
- int mode;
-};
-
struct usbvision_frame {
char *data; /* Frame buffer */
struct usbvision_frame_header isocHeader; /* Header from stream */
@@ -386,7 +380,6 @@ struct usb_usbvision {
int tuner_type;
int tuner_addr;
int bridgeType; // NT1003, NT1004, NT1005
- int channel;
int radio;
int video_inputs; // # of inputs
unsigned long freq;
@@ -441,7 +434,7 @@ struct usb_usbvision {
struct v4l2_capability vcap; /* Video capabilities */
unsigned int ctl_input; /* selected input */
- struct usbvision_tvnorm *tvnorm; /* selected tv norm */
+ v4l2_std_id tvnormId; /* selected tv norm */
unsigned char video_endp; /* 0x82 for USBVISION devices based */
// Decompression stuff:
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index ede8543818bf..9eac65f34bff 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -19,7 +19,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 13ee550d3215..c3440b280d20 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -65,11 +65,6 @@
#include <linux/kmod.h>
#endif
-#if defined(CONFIG_UST) || defined(CONFIG_UST_MODULE)
-#include <linux/ust.h>
-#endif
-
-
#include <linux/videodev.h>
MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
@@ -716,6 +711,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_LOUDNESS:
case V4L2_CID_MPEG_AUDIO_MUTE:
+ case V4L2_CID_MPEG_VIDEO_MUTE:
case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
case V4L2_CID_MPEG_VIDEO_PULLDOWN:
qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
@@ -939,16 +935,25 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc
When no more controls are available 0 is returned. */
u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
{
- u32 ctrl_class;
+ u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
const u32 *pctrl;
- /* if no query is desired, then just return the control ID */
- if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0)
- return id;
if (ctrl_classes == NULL)
return 0;
+
+ /* if no query is desired, then check if the ID is part of ctrl_classes */
+ if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
+ /* find class */
+ while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
+ ctrl_classes++;
+ if (*ctrl_classes == NULL)
+ return 0;
+ pctrl = *ctrl_classes;
+ /* find control ID */
+ while (*pctrl && *pctrl != id) pctrl++;
+ return *pctrl ? id : 0;
+ }
id &= V4L2_CTRL_ID_MASK;
- ctrl_class = V4L2_CTRL_ID2CLASS(id);
id++; /* select next control */
/* find first class that matches (or is greater than) the class of
the ID */
diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
new file mode 100644
index 000000000000..8b4ef530a3a8
--- /dev/null
+++ b/drivers/media/video/v4l2-int-device.c
@@ -0,0 +1,158 @@
+/*
+ * drivers/media/video/v4l2-int-device.c
+ *
+ * V4L2 internal ioctl interface.
+ *
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/sort.h>
+#include <linux/string.h>
+
+#include <media/v4l2-int-device.h>
+
+static DEFINE_MUTEX(mutex);
+static LIST_HEAD(int_list);
+
+static void v4l2_int_device_try_attach_all(void)
+{
+ struct v4l2_int_device *m, *s;
+
+ list_for_each_entry(m, &int_list, head) {
+ if (m->type != v4l2_int_type_master)
+ continue;
+
+ list_for_each_entry(s, &int_list, head) {
+ if (s->type != v4l2_int_type_slave)
+ continue;
+
+ /* Slave is connected? */
+ if (s->u.slave->master)
+ continue;
+
+ /* Slave wants to attach to master? */
+ if (s->u.slave->attach_to[0] != 0
+ && strncmp(m->name, s->u.slave->attach_to,
+ V4L2NAMESIZE))
+ continue;
+
+ if (!try_module_get(m->module))
+ continue;
+
+ if (m->u.master->attach(m, s)) {
+ module_put(m->module);
+ continue;
+ }
+
+ s->u.slave->master = m;
+ }
+ }
+}
+
+static int ioctl_sort_cmp(const void *a, const void *b)
+{
+ const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b;
+
+ if (d1->num > d2->num)
+ return 1;
+
+ if (d1->num < d2->num)
+ return -1;
+
+ return 0;
+}
+
+int v4l2_int_device_register(struct v4l2_int_device *d)
+{
+ if (d->type == v4l2_int_type_slave)
+ sort(d->u.slave->ioctls, d->u.slave->num_ioctls,
+ sizeof(struct v4l2_int_ioctl_desc),
+ &ioctl_sort_cmp, NULL);
+ mutex_lock(&mutex);
+ list_add(&d->head, &int_list);
+ v4l2_int_device_try_attach_all();
+ mutex_unlock(&mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_register);
+
+void v4l2_int_device_unregister(struct v4l2_int_device *d)
+{
+ mutex_lock(&mutex);
+ list_del(&d->head);
+ if (d->type == v4l2_int_type_slave
+ && d->u.slave->master != NULL) {
+ d->u.slave->master->u.master->detach(d);
+ module_put(d->u.slave->master->module);
+ d->u.slave->master = NULL;
+ }
+ mutex_unlock(&mutex);
+}
+EXPORT_SYMBOL_GPL(v4l2_int_device_unregister);
+
+/* Adapted from search_extable in extable.c. */
+static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
+ v4l2_int_ioctl_func *no_such_ioctl)
+{
+ const struct v4l2_int_ioctl_desc *first = slave->ioctls;
+ const struct v4l2_int_ioctl_desc *last =
+ first + slave->num_ioctls - 1;
+
+ while (first <= last) {
+ const struct v4l2_int_ioctl_desc *mid;
+
+ mid = (last - first) / 2 + first;
+
+ if (mid->num < cmd)
+ first = mid + 1;
+ else if (mid->num > cmd)
+ last = mid - 1;
+ else
+ return mid->func;
+ }
+
+ return no_such_ioctl;
+}
+
+static int no_such_ioctl_0(struct v4l2_int_device *d)
+{
+ return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
+{
+ return ((v4l2_int_ioctl_func_0 *)
+ find_ioctl(d->u.slave, cmd,
+ (v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
+}
+
+static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
+{
+ return ((v4l2_int_ioctl_func_1 *)
+ find_ioctl(d->u.slave, cmd,
+ (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
+}
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/videobuf-core.c
index a32dfbe0585a..c606332512b6 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/videobuf-core.c
@@ -1,313 +1,63 @@
/*
+ * generic helper functions for handling video4linux capture buffers
*
- * generic helper functions for video4linux capture buffers, to handle
- * memory management and PCI DMA.
- * Right now, bttv, saa7134, saa7146 and cx88 use it.
+ * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
*
- * The functions expect the hardware being able to scatter gatter
- * (i.e. the buffers are not linear in physical memory, but fragmented
- * into PAGE_SIZE chunks). They also assume the driver does not need
- * to touch the video data.
- *
- * device specific map/unmap/sync stuff now are mapped as operations
- * to allow its usage by USB and virtual devices.
- *
- * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
- * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ * Highly based on video-buf written originally by:
+ * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
* (c) 2006 Ted Walther and John Sokol
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
#include <linux/slab.h>
-#include <linux/pci.h>
#include <linux/interrupt.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <media/video-buf.h>
+#include <media/videobuf-core.h>
-#define MAGIC_DMABUF 0x19721112
-#define MAGIC_BUFFER 0x20040302
+#define MAGIC_BUFFER 0x20070728
#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
{ printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
static int debug = 0;
module_param(debug, int, 0644);
-MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_DESCRIPTION("helper module to manage video4linux buffers");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL");
#define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_DEBUG "vbuf: " fmt , ## arg)
-struct scatterlist*
-videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
-{
- struct scatterlist *sglist;
- struct page *pg;
- int i;
-
- sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
- if (NULL == sglist)
- return NULL;
- for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
- pg = vmalloc_to_page(virt);
- if (NULL == pg)
- goto err;
- BUG_ON(PageHighMem(pg));
- sglist[i].page = pg;
- sglist[i].length = PAGE_SIZE;
- }
- return sglist;
-
- err:
- kfree(sglist);
- return NULL;
-}
-
-struct scatterlist*
-videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
-{
- struct scatterlist *sglist;
- int i = 0;
-
- if (NULL == pages[0])
- return NULL;
- sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
- if (NULL == sglist)
- return NULL;
-
- if (NULL == pages[0])
- goto nopage;
- if (PageHighMem(pages[0]))
- /* DMA to highmem pages might not work */
- goto highmem;
- sglist[0].page = pages[0];
- sglist[0].offset = offset;
- sglist[0].length = PAGE_SIZE - offset;
- for (i = 1; i < nr_pages; i++) {
- if (NULL == pages[i])
- goto nopage;
- if (PageHighMem(pages[i]))
- goto highmem;
- sglist[i].page = pages[i];
- sglist[i].length = PAGE_SIZE;
- }
- return sglist;
-
- nopage:
- dprintk(2,"sgl: oops - no page\n");
- kfree(sglist);
- return NULL;
-
- highmem:
- dprintk(2,"sgl: oops - highmem page\n");
- kfree(sglist);
- return NULL;
-}
-
/* --------------------------------------------------------------------- */
-void videobuf_dma_init(struct videobuf_dmabuf *dma)
-{
- memset(dma,0,sizeof(*dma));
- dma->magic = MAGIC_DMABUF;
-}
+#define CALL(q, f, arg...) \
+ ( (q->int_ops->f)? q->int_ops->f(arg) : 0)
-int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
- unsigned long data, unsigned long size)
+void* videobuf_alloc(struct videobuf_queue* q)
{
- unsigned long first,last;
- int err, rw = 0;
-
- dma->direction = direction;
- switch (dma->direction) {
- case PCI_DMA_FROMDEVICE: rw = READ; break;
- case PCI_DMA_TODEVICE: rw = WRITE; break;
- default: BUG();
- }
-
- first = (data & PAGE_MASK) >> PAGE_SHIFT;
- last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
- dma->offset = data & ~PAGE_MASK;
- dma->nr_pages = last-first+1;
- dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*),
- GFP_KERNEL);
- if (NULL == dma->pages)
- return -ENOMEM;
- dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
- data,size,dma->nr_pages);
-
- dma->varea = (void *) data;
-
- down_read(&current->mm->mmap_sem);
- err = get_user_pages(current,current->mm,
- data & PAGE_MASK, dma->nr_pages,
- rw == READ, 1, /* force */
- dma->pages, NULL);
- up_read(&current->mm->mmap_sem);
- if (err != dma->nr_pages) {
- dma->nr_pages = (err >= 0) ? err : 0;
- dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages);
- return err < 0 ? err : -EINVAL;
- }
- return 0;
-}
-
-int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
- int nr_pages)
-{
- dprintk(1,"init kernel [%d pages]\n",nr_pages);
- dma->direction = direction;
- dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
- if (NULL == dma->vmalloc) {
- dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages);
- return -ENOMEM;
- }
- dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
- (unsigned long)dma->vmalloc,
- nr_pages << PAGE_SHIFT);
- memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT);
- dma->nr_pages = nr_pages;
- return 0;
-}
-
-int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
- dma_addr_t addr, int nr_pages)
-{
- dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n",
- nr_pages,(unsigned long)addr);
- dma->direction = direction;
- if (0 == addr)
- return -EINVAL;
-
- dma->bus_addr = addr;
- dma->nr_pages = nr_pages;
- return 0;
-}
-
-int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
-{
- void *dev=q->dev;
-
- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
- BUG_ON(0 == dma->nr_pages);
-
- if (dma->pages) {
- dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
- dma->offset);
- }
- if (dma->vmalloc) {
- dma->sglist = videobuf_vmalloc_to_sg
- (dma->vmalloc,dma->nr_pages);
- }
- if (dma->bus_addr) {
- dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
- if (NULL != dma->sglist) {
- dma->sglen = 1;
- sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
- dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK;
- sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE;
- }
- }
- if (NULL == dma->sglist) {
- dprintk(1,"scatterlist is NULL\n");
- return -ENOMEM;
- }
- if (!dma->bus_addr) {
- if (q->ops->vb_map_sg) {
- dma->sglen = q->ops->vb_map_sg(dev,dma->sglist,
- dma->nr_pages, dma->direction);
- }
- if (0 == dma->sglen) {
- printk(KERN_WARNING
- "%s: videobuf_map_sg failed\n",__FUNCTION__);
- kfree(dma->sglist);
- dma->sglist = NULL;
- dma->sglen = 0;
- return -EIO;
- }
- }
- return 0;
-}
-
-int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
-{
- void *dev=q->dev;
-
- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
- BUG_ON(!dma->sglen);
-
- if (!dma->bus_addr && q->ops->vb_dma_sync_sg)
- q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages,
- dma->direction);
-
- return 0;
-}
-
-int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
-{
- void *dev=q->dev;
-
- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
- if (!dma->sglen)
- return 0;
-
- if (!dma->bus_addr && q->ops->vb_unmap_sg)
- q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages,
- dma->direction);
- kfree(dma->sglist);
- dma->sglist = NULL;
- dma->sglen = 0;
- return 0;
-}
-
-int videobuf_dma_free(struct videobuf_dmabuf *dma)
-{
- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
- BUG_ON(dma->sglen);
-
- if (dma->pages) {
- int i;
- for (i=0; i < dma->nr_pages; i++)
- page_cache_release(dma->pages[i]);
- kfree(dma->pages);
- dma->pages = NULL;
- }
+ struct videobuf_buffer *vb;
- vfree(dma->vmalloc);
- dma->vmalloc = NULL;
- dma->varea = NULL;
+ BUG_ON (q->msize<sizeof(*vb));
- if (dma->bus_addr) {
- dma->bus_addr = 0;
+ if (!q->int_ops || !q->int_ops->alloc) {
+ printk(KERN_ERR "No specific ops defined!\n");
+ BUG();
}
- dma->direction = PCI_DMA_NONE;
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-void* videobuf_alloc(unsigned int size)
-{
- struct videobuf_buffer *vb;
+ vb = q->int_ops->alloc(q->msize);
- vb = kzalloc(size,GFP_KERNEL);
if (NULL != vb) {
- videobuf_dma_init(&vb->dma);
init_waitqueue_head(&vb->done);
vb->magic = MAGIC_BUFFER;
}
+
return vb;
}
@@ -338,127 +88,65 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
return retval;
}
-int
-videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
- struct v4l2_framebuffer *fbuf)
+int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
{
- int err,pages;
- dma_addr_t bus;
-
MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
- switch (vb->memory) {
- case V4L2_MEMORY_MMAP:
- case V4L2_MEMORY_USERPTR:
- if (0 == vb->baddr) {
- /* no userspace addr -- kernel bounce buffer */
- pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
- err = videobuf_dma_init_kernel(&vb->dma,PCI_DMA_FROMDEVICE,
- pages);
- if (0 != err)
- return err;
- } else {
- /* dma directly to userspace */
- err = videobuf_dma_init_user(&vb->dma,PCI_DMA_FROMDEVICE,
- vb->baddr,vb->bsize);
- if (0 != err)
- return err;
- }
- break;
- case V4L2_MEMORY_OVERLAY:
- if (NULL == fbuf)
- return -EINVAL;
- /* FIXME: need sanity checks for vb->boff */
- /*
- * Using a double cast to avoid compiler warnings when
- * building for PAE. Compiler doesn't like direct casting
- * of a 32 bit ptr to 64 bit integer.
- */
- bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
- pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
- err = videobuf_dma_init_overlay(&vb->dma,PCI_DMA_FROMDEVICE,
- bus, pages);
- if (0 != err)
- return err;
- break;
- default:
- BUG();
- }
- err = videobuf_dma_map(q,&vb->dma);
- if (0 != err)
- return err;
-
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
-void videobuf_queue_pci(struct videobuf_queue* q)
-{
- /* If not specified, defaults to PCI map sg */
- if (!q->ops->vb_map_sg)
- q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg;
-
- if (!q->ops->vb_dma_sync_sg)
- q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu;
- if (!q->ops->vb_unmap_sg)
- q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
-}
-
-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
-{
- struct videobuf_queue q;
- struct videobuf_queue_ops qops;
+ /* FIXME: This is required to avoid OOPS on some cases, since mmap_mapper()
+ method should be called before _iolock.
+ On some cases, the mmap_mapper() is called only after scheduling.
- q.dev=pci;
- qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
- qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
- q.ops = &qops;
+ However, this way is just too dirty! Better to wait for some event.
+ */
+ schedule_timeout(HZ);
- return (videobuf_dma_map(&q,dma));
+ return CALL(q,iolock,q,vb,fbuf);
}
-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
-{
- struct videobuf_queue q;
- struct videobuf_queue_ops qops;
-
- q.dev=pci;
- qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
- qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
- q.ops = &qops;
+/* --------------------------------------------------------------------- */
- return (videobuf_dma_unmap(&q,dma));
-}
-void videobuf_queue_init(struct videobuf_queue* q,
+void videobuf_queue_core_init(struct videobuf_queue* q,
struct videobuf_queue_ops *ops,
void *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
unsigned int msize,
- void *priv)
+ void *priv,
+ struct videobuf_qtype_ops *int_ops)
{
memset(q,0,sizeof(*q));
- q->irqlock = irqlock;
- q->dev = dev;
- q->type = type;
- q->field = field;
- q->msize = msize;
- q->ops = ops;
+ q->irqlock = irqlock;
+ q->dev = dev;
+ q->type = type;
+ q->field = field;
+ q->msize = msize;
+ q->ops = ops;
q->priv_data = priv;
+ q->int_ops = int_ops;
- videobuf_queue_pci(q);
+ /* All buffer operations are mandatory */
+ BUG_ON (!q->ops->buf_setup);
+ BUG_ON (!q->ops->buf_prepare);
+ BUG_ON (!q->ops->buf_queue);
+ BUG_ON (!q->ops->buf_release);
+
+ /* Having implementations for abstract methods are mandatory */
+ BUG_ON (!q->int_ops);
mutex_init(&q->lock);
INIT_LIST_HEAD(&q->stream);
}
-int
-videobuf_queue_is_busy(struct videobuf_queue *q)
+int videobuf_queue_is_busy(struct videobuf_queue *q)
{
int i;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
if (q->streaming) {
dprintk(1,"busy: streaming active\n");
return 1;
@@ -490,8 +178,7 @@ videobuf_queue_is_busy(struct videobuf_queue *q)
return 0;
}
-void
-videobuf_queue_cancel(struct videobuf_queue *q)
+void videobuf_queue_cancel(struct videobuf_queue *q)
{
unsigned long flags=0;
int i;
@@ -521,8 +208,7 @@ videobuf_queue_cancel(struct videobuf_queue *q)
/* --------------------------------------------------------------------- */
-enum v4l2_field
-videobuf_next_field(struct videobuf_queue *q)
+enum v4l2_field videobuf_next_field(struct videobuf_queue *q)
{
enum v4l2_field field = q->field;
@@ -540,11 +226,11 @@ videobuf_next_field(struct videobuf_queue *q)
return field;
}
-void
-videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
- enum v4l2_buf_type type)
+static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
+ struct videobuf_buffer *vb, enum v4l2_buf_type type)
{
MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
b->index = vb->i;
b->type = type;
@@ -595,8 +281,7 @@ videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,
b->sequence = vb->field_count >> 1;
}
-int
-videobuf_reqbufs(struct videobuf_queue *q,
+int videobuf_reqbufs(struct videobuf_queue *q,
struct v4l2_requestbuffers *req)
{
unsigned int size,count;
@@ -617,16 +302,18 @@ videobuf_reqbufs(struct videobuf_queue *q,
return -EINVAL;
}
+ mutex_lock(&q->lock);
if (q->streaming) {
dprintk(1,"reqbufs: streaming already exists\n");
- return -EBUSY;
+ retval = -EBUSY;
+ goto done;
}
if (!list_empty(&q->stream)) {
dprintk(1,"reqbufs: stream running\n");
- return -EBUSY;
+ retval = -EBUSY;
+ goto done;
}
- mutex_lock(&q->lock);
count = req->count;
if (count > VIDEO_MAX_FRAME)
count = VIDEO_MAX_FRAME;
@@ -642,15 +329,14 @@ videobuf_reqbufs(struct videobuf_queue *q,
goto done;
}
- req->count = count;
+ req->count = retval;
done:
mutex_unlock(&q->lock);
return retval;
}
-int
-videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
+int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{
if (unlikely(b->type != q->type)) {
dprintk(1,"querybuf: Wrong type.\n");
@@ -664,12 +350,11 @@ videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
dprintk(1,"querybuf: buffer is null.\n");
return -EINVAL;
}
- videobuf_status(b,q->bufs[b->index],q->type);
+ videobuf_status(q,b,q->bufs[b->index],q->type);
return 0;
}
-int
-videobuf_qbuf(struct videobuf_queue *q,
+int videobuf_qbuf(struct videobuf_queue *q,
struct v4l2_buffer *b)
{
struct videobuf_buffer *buf;
@@ -677,6 +362,11 @@ videobuf_qbuf(struct videobuf_queue *q,
unsigned long flags=0;
int retval;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
+ if (b->memory == V4L2_MEMORY_MMAP)
+ down_read(&current->mm->mmap_sem);
+
mutex_lock(&q->lock);
retval = -EBUSY;
if (q->reading) {
@@ -762,16 +452,21 @@ videobuf_qbuf(struct videobuf_queue *q,
done:
mutex_unlock(&q->lock);
+
+ if (b->memory == V4L2_MEMORY_MMAP)
+ up_read(&current->mm->mmap_sem);
+
return retval;
}
-int
-videobuf_dqbuf(struct videobuf_queue *q,
+int videobuf_dqbuf(struct videobuf_queue *q,
struct v4l2_buffer *b, int nonblocking)
{
struct videobuf_buffer *buf;
int retval;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
mutex_lock(&q->lock);
retval = -EBUSY;
if (q->reading) {
@@ -797,12 +492,12 @@ videobuf_dqbuf(struct videobuf_queue *q,
case STATE_ERROR:
dprintk(1,"dqbuf: state is error\n");
retval = -EIO;
- videobuf_dma_sync(q,&buf->dma);
+ CALL(q,sync,q, buf);
buf->state = STATE_IDLE;
break;
case STATE_DONE:
dprintk(1,"dqbuf: state is done\n");
- videobuf_dma_sync(q,&buf->dma);
+ CALL(q,sync,q, buf);
buf->state = STATE_IDLE;
break;
default:
@@ -812,7 +507,7 @@ videobuf_dqbuf(struct videobuf_queue *q,
}
list_del(&buf->stream);
memset(b,0,sizeof(*b));
- videobuf_status(b,buf,q->type);
+ videobuf_status(q,b,buf,q->type);
done:
mutex_unlock(&q->lock);
@@ -822,7 +517,6 @@ videobuf_dqbuf(struct videobuf_queue *q,
int videobuf_streamon(struct videobuf_queue *q)
{
struct videobuf_buffer *buf;
- struct list_head *list;
unsigned long flags=0;
int retval;
@@ -836,11 +530,9 @@ int videobuf_streamon(struct videobuf_queue *q)
q->streaming = 1;
if (q->irqlock)
spin_lock_irqsave(q->irqlock,flags);
- list_for_each(list,&q->stream) {
- buf = list_entry(list, struct videobuf_buffer, stream);
+ list_for_each_entry(buf, &q->stream, stream)
if (buf->state == STATE_PREPARED)
q->ops->buf_queue(q,buf);
- }
if (q->irqlock)
spin_unlock_irqrestore(q->irqlock,flags);
@@ -865,22 +557,25 @@ int videobuf_streamoff(struct videobuf_queue *q)
return retval;
}
-static ssize_t
-videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data,
- size_t count, loff_t *ppos)
+static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
+ char __user *data,
+ size_t count, loff_t *ppos)
{
enum v4l2_field field;
unsigned long flags=0;
int retval;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
/* setup stuff */
- q->read_buf = videobuf_alloc(q->msize);
+ q->read_buf = videobuf_alloc(q);
if (NULL == q->read_buf)
return -ENOMEM;
q->read_buf->memory = V4L2_MEMORY_USERPTR;
q->read_buf->baddr = (unsigned long)data;
q->read_buf->bsize = count;
+
field = videobuf_next_field(q);
retval = q->ops->buf_prepare(q,q->read_buf,field);
if (0 != retval)
@@ -894,7 +589,7 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data,
spin_unlock_irqrestore(q->irqlock,flags);
retval = videobuf_waiton(q->read_buf,0,0);
if (0 == retval) {
- videobuf_dma_sync(q,&q->read_buf->dma);
+ CALL(q,sync,q,q->read_buf);
if (STATE_ERROR == q->read_buf->state)
retval = -EIO;
else
@@ -915,13 +610,16 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
{
enum v4l2_field field;
unsigned long flags=0;
- unsigned size, nbufs, bytes;
+ unsigned size, nbufs;
int retval;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
mutex_lock(&q->lock);
nbufs = 1; size = 0;
q->ops->buf_setup(q,&nbufs,&size);
+
if (NULL == q->read_buf &&
count >= size &&
!nonblocking) {
@@ -935,7 +633,8 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
if (NULL == q->read_buf) {
/* need to capture a new frame */
retval = -ENOMEM;
- q->read_buf = videobuf_alloc(q->msize);
+ q->read_buf = videobuf_alloc(q);
+
dprintk(1,"video alloc=0x%p\n", q->read_buf);
if (NULL == q->read_buf)
goto done;
@@ -943,6 +642,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
q->read_buf->bsize = count; /* preferred size */
field = videobuf_next_field(q);
retval = q->ops->buf_prepare(q,q->read_buf,field);
+
if (0 != retval) {
kfree (q->read_buf);
q->read_buf = NULL;
@@ -950,6 +650,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
}
if (q->irqlock)
spin_lock_irqsave(q->irqlock,flags);
+
q->ops->buf_queue(q,q->read_buf);
if (q->irqlock)
spin_unlock_irqrestore(q->irqlock,flags);
@@ -960,7 +661,8 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
retval = videobuf_waiton(q->read_buf, nonblocking, 1);
if (0 != retval)
goto done;
- videobuf_dma_sync(q,&q->read_buf->dma);
+
+ CALL(q,sync,q,q->read_buf);
if (STATE_ERROR == q->read_buf->state) {
/* catch I/O errors */
@@ -971,16 +673,12 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
goto done;
}
- /* copy to userspace */
- bytes = count;
- if (bytes > q->read_buf->size - q->read_off)
- bytes = q->read_buf->size - q->read_off;
- retval = -EFAULT;
- if (copy_to_user(data, q->read_buf->dma.vmalloc+q->read_off, bytes))
+ /* Copy to userspace */
+ retval=CALL(q,copy_to_user,q,data,count,nonblocking);
+ if (retval<0)
goto done;
- retval = bytes;
- q->read_off += bytes;
+ q->read_off += retval;
if (q->read_off == q->read_buf->size) {
/* all data copied, cleanup */
q->ops->buf_release(q,q->read_buf);
@@ -997,7 +695,7 @@ int videobuf_read_start(struct videobuf_queue *q)
{
enum v4l2_field field;
unsigned long flags=0;
- int count = 0, size = 0;
+ unsigned int count = 0, size = 0;
int err, i;
q->ops->buf_setup(q,&count,&size);
@@ -1008,8 +706,11 @@ int videobuf_read_start(struct videobuf_queue *q)
size = PAGE_ALIGN(size);
err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR);
- if (err)
+ if (err < 0)
return err;
+
+ count = err;
+
for (i = 0; i < count; i++) {
field = videobuf_next_field(q);
err = q->ops->buf_prepare(q,q->bufs[i],field);
@@ -1048,10 +749,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
char __user *data, size_t count, loff_t *ppos,
int vbihack, int nonblocking)
{
- unsigned int *fc, bytes;
- int err, retval;
+ int rc, retval;
unsigned long flags=0;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
dprintk(2,"%s\n",__FUNCTION__);
mutex_lock(&q->lock);
retval = -EBUSY;
@@ -1073,39 +775,23 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
list_del(&q->read_buf->stream);
q->read_off = 0;
}
- err = videobuf_waiton(q->read_buf, nonblocking, 1);
- if (err < 0) {
+ rc = videobuf_waiton(q->read_buf, nonblocking, 1);
+ if (rc < 0) {
if (0 == retval)
- retval = err;
+ retval = rc;
break;
}
if (q->read_buf->state == STATE_DONE) {
- if (vbihack) {
- /* dirty, undocumented hack -- pass the frame counter
- * within the last four bytes of each vbi data block.
- * We need that one to maintain backward compatibility
- * to all vbi decoding software out there ... */
- fc = (unsigned int*)q->read_buf->dma.vmalloc;
- fc += (q->read_buf->size>>2) -1;
- *fc = q->read_buf->field_count >> 1;
- dprintk(1,"vbihack: %d\n",*fc);
- }
-
- /* copy stuff */
- bytes = count;
- if (bytes > q->read_buf->size - q->read_off)
- bytes = q->read_buf->size - q->read_off;
- if (copy_to_user(data + retval,
- q->read_buf->dma.vmalloc + q->read_off,
- bytes)) {
- if (0 == retval)
- retval = -EFAULT;
+ rc = CALL (q,copy_stream, q, data + retval, count,
+ retval, vbihack, nonblocking);
+ if (rc < 0) {
+ retval = rc;
break;
}
- count -= bytes;
- retval += bytes;
- q->read_off += bytes;
+ retval += rc;
+ count -= rc;
+ q->read_off += rc;
} else {
/* some error */
q->read_off = q->read_buf->size;
@@ -1172,81 +858,6 @@ unsigned int videobuf_poll_stream(struct file *file,
return rc;
}
-/* --------------------------------------------------------------------- */
-
-static void
-videobuf_vm_open(struct vm_area_struct *vma)
-{
- struct videobuf_mapping *map = vma->vm_private_data;
-
- dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map,
- map->count,vma->vm_start,vma->vm_end);
- map->count++;
-}
-
-static void
-videobuf_vm_close(struct vm_area_struct *vma)
-{
- struct videobuf_mapping *map = vma->vm_private_data;
- struct videobuf_queue *q = map->q;
- int i;
-
- dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
- map->count,vma->vm_start,vma->vm_end);
-
- map->count--;
- if (0 == map->count) {
- dprintk(1,"munmap %p q=%p\n",map,q);
- mutex_lock(&q->lock);
- for (i = 0; i < VIDEO_MAX_FRAME; i++) {
- if (NULL == q->bufs[i])
- continue;
- if (q->bufs[i])
- ;
- if (q->bufs[i]->map != map)
- continue;
- q->bufs[i]->map = NULL;
- q->bufs[i]->baddr = 0;
- q->ops->buf_release(q,q->bufs[i]);
- }
- mutex_unlock(&q->lock);
- kfree(map);
- }
- return;
-}
-
-/*
- * Get a anonymous page for the mapping. Make sure we can DMA to that
- * memory location with 32bit PCI devices (i.e. don't use highmem for
- * now ...). Bounce buffers don't work very well for the data rates
- * video capture has.
- */
-static struct page*
-videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
- int *type)
-{
- struct page *page;
-
- dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n",
- vaddr,vma->vm_start,vma->vm_end);
- if (vaddr > vma->vm_end)
- return NOPAGE_SIGBUS;
- page = alloc_page(GFP_USER | __GFP_DMA32);
- if (!page)
- return NOPAGE_OOM;
- clear_user_page(page_address(page), vaddr, page);
- if (type)
- *type = VM_FAULT_MINOR;
- return page;
-}
-
-static struct vm_operations_struct videobuf_vm_ops =
-{
- .open = videobuf_vm_open,
- .close = videobuf_vm_close,
- .nopage = videobuf_vm_nopage,
-};
-
int videobuf_mmap_setup(struct videobuf_queue *q,
unsigned int bcount, unsigned int bsize,
enum v4l2_memory memory)
@@ -1254,12 +865,19 @@ int videobuf_mmap_setup(struct videobuf_queue *q,
unsigned int i;
int err;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
err = videobuf_mmap_free(q);
if (0 != err)
return err;
+ /* Allocate and initialize buffers */
for (i = 0; i < bcount; i++) {
- q->bufs[i] = videobuf_alloc(q->msize);
+ q->bufs[i] = videobuf_alloc(q);
+
+ if (q->bufs[i] == NULL)
+ break;
+
q->bufs[i]->i = i;
q->bufs[i]->input = UNSET;
q->bufs[i]->memory = memory;
@@ -1274,18 +892,30 @@ int videobuf_mmap_setup(struct videobuf_queue *q,
break;
}
}
+
+ if (!i)
+ return -ENOMEM;
+
dprintk(1,"mmap setup: %d buffers, %d bytes each\n",
- bcount,bsize);
- return 0;
+ i, bsize);
+
+ return i;
}
int videobuf_mmap_free(struct videobuf_queue *q)
{
int i;
+ int rc;
+
+ if (!q)
+ return 0;
+
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
+ rc = CALL(q,mmap_free,q);
+ if (rc<0)
+ return rc;
- for (i = 0; i < VIDEO_MAX_FRAME; i++)
- if (q->bufs[i] && q->bufs[i]->map)
- return -EBUSY;
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
@@ -1293,118 +923,69 @@ int videobuf_mmap_free(struct videobuf_queue *q)
kfree(q->bufs[i]);
q->bufs[i] = NULL;
}
- return 0;
+
+ return rc;
}
int videobuf_mmap_mapper(struct videobuf_queue *q,
struct vm_area_struct *vma)
{
- struct videobuf_mapping *map;
- unsigned int first,last,size,i;
int retval;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
mutex_lock(&q->lock);
- retval = -EINVAL;
- if (!(vma->vm_flags & VM_WRITE)) {
- dprintk(1,"mmap app bug: PROT_WRITE please\n");
- goto done;
- }
- if (!(vma->vm_flags & VM_SHARED)) {
- dprintk(1,"mmap app bug: MAP_SHARED please\n");
- goto done;
- }
+ retval=CALL(q,mmap_mapper,q,vma);
+ mutex_unlock(&q->lock);
- /* look for first buffer to map */
- for (first = 0; first < VIDEO_MAX_FRAME; first++) {
- if (NULL == q->bufs[first])
- continue;
- if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
- continue;
- if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
- break;
- }
- if (VIDEO_MAX_FRAME == first) {
- dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
- (vma->vm_pgoff << PAGE_SHIFT));
- goto done;
- }
+ return retval;
+}
- /* look for last buffer to map */
- for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) {
- if (NULL == q->bufs[last])
- continue;
- if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
- continue;
- if (q->bufs[last]->map) {
- retval = -EBUSY;
- goto done;
- }
- size += q->bufs[last]->bsize;
- if (size == (vma->vm_end - vma->vm_start))
- break;
- }
- if (VIDEO_MAX_FRAME == last) {
- dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n",
- (vma->vm_end - vma->vm_start));
- goto done;
- }
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int videobuf_cgmbuf(struct videobuf_queue *q,
+ struct video_mbuf *mbuf, int count)
+{
+ struct v4l2_requestbuffers req;
+ int rc,i;
- /* create mapping + update buffer list */
- retval = -ENOMEM;
- map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
- if (NULL == map)
- goto done;
- for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
- q->bufs[i]->map = map;
- q->bufs[i]->baddr = vma->vm_start + size;
+ MAGIC_CHECK(q->int_ops->magic,MAGIC_QTYPE_OPS);
+
+ memset(&req,0,sizeof(req));
+ req.type = q->type;
+ req.count = count;
+ req.memory = V4L2_MEMORY_MMAP;
+ rc = videobuf_reqbufs(q,&req);
+ if (rc < 0)
+ return rc;
+
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
}
- map->count = 1;
- map->start = vma->vm_start;
- map->end = vma->vm_end;
- map->q = q;
- vma->vm_ops = &videobuf_vm_ops;
- vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
- vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
- vma->vm_private_data = map;
- dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n",
- map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last);
- retval = 0;
- done:
- mutex_unlock(&q->lock);
- return retval;
+ return 0;
}
+#endif
/* --------------------------------------------------------------------- */
-EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
-
-EXPORT_SYMBOL_GPL(videobuf_dma_init);
-EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
-EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
-EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
-EXPORT_SYMBOL_GPL(videobuf_dma_map);
-EXPORT_SYMBOL_GPL(videobuf_dma_sync);
-EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
-EXPORT_SYMBOL_GPL(videobuf_dma_free);
-
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
-EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
-
-EXPORT_SYMBOL_GPL(videobuf_alloc);
EXPORT_SYMBOL_GPL(videobuf_waiton);
EXPORT_SYMBOL_GPL(videobuf_iolock);
-EXPORT_SYMBOL_GPL(videobuf_queue_init);
+EXPORT_SYMBOL_GPL(videobuf_alloc);
+
+EXPORT_SYMBOL_GPL(videobuf_queue_core_init);
EXPORT_SYMBOL_GPL(videobuf_queue_cancel);
EXPORT_SYMBOL_GPL(videobuf_queue_is_busy);
EXPORT_SYMBOL_GPL(videobuf_next_field);
-EXPORT_SYMBOL_GPL(videobuf_status);
EXPORT_SYMBOL_GPL(videobuf_reqbufs);
EXPORT_SYMBOL_GPL(videobuf_querybuf);
EXPORT_SYMBOL_GPL(videobuf_qbuf);
EXPORT_SYMBOL_GPL(videobuf_dqbuf);
+EXPORT_SYMBOL_GPL(videobuf_cgmbuf);
EXPORT_SYMBOL_GPL(videobuf_streamon);
EXPORT_SYMBOL_GPL(videobuf_streamoff);
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
new file mode 100644
index 000000000000..8bb7fdd306d6
--- /dev/null
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -0,0 +1,726 @@
+/*
+ * helper functions for PCI DMA video4linux capture buffers
+ *
+ * The functions expect the hardware being able to scatter gatter
+ * (i.e. the buffers are not linear in physical memory, but fragmented
+ * into PAGE_SIZE chunks). They also assume the driver does not need
+ * to touch the video data.
+ *
+ * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
+ *
+ * Highly based on video-buf written originally by:
+ * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
+ * (c) 2006 Ted Walther and John Sokol
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <media/videobuf-dma-sg.h>
+
+#define MAGIC_DMABUF 0x19721112
+#define MAGIC_SG_MEM 0x17890714
+
+#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
+ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+#define dprintk(level, fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg)
+
+/* --------------------------------------------------------------------- */
+
+struct scatterlist*
+videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
+{
+ struct scatterlist *sglist;
+ struct page *pg;
+ int i;
+
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
+ if (NULL == sglist)
+ return NULL;
+ for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
+ pg = vmalloc_to_page(virt);
+ if (NULL == pg)
+ goto err;
+ BUG_ON(PageHighMem(pg));
+ sglist[i].page = pg;
+ sglist[i].length = PAGE_SIZE;
+ }
+ return sglist;
+
+ err:
+ kfree(sglist);
+ return NULL;
+}
+
+struct scatterlist*
+videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
+{
+ struct scatterlist *sglist;
+ int i = 0;
+
+ if (NULL == pages[0])
+ return NULL;
+ sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
+ if (NULL == sglist)
+ return NULL;
+
+ if (NULL == pages[0])
+ goto nopage;
+ if (PageHighMem(pages[0]))
+ /* DMA to highmem pages might not work */
+ goto highmem;
+ sglist[0].page = pages[0];
+ sglist[0].offset = offset;
+ sglist[0].length = PAGE_SIZE - offset;
+ for (i = 1; i < nr_pages; i++) {
+ if (NULL == pages[i])
+ goto nopage;
+ if (PageHighMem(pages[i]))
+ goto highmem;
+ sglist[i].page = pages[i];
+ sglist[i].length = PAGE_SIZE;
+ }
+ return sglist;
+
+ nopage:
+ dprintk(2,"sgl: oops - no page\n");
+ kfree(sglist);
+ return NULL;
+
+ highmem:
+ dprintk(2,"sgl: oops - highmem page\n");
+ kfree(sglist);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------- */
+
+struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
+{
+ struct videbuf_pci_sg_memory *mem=buf->priv;
+ BUG_ON (!mem);
+
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ return &mem->dma;
+}
+
+void videobuf_dma_init(struct videobuf_dmabuf *dma)
+{
+ memset(dma,0,sizeof(*dma));
+ dma->magic = MAGIC_DMABUF;
+}
+
+static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
+ int direction, unsigned long data, unsigned long size)
+{
+ unsigned long first,last;
+ int err, rw = 0;
+
+ dma->direction = direction;
+ switch (dma->direction) {
+ case PCI_DMA_FROMDEVICE: rw = READ; break;
+ case PCI_DMA_TODEVICE: rw = WRITE; break;
+ default: BUG();
+ }
+
+ first = (data & PAGE_MASK) >> PAGE_SHIFT;
+ last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
+ dma->offset = data & ~PAGE_MASK;
+ dma->nr_pages = last-first+1;
+ dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*),
+ GFP_KERNEL);
+ if (NULL == dma->pages)
+ return -ENOMEM;
+ dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
+ data,size,dma->nr_pages);
+
+ dma->varea = (void *) data;
+
+
+ err = get_user_pages(current,current->mm,
+ data & PAGE_MASK, dma->nr_pages,
+ rw == READ, 1, /* force */
+ dma->pages, NULL);
+
+ if (err != dma->nr_pages) {
+ dma->nr_pages = (err >= 0) ? err : 0;
+ dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages);
+ return err < 0 ? err : -EINVAL;
+ }
+ return 0;
+}
+
+int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
+ unsigned long data, unsigned long size)
+{
+ int ret;
+ down_read(&current->mm->mmap_sem);
+ ret = videobuf_dma_init_user_locked(dma, direction, data, size);
+ up_read(&current->mm->mmap_sem);
+
+ return ret;
+}
+
+int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
+ int nr_pages)
+{
+ dprintk(1,"init kernel [%d pages]\n",nr_pages);
+ dma->direction = direction;
+ dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == dma->vmalloc) {
+ dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages);
+ return -ENOMEM;
+ }
+ dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)dma->vmalloc,
+ nr_pages << PAGE_SHIFT);
+ memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT);
+ dma->nr_pages = nr_pages;
+ return 0;
+}
+
+int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
+ dma_addr_t addr, int nr_pages)
+{
+ dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n",
+ nr_pages,(unsigned long)addr);
+ dma->direction = direction;
+ if (0 == addr)
+ return -EINVAL;
+
+ dma->bus_addr = addr;
+ dma->nr_pages = nr_pages;
+ return 0;
+}
+
+int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+{
+ void *dev=q->dev;
+
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(0 == dma->nr_pages);
+
+ if (dma->pages) {
+ dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
+ dma->offset);
+ }
+ if (dma->vmalloc) {
+ dma->sglist = videobuf_vmalloc_to_sg
+ (dma->vmalloc,dma->nr_pages);
+ }
+ if (dma->bus_addr) {
+ dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
+ if (NULL != dma->sglist) {
+ dma->sglen = 1;
+ sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
+ dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK;
+ sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE;
+ }
+ }
+ if (NULL == dma->sglist) {
+ dprintk(1,"scatterlist is NULL\n");
+ return -ENOMEM;
+ }
+ if (!dma->bus_addr) {
+ dma->sglen = pci_map_sg(dev,dma->sglist,
+ dma->nr_pages, dma->direction);
+ if (0 == dma->sglen) {
+ printk(KERN_WARNING
+ "%s: videobuf_map_sg failed\n",__FUNCTION__);
+ kfree(dma->sglist);
+ dma->sglist = NULL;
+ dma->sglen = 0;
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
+{
+ void *dev=q->dev;
+
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(!dma->sglen);
+
+ pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction);
+ return 0;
+}
+
+int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+{
+ void *dev=q->dev;
+
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ if (!dma->sglen)
+ return 0;
+
+ pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction);
+
+ kfree(dma->sglist);
+ dma->sglist = NULL;
+ dma->sglen = 0;
+ return 0;
+}
+
+int videobuf_dma_free(struct videobuf_dmabuf *dma)
+{
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(dma->sglen);
+
+ if (dma->pages) {
+ int i;
+ for (i=0; i < dma->nr_pages; i++)
+ page_cache_release(dma->pages[i]);
+ kfree(dma->pages);
+ dma->pages = NULL;
+ }
+
+ vfree(dma->vmalloc);
+ dma->vmalloc = NULL;
+ dma->varea = NULL;
+
+ if (dma->bus_addr) {
+ dma->bus_addr = 0;
+ }
+ dma->direction = PCI_DMA_NONE;
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+{
+ struct videobuf_queue q;
+
+ q.dev=pci;
+
+ return (videobuf_dma_map(&q,dma));
+}
+
+int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+{
+ struct videobuf_queue q;
+
+ q.dev=pci;
+
+ return (videobuf_dma_unmap(&q,dma));
+}
+
+/* --------------------------------------------------------------------- */
+
+static void
+videobuf_vm_open(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+
+ dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
+ map->count++;
+}
+
+static void
+videobuf_vm_close(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ struct videbuf_pci_sg_memory *mem;
+ int i;
+
+ dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
+
+ map->count--;
+ if (0 == map->count) {
+ dprintk(1,"munmap %p q=%p\n",map,q);
+ mutex_lock(&q->lock);
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+ mem=q->bufs[i]->priv;
+
+ if (!mem)
+ continue;
+
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ if (q->bufs[i]->map != map)
+ continue;
+ q->bufs[i]->map = NULL;
+ q->bufs[i]->baddr = 0;
+ q->ops->buf_release(q,q->bufs[i]);
+ }
+ mutex_unlock(&q->lock);
+ kfree(map);
+ }
+ return;
+}
+
+/*
+ * Get a anonymous page for the mapping. Make sure we can DMA to that
+ * memory location with 32bit PCI devices (i.e. don't use highmem for
+ * now ...). Bounce buffers don't work very well for the data rates
+ * video capture has.
+ */
+static struct page*
+videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
+ int *type)
+{
+ struct page *page;
+
+ dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n",
+ vaddr,vma->vm_start,vma->vm_end);
+ if (vaddr > vma->vm_end)
+ return NOPAGE_SIGBUS;
+ page = alloc_page(GFP_USER | __GFP_DMA32);
+ if (!page)
+ return NOPAGE_OOM;
+ clear_user_page(page_address(page), vaddr, page);
+ if (type)
+ *type = VM_FAULT_MINOR;
+ return page;
+}
+
+static struct vm_operations_struct videobuf_vm_ops =
+{
+ .open = videobuf_vm_open,
+ .close = videobuf_vm_close,
+ .nopage = videobuf_vm_nopage,
+};
+
+/* ---------------------------------------------------------------------
+ * PCI handlers for the generic methods
+ */
+
+/* Allocated area consists on 3 parts:
+ struct video_buffer
+ struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+ struct videobuf_pci_sg_memory
+ */
+
+static void *__videobuf_alloc(size_t size)
+{
+ struct videbuf_pci_sg_memory *mem;
+ struct videobuf_buffer *vb;
+
+ vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
+
+ mem = vb->priv = ((char *)vb)+size;
+ mem->magic=MAGIC_SG_MEM;
+
+ videobuf_dma_init(&mem->dma);
+
+ dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+ __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ mem,(long)sizeof(*mem));
+
+ return vb;
+}
+
+static int __videobuf_iolock (struct videobuf_queue* q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
+{
+ int err,pages;
+ dma_addr_t bus;
+ struct videbuf_pci_sg_memory *mem=vb->priv;
+ BUG_ON(!mem);
+
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ switch (vb->memory) {
+ case V4L2_MEMORY_MMAP:
+ case V4L2_MEMORY_USERPTR:
+ if (0 == vb->baddr) {
+ /* no userspace addr -- kernel bounce buffer */
+ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+ err = videobuf_dma_init_kernel( &mem->dma,
+ PCI_DMA_FROMDEVICE,
+ pages );
+ if (0 != err)
+ return err;
+ } else if (vb->memory == V4L2_MEMORY_USERPTR) {
+ /* dma directly to userspace */
+ err = videobuf_dma_init_user( &mem->dma,
+ PCI_DMA_FROMDEVICE,
+ vb->baddr,vb->bsize );
+ if (0 != err)
+ return err;
+ } else {
+ /* NOTE: HACK: videobuf_iolock on V4L2_MEMORY_MMAP
+ buffers can only be called from videobuf_qbuf
+ we take current->mm->mmap_sem there, to prevent
+ locking inversion, so don't take it here */
+
+ err = videobuf_dma_init_user_locked(&mem->dma,
+ PCI_DMA_FROMDEVICE,
+ vb->baddr, vb->bsize);
+ if (0 != err)
+ return err;
+ }
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ if (NULL == fbuf)
+ return -EINVAL;
+ /* FIXME: need sanity checks for vb->boff */
+ /*
+ * Using a double cast to avoid compiler warnings when
+ * building for PAE. Compiler doesn't like direct casting
+ * of a 32 bit ptr to 64 bit integer.
+ */
+ bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
+ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+ err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
+ bus, pages);
+ if (0 != err)
+ return err;
+ break;
+ default:
+ BUG();
+ }
+ err = videobuf_dma_map(q,&mem->dma);
+ if (0 != err)
+ return err;
+
+ return 0;
+}
+
+static int __videobuf_sync(struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+{
+ struct videbuf_pci_sg_memory *mem=buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ return videobuf_dma_sync(q,&mem->dma);
+}
+
+static int __videobuf_mmap_free(struct videobuf_queue *q)
+{
+ int i;
+
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (q->bufs[i]) {
+ if (q->bufs[i]->map)
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct vm_area_struct *vma)
+{
+ struct videbuf_pci_sg_memory *mem;
+ struct videobuf_mapping *map;
+ unsigned int first,last,size,i;
+ int retval;
+
+ retval = -EINVAL;
+ if (!(vma->vm_flags & VM_WRITE)) {
+ dprintk(1,"mmap app bug: PROT_WRITE please\n");
+ goto done;
+ }
+ if (!(vma->vm_flags & VM_SHARED)) {
+ dprintk(1,"mmap app bug: MAP_SHARED please\n");
+ goto done;
+ }
+
+ /* look for first buffer to map */
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+ mem=q->bufs[first]->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
+ continue;
+ if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
+ break;
+ }
+ if (VIDEO_MAX_FRAME == first) {
+ dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
+ (vma->vm_pgoff << PAGE_SHIFT));
+ goto done;
+ }
+
+ /* look for last buffer to map */
+ for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) {
+ if (NULL == q->bufs[last])
+ continue;
+ if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
+ continue;
+ if (q->bufs[last]->map) {
+ retval = -EBUSY;
+ goto done;
+ }
+ size += q->bufs[last]->bsize;
+ if (size == (vma->vm_end - vma->vm_start))
+ break;
+ }
+ if (VIDEO_MAX_FRAME == last) {
+ dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n",
+ (vma->vm_end - vma->vm_start));
+ goto done;
+ }
+
+ /* create mapping + update buffer list */
+ retval = -ENOMEM;
+ map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+ if (NULL == map)
+ goto done;
+ for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
+ q->bufs[i]->map = map;
+ q->bufs[i]->baddr = vma->vm_start + size;
+ }
+ map->count = 1;
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+ map->q = q;
+ vma->vm_ops = &videobuf_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
+ vma->vm_private_data = map;
+ dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n",
+ map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last);
+ retval = 0;
+
+ done:
+ return retval;
+}
+
+static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+ char __user *data, size_t count,
+ int nonblocking )
+{
+ struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ /* copy to userspace */
+ if (count > q->read_buf->size - q->read_off)
+ count = q->read_buf->size - q->read_off;
+
+ if (copy_to_user(data, mem->dma.vmalloc+q->read_off, count))
+ return -EFAULT;
+
+ return count;
+}
+
+static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ char __user *data, size_t count, size_t pos,
+ int vbihack, int nonblocking )
+{
+ unsigned int *fc;
+ struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ if (vbihack) {
+ /* dirty, undocumented hack -- pass the frame counter
+ * within the last four bytes of each vbi data block.
+ * We need that one to maintain backward compatibility
+ * to all vbi decoding software out there ... */
+ fc = (unsigned int*)mem->dma.vmalloc;
+ fc += (q->read_buf->size>>2) -1;
+ *fc = q->read_buf->field_count >> 1;
+ dprintk(1,"vbihack: %d\n",*fc);
+ }
+
+ /* copy stuff using the common method */
+ count = __videobuf_copy_to_user (q,data,count,nonblocking);
+
+ if ( (count==-EFAULT) && (0 == pos) )
+ return -EFAULT;
+
+ return count;
+}
+
+static struct videobuf_qtype_ops pci_ops = {
+ .magic = MAGIC_QTYPE_OPS,
+
+ .alloc = __videobuf_alloc,
+ .iolock = __videobuf_iolock,
+ .sync = __videobuf_sync,
+ .mmap_free = __videobuf_mmap_free,
+ .mmap_mapper = __videobuf_mmap_mapper,
+ .copy_to_user = __videobuf_copy_to_user,
+ .copy_stream = __videobuf_copy_stream,
+};
+
+void *videobuf_pci_alloc (size_t size)
+{
+ struct videobuf_queue q;
+
+ /* Required to make generic handler to call __videobuf_alloc */
+ q.int_ops=&pci_ops;
+
+ q.msize=size;
+
+ return videobuf_alloc (&q);
+}
+
+void videobuf_queue_pci_init(struct videobuf_queue* q,
+ struct videobuf_queue_ops *ops,
+ void *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+ unsigned int msize,
+ void *priv)
+{
+ videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
+ priv, &pci_ops);
+}
+
+/* --------------------------------------------------------------------- */
+
+EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
+
+EXPORT_SYMBOL_GPL(videobuf_to_dma);
+EXPORT_SYMBOL_GPL(videobuf_dma_init);
+EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
+EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
+EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
+EXPORT_SYMBOL_GPL(videobuf_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_dma_sync);
+EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
+EXPORT_SYMBOL_GPL(videobuf_dma_free);
+
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
+EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
+
+EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/videobuf-dvb.c
index e617925ba31e..880317e04a02 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -22,8 +22,8 @@
#include <linux/file.h>
#include <linux/freezer.h>
-#include <media/video-buf.h>
-#include <media/video-buf-dvb.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
/* ------------------------------------------------------------------ */
@@ -45,6 +45,7 @@ static int videobuf_dvb_thread(void *data)
struct videobuf_buffer *buf;
unsigned long flags;
int err;
+ struct videobuf_dmabuf *dma;
dprintk("dvb thread started\n");
set_freezable();
@@ -56,7 +57,6 @@ static int videobuf_dvb_thread(void *data)
struct videobuf_buffer, stream);
list_del(&buf->stream);
err = videobuf_waiton(buf,0,1);
- BUG_ON(0 != err);
/* no more feeds left or stop_feed() asked us to quit */
if (0 == dvb->nfeeds)
@@ -66,8 +66,9 @@ static int videobuf_dvb_thread(void *data)
try_to_freeze();
/* feed buffer data to demux */
+ dma=videobuf_to_dma(buf);
if (buf->state == STATE_DONE)
- dvb_dmx_swfilter(&dvb->demux, buf->dma.vmalloc,
+ dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
buf->size);
/* requeue buffer */
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
new file mode 100644
index 000000000000..2e3689a12a28
--- /dev/null
+++ b/drivers/media/video/videobuf-vmalloc.c
@@ -0,0 +1,370 @@
+/*
+ * helper functions for vmalloc video4linux capture buffers
+ *
+ * The functions expect the hardware being able to scatter gatter
+ * (i.e. the buffers are not linear in physical memory, but fragmented
+ * into PAGE_SIZE chunks). They also assume the driver does not need
+ * to touch the video data.
+ *
+ * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.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
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <media/videobuf-vmalloc.h>
+
+#define MAGIC_DMABUF 0x17760309
+#define MAGIC_VMAL_MEM 0x18221223
+
+#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
+ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+#define dprintk(level, fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg)
+
+
+/***************************************************************************/
+
+static void
+videobuf_vm_open(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+
+ dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
+
+ map->count++;
+}
+
+static void
+videobuf_vm_close(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ int i;
+
+ dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
+ map->count,vma->vm_start,vma->vm_end);
+
+ map->count--;
+ if (0 == map->count) {
+ dprintk(1,"munmap %p q=%p\n",map,q);
+ mutex_lock(&q->lock);
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+
+ if (q->bufs[i]->map != map)
+ continue;
+
+ q->ops->buf_release(q,q->bufs[i]);
+
+ q->bufs[i]->map = NULL;
+ q->bufs[i]->baddr = 0;
+ }
+ mutex_unlock(&q->lock);
+ kfree(map);
+ }
+ return;
+}
+
+static struct vm_operations_struct videobuf_vm_ops =
+{
+ .open = videobuf_vm_open,
+ .close = videobuf_vm_close,
+};
+
+/* ---------------------------------------------------------------------
+ * vmalloc handlers for the generic methods
+ */
+
+/* Allocated area consists on 3 parts:
+ struct video_buffer
+ struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+ struct videobuf_pci_sg_memory
+ */
+
+static void *__videobuf_alloc(size_t size)
+{
+ struct videbuf_vmalloc_memory *mem;
+ struct videobuf_buffer *vb;
+
+ vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
+
+ mem = vb->priv = ((char *)vb)+size;
+ mem->magic=MAGIC_VMAL_MEM;
+
+ dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+ __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ mem,(long)sizeof(*mem));
+
+ return vb;
+}
+
+static int __videobuf_iolock (struct videobuf_queue* q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
+{
+ int pages;
+
+ struct videbuf_vmalloc_memory *mem=vb->priv;
+
+
+ BUG_ON(!mem);
+
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+
+ /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+ if ((vb->memory != V4L2_MEMORY_MMAP) &&
+ (vb->memory != V4L2_MEMORY_USERPTR) ) {
+ printk(KERN_ERR "Method currently unsupported.\n");
+ return -EINVAL;
+ }
+
+ /* FIXME: should be tested with kernel mmap mem */
+ mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
+ if (NULL == mem->vmalloc) {
+ printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
+ return -ENOMEM;
+ }
+
+ dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)mem->vmalloc,
+ pages << PAGE_SHIFT);
+
+ /* It seems that some kernel versions need to do remap *after*
+ the mmap() call
+ */
+ if (mem->vma) {
+ int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0);
+ kfree(mem->vma);
+ mem->vma=NULL;
+ if (retval<0) {
+ dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n",
+ mem->vmalloc,retval);
+ return retval;
+ }
+ }
+
+ return 0;
+}
+
+static int __videobuf_sync(struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+{
+ return 0;
+}
+
+static int __videobuf_mmap_free(struct videobuf_queue *q)
+{
+ unsigned int i;
+
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (q->bufs[i]) {
+ if (q->bufs[i]->map)
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct vm_area_struct *vma)
+{
+ struct videbuf_vmalloc_memory *mem;
+ struct videobuf_mapping *map;
+ unsigned int first;
+ int retval;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* look for first buffer to map */
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+
+ if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
+ continue;
+ if (q->bufs[first]->boff == offset)
+ break;
+ }
+ if (VIDEO_MAX_FRAME == first) {
+ dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n",
+ (vma->vm_pgoff << PAGE_SHIFT));
+ return -EINVAL;
+ }
+
+ /* create mapping + update buffer list */
+ map = q->bufs[first]->map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+ if (NULL == map)
+ return -ENOMEM;
+
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+ map->q = q;
+
+ q->bufs[first]->baddr = vma->vm_start;
+
+ vma->vm_ops = &videobuf_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_private_data = map;
+
+ mem=q->bufs[first]->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ /* Try to remap memory */
+ retval=remap_vmalloc_range(vma, mem->vmalloc,0);
+ if (retval<0) {
+ dprintk(1,"mmap: postponing remap_vmalloc_range\n");
+
+ mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL);
+ if (!mem->vma) {
+ kfree(map);
+ q->bufs[first]->map=NULL;
+ return -ENOMEM;
+ }
+ memcpy(mem->vma,vma,sizeof(*vma));
+ }
+
+ dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
+ map,q,vma->vm_start,vma->vm_end,
+ (long int) q->bufs[first]->bsize,
+ vma->vm_pgoff,first);
+
+ videobuf_vm_open(vma);
+
+ return (0);
+}
+
+static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+ char __user *data, size_t count,
+ int nonblocking )
+{
+ struct videbuf_vmalloc_memory *mem=q->read_buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ BUG_ON (!mem->vmalloc);
+
+ /* copy to userspace */
+ if (count > q->read_buf->size - q->read_off)
+ count = q->read_buf->size - q->read_off;
+
+ if (copy_to_user(data, mem->vmalloc+q->read_off, count))
+ return -EFAULT;
+
+ return count;
+}
+
+static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ char __user *data, size_t count, size_t pos,
+ int vbihack, int nonblocking )
+{
+ unsigned int *fc;
+ struct videbuf_vmalloc_memory *mem=q->read_buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ if (vbihack) {
+ /* dirty, undocumented hack -- pass the frame counter
+ * within the last four bytes of each vbi data block.
+ * We need that one to maintain backward compatibility
+ * to all vbi decoding software out there ... */
+ fc = (unsigned int*)mem->vmalloc;
+ fc += (q->read_buf->size>>2) -1;
+ *fc = q->read_buf->field_count >> 1;
+ dprintk(1,"vbihack: %d\n",*fc);
+ }
+
+ /* copy stuff using the common method */
+ count = __videobuf_copy_to_user (q,data,count,nonblocking);
+
+ if ( (count==-EFAULT) && (0 == pos) )
+ return -EFAULT;
+
+ return count;
+}
+
+static struct videobuf_qtype_ops qops = {
+ .magic = MAGIC_QTYPE_OPS,
+
+ .alloc = __videobuf_alloc,
+ .iolock = __videobuf_iolock,
+ .sync = __videobuf_sync,
+ .mmap_free = __videobuf_mmap_free,
+ .mmap_mapper = __videobuf_mmap_mapper,
+ .copy_to_user = __videobuf_copy_to_user,
+ .copy_stream = __videobuf_copy_stream,
+};
+
+void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
+ struct videobuf_queue_ops *ops,
+ void *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+ unsigned int msize,
+ void *priv)
+{
+ videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
+ priv, &qops);
+}
+
+EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
+
+void *videobuf_to_vmalloc (struct videobuf_buffer *buf)
+{
+ struct videbuf_vmalloc_memory *mem=buf->priv;
+ BUG_ON (!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ return mem->vmalloc;
+}
+EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
+
+void videobuf_vmalloc_free (struct videobuf_buffer *buf)
+{
+ struct videbuf_vmalloc_memory *mem=buf->priv;
+ BUG_ON (!mem);
+
+ MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+
+ vfree(mem->vmalloc);
+ mem->vmalloc=NULL;
+
+ return;
+}
+EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index b876aca69c73..8d8e517b344f 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -54,15 +54,14 @@
* sysfs stuff
*/
-static ssize_t show_name(struct class_device *cd, char *buf)
+static ssize_t show_name(struct device *cd,
+ struct device_attribute *attr, char *buf)
{
struct video_device *vfd = container_of(cd, struct video_device,
- class_dev);
- return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
+ class_dev);
+ return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
}
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
struct video_device *video_device_alloc(void)
{
struct video_device *vfd;
@@ -76,7 +75,7 @@ void video_device_release(struct video_device *vfd)
kfree(vfd);
}
-static void video_release(struct class_device *cd)
+static void video_release(struct device *cd)
{
struct video_device *vfd = container_of(cd, struct video_device,
class_dev);
@@ -89,9 +88,15 @@ static void video_release(struct class_device *cd)
vfd->release(vfd);
}
+static struct device_attribute video_device_attrs[] = {
+ __ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR_NULL
+};
+
static struct class video_class = {
.name = VIDEO_NAME,
- .release = video_release,
+ .dev_attrs = video_device_attrs,
+ .dev_release = video_release,
};
/*
@@ -448,7 +453,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
if (cmd == VIDIOCGMBUF) {
struct video_mbuf *p=arg;
- memset(p,0,sizeof(p));
+ memset(p, 0, sizeof(*p));
if (!vfd->vidiocgmbuf)
return ret;
@@ -1753,22 +1758,16 @@ int video_register_device(struct video_device *vfd, int type, int nr)
/* sysfs class */
memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev));
if (vfd->dev)
- vfd->class_dev.dev = vfd->dev;
+ vfd->class_dev.parent = vfd->dev;
vfd->class_dev.class = &video_class;
vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
- sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base);
- ret = class_device_register(&vfd->class_dev);
+ sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base);
+ ret = device_register(&vfd->class_dev);
if (ret < 0) {
- printk(KERN_ERR "%s: class_device_register failed\n",
+ printk(KERN_ERR "%s: device_register failed\n",
__FUNCTION__);
goto fail_minor;
}
- ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name);
- if (ret < 0) {
- printk(KERN_ERR "%s: class_device_create_file 'name' failed\n",
- __FUNCTION__);
- goto fail_classdev;
- }
#if 1
/* needed until all drivers are fixed */
@@ -1779,8 +1778,6 @@ int video_register_device(struct video_device *vfd, int type, int nr)
#endif
return 0;
-fail_classdev:
- class_device_unregister(&vfd->class_dev);
fail_minor:
mutex_lock(&videodev_lock);
video_device[vfd->minor] = NULL;
@@ -1804,7 +1801,7 @@ void video_unregister_device(struct video_device *vfd)
panic("videodev: bad unregister");
video_device[vfd->minor]=NULL;
- class_device_unregister(&vfd->class_dev);
+ device_unregister(&vfd->class_dev);
mutex_unlock(&videodev_lock);
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 0c658b74f2c4..9a03dc82c6ca 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -28,7 +28,6 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/moduleparam.h>
#include <linux/time.h>
#include <linux/version.h>
@@ -2077,12 +2076,10 @@ static int vino_wait_for_frame(struct vino_channel_settings *vcs)
init_waitqueue_entry(&wait, current);
/* add ourselves into wait queue */
add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
- /* and set current state */
- set_current_state(TASK_INTERRUPTIBLE);
/* to ensure that schedule_timeout will return immediately
- * if VINO interrupt was triggred meanwhile */
- schedule_timeout(HZ / 10);
+ * if VINO interrupt was triggered meanwhile */
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
if (signal_pending(current))
err = -EINTR;
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 3ef4d0159c33..b532aa280a1b 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/random.h>
#include <linux/version.h>
+#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <linux/dma-mapping.h>
#ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -32,7 +33,7 @@
#include <linux/videodev.h>
#endif
#include <linux/interrupt.h>
-#include <media/video-buf.h>
+#include <media/videobuf-vmalloc.h>
#include <media/v4l2-common.h>
#include <linux/kthread.h>
#include <linux/highmem.h>
@@ -144,10 +145,6 @@ struct vivi_buffer {
struct videobuf_buffer vb;
struct vivi_fmt *fmt;
-
-#ifdef CONFIG_VIVI_SCATTER
- struct sg_to_addr *to_addr;
-#endif
};
struct vivi_dmaqueue {
@@ -168,12 +165,11 @@ static LIST_HEAD(vivi_devlist);
struct vivi_dev {
struct list_head vivi_devlist;
- struct semaphore lock;
+ struct mutex lock;
int users;
/* various device info */
- unsigned int resources;
struct video_device vfd;
struct vivi_dmaqueue vidq;
@@ -232,91 +228,25 @@ static u8 bars[8][3] = {
#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
#define TSTAMP_MIN_X 64
-#ifdef CONFIG_VIVI_SCATTER
-static void prep_to_addr(struct sg_to_addr to_addr[],
- struct videobuf_buffer *vb)
-{
- int i, pos=0;
-
- for (i=0;i<vb->dma.nr_pages;i++) {
- to_addr[i].sg=&vb->dma.sglist[i];
- to_addr[i].pos=pos;
- pos += vb->dma.sglist[i].length;
- }
-}
-
-static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
-{
- int p1=0,p2=pages-1,p3=pages/2;
-
- /* Sanity test */
- BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length);
-
- while (p1+1<p2) {
- if (pos < to_addr[p3].pos) {
- p2=p3;
- } else {
- p1=p3;
- }
- p3=(p1+p2)/2;
- }
- if (pos >= to_addr[p2].pos)
- p1=p2;
-
- return (p1);
-}
-#endif
-
-#ifdef CONFIG_VIVI_SCATTER
-static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
- int hmax, int line, char *timestr)
-#else
static void gen_line(char *basep,int inipos,int wmax,
- int hmax, int line, char *timestr)
-#endif
+ int hmax, int line, int count, char *timestr)
{
int w,i,j,pos=inipos,y;
char *p,*s;
u8 chr,r,g,b,color;
-#ifdef CONFIG_VIVI_SCATTER
- int pgpos,oldpg;
- char *basep;
- struct page *pg;
-
- unsigned long flags;
- spinlock_t spinlock;
-
- spin_lock_init(&spinlock);
-
- /* Get first addr pointed to pixel position */
- oldpg=get_addr_pos(pos,pages,to_addr);
- pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
- spin_lock_irqsave(&spinlock,flags);
- basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
-#endif
/* We will just duplicate the second pixel at the packet */
wmax/=2;
/* Generate a standard color bar pattern */
for (w=0;w<wmax;w++) {
- r=bars[w*7/wmax][0];
- g=bars[w*7/wmax][1];
- b=bars[w*7/wmax][2];
+ int colorpos=((w+count)*8/(wmax+1)) % 8;
+ r=bars[colorpos][0];
+ g=bars[colorpos][1];
+ b=bars[colorpos][2];
for (color=0;color<4;color++) {
-#ifdef CONFIG_VIVI_SCATTER
- pgpos=get_addr_pos(pos,pages,to_addr);
- if (pgpos!=oldpg) {
- pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT);
- kunmap_atomic(basep, KM_BOUNCE_READ);
- basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset;
- oldpg=pgpos;
- }
- p=basep+pos-to_addr[pgpos].pos;
-#else
p=basep+pos;
-#endif
switch (color) {
case 0:
@@ -361,23 +291,7 @@ static void gen_line(char *basep,int inipos,int wmax,
pos=inipos+j*2;
for (color=0;color<4;color++) {
-#ifdef CONFIG_VIVI_SCATTER
- pgpos=get_addr_pos(pos,pages,to_addr);
- if (pgpos!=oldpg) {
- pg=pfn_to_page(sg_dma_address(
- to_addr[pgpos].sg)
- >> PAGE_SHIFT);
- kunmap_atomic(basep,
- KM_BOUNCE_READ);
- basep= kmap_atomic(pg,
- KM_BOUNCE_READ)+
- to_addr[pgpos].sg->offset;
- oldpg=pgpos;
- }
- p=basep+pos-to_addr[pgpos].pos;
-#else
p=basep+pos;
-#endif
y=TO_Y(r,g,b);
@@ -402,12 +316,7 @@ static void gen_line(char *basep,int inipos,int wmax,
end:
-#ifdef CONFIG_VIVI_SCATTER
- kunmap_atomic(basep, KM_BOUNCE_READ);
- spin_unlock_irqrestore(&spinlock,flags);
-#else
return;
-#endif
}
static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
{
@@ -415,47 +324,27 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
int hmax = buf->vb.height;
int wmax = buf->vb.width;
struct timeval ts;
-#ifdef CONFIG_VIVI_SCATTER
- struct sg_to_addr *to_addr=buf->to_addr;
- struct videobuf_buffer *vb=&buf->vb;
-#else
- char *tmpbuf;
-#endif
+ char *tmpbuf = kmalloc(wmax*2,GFP_KERNEL);
+ void *vbuf=videobuf_to_vmalloc (&buf->vb);
+ /* FIXME: move to dev struct */
+ static int mv_count=0;
-#ifdef CONFIG_VIVI_SCATTER
- /* Test if DMA mapping is ready */
- if (!sg_dma_address(&vb->dma.sglist[0]))
+ if (!tmpbuf)
return;
- prep_to_addr(to_addr,vb);
-
- /* Check if there is enough memory */
- BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2);
-#else
- if (buf->vb.dma.varea) {
- tmpbuf=kmalloc (wmax*2, GFP_KERNEL);
- } else {
- tmpbuf=buf->vb.dma.vmalloc;
- }
-
-#endif
-
for (h=0;h<hmax;h++) {
-#ifdef CONFIG_VIVI_SCATTER
- gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr);
-#else
- if (buf->vb.dma.varea) {
- gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr);
- /* FIXME: replacing to __copy_to_user */
- if (copy_to_user(buf->vb.dma.varea+pos,tmpbuf,wmax*2)!=0)
- dprintk(2,"vivifill copy_to_user failed.\n");
- } else {
- gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr);
- }
-#endif
+ gen_line(tmpbuf,0,wmax,hmax,h,mv_count,
+ dev->timestr);
+ /* FIXME: replacing to __copy_to_user */
+ if (copy_to_user(vbuf+pos,tmpbuf,wmax*2)!=0)
+ dprintk(2,"vivifill copy_to_user failed.\n");
pos += wmax*2;
}
+ mv_count++;
+
+ kfree(tmpbuf);
+
/* Updates stream time */
dev->us+=jiffies_to_usecs(jiffies-dev->jiffies);
@@ -478,7 +367,7 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
dev->h,dev->m,dev->s,(dev->us+500)/1000);
dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr,
- (unsigned long)buf->vb.dma.varea,pos);
+ (unsigned long)tmpbuf,pos);
/* Advice that buffer was filled */
buf->vb.state = STATE_DONE;
@@ -618,7 +507,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
static int restart_video_queue(struct vivi_dmaqueue *dma_q)
{
struct vivi_buffer *buf, *prev;
- struct list_head *item;
dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q);
@@ -632,9 +520,7 @@ static int restart_video_queue(struct vivi_dmaqueue *dma_q)
// vivi_start_thread(dma_q);
/* cancel all outstanding capture / vbi requests */
- list_for_each(item,&dma_q->active) {
- buf = list_entry(item, struct vivi_buffer, vb.queue);
-
+ list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) {
list_del(&buf->vb.queue);
buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
@@ -706,8 +592,12 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
if (0 == *count)
*count = 32;
+
while (*size * *count > vid_limit * 1024 * 1024)
(*count)--;
+
+ dprintk(1,"%s, count=%d, size=%d\n",__FUNCTION__,*count, *size);
+
return 0;
}
@@ -718,15 +608,8 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
if (in_interrupt())
BUG();
-#ifdef CONFIG_VIVI_SCATTER
- /*FIXME: Maybe a spinlock is required here */
- kfree(buf->to_addr);
- buf->to_addr=NULL;
-#endif
-
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_unmap(vq, &buf->vb.dma);
- videobuf_dma_free(&buf->vb.dma);
+ videobuf_vmalloc_free(&buf->vb);
buf->vb.state = STATE_NEEDS_INIT;
}
@@ -740,7 +623,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb);
int rc, init_buffer = 0;
-// dprintk(1,"%s, field=%d\n",__FUNCTION__,field);
+ dprintk(1,"%s, field=%d\n",__FUNCTION__,field);
BUG_ON(NULL == fh->fmt);
if (fh->width < 48 || fh->width > norm_maxw() ||
@@ -768,12 +651,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
buf->vb.state = STATE_PREPARED;
-#ifdef CONFIG_VIVI_SCATTER
- if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) {
- rc=-ENOMEM;
- goto fail;
- }
-#endif
return 0;
fail:
@@ -838,88 +715,14 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb
free_buffer(vq,buf);
}
-#ifdef CONFIG_VIVI_SCATTER
-static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents,
- int direction)
-{
- int i;
-
- dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents);
- BUG_ON(direction == DMA_NONE);
-
- for (i = 0; i < nents; i++ ) {
- BUG_ON(!sg[i].page);
-
- sg_dma_address(&sg[i]) = page_to_phys(sg[i].page) + sg[i].offset;
- }
-
- return nents;
-}
-
-static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
- int direction)
-{
- dprintk(1,"%s\n",__FUNCTION__);
- return 0;
-}
-
-static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages,
- int direction)
-{
-// dprintk(1,"%s\n",__FUNCTION__);
-
-// flush_write_buffers();
- return 0;
-}
-#endif
-
static struct videobuf_queue_ops vivi_video_qops = {
.buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release = buffer_release,
-
- /* Non-pci handling routines */
-// .vb_map_sg = vivi_map_sg,
-// .vb_dma_sync_sg = vivi_dma_sync_sg,
-// .vb_unmap_sg = vivi_unmap_sg,
};
/* ------------------------------------------------------------------
- IOCTL handling
- ------------------------------------------------------------------*/
-
-
-static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
-{
- /* is it free? */
- down(&dev->lock);
- if (dev->resources) {
- /* no, someone else uses it */
- up(&dev->lock);
- return 0;
- }
- /* it's free, grab it */
- dev->resources =1;
- dprintk(1,"res: get\n");
- up(&dev->lock);
- return 1;
-}
-
-static int res_locked(struct vivi_dev *dev)
-{
- return (dev->resources);
-}
-
-static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
-{
- down(&dev->lock);
- dev->resources = 0;
- dprintk(1,"res: put\n");
- up(&dev->lock);
-}
-
-/* ------------------------------------------------------------------
IOCTL vidioc handling
------------------------------------------------------------------*/
static int vidioc_querycap (struct file *file, void *priv,
@@ -979,8 +782,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
field = f->fmt.pix.field;
if (field == V4L2_FIELD_ANY) {
-// field=V4L2_FIELD_INTERLACED;
- field=V4L2_FIELD_SEQ_TB;
+ field=V4L2_FIELD_INTERLACED;
} else if (V4L2_FIELD_INTERLACED != field) {
dprintk(1,"Field type invalid.\n");
return -EINVAL;
@@ -1058,57 +860,33 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
{
struct vivi_fh *fh=priv;
- struct videobuf_queue *q=&fh->vb_vidq;
- struct v4l2_requestbuffers req;
- unsigned int i;
- int ret;
-
- req.type = q->type;
- req.count = 8;
- req.memory = V4L2_MEMORY_MMAP;
- ret = videobuf_reqbufs(q,&req);
- if (ret < 0)
- return (ret);
- mbuf->frames = req.count;
- mbuf->size = 0;
- for (i = 0; i < mbuf->frames; i++) {
- mbuf->offsets[i] = q->bufs[i]->boff;
- mbuf->size += q->bufs[i]->bsize;
- }
- return (0);
+ return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8);
}
#endif
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct vivi_fh *fh=priv;
- struct vivi_dev *dev = fh->dev;
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (i != fh->type)
return -EINVAL;
- if (!res_get(dev,fh))
- return -EBUSY;
- return (videobuf_streamon(&fh->vb_vidq));
+ return videobuf_streamon(&fh->vb_vidq);
}
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct vivi_fh *fh=priv;
- struct vivi_dev *dev = fh->dev;
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (i != fh->type)
return -EINVAL;
- videobuf_streamoff(&fh->vb_vidq);
- res_free(dev,fh);
-
- return (0);
+ return videobuf_streamoff(&fh->vb_vidq);
}
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i)
@@ -1201,31 +979,25 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
static int vivi_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct vivi_dev *h,*dev = NULL;
+ struct vivi_dev *dev;
struct vivi_fh *fh;
- struct list_head *list;
- enum v4l2_buf_type type = 0;
int i;
printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor);
- list_for_each(list,&vivi_devlist) {
- h = list_entry(list, struct vivi_dev, vivi_devlist);
- if (h->vfd.minor == minor) {
- dev = h;
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- }
- }
- if (NULL == dev)
- return -ENODEV;
+ list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
+ if (dev->vfd.minor == minor)
+ goto found;
+ return -ENODEV;
+found:
/* If more than one user, mutex should be added */
dev->users++;
- dprintk(1,"open minor=%d type=%s users=%d\n",
- minor,v4l2_type_names[type],dev->users);
+ dprintk(1, "open minor=%d type=%s users=%d\n", minor,
+ v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
@@ -1260,19 +1032,11 @@ static int vivi_open(struct inode *inode, struct file *file)
sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
dev->h,dev->m,dev->s,(dev->us+500)/1000);
-#ifdef CONFIG_VIVI_SCATTER
- videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops,
+ videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
NULL, NULL,
fh->type,
V4L2_FIELD_INTERLACED,
sizeof(struct vivi_buffer),fh);
-#else
- videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops,
- NULL, NULL,
- fh->type,
- V4L2_FIELD_INTERLACED,
- sizeof(struct vivi_buffer),fh);
-#endif
return 0;
}
@@ -1283,9 +1047,7 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
struct vivi_fh *fh = file->private_data;
if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- if (res_locked(fh->dev))
- return -EBUSY;
- return videobuf_read_one(&fh->vb_vidq, data, count, ppos,
+ return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
}
return 0;
@@ -1295,31 +1057,14 @@ static unsigned int
vivi_poll(struct file *file, struct poll_table_struct *wait)
{
struct vivi_fh *fh = file->private_data;
- struct vivi_buffer *buf;
+ struct videobuf_queue *q = &fh->vb_vidq;
dprintk(1,"%s\n",__FUNCTION__);
if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
return POLLERR;
- if (res_get(fh->dev,fh)) {
- dprintk(1,"poll: mmap interface\n");
- /* streaming capture */
- if (list_empty(&fh->vb_vidq.stream))
- return POLLERR;
- buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream);
- } else {
- dprintk(1,"poll: read() interface\n");
- /* read() capture */
- buf = (struct vivi_buffer*)fh->vb_vidq.read_buf;
- if (NULL == buf)
- return POLLERR;
- }
- poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == STATE_DONE ||
- buf->vb.state == STATE_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
+ return videobuf_poll_stream(file, q, wait);
}
static int vivi_release(struct inode *inode, struct file *file)
@@ -1367,7 +1112,7 @@ static const struct file_operations vivi_fops = {
.read = vivi_read,
.poll = vivi_poll,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .mmap = vivi_mmap,
+ .mmap = vivi_mmap,
.llseek = no_llseek,
};
@@ -1423,7 +1168,7 @@ static int __init vivi_init(void)
init_waitqueue_head(&dev->vidq.wq);
/* initialize locks */
- init_MUTEX(&dev->lock);
+ mutex_init(&dev->lock);
dev->vidq.timeout.function = vivi_vid_timeout;
dev->vidq.timeout.data = (unsigned long)dev;
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c
new file mode 100644
index 000000000000..63002e0ac764
--- /dev/null
+++ b/drivers/media/video/vp27smpx.c
@@ -0,0 +1,212 @@
+/*
+ * vp27smpx - driver version 0.0.1
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com>
+ * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("vp27smpx driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static unsigned short normal_i2c[] = { 0xb6 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+
+struct vp27smpx_state {
+ int radio;
+ u32 audmode;
+};
+
+static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode)
+{
+ struct vp27smpx_state *state = i2c_get_clientdata(client);
+ u8 data[3] = { 0x00, 0x00, 0x04 };
+
+ switch (audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ data[1] = 0x01;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ data[1] = 0x02;
+ break;
+ }
+
+ if (i2c_master_send(client, data, sizeof(data)) != sizeof(data)) {
+ v4l_err(client, "%s: I/O error setting audmode\n", client->name);
+ }
+ else {
+ state->audmode = audmode;
+ }
+}
+
+static int vp27smpx_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ struct vp27smpx_state *state = i2c_get_clientdata(client);
+ struct v4l2_tuner *vt = arg;
+
+ switch (cmd) {
+ case AUDC_SET_RADIO:
+ state->radio = 1;
+ break;
+
+ case VIDIOC_S_STD:
+ state->radio = 0;
+ break;
+
+ case VIDIOC_S_TUNER:
+ if (!state->radio)
+ vp27smpx_set_audmode(client, vt->audmode);
+ break;
+
+ case VIDIOC_G_TUNER:
+ if (state->radio)
+ break;
+ vt->audmode = state->audmode;
+ vt->capability = V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+ vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+ break;
+
+ case VIDIOC_G_CHIP_IDENT:
+ return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_VP27SMPX, 0);
+
+ case VIDIOC_LOG_STATUS:
+ v4l_info(client, "Audio Mode: %u%s\n", state->audmode,
+ state->radio ? " (Radio)" : "");
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static struct i2c_driver i2c_driver;
+
+static int vp27smpx_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct vp27smpx_state *state;
+
+ /* Check if the adapter supports the needed features */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == 0)
+ return -ENOMEM;
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "vp27smpx");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ i2c_set_clientdata(client, state);
+
+ /* initialize vp27smpx */
+ vp27smpx_set_audmode(client, state->audmode);
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int vp27smpx_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, vp27smpx_attach);
+ return 0;
+}
+
+static int vp27smpx_detach(struct i2c_client *client)
+{
+ struct vp27smpx_state *state = i2c_get_clientdata(client);
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err) {
+ return err;
+ }
+ kfree(state);
+ kfree(client);
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "vp27smpx",
+ },
+ .id = I2C_DRIVERID_VP27SMPX,
+ .attach_adapter = vp27smpx_probe,
+ .detach_client = vp27smpx_detach,
+ .command = vp27smpx_command,
+};
+
+
+static int __init vp27smpx_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit vp27smpx_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(vp27smpx_init_module);
+module_exit(vp27smpx_cleanup_module);
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 8f31613b9903..5a1b5f5a7d46 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -42,7 +42,6 @@
#include <asm/page.h>
#include <asm/uaccess.h>
#include <linux/page-flags.h>
-#include <linux/moduleparam.h>
#include "w9968cf.h"
#include "w9968cf_decoder.h"
@@ -2680,7 +2679,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
/* This the only safe way to prevent race conditions with disconnect */
if (!down_read_trylock(&w9968cf_disconnect))
- return -ERESTARTSYS;
+ return -EAGAIN;
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index 8f6741a28a47..1bf4cbec6a87 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -321,12 +321,14 @@ static int wm8739_probe(struct i2c_adapter *adapter)
static int wm8739_detach(struct i2c_client *client)
{
+ struct wm8739_state *state = i2c_get_clientdata(client);
int err;
err = i2c_detach_client(client);
if (err)
return err;
+ kfree(state);
kfree(client);
return 0;
}
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 4df5d30d4d09..9f7e894ef962 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -222,12 +222,14 @@ static int wm8775_probe(struct i2c_adapter *adapter)
static int wm8775_detach(struct i2c_client *client)
{
+ struct wm8775_state *state = i2c_get_clientdata(client);
int err;
err = i2c_detach_client(client);
if (err) {
return err;
}
+ kfree(state);
kfree(client);
return 0;
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig
index 47cd93f9c7de..edb00293cd59 100644
--- a/drivers/media/video/zc0301/Kconfig
+++ b/drivers/media/video/zc0301/Kconfig
@@ -1,6 +1,6 @@
config USB_ZC0301
tristate "USB ZC0301[P] Image Processor and Control Chip support"
- depends on VIDEO_V4L1
+ depends on VIDEO_V4L2
---help---
Say Y here if you want support for cameras based on the ZC0301 or
ZC0301P Image Processors and Control Chips.
diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h
index 710f12eb9126..a2de50efa31a 100644
--- a/drivers/media/video/zc0301/zc0301.h
+++ b/drivers/media/video/zc0301/zc0301.h
@@ -36,6 +36,7 @@
#include <linux/rwsem.h>
#include <linux/stddef.h>
#include <linux/string.h>
+#include <linux/kref.h>
#include "zc0301_sensor.h"
@@ -98,7 +99,7 @@ struct zc0301_module_param {
u16 frame_timeout;
};
-static DECLARE_RWSEM(zc0301_disconnect);
+static DECLARE_RWSEM(zc0301_dev_lock);
struct zc0301_device {
struct video_device* v4ldev;
@@ -121,12 +122,14 @@ struct zc0301_device {
struct zc0301_module_param module_param;
+ struct kref kref;
enum zc0301_dev_state state;
u8 users;
- struct mutex dev_mutex, fileop_mutex;
+ struct completion probe;
+ struct mutex open_mutex, fileop_mutex;
spinlock_t queue_lock;
- wait_queue_head_t open, wait_frame, wait_stream;
+ wait_queue_head_t wait_open, wait_frame, wait_stream;
};
/*****************************************************************************/
@@ -156,8 +159,8 @@ do { \
else if ((level) == 2) \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
- dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+ __FILE__, __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -166,8 +169,8 @@ do { \
if ((level) == 1 || (level) == 2) \
pr_info("zc0301: " fmt "\n", ## args); \
else if ((level) == 3) \
- pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -183,8 +186,8 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+ __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index f1120551c70c..08a93c31c0a0 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -26,7 +26,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
-#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/device.h>
@@ -49,11 +48,11 @@
#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \
"Image Processor and Control Chip"
-#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia"
+#define ZC0301_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia"
#define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.07"
-#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 7)
+#define ZC0301_MODULE_VERSION "1:1.10"
+#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 10)
/*****************************************************************************/
@@ -573,7 +572,8 @@ static int zc0301_init(struct zc0301_device* cam)
int err = 0;
if (!(cam->state & DEV_INITIALIZED)) {
- init_waitqueue_head(&cam->open);
+ mutex_init(&cam->open_mutex);
+ init_waitqueue_head(&cam->wait_open);
qctrl = s->qctrl;
rect = &(s->cropcap.defrect);
cam->compression.quality = ZC0301_COMPRESSION_QUALITY;
@@ -634,59 +634,73 @@ static int zc0301_init(struct zc0301_device* cam)
return 0;
}
+/*****************************************************************************/
-static void zc0301_release_resources(struct zc0301_device* cam)
+static void zc0301_release_resources(struct kref *kref)
{
+ struct zc0301_device *cam = container_of(kref, struct zc0301_device,
+ kref);
DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
+ usb_put_dev(cam->usbdev);
kfree(cam->control_buffer);
+ kfree(cam);
}
-/*****************************************************************************/
static int zc0301_open(struct inode* inode, struct file* filp)
{
struct zc0301_device* cam;
int err = 0;
- /*
- This is the only safe way to prevent race conditions with
- disconnect
- */
- if (!down_read_trylock(&zc0301_disconnect))
- return -ERESTARTSYS;
+ if (!down_read_trylock(&zc0301_dev_lock))
+ return -EAGAIN;
cam = video_get_drvdata(video_devdata(filp));
- if (mutex_lock_interruptible(&cam->dev_mutex)) {
- up_read(&zc0301_disconnect);
+ if (wait_for_completion_interruptible(&cam->probe)) {
+ up_read(&zc0301_dev_lock);
+ return -ERESTARTSYS;
+ }
+
+ kref_get(&cam->kref);
+
+ if (mutex_lock_interruptible(&cam->open_mutex)) {
+ kref_put(&cam->kref, zc0301_release_resources);
+ up_read(&zc0301_dev_lock);
return -ERESTARTSYS;
}
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+ err = -ENODEV;
+ goto out;
+ }
+
if (cam->users) {
DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
err = -EWOULDBLOCK;
goto out;
}
- mutex_unlock(&cam->dev_mutex);
- err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
+ DBG(2, "A blocking open() has been requested. Wait for the "
+ "device to be released...");
+ up_read(&zc0301_dev_lock);
+ err = wait_event_interruptible_exclusive(cam->wait_open,
+ (cam->state & DEV_DISCONNECTED)
|| !cam->users);
- if (err) {
- up_read(&zc0301_disconnect);
- return err;
- }
+ down_read(&zc0301_dev_lock);
+ if (err)
+ goto out;
if (cam->state & DEV_DISCONNECTED) {
- up_read(&zc0301_disconnect);
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
- mutex_lock(&cam->dev_mutex);
}
-
if (cam->state & DEV_MISCONFIGURED) {
err = zc0301_init(cam);
if (err) {
@@ -711,36 +725,32 @@ static int zc0301_open(struct inode* inode, struct file* filp)
DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
out:
- mutex_unlock(&cam->dev_mutex);
- up_read(&zc0301_disconnect);
+ mutex_unlock(&cam->open_mutex);
+ if (err)
+ kref_put(&cam->kref, zc0301_release_resources);
+ up_read(&zc0301_dev_lock);
return err;
}
static int zc0301_release(struct inode* inode, struct file* filp)
{
- struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+ struct zc0301_device* cam;
- mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
+ down_write(&zc0301_dev_lock);
- zc0301_stop_transfer(cam);
+ cam = video_get_drvdata(video_devdata(filp));
+ zc0301_stop_transfer(cam);
zc0301_release_buffers(cam);
-
- if (cam->state & DEV_DISCONNECTED) {
- zc0301_release_resources(cam);
- usb_put_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
- kfree(cam);
- return 0;
- }
-
cam->users--;
- wake_up_interruptible_nr(&cam->open, 1);
+ wake_up_interruptible_nr(&cam->wait_open, 1);
DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
- mutex_unlock(&cam->dev_mutex);
+ kref_put(&cam->kref, zc0301_release_resources);
+
+ up_write(&zc0301_dev_lock);
return 0;
}
@@ -775,7 +785,7 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
DBG(3, "Close and open the device again to choose the read "
"method");
mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
+ return -EBUSY;
}
if (cam->io == IO_NONE) {
@@ -953,7 +963,12 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
return -EIO;
}
- if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -EACCES;
+ }
+
+ if (cam->io != IO_MMAP ||
size != PAGE_ALIGN(cam->frame[0].buf.length)) {
mutex_unlock(&cam->fileop_mutex);
return -EINVAL;
@@ -984,7 +999,6 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
vma->vm_ops = &zc0301_vm_ops;
vma->vm_private_data = &cam->frame[i];
-
zc0301_vm_open(vma);
mutex_unlock(&cam->fileop_mutex);
@@ -1211,7 +1225,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_CROP failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
if (!s->set_crop) {
@@ -1434,7 +1448,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_FMT failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -1544,14 +1558,14 @@ zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg)
if (cam->io == IO_READ) {
DBG(3, "Close and open the device again to choose the mmap "
"I/O method");
- return -EINVAL;
+ return -EBUSY;
}
for (i = 0; i < cam->nbuffers; i++)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_REQBUFS failed. "
"Previous buffers are still mapped.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -1699,9 +1713,6 @@ zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg)
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
return -EINVAL;
- if (list_empty(&cam->inqueue))
- return -EINVAL;
-
cam->stream = STREAM_ON;
DBG(3, "Stream on");
@@ -1949,8 +1960,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- mutex_init(&cam->dev_mutex);
-
DBG(2, "ZC0301[P] Image Processor and Control Chip detected "
"(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
@@ -1982,7 +1991,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->release = video_device_release;
video_set_drvdata(cam->v4ldev, cam);
- mutex_lock(&cam->dev_mutex);
+ init_completion(&cam->probe);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]);
@@ -1992,7 +2001,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(1, "Free /dev/videoX node not found");
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
goto fail;
}
@@ -2004,8 +2013,10 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
usb_set_intfdata(intf, cam);
+ kref_init(&cam->kref);
+ usb_get_dev(cam->usbdev);
- mutex_unlock(&cam->dev_mutex);
+ complete_all(&cam->probe);
return 0;
@@ -2022,40 +2033,31 @@ fail:
static void zc0301_usb_disconnect(struct usb_interface* intf)
{
- struct zc0301_device* cam = usb_get_intfdata(intf);
-
- if (!cam)
- return;
+ struct zc0301_device* cam;
- down_write(&zc0301_disconnect);
+ down_write(&zc0301_dev_lock);
- mutex_lock(&cam->dev_mutex);
+ cam = usb_get_intfdata(intf);
DBG(2, "Disconnecting %s...", cam->v4ldev->name);
- wake_up_interruptible_all(&cam->open);
-
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
- "memory deallocation are deferred on close.",
+ "memory deallocation are deferred.",
cam->v4ldev->minor);
cam->state |= DEV_MISCONFIGURED;
zc0301_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
wake_up_interruptible(&cam->wait_frame);
wake_up(&cam->wait_stream);
- usb_get_dev(cam->usbdev);
- } else {
+ } else
cam->state |= DEV_DISCONNECTED;
- zc0301_release_resources(cam);
- }
- mutex_unlock(&cam->dev_mutex);
+ wake_up_interruptible_all(&cam->wait_open);
- if (!cam->users)
- kfree(cam);
+ kref_put(&cam->kref, zc0301_release_resources);
- up_write(&zc0301_disconnect);
+ up_write(&zc0301_dev_lock);
}
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c
index 3efb92a0d0da..24b0dfba357e 100644
--- a/drivers/media/video/zc0301/zc0301_pas202bcb.c
+++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c
@@ -327,6 +327,7 @@ static struct zc0301_sensor pas202bcb = {
.height = 480,
.pixelformat = V4L2_PIX_FMT_JPEG,
.priv = 8,
+ .colorspace = V4L2_COLORSPACE_JPEG,
},
};
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c
index 5784b1d1491c..9519aba3612e 100644
--- a/drivers/media/video/zc0301/zc0301_pb0330.c
+++ b/drivers/media/video/zc0301/zc0301_pb0330.c
@@ -157,6 +157,7 @@ static struct zc0301_sensor pb0330 = {
.height = 480,
.pixelformat = V4L2_PIX_FMT_JPEG,
.priv = 8,
+ .colorspace = V4L2_COLORSPACE_JPEG,
},
};
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index 44e82cff9319..70fe6fc6cdd5 100644
--- a/drivers/media/video/zc0301/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -23,7 +23,7 @@
#define _ZC0301_SENSOR_H_
#include <linux/usb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
#include <linux/device.h>
#include <linux/stddef.h>
#include <linux/errno.h>
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
index 8fb4a3414e0a..937c4a616c0e 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran.h
@@ -240,11 +240,16 @@ enum gpcs_type {
struct zoran_format {
char *name;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
int palette;
+#endif
+#ifdef CONFIG_VIDEO_V4L2
__u32 fourcc;
int colorspace;
+#endif
int depth;
__u32 flags;
+ __u32 vfespfr;
};
/* flags */
#define ZORAN_FORMAT_COMPRESSED 1<<0
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 73162a3a61dd..48da36a15fca 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -64,15 +64,15 @@
extern const struct zoran_format zoran_formats[];
static int card[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(card, int, NULL, 0);
+module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "The type of card");
static int encoder[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(encoder, int, NULL, 0);
+module_param_array(encoder, int, NULL, 0444);
MODULE_PARM_DESC(encoder, "i2c TV encoder");
static int decoder[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(decoder, int, NULL, 0);
+module_param_array(decoder, int, NULL, 0444);
MODULE_PARM_DESC(decoder, "i2c TV decoder");
/*
@@ -84,29 +84,31 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder");
*/
static unsigned long vidmem = 0; /* Video memory base address */
-module_param(vidmem, ulong, 0);
+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 int default_input = 0; /* 0=Composite, 1=S-Video */
-module_param(default_input, int, 0);
+static unsigned int default_input = 0; /* 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, 0);
+module_param(default_mux, int, 0644);
MODULE_PARM_DESC(default_mux,
"Default 6 Eyes mux setting (Input selection)");
static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */
-module_param(default_norm, int, 0);
+module_param(default_norm, int, 0444);
MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
-static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
-module_param(video_nr, int, 0);
-MODULE_PARM_DESC(video_nr, "video device number");
+/* /dev/videoN, -1 for autodetect */
+static int video_nr[BUZ_MAX] = {-1, -1, -1, -1};
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
/*
Number and size of grab buffers for Video 4 Linux
@@ -127,28 +129,27 @@ MODULE_PARM_DESC(video_nr, "video device number");
int v4l_nbufs = 2;
int v4l_bufsize = 128; /* Everybody should be able to work with this setting */
-module_param(v4l_nbufs, int, 0);
+module_param(v4l_nbufs, int, 0644);
MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
-module_param(v4l_bufsize, int, 0);
+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, 0);
+module_param(jpg_nbufs, int, 0644);
MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
-module_param(jpg_bufsize, int, 0);
+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, 0);
+module_param(pass_through, int, 0644);
MODULE_PARM_DESC(pass_through,
"Pass TV signal through to TV-out when idling");
-static int debug = 1;
-int *zr_debug = &debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
+int zr36067_debug = 1;
+module_param_named(debug, zr36067_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-5)");
MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
MODULE_AUTHOR("Serguei Miridonov");
@@ -161,12 +162,6 @@ static struct pci_device_id zr36067_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
-#define dprintk(num, format, args...) \
- do { \
- if (*zr_debug >= num) \
- printk(format, ##args); \
- } while (0)
-
int zoran_num; /* number of Buzs in use */
struct zoran zoran[BUZ_MAX];
@@ -1075,7 +1070,7 @@ test_interrupts (struct zoran *zr)
if (timeout) {
dprintk(1, ": time spent: %d\n", 1 * HZ - timeout);
}
- if (*zr_debug > 1)
+ if (zr36067_debug > 1)
print_interrupts(zr);
btwrite(icr, ZR36057_ICR);
}
@@ -1121,7 +1116,14 @@ zr36057_init (struct zoran *zr)
zr->timing = zr->card.tvn[zr->norm];
}
- zr->input = default_input = (default_input ? 1 : 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;
/* Should the following be reset at every open ? */
zr->hue = 32768;
@@ -1153,12 +1155,12 @@ zr36057_init (struct zoran *zr)
*/
memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
- err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr);
+ err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
if (err < 0)
goto exit_unregister;
zoran_init_hardware(zr);
- if (*zr_debug > 2)
+ if (zr36067_debug > 2)
detect_guest_activity(zr);
test_interrupts(zr);
if (!pass_through) {
@@ -1620,7 +1622,7 @@ init_dc10_cards (void)
}
/* random nonsense */
- dprintk(5, KERN_DEBUG "Jotti is een held!\n");
+ dprintk(6, KERN_DEBUG "Jotti is een held!\n");
/* some mainboards might not do PCI-PCI data transfer well */
if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h
index ad997c30bee5..8444ca0a5f3f 100644
--- a/drivers/media/video/zoran_card.h
+++ b/drivers/media/video/zoran_card.h
@@ -30,6 +30,14 @@
#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 int zoran_num;
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index b0752767ee4f..68c7c505587e 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -52,6 +52,7 @@
#include "videocodec.h"
#include "zoran.h"
#include "zoran_device.h"
+#include "zoran_card.h"
#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \
ZR36057_ISR_GIRQ1 | \
@@ -59,14 +60,6 @@
extern const struct zoran_format zoran_formats[];
-extern int *zr_debug;
-
-#define dprintk(num, format, args...) \
- do { \
- if (*zr_debug >= num) \
- printk(format, ##args); \
- } while (0)
-
static int lml33dpath = 0; /* 1 will use digital path in capture
* mode instead of analog. It can be
* used for picture adjustments using
@@ -76,7 +69,7 @@ static int lml33dpath = 0; /* 1 will use digital path in capture
* load on Bt819 input, there will be
* some image imperfections */
-module_param(lml33dpath, bool, 0);
+module_param(lml33dpath, bool, 0644);
MODULE_PARM_DESC(lml33dpath,
"Use digital path capture mode (on LML33 cards)");
@@ -174,7 +167,7 @@ post_office_read (struct zoran *zr,
static void
dump_guests (struct zoran *zr)
{
- if (*zr_debug > 2) {
+ if (zr36067_debug > 2) {
int i, guest[8];
for (i = 1; i < 8; i++) { // Don't read jpeg codec here
@@ -429,8 +422,6 @@ zr36057_set_vfe (struct zoran *zr,
reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
reg |= (DispMode << ZR36057_VFESPFR_DispMode);
- if (format->palette != VIDEO_PALETTE_YUV422 && format->palette != VIDEO_PALETTE_YUYV)
- reg |= ZR36057_VFESPFR_LittleEndian;
/* 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 */
@@ -439,36 +430,6 @@ zr36057_set_vfe (struct zoran *zr,
if (zr->norm != VIDEO_MODE_NTSC)
reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang
reg |= ZR36057_VFESPFR_TopField;
- switch (format->palette) {
-
- case VIDEO_PALETTE_YUYV:
- case VIDEO_PALETTE_YUV422:
- reg |= ZR36057_VFESPFR_YUV422;
- break;
-
- case VIDEO_PALETTE_RGB555:
- reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif;
- break;
-
- case VIDEO_PALETTE_RGB565:
- reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif;
- break;
-
- case VIDEO_PALETTE_RGB24:
- reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24;
- break;
-
- case VIDEO_PALETTE_RGB32:
- reg |= ZR36057_VFESPFR_RGB888;
- break;
-
- default:
- dprintk(1,
- KERN_INFO "%s: set_vfe() - unknown color_fmt=%x\n",
- ZR_DEVNAME(zr), format->palette);
- return;
-
- }
if (HorDcm >= 48) {
reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */
} else if (HorDcm >= 32) {
@@ -476,6 +437,7 @@ zr36057_set_vfe (struct zoran *zr,
} else if (HorDcm >= 16) {
reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */
}
+ reg |= format->vfespfr;
btwrite(reg, ZR36057_VFESPFR);
/* display configuration */
@@ -651,11 +613,17 @@ zr36057_set_memgrab (struct zoran *zr,
int mode)
{
if (mode) {
- if (btread(ZR36057_VSSFGR) &
- (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab))
+ /* 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 or FrameGrab on!?\n",
+ "%s: zr36057_set_memgrab(1) with SnapShot on!?\n",
ZR_DEVNAME(zr));
/* switch on VSync interrupts */
@@ -672,11 +640,12 @@ zr36057_set_memgrab (struct zoran *zr,
zr->v4l_memgrab_active = 1;
} else {
- zr->v4l_memgrab_active = 0;
-
/* 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);
@@ -1295,7 +1264,7 @@ error_handler (struct zoran *zr,
zr->num_errors++;
/* Report error */
- if (*zr_debug > 1 && zr->num_errors <= 8) {
+ if (zr36067_debug > 1 && zr->num_errors <= 8) {
long frame;
frame =
zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
@@ -1555,7 +1524,7 @@ zoran_irq (int irq,
if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
- if (*zr_debug > 1 &&
+ if (zr36067_debug > 1 &&
(!zr->frame_num || zr->JPEG_error)) {
printk(KERN_INFO
"%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
@@ -1592,7 +1561,7 @@ zoran_irq (int irq,
zr->JPEG_missed;
}
- if (*zr_debug > 2 && zr->frame_num < 6) {
+ if (zr36067_debug > 2 && zr->frame_num < 6) {
int i;
printk("%s: seq=%ld stat_com:",
ZR_DEVNAME(zr), zr->jpg_seq_num);
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index cf0ed6cbb0e3..1c14fa2bd411 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -99,106 +99,106 @@
#include <asm/byteorder.h>
-const struct zoran_format zoran_formats[] = {
- {
- .name = "15-bit RGB",
- .palette = VIDEO_PALETTE_RGB555,
-#ifdef CONFIG_VIDEO_V4L2
-#ifdef __LITTLE_ENDIAN
- .fourcc = V4L2_PIX_FMT_RGB555,
+#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
+#define ZFMT(pal, fcc, cs) \
+ .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
+#elif defined(CONFIG_VIDEO_V4L2)
+#define ZFMT(pal, fcc, cs) \
+ .fourcc = (fcc), .colorspace = (cs)
#else
- .fourcc = V4L2_PIX_FMT_RGB555X,
-#endif
- .colorspace = V4L2_COLORSPACE_SRGB,
+#define ZFMT(pal, fcc, cs) \
+ .palette = (pal)
#endif
+
+const struct zoran_format zoran_formats[] = {
+ {
+ .name = "15-bit RGB LE",
+ ZFMT(VIDEO_PALETTE_RGB555,
+ V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB),
.depth = 15,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
+ ZR36057_VFESPFR_LittleEndian,
}, {
- .name = "16-bit RGB",
- .palette = VIDEO_PALETTE_RGB565,
-#ifdef CONFIG_VIDEO_V4L2
-#ifdef __LITTLE_ENDIAN
- .fourcc = V4L2_PIX_FMT_RGB565,
-#else
- .fourcc = V4L2_PIX_FMT_RGB565X,
-#endif
- .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+ .name = "15-bit RGB BE",
+ ZFMT(-1,
+ V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB),
+ .depth = 15,
+ .flags = ZORAN_FORMAT_CAPTURE |
+ ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
+ }, {
+ .name = "16-bit RGB LE",
+ ZFMT(VIDEO_PALETTE_RGB565,
+ V4L2_PIX_FMT_RGB565, 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",
+ ZFMT(-1,
+ V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE |
+ ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
}, {
.name = "24-bit RGB",
- .palette = VIDEO_PALETTE_RGB24,
-#ifdef CONFIG_VIDEO_V4L2
-#ifdef __LITTLE_ENDIAN
- .fourcc = V4L2_PIX_FMT_BGR24,
-#else
- .fourcc = V4L2_PIX_FMT_RGB24,
-#endif
- .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+ ZFMT(VIDEO_PALETTE_RGB24,
+ V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB),
.depth = 24,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
}, {
- .name = "32-bit RGB",
- .palette = VIDEO_PALETTE_RGB32,
-#ifdef CONFIG_VIDEO_V4L2
-#ifdef __LITTLE_ENDIAN
- .fourcc = V4L2_PIX_FMT_BGR32,
-#else
- .fourcc = V4L2_PIX_FMT_RGB32,
-#endif
- .colorspace = V4L2_COLORSPACE_SRGB,
-#endif
+ .name = "32-bit RGB LE",
+ ZFMT(VIDEO_PALETTE_RGB32,
+ V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB),
.depth = 32,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
+ }, {
+ .name = "32-bit RGB BE",
+ ZFMT(-1,
+ V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB),
+ .depth = 32,
+ .flags = ZORAN_FORMAT_CAPTURE |
+ ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_RGB888,
}, {
.name = "4:2:2, packed, YUYV",
- .palette = VIDEO_PALETTE_YUV422,
-#ifdef CONFIG_VIDEO_V4L2
- .fourcc = V4L2_PIX_FMT_YUYV,
- .colorspace = V4L2_COLORSPACE_SMPTE170M,
-#endif
+ ZFMT(VIDEO_PALETTE_YUV422,
+ V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M),
.depth = 16,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_YUV422,
+ }, {
+ .name = "4:2:2, packed, UYVY",
+ ZFMT(VIDEO_PALETTE_UYVY,
+ V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M),
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE |
+ ZORAN_FORMAT_OVERLAY,
+ .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
}, {
.name = "Hardware-encoded Motion-JPEG",
- .palette = -1,
-#ifdef CONFIG_VIDEO_V4L2
- .fourcc = V4L2_PIX_FMT_MJPEG,
- .colorspace = V4L2_COLORSPACE_SMPTE170M,
-#endif
+ ZFMT(-1,
+ V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M),
.depth = 0,
.flags = ZORAN_FORMAT_CAPTURE |
ZORAN_FORMAT_PLAYBACK |
ZORAN_FORMAT_COMPRESSED,
}
};
-static const int zoran_num_formats =
- (sizeof(zoran_formats) / sizeof(struct zoran_format));
+#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
-#if !defined(CONFIG_BIGPHYS_AREA)
-//#undef CONFIG_BIGPHYS_AREA
-#define BUZ_USE_HIMEM
-#endif
-
-#if defined(CONFIG_BIGPHYS_AREA)
-# include <linux/bigphysarea.h>
-#endif
-extern int *zr_debug;
-
-#define dprintk(num, format, args...) \
- do { \
- if (*zr_debug >= num) \
- printk(format, ##args); \
- } while (0)
extern int v4l_nbufs;
extern int v4l_bufsize;
@@ -207,8 +207,8 @@ extern int jpg_bufsize;
extern int pass_through;
static int lock_norm = 0; /* 1=Don't change TV standard (norm) */
-module_param(lock_norm, int, 0);
-MODULE_PARM_DESC(lock_norm, "Users can't change norm");
+module_param(lock_norm, int, 0644);
+MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
#ifdef CONFIG_VIDEO_V4L2
/* small helper function for calculating buffersizes for v4l2
@@ -250,7 +250,6 @@ static void jpg_fbuffer_free(struct file *file);
* Linux with the necessary memory left over).
*/
-#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)
static unsigned long
get_high_mem (unsigned long size)
{
@@ -314,7 +313,6 @@ get_high_mem (unsigned long size)
return hi_mem_ph;
}
-#endif
static int
v4l_fbuffer_alloc (struct file *file)
@@ -323,9 +321,7 @@ v4l_fbuffer_alloc (struct file *file)
struct zoran *zr = fh->zr;
int i, off;
unsigned char *mem;
-#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)
unsigned long pmem = 0;
-#endif
/* we might have old buffers lying around... */
if (fh->v4l_buffers.ready_to_be_freed) {
@@ -343,10 +339,7 @@ v4l_fbuffer_alloc (struct file *file)
if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
/* Use kmalloc */
- mem =
- (unsigned char *) kmalloc(fh->v4l_buffers.
- buffer_size,
- GFP_KERNEL);
+ mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
if (mem == 0) {
dprintk(1,
KERN_ERR
@@ -369,39 +362,6 @@ v4l_fbuffer_alloc (struct file *file)
ZR_DEVNAME(zr), i, (unsigned long) mem,
virt_to_bus(mem));
} else {
-#if defined(CONFIG_BIGPHYS_AREA)
- /* Use bigphysarea_alloc_pages */
-
- int n =
- (fh->v4l_buffers.buffer_size + PAGE_SIZE -
- 1) / PAGE_SIZE;
-
- mem =
- (unsigned char *) bigphysarea_alloc_pages(n, 0,
- GFP_KERNEL);
- if (mem == 0) {
- dprintk(1,
- KERN_ERR
- "%s: v4l_fbuffer_alloc() - bigphysarea_alloc_pages for V4L buf %d failed\n",
- ZR_DEVNAME(zr), i);
- v4l_fbuffer_free(file);
- return -ENOBUFS;
- }
- fh->v4l_buffers.buffer[i].fbuffer = mem;
- fh->v4l_buffers.buffer[i].fbuffer_phys =
- virt_to_phys(mem);
- fh->v4l_buffers.buffer[i].fbuffer_bus =
- virt_to_bus(mem);
- dprintk(4,
- KERN_INFO
- "%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)\n",
- ZR_DEVNAME(zr), i, (unsigned) mem,
- (unsigned) virt_to_bus(mem));
-
- /* Zero out the allocated memory */
- memset(fh->v4l_buffers.buffer[i].fbuffer, 0,
- fh->v4l_buffers.buffer_size);
-#elif defined(BUZ_USE_HIMEM)
/* Use high memory which has been left at boot time */
@@ -441,20 +401,6 @@ v4l_fbuffer_alloc (struct file *file)
fh->v4l_buffers.buffer[i].fbuffer_bus =
pmem + i * fh->v4l_buffers.buffer_size;
}
-#else
- /* No bigphysarea present, usage of high memory disabled,
- * but user wants buffers of more than MAX_KMALLOC_MEM */
- dprintk(1,
- KERN_ERR
- "%s: v4l_fbuffer_alloc() - no bigphysarea_patch present, usage of high memory disabled,\n",
- ZR_DEVNAME(zr));
- dprintk(1,
- KERN_ERR
- "%s: v4l_fbuffer_alloc() - sorry, could not allocate %d V4L buffers of size %d KB.\n",
- ZR_DEVNAME(zr), fh->v4l_buffers.num_buffers,
- fh->v4l_buffers.buffer_size >> 10);
- return -ENOBUFS;
-#endif
}
}
@@ -485,11 +431,6 @@ v4l_fbuffer_free (struct file *file)
ClearPageReserved(MAP_NR(mem + off));
kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
}
-#if defined(CONFIG_BIGPHYS_AREA)
- else
- bigphysarea_free_pages((void *) fh->v4l_buffers.
- buffer[i].fbuffer);
-#endif
fh->v4l_buffers.buffer[i].fbuffer = NULL;
}
@@ -831,13 +772,13 @@ v4l_grab (struct file *file,
struct zoran *zr = fh->zr;
int res = 0, i;
- for (i = 0; i < zoran_num_formats; i++) {
+ for (i = 0; i < NUM_FORMATS; i++) {
if (zoran_formats[i].palette == mp->format &&
zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&
!(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))
break;
}
- if (i == zoran_num_formats || zoran_formats[i].depth == 0) {
+ if (i == NUM_FORMATS || zoran_formats[i].depth == 0) {
dprintk(1,
KERN_ERR
"%s: v4l_grab() - wrong bytes-per-pixel format\n",
@@ -1154,12 +1095,10 @@ jpg_sync (struct file *file,
frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
/* buffer should now be in BUZ_STATE_DONE */
- if (*zr_debug > 0)
- if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
- dprintk(2,
- KERN_ERR
- "%s: jpg_sync() - internal state error\n",
- ZR_DEVNAME(zr));
+ if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
+ dprintk(2,
+ KERN_ERR "%s: jpg_sync() - internal state error\n",
+ ZR_DEVNAME(zr));
*bs = zr->jpg_buffers.buffer[frame].bs;
bs->frame = frame;
@@ -1236,10 +1175,14 @@ zoran_close_end_session (struct file *file)
/* v4l capture */
if (fh->v4l_buffers.active != ZORAN_FREE) {
+ long flags;
+
+ spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
zr->v4l_buffers.allocated = 0;
zr->v4l_buffers.active = fh->v4l_buffers.active =
ZORAN_FREE;
+ spin_unlock_irqrestore(&zr->spinlock, flags);
}
/* v4l buffers */
@@ -1433,7 +1376,7 @@ zoran_close (struct inode *inode,
/* disable interrupts */
btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
- if (*zr_debug > 1)
+ if (zr36067_debug > 1)
print_interrupts(zr);
/* Overlay off */
@@ -2170,7 +2113,7 @@ zoran_do_ioctl (struct inode *inode,
vpict->colour, vpict->contrast, vpict->depth,
vpict->palette);
- for (i = 0; i < zoran_num_formats; i++) {
+ for (i = 0; i < NUM_FORMATS; i++) {
const struct zoran_format *fmt = &zoran_formats[i];
if (fmt->palette != -1 &&
@@ -2179,7 +2122,7 @@ zoran_do_ioctl (struct inode *inode,
fmt->depth == vpict->depth)
break;
}
- if (i == zoran_num_formats) {
+ if (i == NUM_FORMATS) {
dprintk(1,
KERN_ERR
"%s: VIDIOCSPICT - Invalid palette %d\n",
@@ -2283,10 +2226,10 @@ zoran_do_ioctl (struct inode *inode,
ZR_DEVNAME(zr), vbuf->base, vbuf->width,
vbuf->height, vbuf->depth, vbuf->bytesperline);
- for (i = 0; i < zoran_num_formats; i++)
+ for (i = 0; i < NUM_FORMATS; i++)
if (zoran_formats[i].depth == vbuf->depth)
break;
- if (i == zoran_num_formats) {
+ if (i == NUM_FORMATS) {
dprintk(1,
KERN_ERR
"%s: VIDIOCSFBUF - invalid fbuf depth %d\n",
@@ -2735,14 +2678,14 @@ zoran_do_ioctl (struct inode *inode,
return -EINVAL;
}
- for (i = 0; i < zoran_num_formats; i++) {
+ for (i = 0; i < NUM_FORMATS; i++) {
if (zoran_formats[i].flags & flag)
num++;
if (num == fmt->index)
break;
}
if (fmt->index < 0 /* late, but not too late */ ||
- i == zoran_num_formats)
+ i == NUM_FORMATS)
return -EINVAL;
memset(fmt, 0, sizeof(*fmt));
@@ -2800,7 +2743,8 @@ zoran_do_ioctl (struct inode *inode,
fmt->fmt.pix.height =
fh->v4l_settings.height;
fmt->fmt.pix.sizeimage =
- fh->v4l_buffers.buffer_size;
+ fh->v4l_settings.bytesperline *
+ fh->v4l_settings.height;
fmt->fmt.pix.pixelformat =
fh->v4l_settings.format->fourcc;
fmt->fmt.pix.colorspace =
@@ -3004,11 +2948,11 @@ zoran_do_ioctl (struct inode *inode,
sfmtjpg_unlock_and_return:
mutex_unlock(&zr->resource_lock);
} else {
- for (i = 0; i < zoran_num_formats; i++)
+ for (i = 0; i < NUM_FORMATS; i++)
if (fmt->fmt.pix.pixelformat ==
zoran_formats[i].fourcc)
break;
- if (i == zoran_num_formats) {
+ if (i == NUM_FORMATS) {
dprintk(1,
KERN_ERR
"%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n",
@@ -3047,8 +2991,9 @@ zoran_do_ioctl (struct inode *inode,
/* tell the user the
* results/missing stuff */
- fmt->fmt.pix.sizeimage = fh->v4l_buffers.buffer_size /*zr->gbpl * zr->gheight */
- ;
+ fmt->fmt.pix.sizeimage =
+ fh->v4l_settings.height *
+ fh->v4l_settings.bytesperline;
if (BUZ_MAX_HEIGHT <
(fh->v4l_settings.height * 2))
fmt->fmt.pix.field =
@@ -3116,10 +3061,10 @@ zoran_do_ioctl (struct inode *inode,
fb->fmt.bytesperline, fb->fmt.pixelformat,
(char *) &printformat);
- for (i = 0; i < zoran_num_formats; i++)
+ for (i = 0; i < NUM_FORMATS; i++)
if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
break;
- if (i == zoran_num_formats) {
+ if (i == NUM_FORMATS) {
dprintk(1,
KERN_ERR
"%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
@@ -3248,7 +3193,7 @@ zoran_do_ioctl (struct inode *inode,
"%s: VIDIOC_QUERYBUF - index=%d, type=%d\n",
ZR_DEVNAME(zr), buf->index, buf->type);
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, sizeof(*buf));
buf->type = type;
buf->index = index;
@@ -3502,8 +3447,13 @@ zoran_do_ioctl (struct inode *inode,
goto strmoff_unlock_and_return;
/* unload capture */
- if (zr->v4l_memgrab_active)
+ if (zr->v4l_memgrab_active) {
+ long flags;
+
+ spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
+ spin_unlock_irqrestore(&zr->spinlock, flags);
+ }
for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
zr->v4l_buffers.buffer[i].state =
@@ -3767,11 +3717,11 @@ zoran_do_ioctl (struct inode *inode,
dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
ZR_DEVNAME(zr), (unsigned long long)*std);
- if (*std == V4L2_STD_PAL)
+ if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
norm = VIDEO_MODE_PAL;
- else if (*std == V4L2_STD_NTSC)
+ else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
norm = VIDEO_MODE_NTSC;
- else if (*std == V4L2_STD_SECAM)
+ else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
norm = VIDEO_MODE_SECAM;
else if (*std == V4L2_STD_ALL)
norm = VIDEO_MODE_AUTO;
@@ -4212,11 +4162,11 @@ zoran_do_ioctl (struct inode *inode,
V4L2_BUF_TYPE_VIDEO_CAPTURE) {
int i;
- for (i = 0; i < zoran_num_formats; i++)
+ for (i = 0; i < NUM_FORMATS; i++)
if (zoran_formats[i].fourcc ==
fmt->fmt.pix.pixelformat)
break;
- if (i == zoran_num_formats) {
+ if (i == NUM_FORMATS) {
res = -EINVAL;
goto tryfmt_unlock_and_return;
}
@@ -4276,8 +4226,8 @@ zoran_poll (struct file *file,
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
- wait_queue_head_t *queue = NULL;
int res = 0, frame;
+ unsigned long flags;
/* we should check whether buffers are ready to be synced on
* (w/o waits - O_NONBLOCK) here
@@ -4291,51 +4241,58 @@ zoran_poll (struct file *file,
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW:
- if (fh->v4l_buffers.active == ZORAN_FREE ||
- zr->v4l_pend_head == zr->v4l_pend_tail) {
- dprintk(1,
- "%s: zoran_poll() - no buffers queued\n",
- ZR_DEVNAME(zr));
- res = POLLNVAL;
- goto poll_unlock_and_return;
- }
- queue = &zr->v4l_capq;
- frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
- poll_wait(file, queue, wait);
- if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
+ 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), __FUNCTION__,
+ "FAL"[fh->v4l_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->v4l_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:
- if (fh->jpg_buffers.active == ZORAN_FREE ||
- zr->jpg_que_head == zr->jpg_que_tail) {
- dprintk(1,
- "%s: zoran_poll() - no buffers queued\n",
- ZR_DEVNAME(zr));
- res = POLLNVAL;
- goto poll_unlock_and_return;
- }
- queue = &zr->jpg_capq;
+ poll_wait(file, &zr->jpg_capq, wait);
frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
- poll_wait(file, queue, wait);
- if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
+
+ 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), __FUNCTION__,
+ "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+ "UPMD"[zr->jpg_buffers.buffer[frame].state],
+ zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+ if (fh->jpg_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: zoran_poll() - internal error, unknown map_mode=%d\n",
ZR_DEVNAME(zr), fh->map_mode);
res = POLLNVAL;
- goto poll_unlock_and_return;
}
-poll_unlock_and_return:
mutex_unlock(&zr->resource_lock);
return res;
@@ -4431,11 +4388,15 @@ zoran_vm_close (struct vm_area_struct *vma)
mutex_lock(&zr->resource_lock);
if (fh->v4l_buffers.active != ZORAN_FREE) {
+ long flags;
+
+ spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
zr->v4l_buffers.allocated = 0;
zr->v4l_buffers.active =
fh->v4l_buffers.active =
ZORAN_FREE;
+ spin_unlock_irqrestore(&zr->spinlock, flags);
}
//v4l_fbuffer_free(file);
fh->v4l_buffers.allocated = 0;
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index 446ae8d5c3df..328ed6e7ac6a 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -48,14 +48,7 @@
#include "videocodec.h"
#include "zoran.h"
#include "zoran_procfs.h"
-
-extern int *zr_debug;
-
-#define dprintk(num, format, args...) \
- do { \
- if (*zr_debug >= num) \
- printk(format, ##args); \
- } while (0)
+#include "zoran_card.h"
#ifdef CONFIG_PROC_FS
struct procfs_params_zr36067 {
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
index 62f77584fb85..dd084555da8f 100644
--- a/drivers/media/video/zr36016.c
+++ b/drivers/media/video/zr36016.c
@@ -38,11 +38,11 @@
#include<linux/videodev.h> */
/* I/O commands, error codes */
-#include<asm/io.h>
+#include <asm/io.h>
//#include<errno.h>
/* v4l API */
-#include<linux/videodev.h>
+#include <linux/videodev.h>
/* headerfile of this module */
#include"zr36016.h"
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index a6bbd125631c..9f622e00c479 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -38,14 +38,14 @@
#include<linux/videodev.h> */
/* I/O commands, error codes */
-#include<asm/io.h>
+#include <asm/io.h>
//#include<errno.h>
/* headerfile of this module */
-#include"zr36050.h"
+#include "zr36050.h"
/* codec io API */
-#include"videocodec.h"
+#include "videocodec.h"
/* it doesn't make sense to have more than 20 or so,
just to prevent some unwanted loops */
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
index 97c8f9b9dc12..1ef14fef08e6 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zr36060.c
@@ -38,14 +38,14 @@
#include<linux/videodev.h> */
/* I/O commands, error codes */
-#include<asm/io.h>
+#include <asm/io.h>
//#include<errno.h>
/* headerfile of this module */
-#include"zr36060.h"
+#include "zr36060.h"
/* codec io API */
-#include"videocodec.h"
+#include "videocodec.h"
/* it doesn't make sense to have more than 20 or so,
just to prevent some unwanted loops */
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index b5d3364c94c7..6f1892585cbb 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -92,6 +92,7 @@ static struct usb_device_id device_table[] = {
{USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 },
{USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 },
{USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 },
+ {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
{} /* Terminating entry */
};
@@ -792,6 +793,7 @@ static int zr364xx_probe(struct usb_interface *intf,
{
struct usb_device *udev = interface_to_usbdev(intf);
struct zr364xx_camera *cam = NULL;
+ int err;
DBG("probing...");
@@ -799,12 +801,11 @@ static int zr364xx_probe(struct usb_interface *intf,
info("model %04x:%04x detected", udev->descriptor.idVendor,
udev->descriptor.idProduct);
- if ((cam =
- kmalloc(sizeof(struct zr364xx_camera), GFP_KERNEL)) == NULL) {
+ cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
+ if (cam == NULL) {
info("cam: out of memory !");
- return -ENODEV;
+ return -ENOMEM;
}
- memset(cam, 0x00, sizeof(struct zr364xx_camera));
/* save the init method used by this camera */
cam->method = id->driver_info;
@@ -812,7 +813,7 @@ static int zr364xx_probe(struct usb_interface *intf,
if (cam->vdev == NULL) {
info("cam->vdev: out of memory !");
kfree(cam);
- return -ENODEV;
+ return -ENOMEM;
}
memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));
video_set_drvdata(cam->vdev, cam);
@@ -858,12 +859,13 @@ static int zr364xx_probe(struct usb_interface *intf,
cam->brightness = 64;
mutex_init(&cam->lock);
- if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
+ err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
+ if (err) {
info("video_register_device failed");
video_device_release(cam->vdev);
kfree(cam->buffer);
kfree(cam);
- return -ENODEV;
+ return err;
}
usb_set_intfdata(intf, cam);
@@ -905,7 +907,7 @@ static struct usb_driver zr364xx_driver = {
static int __init zr364xx_init(void)
{
int retval;
- retval = usb_register(&zr364xx_driver) < 0;
+ retval = usb_register(&zr364xx_driver);
if (retval)
info("usb_register failed!");
else