summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-06-09 11:55:06 +0200
committerJean-Francois Moine <moinejf@free.fr>2008-06-09 11:55:06 +0200
commita76f49b7ffe277c032fab5226bc092da0b324799 (patch)
tree47dcbd1db7c6c3f9493092a643c9ee5cfb578def
parent80fb482585b549df0669ef539d101369fae7a40a (diff)
parent18e4796addabb3886c9346e035ee30bb96bbcd74 (diff)
downloadmediapointer-dvb-s2-a76f49b7ffe277c032fab5226bc092da0b324799.tar.gz
mediapointer-dvb-s2-a76f49b7ffe277c032fab5226bc092da0b324799.tar.bz2
From: Jean-Francois Moine <moinejf@free.fr>
Update from main repository. Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
-rw-r--r--linux/Documentation/video4linux/CARDLIST.au08284
-rw-r--r--linux/Documentation/video4linux/CARDLIST.cx238854
-rw-r--r--linux/Documentation/video4linux/CARDLIST.cx882
-rw-r--r--linux/Documentation/video4linux/CARDLIST.em28xx6
-rw-r--r--linux/Documentation/video4linux/CARDLIST.saa71347
-rw-r--r--linux/Documentation/video4linux/cx18.txt36
-rwxr-xr-xlinux/Documentation/video4linux/extract_xc3028.pl46
-rw-r--r--linux/arch/arm/mach-pxa/devices.c26
-rw-r--r--linux/arch/arm/mach-pxa/pcm990-baseboard.c26
-rw-r--r--linux/drivers/media/Kconfig168
-rw-r--r--linux/drivers/media/Makefile7
-rw-r--r--linux/drivers/media/common/Makefile1
-rw-r--r--linux/drivers/media/common/ir-keymaps.c76
-rw-r--r--linux/drivers/media/common/saa7146_core.c21
-rw-r--r--linux/drivers/media/common/saa7146_fops.c2
-rw-r--r--linux/drivers/media/common/saa7146_i2c.c6
-rw-r--r--linux/drivers/media/common/tuners/Kconfig164
-rw-r--r--linux/drivers/media/common/tuners/Makefile26
-rw-r--r--linux/drivers/media/common/tuners/mt2060.c (renamed from linux/drivers/media/dvb/frontends/mt2060.c)0
-rw-r--r--linux/drivers/media/common/tuners/mt2060.h (renamed from linux/drivers/media/dvb/frontends/mt2060.h)6
-rw-r--r--linux/drivers/media/common/tuners/mt2060_priv.h (renamed from linux/drivers/media/dvb/frontends/mt2060_priv.h)0
-rw-r--r--linux/drivers/media/common/tuners/mt20xx.c (renamed from linux/drivers/media/video/mt20xx.c)0
-rw-r--r--linux/drivers/media/common/tuners/mt20xx.h (renamed from linux/drivers/media/video/mt20xx.h)4
-rw-r--r--linux/drivers/media/common/tuners/mt2131.c (renamed from linux/drivers/media/dvb/frontends/mt2131.c)14
-rw-r--r--linux/drivers/media/common/tuners/mt2131.h (renamed from linux/drivers/media/dvb/frontends/mt2131.h)6
-rw-r--r--linux/drivers/media/common/tuners/mt2131_priv.h (renamed from linux/drivers/media/dvb/frontends/mt2131_priv.h)0
-rw-r--r--linux/drivers/media/common/tuners/mt2266.c (renamed from linux/drivers/media/dvb/frontends/mt2266.c)0
-rw-r--r--linux/drivers/media/common/tuners/mt2266.h (renamed from linux/drivers/media/dvb/frontends/mt2266.h)6
-rw-r--r--linux/drivers/media/common/tuners/mxl5005s.c4112
-rw-r--r--linux/drivers/media/common/tuners/mxl5005s.h131
-rw-r--r--linux/drivers/media/common/tuners/qt1010.c (renamed from linux/drivers/media/dvb/frontends/qt1010.c)0
-rw-r--r--linux/drivers/media/common/tuners/qt1010.h (renamed from linux/drivers/media/dvb/frontends/qt1010.h)6
-rw-r--r--linux/drivers/media/common/tuners/qt1010_priv.h (renamed from linux/drivers/media/dvb/frontends/qt1010_priv.h)0
-rw-r--r--linux/drivers/media/common/tuners/tda18271-common.c (renamed from linux/drivers/media/dvb/frontends/tda18271-common.c)28
-rw-r--r--linux/drivers/media/common/tuners/tda18271-fe.c (renamed from linux/drivers/media/dvb/frontends/tda18271-fe.c)168
-rw-r--r--linux/drivers/media/common/tuners/tda18271-maps.c (renamed from linux/drivers/media/dvb/frontends/tda18271-tables.c)2
-rw-r--r--linux/drivers/media/common/tuners/tda18271-priv.h (renamed from linux/drivers/media/dvb/frontends/tda18271-priv.h)11
-rw-r--r--linux/drivers/media/common/tuners/tda18271.h (renamed from linux/drivers/media/dvb/frontends/tda18271.h)4
-rw-r--r--linux/drivers/media/common/tuners/tda827x.c (renamed from linux/drivers/media/dvb/frontends/tda827x.c)4
-rw-r--r--linux/drivers/media/common/tuners/tda827x.h (renamed from linux/drivers/media/dvb/frontends/tda827x.h)6
-rw-r--r--linux/drivers/media/common/tuners/tda8290.c (renamed from linux/drivers/media/video/tda8290.c)14
-rw-r--r--linux/drivers/media/common/tuners/tda8290.h (renamed from linux/drivers/media/video/tda8290.h)6
-rw-r--r--linux/drivers/media/common/tuners/tda9887.c (renamed from linux/drivers/media/video/tda9887.c)0
-rw-r--r--linux/drivers/media/common/tuners/tda9887.h (renamed from linux/drivers/media/video/tda9887.h)4
-rw-r--r--linux/drivers/media/common/tuners/tea5761.c (renamed from linux/drivers/media/video/tea5761.c)17
-rw-r--r--linux/drivers/media/common/tuners/tea5761.h (renamed from linux/drivers/media/video/tea5761.h)6
-rw-r--r--linux/drivers/media/common/tuners/tea5767.c (renamed from linux/drivers/media/video/tea5767.c)18
-rw-r--r--linux/drivers/media/common/tuners/tea5767.h (renamed from linux/drivers/media/video/tea5767.h)6
-rw-r--r--linux/drivers/media/common/tuners/tuner-i2c.h (renamed from linux/drivers/media/video/tuner-i2c.h)8
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.c (renamed from linux/drivers/media/video/tuner-simple.c)8
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.h (renamed from linux/drivers/media/video/tuner-simple.h)4
-rw-r--r--linux/drivers/media/common/tuners/tuner-types.c (renamed from linux/drivers/media/video/tuner-types.c)0
-rw-r--r--linux/drivers/media/common/tuners/tuner-xc2028-types.h (renamed from linux/drivers/media/video/tuner-xc2028-types.h)33
-rw-r--r--linux/drivers/media/common/tuners/tuner-xc2028.c (renamed from linux/drivers/media/video/tuner-xc2028.c)183
-rw-r--r--linux/drivers/media/common/tuners/tuner-xc2028.h (renamed from linux/drivers/media/video/tuner-xc2028.h)8
-rw-r--r--linux/drivers/media/common/tuners/xc5000.c (renamed from linux/drivers/media/dvb/frontends/xc5000.c)53
-rw-r--r--linux/drivers/media/common/tuners/xc5000.h (renamed from linux/drivers/media/dvb/frontends/xc5000.h)30
-rw-r--r--linux/drivers/media/common/tuners/xc5000_priv.h (renamed from linux/drivers/media/dvb/frontends/xc5000_priv.h)2
-rw-r--r--linux/drivers/media/dvb/Kconfig4
-rw-r--r--linux/drivers/media/dvb/b2c2/Kconfig4
-rw-r--r--linux/drivers/media/dvb/b2c2/Makefile2
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-dma.c4
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c52
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-sram.c28
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-usb.c2
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop.c8
-rw-r--r--linux/drivers/media/dvb/bt8xx/Kconfig3
-rw-r--r--linux/drivers/media/dvb/bt8xx/Makefile2
-rw-r--r--linux/drivers/media/dvb/bt8xx/dst.c4
-rw-r--r--linux/drivers/media/dvb/bt8xx/dst_ca.c10
-rw-r--r--linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c9
-rw-r--r--linux/drivers/media/dvb/cinergyT2/Kconfig2
-rw-r--r--linux/drivers/media/dvb/cinergyT2/cinergyT2.c55
-rw-r--r--linux/drivers/media/dvb/dvb-core/Kconfig34
-rw-r--r--linux/drivers/media/dvb/dvb-core/dmxdev.c77
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c64
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_demux.c4
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c32
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_net.c46
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c6
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h8
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.c45
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.h15
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig38
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Makefile5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/a800.c6
-rw-r--r--linux/drivers/media/dvb/dvb-usb/af9005.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/anysee.c558
-rw-r--r--linux/drivers/media/dvb/dvb-usb/anysee.h304
-rw-r--r--linux/drivers/media/dvb/dvb-usb/au6610.c89
-rw-r--r--linux/drivers/media/dvb/dvb-usb/au6610.h22
-rw-r--r--linux/drivers/media/dvb/dvb-usb/cxusb.c38
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_core.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_devices.c25
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dibusb-mb.c14
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dibusb-mc.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/digitv.c8
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dtt200u.c17
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h3
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c9
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c2
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h2
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c16
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb.h5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/gl861.c6
-rw-r--r--linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c4
-rw-r--r--linux/drivers/media/dvb/dvb-usb/gp8psk.c15
-rw-r--r--linux/drivers/media/dvb/dvb-usb/m920x.c41
-rw-r--r--linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/opera1.c8
-rw-r--r--linux/drivers/media/dvb/dvb-usb/ttusb2.c9
-rw-r--r--linux/drivers/media/dvb/dvb-usb/umt-010.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/vp702x-fe.c18
-rw-r--r--linux/drivers/media/dvb/dvb-usb/vp702x.c5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/vp7045.c6
-rw-r--r--linux/drivers/media/dvb/frontends/Kconfig162
-rw-r--r--linux/drivers/media/dvb/frontends/Makefile16
-rw-r--r--linux/drivers/media/dvb/frontends/au8522.c697
-rw-r--r--linux/drivers/media/dvb/frontends/au8522.h56
-rw-r--r--linux/drivers/media/dvb/frontends/bcm3510.c4
-rw-r--r--linux/drivers/media/dvb/frontends/bcm3510.h2
-rw-r--r--linux/drivers/media/dvb/frontends/bsbe1.h58
-rw-r--r--linux/drivers/media/dvb/frontends/bsru6.h2
-rw-r--r--linux/drivers/media/dvb/frontends/cx22700.c12
-rw-r--r--linux/drivers/media/dvb/frontends/cx22700.h2
-rw-r--r--linux/drivers/media/dvb/frontends/cx22702.c24
-rw-r--r--linux/drivers/media/dvb/frontends/cx22702.h2
-rw-r--r--linux/drivers/media/dvb/frontends/cx24110.c6
-rw-r--r--linux/drivers/media/dvb/frontends/cx24110.h2
-rw-r--r--linux/drivers/media/dvb/frontends/dib0070.h15
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000.h2
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000mc.h2
-rw-r--r--linux/drivers/media/dvb/frontends/dib7000p.c8
-rw-r--r--linux/drivers/media/dvb/frontends/dib7000p.h17
-rw-r--r--linux/drivers/media/dvb/frontends/drx397xD.c1583
-rw-r--r--linux/drivers/media/dvb/frontends/drx397xD.h130
-rw-r--r--linux/drivers/media/dvb/frontends/drx397xD_fw.h40
-rw-r--r--linux/drivers/media/dvb/frontends/dvb-pll.c47
-rw-r--r--linux/drivers/media/dvb/frontends/dvb-pll.h3
-rw-r--r--linux/drivers/media/dvb/frontends/isl6405.h2
-rw-r--r--linux/drivers/media/dvb/frontends/isl6421.h2
-rw-r--r--linux/drivers/media/dvb/frontends/itd1000.c408
-rw-r--r--linux/drivers/media/dvb/frontends/itd1000.h42
-rw-r--r--linux/drivers/media/dvb/frontends/itd1000_priv.h88
-rw-r--r--linux/drivers/media/dvb/frontends/l64781.c2
-rw-r--r--linux/drivers/media/dvb/frontends/l64781.h2
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt330x.c38
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt330x.h2
-rw-r--r--linux/drivers/media/dvb/frontends/lnbp21.h2
-rw-r--r--linux/drivers/media/dvb/frontends/mt312.c160
-rw-r--r--linux/drivers/media/dvb/frontends/mt312.h9
-rw-r--r--linux/drivers/media/dvb/frontends/mt312_priv.h5
-rw-r--r--linux/drivers/media/dvb/frontends/mt352.c8
-rw-r--r--linux/drivers/media/dvb/frontends/mt352.h2
-rw-r--r--linux/drivers/media/dvb/frontends/nxt200x.c26
-rw-r--r--linux/drivers/media/dvb/frontends/nxt200x.h2
-rw-r--r--linux/drivers/media/dvb/frontends/nxt6000.h2
-rw-r--r--linux/drivers/media/dvb/frontends/or51132.c16
-rw-r--r--linux/drivers/media/dvb/frontends/or51132.h2
-rw-r--r--linux/drivers/media/dvb/frontends/or51211.c6
-rw-r--r--linux/drivers/media/dvb/frontends/or51211.h2
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.c49
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.h2
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1411.c887
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1411.h90
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1420.c542
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1420.h64
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1420_priv.h380
-rw-r--r--linux/drivers/media/dvb/frontends/sp8870.c26
-rw-r--r--linux/drivers/media/dvb/frontends/sp8870.h2
-rw-r--r--linux/drivers/media/dvb/frontends/sp887x.c18
-rw-r--r--linux/drivers/media/dvb/frontends/sp887x.h2
-rw-r--r--linux/drivers/media/dvb/frontends/stv0297.c14
-rw-r--r--linux/drivers/media/dvb/frontends/stv0297.h2
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.c85
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.h13
-rw-r--r--linux/drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--linux/drivers/media/dvb/frontends/tda10023.c197
-rw-r--r--linux/drivers/media/dvb/frontends/tda1002x.h35
-rw-r--r--linux/drivers/media/dvb/frontends/tda10048.c846
-rw-r--r--linux/drivers/media/dvb/frontends/tda10048.h63
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.c56
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.h4
-rw-r--r--linux/drivers/media/dvb/frontends/tda10086.c145
-rw-r--r--linux/drivers/media/dvb/frontends/tda10086.h14
-rw-r--r--linux/drivers/media/dvb/frontends/tda8083.c4
-rw-r--r--linux/drivers/media/dvb/frontends/tda8083.h2
-rw-r--r--linux/drivers/media/dvb/frontends/tda826x.c23
-rw-r--r--linux/drivers/media/dvb/frontends/tda826x.h2
-rw-r--r--linux/drivers/media/dvb/frontends/tua6100.c2
-rw-r--r--linux/drivers/media/dvb/frontends/tua6100.h2
-rw-r--r--linux/drivers/media/dvb/frontends/ves1820.c4
-rw-r--r--linux/drivers/media/dvb/frontends/ves1820.h2
-rw-r--r--linux/drivers/media/dvb/frontends/ves1x93.c6
-rw-r--r--linux/drivers/media/dvb/frontends/ves1x93.h2
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.c6
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.h2
-rw-r--r--linux/drivers/media/dvb/pluto2/pluto2.c5
-rw-r--r--linux/drivers/media/dvb/ttpci/Kconfig3
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.c25
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.h2
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_av.c34
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_hw.c42
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_ir.c6
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110_v4l.c4
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-av.c28
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-ci.c4
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-core.c9
-rw-r--r--linux/drivers/media/dvb/ttpci/budget.c111
-rw-r--r--linux/drivers/media/dvb/ttpci/budget.h5
-rw-r--r--linux/drivers/media/dvb/ttpci/ttpci-eeprom.c2
-rw-r--r--linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c56
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/Kconfig3
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c137
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c14
-rw-r--r--linux/drivers/media/radio/radio-aimslab.c1
-rw-r--r--linux/drivers/media/radio/radio-si470x.c483
-rw-r--r--linux/drivers/media/radio/radio-typhoon.c40
-rw-r--r--linux/drivers/media/video/Kconfig69
-rw-r--r--linux/drivers/media/video/Makefile15
-rw-r--r--linux/drivers/media/video/adv7170.c2
-rw-r--r--linux/drivers/media/video/adv7175.c2
-rw-r--r--linux/drivers/media/video/au0828/Kconfig13
-rw-r--r--linux/drivers/media/video/au0828/Makefile9
-rw-r--r--linux/drivers/media/video/au0828/au0828-cards.c181
-rw-r--r--linux/drivers/media/video/au0828/au0828-cards.h25
-rw-r--r--linux/drivers/media/video/au0828/au0828-core.c262
-rw-r--r--linux/drivers/media/video/au0828/au0828-dvb.c393
-rw-r--r--linux/drivers/media/video/au0828/au0828-i2c.c384
-rw-r--r--linux/drivers/media/video/au0828/au0828-reg.h38
-rw-r--r--linux/drivers/media/video/au0828/au0828.h132
-rw-r--r--linux/drivers/media/video/bt819.c2
-rw-r--r--linux/drivers/media/video/bt856.c2
-rw-r--r--linux/drivers/media/video/bt8xx/Kconfig1
-rw-r--r--linux/drivers/media/video/bt8xx/Makefile1
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-cards.c5
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c49
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-risc.c8
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-vbi.c6
-rw-r--r--linux/drivers/media/video/bt8xx/bttvp.h8
-rw-r--r--linux/drivers/media/video/btcx-risc.c2
-rw-r--r--linux/drivers/media/video/btcx-risc.h4
-rw-r--r--linux/drivers/media/video/c-qcam.c7
-rw-r--r--linux/drivers/media/video/cafe_ccic.c18
-rw-r--r--linux/drivers/media/video/compat_ioctl32.c1
-rw-r--r--linux/drivers/media/video/cpia.h4
-rw-r--r--linux/drivers/media/video/cpia2/cpia2_core.c12
-rw-r--r--linux/drivers/media/video/cpia_usb.c2
-rw-r--r--linux/drivers/media/video/cs5345.c14
-rw-r--r--linux/drivers/media/video/cs53l32a.c19
-rw-r--r--linux/drivers/media/video/cx18/Kconfig23
-rw-r--r--linux/drivers/media/video/cx18/Makefile11
-rw-r--r--linux/drivers/media/video/cx18/cx18-audio.c73
-rw-r--r--linux/drivers/media/video/cx18/cx18-audio.h26
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-audio.c361
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.c888
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.h322
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-firmware.c120
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-vbi.c413
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.c281
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.h131
-rw-r--r--linux/drivers/media/video/cx18/cx18-controls.c306
-rw-r--r--linux/drivers/media/video/cx18/cx18-controls.h24
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.c962
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.h516
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.c286
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.h25
-rw-r--r--linux/drivers/media/video/cx18/cx18-fileops.c749
-rw-r--r--linux/drivers/media/video/cx18/cx18-fileops.h36
-rw-r--r--linux/drivers/media/video/cx18/cx18-firmware.c380
-rw-r--r--linux/drivers/media/video/cx18/cx18-firmware.h25
-rw-r--r--linux/drivers/media/video/cx18/cx18-gpio.c100
-rw-r--r--linux/drivers/media/video/cx18/cx18-gpio.h24
-rw-r--r--linux/drivers/media/video/cx18/cx18-i2c.c465
-rw-r--r--linux/drivers/media/video/cx18/cx18-i2c.h33
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.c878
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.h30
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.c181
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.h37
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.c372
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.h73
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.c272
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.h55
-rw-r--r--linux/drivers/media/video/cx18/cx18-scb.c121
-rw-r--r--linux/drivers/media/video/cx18/cx18-scb.h285
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.c603
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.h33
-rw-r--r--linux/drivers/media/video/cx18/cx18-vbi.c208
-rw-r--r--linux/drivers/media/video/cx18/cx18-vbi.h26
-rw-r--r--linux/drivers/media/video/cx18/cx18-version.h34
-rw-r--r--linux/drivers/media/video/cx18/cx18-video.c45
-rw-r--r--linux/drivers/media/video/cx18/cx18-video.h22
-rw-r--r--linux/drivers/media/video/cx18/cx23418.h458
-rw-r--r--linux/drivers/media/video/cx23885/Kconfig16
-rw-r--r--linux/drivers/media/video/cx23885/Makefile3
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-417.c1772
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-cards.c166
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-core.c314
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-dvb.c191
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-i2c.c44
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-video.c80
-rw-r--r--linux/drivers/media/video/cx23885/cx23885.h28
-rw-r--r--linux/drivers/media/video/cx25840/Kconfig1
-rw-r--r--linux/drivers/media/video/cx25840/cx25840-core.c22
-rw-r--r--linux/drivers/media/video/cx88/Kconfig7
-rw-r--r--linux/drivers/media/video/cx88/Makefile1
-rw-r--r--linux/drivers/media/video/cx88/cx88-alsa.c6
-rw-r--r--linux/drivers/media/video/cx88/cx88-blackbird.c30
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c68
-rw-r--r--linux/drivers/media/video/cx88/cx88-core.c12
-rw-r--r--linux/drivers/media/video/cx88/cx88-dvb.c298
-rw-r--r--linux/drivers/media/video/cx88/cx88-i2c.c31
-rw-r--r--linux/drivers/media/video/cx88/cx88-mpeg.c16
-rw-r--r--linux/drivers/media/video/cx88/cx88-tvaudio.c24
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c24
-rw-r--r--linux/drivers/media/video/dpc7146.c2
-rw-r--r--linux/drivers/media/video/em28xx/Kconfig13
-rw-r--r--linux/drivers/media/video/em28xx/Makefile2
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-audio.c2
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c269
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c848
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-dvb.c528
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-i2c.c154
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-input.c28
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-reg.h88
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c1147
-rw-r--r--linux/drivers/media/video/em28xx/em28xx.h324
-rw-r--r--linux/drivers/media/video/et61x251/et61x251.h6
-rw-r--r--linux/drivers/media/video/et61x251/et61x251_core.c2
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c24
-rw-r--r--linux/drivers/media/video/ivtv/Kconfig3
-rw-r--r--linux/drivers/media/video/ivtv/Makefile1
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-cards.c146
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-cards.h6
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-controls.c4
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.c60
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.h10
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-fileops.c12
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-gpio.c20
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-i2c.c29
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.c62
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.h6
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-irq.c12
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-mailbox.c11
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-queue.c14
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-streams.c50
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-streams.h2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-vbi.c3
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-version.h2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-yuv.c8
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-yuv.h2
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c90
-rw-r--r--linux/drivers/media/video/m52790.c16
-rw-r--r--linux/drivers/media/video/meye.c1367
-rw-r--r--linux/drivers/media/video/msp3400-driver.c28
-rw-r--r--linux/drivers/media/video/mt9m001.c19
-rw-r--r--linux/drivers/media/video/mt9v022.c19
-rw-r--r--linux/drivers/media/video/mxb.c5
-rw-r--r--linux/drivers/media/video/ov511.c3
-rw-r--r--linux/drivers/media/video/ov511.h2
-rw-r--r--linux/drivers/media/video/ovcamchip/ovcamchip_priv.h4
-rw-r--r--linux/drivers/media/video/pvrusb2/Kconfig50
-rw-r--r--linux/drivers/media/video/pvrusb2/Makefile7
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.c3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-context.c292
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-context.h13
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c5
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c7
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debug.h2
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c25
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c253
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h36
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c438
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-dvb.h45
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c10
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-encoder.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h49
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h9
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c690
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h17
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-io.c33
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-io.h13
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-main.c17
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-std.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-std.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c511
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-util.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c124
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h1
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2.h1
-rw-r--r--linux/drivers/media/video/pwc/pwc-if.c13
-rw-r--r--linux/drivers/media/video/pwc/pwc-v4l.c4
-rw-r--r--linux/drivers/media/video/pxa_camera.c480
-rw-r--r--linux/drivers/media/video/saa7110.c4
-rw-r--r--linux/drivers/media/video/saa7111.c2
-rw-r--r--linux/drivers/media/video/saa7114.c2
-rw-r--r--linux/drivers/media/video/saa7115.c51
-rw-r--r--linux/drivers/media/video/saa7127.c16
-rw-r--r--linux/drivers/media/video/saa7134/Kconfig5
-rw-r--r--linux/drivers/media/video/saa7134/Makefile1
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-alsa.c4
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c336
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c6
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-dvb.c159
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-empress.c19
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-i2c.c44
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-input.c14
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-reg.h1
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-tvaudio.c24
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-video.c48
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h1
-rw-r--r--linux/drivers/media/video/saa717x.c1547
-rw-r--r--linux/drivers/media/video/saa7185.c2
-rw-r--r--linux/drivers/media/video/se401.c6
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102.h6
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_core.c2
-rw-r--r--linux/drivers/media/video/soc_camera.c28
-rw-r--r--linux/drivers/media/video/stk-webcam.c27
-rw-r--r--linux/drivers/media/video/stv680.c2
-rw-r--r--linux/drivers/media/video/tcm825x.c22
-rw-r--r--linux/drivers/media/video/tcm825x.h1
-rw-r--r--linux/drivers/media/video/tda9840.c6
-rw-r--r--linux/drivers/media/video/tea6415c.c6
-rw-r--r--linux/drivers/media/video/tea6420.c6
-rw-r--r--linux/drivers/media/video/tlv320aic23b.c15
-rw-r--r--linux/drivers/media/video/tuner-core.c292
-rw-r--r--linux/drivers/media/video/tvaudio.c21
-rw-r--r--linux/drivers/media/video/tveeprom.c10
-rw-r--r--linux/drivers/media/video/tvp5150.c4
-rw-r--r--linux/drivers/media/video/upd64031a.c15
-rw-r--r--linux/drivers/media/video/upd64083.c15
-rw-r--r--linux/drivers/media/video/usbvideo/ibmcam.c62
-rw-r--r--linux/drivers/media/video/usbvideo/konicawc.c2
-rw-r--r--linux/drivers/media/video/usbvideo/quickcam_messenger.c4
-rw-r--r--linux/drivers/media/video/usbvideo/usbvideo.c140
-rw-r--r--linux/drivers/media/video/usbvideo/vicam.c8
-rw-r--r--linux/drivers/media/video/usbvision/Makefile1
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-video.c18
-rw-r--r--linux/drivers/media/video/v4l2-common.c7
-rw-r--r--linux/drivers/media/video/videobuf-core.c75
-rw-r--r--linux/drivers/media/video/videobuf-dma-sg.c19
-rw-r--r--linux/drivers/media/video/videobuf-dvb.c16
-rw-r--r--linux/drivers/media/video/videobuf-vmalloc.c208
-rw-r--r--linux/drivers/media/video/videocodec.c113
-rw-r--r--linux/drivers/media/video/videodev.c367
-rw-r--r--linux/drivers/media/video/vino.c2
-rw-r--r--linux/drivers/media/video/vivi.c46
-rw-r--r--linux/drivers/media/video/vp27smpx.c17
-rw-r--r--linux/drivers/media/video/w9966.c2
-rw-r--r--linux/drivers/media/video/w9968cf.h6
-rw-r--r--linux/drivers/media/video/wm8739.c14
-rw-r--r--linux/drivers/media/video/wm8775.c14
-rw-r--r--linux/drivers/media/video/zc0301/zc0301.h6
-rw-r--r--linux/drivers/media/video/zc0301/zc0301_core.c2
-rw-r--r--linux/drivers/media/video/zoran.h20
-rw-r--r--linux/drivers/media/video/zoran_device.c4
-rw-r--r--linux/drivers/media/video/zoran_driver.c36
-rw-r--r--linux/drivers/media/video/zoran_procfs.c7
-rw-r--r--linux/drivers/media/video/zr364xx.c18
-rw-r--r--linux/include/asm-arm/arch-pxa/pxa-regs.h606
-rw-r--r--linux/include/linux/i2c-id.h4
-rw-r--r--linux/include/linux/videodev2.h16
-rw-r--r--linux/include/media/cx25840.h6
-rw-r--r--linux/include/media/ir-common.h1
-rw-r--r--linux/include/media/v4l2-chip-ident.h1
-rw-r--r--linux/include/media/v4l2-common.h4
-rw-r--r--linux/include/media/v4l2-dev.h78
-rw-r--r--linux/include/media/v4l2-i2c-drv-legacy.h18
-rw-r--r--linux/include/media/v4l2-i2c-drv.h18
-rw-r--r--linux/include/media/videobuf-core.h24
-rw-r--r--linux/include/media/videobuf-dma-sg.h3
-rw-r--r--linux/include/media/videobuf-dvb.h3
-rw-r--r--linux/include/media/videobuf-vmalloc.h4
-rwxr-xr-xmailimport5
-rw-r--r--v4l/compat.h74
-rw-r--r--v4l/obsolete.txt18
-rwxr-xr-xv4l/scripts/au0828.pl48
-rwxr-xr-xv4l/scripts/cardlist7
-rwxr-xr-xv4l/scripts/checkpatch.pl750
-rwxr-xr-xv4l/scripts/hghead.pl2
-rw-r--r--v4l/versions.txt6
-rw-r--r--v4l2-apps/util/Makefile11
-rw-r--r--v4l2-apps/util/cx18-ctl.c496
-rw-r--r--v4l2-apps/util/ivtv-ctl.c687
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp111
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp3
506 files changed, 38831 insertions, 7648 deletions
diff --git a/linux/Documentation/video4linux/CARDLIST.au0828 b/linux/Documentation/video4linux/CARDLIST.au0828
new file mode 100644
index 000000000..aaae36031
--- /dev/null
+++ b/linux/Documentation/video4linux/CARDLIST.au0828
@@ -0,0 +1,4 @@
+ 0 -> Unknown board (au0828)
+ 1 -> Hauppauge HVR950Q (au0828) [2040:7200]
+ 2 -> Hauppauge HVR850 (au0828) [2040:7240]
+ 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620]
diff --git a/linux/Documentation/video4linux/CARDLIST.cx23885 b/linux/Documentation/video4linux/CARDLIST.cx23885
index 0924e6e14..f0e613ba5 100644
--- a/linux/Documentation/video4linux/CARDLIST.cx23885
+++ b/linux/Documentation/video4linux/CARDLIST.cx23885
@@ -5,3 +5,7 @@
4 -> DViCO FusionHDTV5 Express [18ac:d500]
5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797]
6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717]
+ 7 -> Hauppauge WinTV-HVR1200 [0070:71d1,0070:71d3]
+ 8 -> Hauppauge WinTV-HVR1700 [0070:8101]
+ 9 -> Hauppauge WinTV-HVR1400 [0070:8010]
+ 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618]
diff --git a/linux/Documentation/video4linux/CARDLIST.cx88 b/linux/Documentation/video4linux/CARDLIST.cx88
index 543957346..7cf5685d3 100644
--- a/linux/Documentation/video4linux/CARDLIST.cx88
+++ b/linux/Documentation/video4linux/CARDLIST.cx88
@@ -60,7 +60,7 @@
59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530]
60 -> Pinnacle Hybrid PCTV [12ab:1788]
61 -> Winfast TV2000 XP Global [107d:6f18]
- 62 -> PowerColor Real Angel 330 [14f1:ea3d]
+ 62 -> PowerColor RA330 [14f1:ea3d]
63 -> Geniatech X8000-MT DVBT [14f1:8852]
64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30]
65 -> DViCO FusionHDTV 7 Gold [18ac:d610]
diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx
index f40e09296..c7e23942c 100644
--- a/linux/Documentation/video4linux/CARDLIST.em28xx
+++ b/linux/Documentation/video4linux/CARDLIST.em28xx
@@ -8,10 +8,12 @@
7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
- 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500,2040:6502]
+ 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
15 -> V-Gear PocketTV (em2800)
- 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513]
+ 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f]
+ 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
+ 18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134
index fe925b335..67937df1e 100644
--- a/linux/Documentation/video4linux/CARDLIST.saa7134
+++ b/linux/Documentation/video4linux/CARDLIST.saa7134
@@ -25,8 +25,8 @@
24 -> KNC One TV-Station DVR [1894:a006]
25 -> ASUS TV-FM 7133 [1043:4843]
26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b]
- 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
- 28 -> Manli MuchTV M-TV001/Behold TV 401
+ 27 -> Manli MuchTV M-TV002
+ 28 -> Manli MuchTV M-TV001
29 -> Nagase Sangyo TransGear 3000TV [1461:050c]
30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4]
31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
@@ -128,7 +128,7 @@
127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
-130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
+130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193,5ace:6191]
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
132 -> Genius TVGO AM11MCE
133 -> NXP Snake DVB-S reference design
@@ -140,3 +140,4 @@
139 -> Compro VideoMate T750 [185b:c900]
140 -> Avermedia DVB-S Pro A700 [1461:a7a1]
141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2]
+142 -> Beholder BeholdTV H6 [5ace:6290]
diff --git a/linux/Documentation/video4linux/cx18.txt b/linux/Documentation/video4linux/cx18.txt
new file mode 100644
index 000000000..6842c2628
--- /dev/null
+++ b/linux/Documentation/video4linux/cx18.txt
@@ -0,0 +1,36 @@
+Some notes regarding the cx18 driver for the Conexant CX23418 MPEG
+encoder chip:
+
+1) The only hardware currently supported is the Hauppauge HVR-1600
+ card and the Compro VideoMate H900 (note that this card only
+ supports analog input, it has no digital tuner!).
+
+2) Some people have problems getting the i2c bus to work. Cause unknown.
+ The symptom is that the eeprom cannot be read and the card is
+ unusable.
+
+3) The audio from the analog tuner is mono only. Probably caused by
+ incorrect audio register information in the datasheet. We are
+ waiting for updated information from Conexant.
+
+4) VBI (raw or sliced) has not yet been implemented.
+
+5) MPEG indexing is not yet implemented.
+
+6) The driver is still a bit rough around the edges, this should
+ improve over time.
+
+
+Firmware:
+
+The firmware needs to be extracted from the Windows Hauppauge HVR-1600
+driver, available here:
+
+http://hauppauge.lightpath.net/software/install_cd/hauppauge_cd_3.4d1.zip
+
+Unzip, then copy the following files to the firmware directory
+and rename them as follows:
+
+Drivers/Driver18/hcw18apu.rom -> v4l-cx23418-apu.fw
+Drivers/Driver18/hcw18enc.rom -> v4l-cx23418-cpu.fw
+Drivers/Driver18/hcw18mlC.rom -> v4l-cx23418-dig.fw
diff --git a/linux/Documentation/video4linux/extract_xc3028.pl b/linux/Documentation/video4linux/extract_xc3028.pl
index cced8ac5c..2cb816047 100755
--- a/linux/Documentation/video4linux/extract_xc3028.pl
+++ b/linux/Documentation/video4linux/extract_xc3028.pl
@@ -686,11 +686,11 @@ sub main_firmware($$$$)
write_hunk(812664, 192);
#
- # Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
+ # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192
#
- write_le32(0x60000000); # Type
- write_le64(0x00000000, 0x00002000); # ID
+ write_le32(0x6002b004); # Type
+ write_le64(0x00000000, 0x0000b700); # ID
write_le16(4500); # IF
write_le32(192); # Size
write_hunk(807672, 192);
@@ -706,10 +706,10 @@ sub main_firmware($$$$)
write_hunk(807864, 192);
#
- # Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
+ # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192
#
- write_le32(0x62000100); # Type
+ write_le32(0x620003e0); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4760); # IF
write_le32(192); # Size
@@ -726,30 +726,30 @@ sub main_firmware($$$$)
write_hunk(811512, 192);
#
- # Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
+ # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192
#
- write_le32(0x62000080); # Type
+ write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5260); # IF
write_le32(192); # Size
write_hunk(810552, 192);
#
- # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+ # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192
#
write_le32(0x60008000); # Type
- write_le64(0x00000008, 0x00000007); # ID
+ write_le64(0x0000000f, 0x00000007); # ID
write_le16(5320); # IF
write_le32(192); # Size
write_hunk(810744, 192);
#
- # Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
+ # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192
#
- write_le32(0x64000200); # Type
+ write_le32(0x65000380); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5400); # IF
write_le32(192); # Size
@@ -766,50 +766,50 @@ sub main_firmware($$$$)
write_hunk(809592, 192);
#
- # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
+ # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192
#
write_le32(0x60000000); # Type
- write_le64(0x00000002, 0x00000007); # ID
+ write_le64(0x00000003, 0x00000007); # ID
write_le16(5640); # IF
write_le32(192); # Size
write_hunk(808440, 192);
#
- # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
+ # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192
#
write_le32(0x60000000); # Type
- write_le64(0x00000008, 0x00000007); # ID
+ write_le64(0x0000000c, 0x00000007); # ID
write_le16(5740); # IF
write_le32(192); # Size
write_hunk(808632, 192);
#
- # Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
+ # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192
#
- write_le32(0x61000080); # Type
+ write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5900); # IF
write_le32(192); # Size
write_hunk(810360, 192);
#
- # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
+ # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192
#
write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x00000010); # ID
+ write_le64(0x0000000c, 0x04c000f0); # ID
write_le16(6000); # IF
write_le32(192); # Size
write_hunk(808824, 192);
#
- # Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
+ # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192
#
- write_le32(0x68000060); # Type
+ write_le32(0x68050060); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(6200); # IF
write_le32(192); # Size
@@ -846,11 +846,11 @@ sub main_firmware($$$$)
write_hunk(809208, 192);
#
- # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
+ # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192
#
write_le32(0x60008000); # Type
- write_le64(0x00000000, 0x04000000); # ID
+ write_le64(0x0000000c, 0x044000e0); # ID
write_le16(6500); # IF
write_le32(192); # Size
write_hunk(811128, 192);
diff --git a/linux/arch/arm/mach-pxa/devices.c b/linux/arch/arm/mach-pxa/devices.c
index 3838aabdf..d6c05b6ea 100644
--- a/linux/arch/arm/mach-pxa/devices.c
+++ b/linux/arch/arm/mach-pxa/devices.c
@@ -11,6 +11,7 @@
#include <asm/arch/irda.h>
#include <asm/arch/i2c.h>
#include <asm/arch/ohci.h>
+#include <asm/arch/pxa27x_keypad.h>
#include <asm/arch/camera.h>
#include "devices.h"
@@ -397,6 +398,31 @@ struct platform_device pxa25x_device_assp = {
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+static struct resource pxa27x_resource_keypad[] = {
+ [0] = {
+ .start = 0x41500000,
+ .end = 0x4150004c,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_KEYPAD,
+ .end = IRQ_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pxa27x_device_keypad = {
+ .name = "pxa27x-keypad",
+ .id = -1,
+ .resource = pxa27x_resource_keypad,
+ .num_resources = ARRAY_SIZE(pxa27x_resource_keypad),
+};
+
+void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
+{
+ pxa_register_device(&pxa27x_device_keypad, info);
+}
+
static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);
static struct resource pxa27x_resource_ohci[] = {
diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c
index 07ac050f2..49d951db0 100644
--- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -32,6 +32,7 @@
#include <asm/arch/camera.h>
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pcm990_baseboard.h>
@@ -270,16 +271,16 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
static int pcm990_pxacamera_init(struct device *dev)
{
- pxa_gpio_mode(GPIO98_CIF_DD0_MD);
- pxa_gpio_mode(GPIO105_CIF_DD1_MD);
- pxa_gpio_mode(GPIO104_CIF_DD2_MD);
- pxa_gpio_mode(GPIO103_CIF_DD3_MD);
- pxa_gpio_mode(GPIO95_CIF_DD4_MD);
- pxa_gpio_mode(GPIO94_CIF_DD5_MD);
- pxa_gpio_mode(GPIO93_CIF_DD6_MD);
- pxa_gpio_mode(GPIO108_CIF_DD7_MD);
- pxa_gpio_mode(GPIO107_CIF_DD8_MD);
- pxa_gpio_mode(GPIO106_CIF_DD9_MD);
+ pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
+ pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
+ pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
+ pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
+ pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
+ pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
+ pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
+ pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
+ pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
+ pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
pxa_gpio_mode(GPIO43_CIF_FV_MD);
@@ -319,16 +320,13 @@ static struct soc_camera_link iclink[] = {
static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
{
/* Must initialize before the camera(s) */
- I2C_BOARD_INFO("pca953x", 0x41),
- .type = "pca9536",
+ I2C_BOARD_INFO("pca9536", 0x41),
.platform_data = &pca9536_data,
}, {
I2C_BOARD_INFO("mt9v022", 0x48),
- .type = "mt9v022",
.platform_data = &iclink[0], /* With extender */
}, {
I2C_BOARD_INFO("mt9m001", 0x5d),
- .type = "mt9m001",
.platform_data = &iclink[0], /* With extender */
},
};
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig
index 1f7244cff..7a7803b5d 100644
--- a/linux/drivers/media/Kconfig
+++ b/linux/drivers/media/Kconfig
@@ -5,16 +5,20 @@
menu "Multimedia devices"
depends on HAS_IOMEM
+comment "Multimedia core support"
+
+#
+# V4L core and enabled API's
+#
+
config VIDEO_DEV
tristate "Video For Linux"
---help---
- Support for audio/video capture and overlay devices and FM radio
- cards. The exact capabilities of each device vary.
+ V4L core support for video capture and overlay devices, webcams and
+ AM/FM radio cards.
This kernel includes support for the new Video for Linux Two API,
- (V4L2) as well as the original system. Drivers and applications
- need to be rewritten to use V4L2, but drivers for popular cards
- and applications for most video capture functions already exist.
+ (V4L2).
Additional info and docs are available on the web at
<http://linuxtv.org>
@@ -30,14 +34,17 @@ config VIDEO_V4L2_COMMON
depends on (I2C || I2C=n) && VIDEO_DEV
default (I2C || I2C=n) && VIDEO_DEV
-config VIDEO_V4L1
+config VIDEO_ALLOW_V4L1
bool "Enable Video For Linux API 1 (DEPRECATED)"
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
default VIDEO_DEV && VIDEO_V4L2_COMMON
select VIDEO_V4L1_COMPAT
---help---
- Enables a compatibility API used by most V4L2 devices to allow
- its usage with legacy applications that supports only V4L1 api.
+ Enables drivers based on the legacy V4L1 API.
+
+ This api were developed to be used at Kernel 2.2 and 2.4, but
+ lacks support for several video standards. There are several
+ drivers at kernel that still depends on it.
If you are unsure as to whether this is required, answer Y.
@@ -46,9 +53,8 @@ config VIDEO_V4L1_COMPAT
depends on VIDEO_DEV
default VIDEO_DEV
---help---
- This api were developed to be used at Kernel 2.2 and 2.4, but
- lacks support for several video standards. There are several
- drivers at kernel that still depends on it.
+ Enables a compatibility API used by most V4L2 devices to allow
+ its usage with legacy applications that supports only V4L1 api.
Documentation for the original API is included in the file
<Documentation/video4linux/API.html>.
@@ -58,130 +64,56 @@ config VIDEO_V4L1_COMPAT
If you are unsure as to whether this is required, answer Y.
-config VIDEO_V4L2
- bool
- depends on VIDEO_DEV && VIDEO_V4L2_COMMON
- default VIDEO_DEV && VIDEO_V4L2_COMMON
-
-source "drivers/media/video/Kconfig"
-
-source "drivers/media/radio/Kconfig"
-
-source "drivers/media/dvb/Kconfig"
-
-source "drivers/media/common/Kconfig"
+#
+# DVB Core
+#
-config VIDEO_TUNER
- tristate
- depends on I2C
- select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE
- 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
- select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE
-
-menuconfig VIDEO_TUNER_CUSTOMIZE
- bool "Customize analog tuner modules to build"
- depends on VIDEO_TUNER
+config DVB_CORE
+ tristate "DVB for Linux"
+ depends on NET && INET
+ select CRC32
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
+ DVB core utility functions for device handling, software fallbacks etc.
-config TUNER_XC2028
- tristate "XCeive xc2028/xc3028 tuners"
- depends on I2C && FW_LOADER
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for the xc2028/xc3028 tuners.
+ Enable this if you own a DVB/ATSC adapter and want to use it or if
+ you compile Linux for a digital SetTopBox.
-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/8295 + 8275(a)/18271 tuner combo"
- depends on I2C
- select DVB_TDA827X
- select DVB_TDA18271
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for Philips TDA8290+8275(a) tuner.
+ Say Y when you have a DVB or an ATSC card and want to use it.
-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.
+ API specs and user tools are available from <http://www.linuxtv.org/>.
-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.
+ Please report problems regarding this support to the LinuxDVB
+ mailing list.
-config TUNER_SIMPLE
- tristate "Simple tuner support"
- depends on I2C
- select TUNER_TDA9887
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for various simple tuners.
+ If unsure say N.
-config TUNER_TDA9887
- tristate "TDA 9885/6/7 analog IF demodulator"
- depends on I2C
- default m if VIDEO_TUNER_CUSTOMIZE
- help
- Say Y here to include support for Philips TDA9885/6/7
- analog IF demodulator.
+config VIDEO_MEDIA
+ tristate
+ default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV)
-endif # VIDEO_TUNER_CUSTOMIZE
+comment "Multimedia drivers"
-config VIDEOBUF_GEN
- tristate
+source "drivers/media/common/Kconfig"
-config VIDEOBUF_DMA_SG
- depends on HAS_DMA
- select VIDEOBUF_GEN
- tristate
+#
+# Tuner drivers for DVB and V4L
+#
-config VIDEOBUF_VMALLOC
- select VIDEOBUF_GEN
- tristate
+source "drivers/media/common/tuners/Kconfig"
-config VIDEOBUF_DVB
- tristate
- select VIDEOBUF_GEN
- select VIDEOBUF_DMA_SG
+#
+# Video/Radio/Hybrid adapters
+#
-config VIDEO_BTCX
- tristate
+source "drivers/media/video/Kconfig"
-config VIDEO_IR_I2C
- tristate
+source "drivers/media/radio/Kconfig"
-config VIDEO_IR
- tristate
- depends on INPUT
- select VIDEO_IR_I2C if I2C
+#
+# DVB adapters
+#
-config VIDEO_TVEEPROM
- tristate
- depends on I2C
+source "drivers/media/dvb/Kconfig"
config DAB
boolean "DAB adapters"
diff --git a/linux/drivers/media/Makefile b/linux/drivers/media/Makefile
index 7b8bb6949..09a829d8a 100644
--- a/linux/drivers/media/Makefile
+++ b/linux/drivers/media/Makefile
@@ -2,10 +2,7 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := common/
-obj-y += video/
+obj-y += common/ video/
+
obj-$(CONFIG_VIDEO_DEV) += radio/
obj-$(CONFIG_DVB_CORE) += dvb/
-ifeq ($(CONFIG_DVB_CORE),)
- obj-$(CONFIG_VIDEO_TUNER) += dvb/frontends/
-endif
diff --git a/linux/drivers/media/common/Makefile b/linux/drivers/media/common/Makefile
index 8e7448230..351b98b9b 100644
--- a/linux/drivers/media/common/Makefile
+++ b/linux/drivers/media/common/Makefile
@@ -2,6 +2,7 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o
saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
ir-common-objs := ir-functions.o ir-keymaps.o
+obj-y += tuners/
obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
obj-$(CONFIG_VIDEO_IR) += ir-common.o
diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c
index 4e5db8cd5..e750bfee1 100644
--- a/linux/drivers/media/common/ir-keymaps.c
+++ b/linux/drivers/media/common/ir-keymaps.c
@@ -772,7 +772,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
[ 0x12 ] = KEY_CHANNELUP, // Channel +
[ 0x13 ] = KEY_CHANNELDOWN, // Channel -
[ 0x06 ] = KEY_AGAIN, // Recall
- [ 0x10 ] = KEY_ENTER, // Enter
+ [ 0x10 ] = KEY_ENTER, // Enter
+
+ [ 0x19 ] = KEY_BACK, // Rewind ( <<< )
+ [ 0x1f ] = KEY_FORWARD, // Forward ( >>> )
+ [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button)
};
EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
@@ -2089,6 +2093,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_behold);
+/* Beholder Intl. Ltd. 2008
+ * Dmitry Belimov d.belimov@google.com
+ * Keytable is used by BeholdTV Columbus
+ * The "ascii-art picture" below (in comments, first row
+ * is the keycode in hex, and subsequent row(s) shows
+ * the button labels (several variants when appropriate)
+ * helps to descide which keycodes to assign to the buttons.
+ */
+IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
+
+ /* 0x13 0x11 0x1C 0x12 *
+ * Mute Source TV/FM Power *
+ * */
+
+ [0x13] = KEY_MUTE,
+ [0x11] = KEY_PROPS,
+ [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */
+ [0x12] = KEY_POWER,
+
+ /* 0x01 0x02 0x03 0x0D *
+ * 1 2 3 Stereo *
+ * *
+ * 0x04 0x05 0x06 0x19 *
+ * 4 5 6 Snapshot *
+ * *
+ * 0x07 0x08 0x09 0x10 *
+ * 7 8 9 Zoom *
+ * */
+ [0x01] = KEY_1,
+ [0x02] = KEY_2,
+ [0x03] = KEY_3,
+ [0x0D] = KEY_SETUP, /* Setup key */
+ [0x04] = KEY_4,
+ [0x05] = KEY_5,
+ [0x06] = KEY_6,
+ [0x19] = KEY_BOOKMARKS, /* Snapshot key */
+ [0x07] = KEY_7,
+ [0x08] = KEY_8,
+ [0x09] = KEY_9,
+ [0x10] = KEY_ZOOM,
+
+ /* 0x0A 0x00 0x0B 0x0C *
+ * RECALL 0 ChannelUp VolumeUp *
+ * */
+ [0x0A] = KEY_AGAIN,
+ [0x00] = KEY_0,
+ [0x0B] = KEY_CHANNELUP,
+ [0x0C] = KEY_VOLUMEUP,
+
+ /* 0x1B 0x1D 0x15 0x18 *
+ * Timeshift Record ChannelDown VolumeDown *
+ * */
+
+ [0x1B] = KEY_REWIND,
+ [0x1D] = KEY_RECORD,
+ [0x15] = KEY_CHANNELDOWN,
+ [0x18] = KEY_VOLUMEDOWN,
+
+ /* 0x0E 0x1E 0x0F 0x1A *
+ * Stop Pause Previouse Next *
+ * */
+
+ [0x0E] = KEY_STOP,
+ [0x1E] = KEY_PAUSE,
+ [0x0F] = KEY_PREVIOUS,
+ [0x1A] = KEY_NEXT,
+
+};
+EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
+
/*
* Remote control for the Genius TVGO A11MCE
* Adrian Pardini <pardo.bsso@gmail.com>
diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c
index c24723a67..973989dd4 100644
--- a/linux/drivers/media/common/saa7146_core.c
+++ b/linux/drivers/media/common/saa7146_core.c
@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
if (err) {
printk(KERN_ERR "%s: %s timed out while waiting for "
"registers getting programmed\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
saa7146_read(dev, MC2);
if (err) {
DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __FUNCTION__));
+ "completion\n", dev->name, __func__));
return -ETIMEDOUT;
}
msleep(1);
@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
if (!loops--) {
printk(KERN_ERR "%s: %s timed out while waiting for "
"registers getting programmed\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -ETIMEDOUT;
}
udelay(1);
@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
saa7146_read(dev, MC2);
if (!loops--) {
DEB_S(("%s: %s timed out while waiting for transfer "
- "completion\n", dev->name, __FUNCTION__));
+ "completion\n", dev->name, __func__));
return -ETIMEDOUT;
}
udelay(5);
@@ -310,25 +310,22 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
return IRQ_NONE;
}
- if( NULL != (dev->ext)) {
- if( 0 != (dev->ext->irq_mask & isr )) {
- if( NULL != dev->ext->irq_func ) {
+ if (dev->ext) {
+ if (dev->ext->irq_mask & isr) {
+ if (dev->ext->irq_func)
dev->ext->irq_func(dev, &isr);
- }
isr &= ~dev->ext->irq_mask;
}
}
if (0 != (isr & (MASK_27))) {
DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
- if( NULL != dev->vv_data && NULL != dev->vv_callback) {
+ if (dev->vv_data && dev->vv_callback)
dev->vv_callback(dev,isr);
- }
isr &= ~MASK_27;
}
if (0 != (isr & (MASK_28))) {
- if( NULL != dev->vv_data && NULL != dev->vv_callback) {
+ if (dev->vv_data && dev->vv_callback)
dev->vv_callback(dev,isr);
- }
isr &= ~MASK_28;
}
if (0 != (isr & (MASK_16|MASK_17))) {
diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c
index fee81488f..ac035cbcf 100644
--- a/linux/drivers/media/common/saa7146_fops.c
+++ b/linux/drivers/media/common/saa7146_fops.c
@@ -273,7 +273,7 @@ static int fops_open(struct inode *inode, struct file *file)
result = 0;
out:
- if( fh != NULL && result != 0 ) {
+ if (fh && result != 0) {
kfree(fh);
file->private_data = NULL;
}
diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c
index 40527fa6c..a2447ff60 100644
--- a/linux/drivers/media/common/saa7146_i2c.c
+++ b/linux/drivers/media/common/saa7146_i2c.c
@@ -204,7 +204,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
return -ERESTARTSYS;
printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -EIO;
}
status = saa7146_read(dev, I2C_STATUS);
@@ -222,7 +222,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
}
if (time_after(jiffies,timeout)) {
printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -EIO;
}
}
@@ -239,7 +239,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
* (no answer from nonexisistant device...)
*/
printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
- dev->name, __FUNCTION__);
+ dev->name, __func__);
return -EIO;
}
if (++trial < 50 && short_delay)
diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig
new file mode 100644
index 000000000..85482960d
--- /dev/null
+++ b/linux/drivers/media/common/tuners/Kconfig
@@ -0,0 +1,164 @@
+config MEDIA_ATTACH
+ bool "Load and attach frontend and tuner driver modules as needed"
+ depends on VIDEO_MEDIA
+ depends on MODULES
+ help
+ Remove the static dependency of DVB card drivers on all
+ frontend modules for all possible card variants. Instead,
+ allow the card drivers to only load the frontend modules
+ they require.
+
+ Also, tuner module will automatically load a tuner driver
+ when needed, for analog mode.
+
+ This saves several KBytes of memory.
+
+ Note: You will need module-init-tools v3.2 or later for this feature.
+
+ If unsure say Y.
+
+config MEDIA_TUNER
+ tristate
+ default VIDEO_MEDIA && I2C
+ depends on VIDEO_MEDIA && I2C
+ select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
+ select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
+ select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
+ select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+ select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE
+
+menuconfig MEDIA_TUNER_CUSTOMIZE
+ bool "Customize analog and hybrid tuner modules to build"
+ depends on MEDIA_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/DVB devices which cannot be tuned due to lack of
+ driver support
+
+ If unsure say N.
+
+if MEDIA_TUNER_CUSTOMIZE
+
+config MEDIA_TUNER_SIMPLE
+ tristate "Simple tuner support"
+ depends on VIDEO_MEDIA && I2C
+ select MEDIA_TUNER_TDA9887
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for various simple tuners.
+
+config MEDIA_TUNER_TDA8290
+ tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
+ depends on VIDEO_MEDIA && I2C
+ select MEDIA_TUNER_TDA827X
+ select MEDIA_TUNER_TDA18271
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for Philips TDA8290+8275(a) tuner.
+
+config MEDIA_TUNER_TDA827X
+ tristate "Philips TDA827X silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-T silicon tuner module. Say Y when you want to support this tuner.
+
+config MEDIA_TUNER_TDA18271
+ tristate "NXP TDA18271 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A silicon tuner module. Say Y when you want to support this tuner.
+
+config MEDIA_TUNER_TDA9887
+ tristate "TDA 9885/6/7 analog IF demodulator"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for Philips TDA9885/6/7
+ analog IF demodulator.
+
+config MEDIA_TUNER_TEA5761
+ tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
+ depends on VIDEO_MEDIA && I2C
+ depends on EXPERIMENTAL
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the Philips TEA5761 radio tuner.
+
+config MEDIA_TUNER_TEA5767
+ tristate "TEA 5767 radio tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the Philips TEA5767 radio tuner.
+
+config MEDIA_TUNER_MT20XX
+ tristate "Microtune 2032 / 2050 tuners"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the MT2032 / MT2050 tuner.
+
+config MEDIA_TUNER_MT2060
+ tristate "Microtune MT2060 silicon IF tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon IF tuner MT2060 from Microtune.
+
+config MEDIA_TUNER_MT2266
+ tristate "Microtune MT2266 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon baseband tuner MT2266 from Microtune.
+
+config MEDIA_TUNER_MT2131
+ tristate "Microtune MT2131 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon baseband tuner MT2131 from Microtune.
+
+config MEDIA_TUNER_QT1010
+ tristate "Quantek QT1010 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon tuner QT1010 from Quantek.
+
+config MEDIA_TUNER_XC2028
+ tristate "XCeive xc2028/xc3028 tuners"
+ depends on VIDEO_MEDIA && I2C
+ depends on HOTPLUG
+ select FW_LOADER
+ default m if MEDIA_TUNER_CUSTOMIZE
+ help
+ Say Y here to include support for the xc2028/xc3028 tuners.
+
+config MEDIA_TUNER_XC5000
+ tristate "Xceive XC5000 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ depends on HOTPLUG
+ select FW_LOADER
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon tuner XC5000 from Xceive.
+ This device is only used inside a SiP called togther with a
+ demodulator for now.
+
+config MEDIA_TUNER_MXL5005S
+ tristate "MaxLinear MSL5005S silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the silicon tuner MXL5005S from MaxLinear.
+
+endif # MEDIA_TUNER_CUSTOMIZE
diff --git a/linux/drivers/media/common/tuners/Makefile b/linux/drivers/media/common/tuners/Makefile
new file mode 100644
index 000000000..55f7e6706
--- /dev/null
+++ b/linux/drivers/media/common/tuners/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for common V4L/DVB tuners
+#
+
+tda18271-objs := tda18271-maps.o tda18271-common.o tda18271-fe.o
+
+obj-$(CONFIG_MEDIA_TUNER_XC2028) += tuner-xc2028.o
+obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-simple.o
+# tuner-types will be merged into tuner-simple, in the future
+obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-types.o
+obj-$(CONFIG_MEDIA_TUNER_MT20XX) += mt20xx.o
+obj-$(CONFIG_MEDIA_TUNER_TDA8290) += tda8290.o
+obj-$(CONFIG_MEDIA_TUNER_TEA5767) += tea5767.o
+obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o
+obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
+obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
+obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
+obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
+obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
+obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/dvb/frontends/mt2060.c b/linux/drivers/media/common/tuners/mt2060.c
index 355817754..355817754 100644
--- a/linux/drivers/media/dvb/frontends/mt2060.c
+++ b/linux/drivers/media/common/tuners/mt2060.c
diff --git a/linux/drivers/media/dvb/frontends/mt2060.h b/linux/drivers/media/common/tuners/mt2060.h
index 0a86eab3a..cb60caffb 100644
--- a/linux/drivers/media/dvb/frontends/mt2060.h
+++ b/linux/drivers/media/common/tuners/mt2060.h
@@ -30,14 +30,14 @@ struct mt2060_config {
u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
};
-#if defined(CONFIG_DVB_TUNER_MT2060) || (defined(CONFIG_DVB_TUNER_MT2060_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT2060) || (defined(CONFIG_MEDIA_TUNER_MT2060_MODULE) && defined(MODULE))
extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
#else
static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TUNER_MT2060
+#endif // CONFIG_MEDIA_TUNER_MT2060
#endif
diff --git a/linux/drivers/media/dvb/frontends/mt2060_priv.h b/linux/drivers/media/common/tuners/mt2060_priv.h
index 5eaccdefd..5eaccdefd 100644
--- a/linux/drivers/media/dvb/frontends/mt2060_priv.h
+++ b/linux/drivers/media/common/tuners/mt2060_priv.h
diff --git a/linux/drivers/media/video/mt20xx.c b/linux/drivers/media/common/tuners/mt20xx.c
index d2c281aeb..d2c281aeb 100644
--- a/linux/drivers/media/video/mt20xx.c
+++ b/linux/drivers/media/common/tuners/mt20xx.c
diff --git a/linux/drivers/media/video/mt20xx.h b/linux/drivers/media/common/tuners/mt20xx.h
index 5e9c825d2..259553a24 100644
--- a/linux/drivers/media/video/mt20xx.h
+++ b/linux/drivers/media/common/tuners/mt20xx.h
@@ -20,7 +20,7 @@
#include <linux/i2c.h>
#include "dvb_frontend.h"
-#if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT20XX) || (defined(CONFIG_MEDIA_TUNER_MT20XX_MODULE) && defined(MODULE))
extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
struct i2c_adapter* i2c_adap,
u8 i2c_addr);
@@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
struct i2c_adapter* i2c_adap,
u8 i2c_addr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/dvb/frontends/mt2131.c b/linux/drivers/media/common/tuners/mt2131.c
index 47e081c2e..becc409d9 100644
--- a/linux/drivers/media/dvb/frontends/mt2131.c
+++ b/linux/drivers/media/common/tuners/mt2131.c
@@ -111,7 +111,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
priv->bandwidth = 0;
freq = params->frequency / 1000; // Hz -> kHz
- dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
+ dprintk(1, "%s() freq=%d\n", __func__, freq);
f_lo1 = freq + MT2131_IF1 * 1000;
f_lo1 = (f_lo1 / 250) * 250;
@@ -188,7 +188,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct mt2131_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
*frequency = priv->frequency;
return 0;
}
@@ -196,7 +196,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
{
struct mt2131_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
*bandwidth = priv->bandwidth;
return 0;
}
@@ -215,7 +215,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
mt2131_readreg(priv, 0x09, &afc_status);
dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
- __FUNCTION__, lock_status, afc_status);
+ __func__, lock_status, afc_status);
return 0;
}
@@ -224,7 +224,7 @@ static int mt2131_init(struct dvb_frontend *fe)
{
struct mt2131_priv *priv = fe->tuner_priv;
int ret;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if ((ret = mt2131_writeregs(priv, mt2131_config1,
sizeof(mt2131_config1))) < 0)
@@ -244,7 +244,7 @@ static int mt2131_init(struct dvb_frontend *fe)
static int mt2131_release(struct dvb_frontend *fe)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
@@ -274,7 +274,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
struct mt2131_priv *priv = NULL;
u8 id = 0;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
if (priv == NULL)
diff --git a/linux/drivers/media/dvb/frontends/mt2131.h b/linux/drivers/media/common/tuners/mt2131.h
index 1e4ffe7dc..cd8376f6f 100644
--- a/linux/drivers/media/dvb/frontends/mt2131.h
+++ b/linux/drivers/media/common/tuners/mt2131.h
@@ -30,7 +30,7 @@ struct mt2131_config {
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))
+#if defined(CONFIG_MEDIA_TUNER_MT2131) || (defined(CONFIG_MEDIA_TUNER_MT2131_MODULE) && defined(MODULE))
extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct mt2131_config *cfg,
@@ -41,10 +41,10 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
struct mt2131_config *cfg,
u16 if1)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif /* CONFIG_DVB_TUNER_MT2131 */
+#endif /* CONFIG_MEDIA_TUNER_MT2131 */
#endif /* __MT2131_H__ */
diff --git a/linux/drivers/media/dvb/frontends/mt2131_priv.h b/linux/drivers/media/common/tuners/mt2131_priv.h
index e930759c2..e930759c2 100644
--- a/linux/drivers/media/dvb/frontends/mt2131_priv.h
+++ b/linux/drivers/media/common/tuners/mt2131_priv.h
diff --git a/linux/drivers/media/dvb/frontends/mt2266.c b/linux/drivers/media/common/tuners/mt2266.c
index 9927a1a55..9927a1a55 100644
--- a/linux/drivers/media/dvb/frontends/mt2266.c
+++ b/linux/drivers/media/common/tuners/mt2266.c
diff --git a/linux/drivers/media/dvb/frontends/mt2266.h b/linux/drivers/media/common/tuners/mt2266.h
index f31dd613a..4d083882d 100644
--- a/linux/drivers/media/dvb/frontends/mt2266.h
+++ b/linux/drivers/media/common/tuners/mt2266.h
@@ -24,14 +24,14 @@ struct mt2266_config {
u8 i2c_address;
};
-#if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT2266) || (defined(CONFIG_MEDIA_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__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TUNER_MT2266
+#endif // CONFIG_MEDIA_TUNER_MT2266
#endif
diff --git a/linux/drivers/media/common/tuners/mxl5005s.c b/linux/drivers/media/common/tuners/mxl5005s.c
new file mode 100644
index 000000000..e356db855
--- /dev/null
+++ b/linux/drivers/media/common/tuners/mxl5005s.c
@@ -0,0 +1,4112 @@
+/*
+ MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
+
+ Copyright (C) 2008 MaxLinear
+ Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
+ Functions:
+ mxl5005s_reset()
+ mxl5005s_writereg()
+ mxl5005s_writeregs()
+ mxl5005s_init()
+ mxl5005s_reconfigure()
+ mxl5005s_AssignTunerMode()
+ mxl5005s_set_params()
+ mxl5005s_get_frequency()
+ mxl5005s_get_bandwidth()
+ mxl5005s_release()
+ mxl5005s_attach()
+
+ Copyright (C) 2008 Realtek
+ Copyright (C) 2008 Jan Hoogenraad
+ Functions:
+ mxl5005s_SetRfFreqHz()
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+ History of this driver (Steven Toth):
+ I was given a public release of a linux driver that included
+ support for the MaxLinear MXL5005S silicon tuner. Analysis of
+ the tuner driver showed clearly three things.
+
+ 1. The tuner driver didn't support the LinuxTV tuner API
+ so the code Realtek added had to be removed.
+
+ 2. A significant amount of the driver is reference driver code
+ from MaxLinear, I felt it was important to identify and
+ preserve this.
+
+ 3. New code has to be added to interface correctly with the
+ LinuxTV API, as a regular kernel module.
+
+ Other than the reference driver enum's, I've clearly marked
+ sections of the code and retained the copyright of the
+ respective owners.
+*/
+#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 "mxl5005s.h"
+
+static int debug;
+
+#define dprintk(level, arg...) do { \
+ if (level <= debug) \
+ printk(arg); \
+ } while (0)
+
+#define TUNER_REGS_NUM 104
+#define INITCTRL_NUM 40
+
+#ifdef _MXL_PRODUCTION
+#define CHCTRL_NUM 39
+#else
+#define CHCTRL_NUM 36
+#endif
+
+#define MXLCTRL_NUM 189
+#define MASTER_CONTROL_ADDR 9
+
+/* Enumeration of Master Control Register State */
+enum master_control_state {
+ MC_LOAD_START = 1,
+ MC_POWER_DOWN,
+ MC_SYNTH_RESET,
+ MC_SEQ_OFF
+};
+
+/* Enumeration of MXL5005 Tuner Modulation Type */
+enum {
+ MXL_DEFAULT_MODULATION = 0,
+ MXL_DVBT,
+ MXL_ATSC,
+ MXL_QAM,
+ MXL_ANALOG_CABLE,
+ MXL_ANALOG_OTA
+};
+
+/* MXL5005 Tuner Register Struct */
+struct TunerReg {
+ u16 Reg_Num; /* Tuner Register Address */
+ u16 Reg_Val; /* Current sw programmed value waiting to be writen */
+};
+
+enum {
+ /* Initialization Control Names */
+ DN_IQTN_AMP_CUT = 1, /* 1 */
+ BB_MODE, /* 2 */
+ BB_BUF, /* 3 */
+ BB_BUF_OA, /* 4 */
+ BB_ALPF_BANDSELECT, /* 5 */
+ BB_IQSWAP, /* 6 */
+ BB_DLPF_BANDSEL, /* 7 */
+ RFSYN_CHP_GAIN, /* 8 */
+ RFSYN_EN_CHP_HIGAIN, /* 9 */
+ AGC_IF, /* 10 */
+ AGC_RF, /* 11 */
+ IF_DIVVAL, /* 12 */
+ IF_VCO_BIAS, /* 13 */
+ CHCAL_INT_MOD_IF, /* 14 */
+ CHCAL_FRAC_MOD_IF, /* 15 */
+ DRV_RES_SEL, /* 16 */
+ I_DRIVER, /* 17 */
+ EN_AAF, /* 18 */
+ EN_3P, /* 19 */
+ EN_AUX_3P, /* 20 */
+ SEL_AAF_BAND, /* 21 */
+ SEQ_ENCLK16_CLK_OUT, /* 22 */
+ SEQ_SEL4_16B, /* 23 */
+ XTAL_CAPSELECT, /* 24 */
+ IF_SEL_DBL, /* 25 */
+ RFSYN_R_DIV, /* 26 */
+ SEQ_EXTSYNTHCALIF, /* 27 */
+ SEQ_EXTDCCAL, /* 28 */
+ AGC_EN_RSSI, /* 29 */
+ RFA_ENCLKRFAGC, /* 30 */
+ RFA_RSSI_REFH, /* 31 */
+ RFA_RSSI_REF, /* 32 */
+ RFA_RSSI_REFL, /* 33 */
+ RFA_FLR, /* 34 */
+ RFA_CEIL, /* 35 */
+ SEQ_EXTIQFSMPULSE, /* 36 */
+ OVERRIDE_1, /* 37 */
+ BB_INITSTATE_DLPF_TUNE, /* 38 */
+ TG_R_DIV, /* 39 */
+ EN_CHP_LIN_B, /* 40 */
+
+ /* Channel Change Control Names */
+ DN_POLY = 51, /* 51 */
+ DN_RFGAIN, /* 52 */
+ DN_CAP_RFLPF, /* 53 */
+ DN_EN_VHFUHFBAR, /* 54 */
+ DN_GAIN_ADJUST, /* 55 */
+ DN_IQTNBUF_AMP, /* 56 */
+ DN_IQTNGNBFBIAS_BST, /* 57 */
+ RFSYN_EN_OUTMUX, /* 58 */
+ RFSYN_SEL_VCO_OUT, /* 59 */
+ RFSYN_SEL_VCO_HI, /* 60 */
+ RFSYN_SEL_DIVM, /* 61 */
+ RFSYN_RF_DIV_BIAS, /* 62 */
+ DN_SEL_FREQ, /* 63 */
+ RFSYN_VCO_BIAS, /* 64 */
+ CHCAL_INT_MOD_RF, /* 65 */
+ CHCAL_FRAC_MOD_RF, /* 66 */
+ RFSYN_LPF_R, /* 67 */
+ CHCAL_EN_INT_RF, /* 68 */
+ TG_LO_DIVVAL, /* 69 */
+ TG_LO_SELVAL, /* 70 */
+ TG_DIV_VAL, /* 71 */
+ TG_VCO_BIAS, /* 72 */
+ SEQ_EXTPOWERUP, /* 73 */
+ OVERRIDE_2, /* 74 */
+ OVERRIDE_3, /* 75 */
+ OVERRIDE_4, /* 76 */
+ SEQ_FSM_PULSE, /* 77 */
+ GPIO_4B, /* 78 */
+ GPIO_3B, /* 79 */
+ GPIO_4, /* 80 */
+ GPIO_3, /* 81 */
+ GPIO_1B, /* 82 */
+ DAC_A_ENABLE, /* 83 */
+ DAC_B_ENABLE, /* 84 */
+ DAC_DIN_A, /* 85 */
+ DAC_DIN_B, /* 86 */
+#ifdef _MXL_PRODUCTION
+ RFSYN_EN_DIV, /* 87 */
+ RFSYN_DIVM, /* 88 */
+ DN_BYPASS_AGC_I2C /* 89 */
+#endif
+};
+
+/*
+ * The following context is source code provided by MaxLinear.
+ * MaxLinear source code - Common_MXL.h (?)
+ */
+
+/* Constants */
+#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104
+#define MXL5005S_LATCH_BYTE 0xfe
+
+/* Register address, MSB, and LSB */
+#define MXL5005S_BB_IQSWAP_ADDR 59
+#define MXL5005S_BB_IQSWAP_MSB 0
+#define MXL5005S_BB_IQSWAP_LSB 0
+
+#define MXL5005S_BB_DLPF_BANDSEL_ADDR 53
+#define MXL5005S_BB_DLPF_BANDSEL_MSB 4
+#define MXL5005S_BB_DLPF_BANDSEL_LSB 3
+
+/* Standard modes */
+enum {
+ MXL5005S_STANDARD_DVBT,
+ MXL5005S_STANDARD_ATSC,
+};
+#define MXL5005S_STANDARD_MODE_NUM 2
+
+/* Bandwidth modes */
+enum {
+ MXL5005S_BANDWIDTH_6MHZ = 6000000,
+ MXL5005S_BANDWIDTH_7MHZ = 7000000,
+ MXL5005S_BANDWIDTH_8MHZ = 8000000,
+};
+#define MXL5005S_BANDWIDTH_MODE_NUM 3
+
+/* MXL5005 Tuner Control Struct */
+struct TunerControl {
+ u16 Ctrl_Num; /* Control Number */
+ u16 size; /* Number of bits to represent Value */
+ u16 addr[25]; /* Array of Tuner Register Address for each bit pos */
+ u16 bit[25]; /* Array of bit pos in Reg Addr for each bit pos */
+ u16 val[25]; /* Binary representation of Value */
+};
+
+/* MXL5005 Tuner Struct */
+struct mxl5005s_state {
+ u8 Mode; /* 0: Analog Mode ; 1: Digital Mode */
+ u8 IF_Mode; /* for Analog Mode, 0: zero IF; 1: low IF */
+ u32 Chan_Bandwidth; /* filter channel bandwidth (6, 7, 8) */
+ u32 IF_OUT; /* Desired IF Out Frequency */
+ u16 IF_OUT_LOAD; /* IF Out Load Resistor (200/300 Ohms) */
+ u32 RF_IN; /* RF Input Frequency */
+ u32 Fxtal; /* XTAL Frequency */
+ u8 AGC_Mode; /* AGC Mode 0: Dual AGC; 1: Single AGC */
+ u16 TOP; /* Value: take over point */
+ u8 CLOCK_OUT; /* 0: turn off clk out; 1: turn on clock out */
+ u8 DIV_OUT; /* 4MHz or 16MHz */
+ u8 CAPSELECT; /* 0: disable On-Chip pulling cap; 1: enable */
+ u8 EN_RSSI; /* 0: disable RSSI; 1: enable RSSI */
+
+ /* Modulation Type; */
+ /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */
+ u8 Mod_Type;
+
+ /* Tracking Filter Type */
+ /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */
+ u8 TF_Type;
+
+ /* Calculated Settings */
+ u32 RF_LO; /* Synth RF LO Frequency */
+ u32 IF_LO; /* Synth IF LO Frequency */
+ u32 TG_LO; /* Synth TG_LO Frequency */
+
+ /* Pointers to ControlName Arrays */
+ u16 Init_Ctrl_Num; /* Number of INIT Control Names */
+ struct TunerControl
+ Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */
+
+ u16 CH_Ctrl_Num; /* Number of CH Control Names */
+ struct TunerControl
+ CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */
+
+ u16 MXL_Ctrl_Num; /* Number of MXL Control Names */
+ struct TunerControl
+ MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */
+
+ /* Pointer to Tuner Register Array */
+ u16 TunerRegs_Num; /* Number of Tuner Registers */
+ struct TunerReg
+ TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */
+
+ /* Linux driver framework specific */
+ struct mxl5005s_config *config;
+ struct dvb_frontend *frontend;
+ struct i2c_adapter *i2c;
+
+ /* Cache values */
+ u32 current_mode;
+
+};
+
+static u16 MXL_GetMasterControl(u8 *MasterReg, int state);
+static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value);
+static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value);
+static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
+ u8 bitVal);
+static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum,
+ u8 *RegVal, int *count);
+static u32 MXL_Ceiling(u32 value, u32 resolution);
+static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal);
+static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
+ u32 value, u16 controlGroup);
+static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
+static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
+ u8 *RegVal, int *count);
+static u32 MXL_GetXtalInt(u32 Xtal_Freq);
+static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
+static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
+static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
+static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
+ u8 *RegVal, int *count);
+static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
+ u8 *datatable, u8 len);
+static u16 MXL_IFSynthInit(struct dvb_frontend *fe);
+static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
+ u32 bandwidth);
+static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type,
+ u32 bandwidth);
+
+/* ----------------------------------------------------------------
+ * Begin: Custom code salvaged from the Realtek driver.
+ * Copyright (C) 2008 Realtek
+ * Copyright (C) 2008 Jan Hoogenraad
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * Released by Realtek under GPLv2.
+ * Thanks to Realtek for a lot of support we received !
+ *
+ * Revision: 080314 - original version
+ */
+
+static int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
+ unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
+ int TableLen;
+
+ u32 IfDivval = 0;
+ unsigned char MasterControlByte;
+
+ dprintk(1, "%s() freq=%ld\n", __func__, RfFreqHz);
+
+ /* Set MxL5005S tuner RF frequency according to example code. */
+
+ /* Tuner RF frequency setting stage 0 */
+ MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
+ AddrTable[0] = MASTER_CONTROL_ADDR;
+ ByteTable[0] |= state->config->AgcMasterByte;
+
+ mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
+
+ /* Tuner RF frequency setting stage 1 */
+ MXL_TuneRF(fe, RfFreqHz);
+
+ MXL_ControlRead(fe, IF_DIVVAL, &IfDivval);
+
+ MXL_ControlWrite(fe, SEQ_FSM_PULSE, 0);
+ MXL_ControlWrite(fe, SEQ_EXTPOWERUP, 1);
+ MXL_ControlWrite(fe, IF_DIVVAL, 8);
+ MXL_GetCHRegister(fe, AddrTable, ByteTable, &TableLen);
+
+ MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START);
+ AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
+ ByteTable[TableLen] = MasterControlByte |
+ state->config->AgcMasterByte;
+ TableLen += 1;
+
+ mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
+
+ /* Wait 30 ms. */
+ msleep(150);
+
+ /* Tuner RF frequency setting stage 2 */
+ MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1);
+ MXL_ControlWrite(fe, IF_DIVVAL, IfDivval);
+ MXL_GetCHRegister_ZeroIF(fe, AddrTable, ByteTable, &TableLen);
+
+ MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START);
+ AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
+ ByteTable[TableLen] = MasterControlByte |
+ state->config->AgcMasterByte ;
+ TableLen += 1;
+
+ mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
+
+ msleep(100);
+
+ return 0;
+}
+/* End: Custom code taken from the Realtek driver */
+
+/* ----------------------------------------------------------------
+ * Begin: Reference driver code found in the Realtek driver.
+ * Copyright (C) 2008 MaxLinear
+ */
+static u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ state->TunerRegs_Num = TUNER_REGS_NUM ;
+
+ state->TunerRegs[0].Reg_Num = 9 ;
+ state->TunerRegs[0].Reg_Val = 0x40 ;
+
+ state->TunerRegs[1].Reg_Num = 11 ;
+ state->TunerRegs[1].Reg_Val = 0x19 ;
+
+ state->TunerRegs[2].Reg_Num = 12 ;
+ state->TunerRegs[2].Reg_Val = 0x60 ;
+
+ state->TunerRegs[3].Reg_Num = 13 ;
+ state->TunerRegs[3].Reg_Val = 0x00 ;
+
+ state->TunerRegs[4].Reg_Num = 14 ;
+ state->TunerRegs[4].Reg_Val = 0x00 ;
+
+ state->TunerRegs[5].Reg_Num = 15 ;
+ state->TunerRegs[5].Reg_Val = 0xC0 ;
+
+ state->TunerRegs[6].Reg_Num = 16 ;
+ state->TunerRegs[6].Reg_Val = 0x00 ;
+
+ state->TunerRegs[7].Reg_Num = 17 ;
+ state->TunerRegs[7].Reg_Val = 0x00 ;
+
+ state->TunerRegs[8].Reg_Num = 18 ;
+ state->TunerRegs[8].Reg_Val = 0x00 ;
+
+ state->TunerRegs[9].Reg_Num = 19 ;
+ state->TunerRegs[9].Reg_Val = 0x34 ;
+
+ state->TunerRegs[10].Reg_Num = 21 ;
+ state->TunerRegs[10].Reg_Val = 0x00 ;
+
+ state->TunerRegs[11].Reg_Num = 22 ;
+ state->TunerRegs[11].Reg_Val = 0x6B ;
+
+ state->TunerRegs[12].Reg_Num = 23 ;
+ state->TunerRegs[12].Reg_Val = 0x35 ;
+
+ state->TunerRegs[13].Reg_Num = 24 ;
+ state->TunerRegs[13].Reg_Val = 0x70 ;
+
+ state->TunerRegs[14].Reg_Num = 25 ;
+ state->TunerRegs[14].Reg_Val = 0x3E ;
+
+ state->TunerRegs[15].Reg_Num = 26 ;
+ state->TunerRegs[15].Reg_Val = 0x82 ;
+
+ state->TunerRegs[16].Reg_Num = 31 ;
+ state->TunerRegs[16].Reg_Val = 0x00 ;
+
+ state->TunerRegs[17].Reg_Num = 32 ;
+ state->TunerRegs[17].Reg_Val = 0x40 ;
+
+ state->TunerRegs[18].Reg_Num = 33 ;
+ state->TunerRegs[18].Reg_Val = 0x53 ;
+
+ state->TunerRegs[19].Reg_Num = 34 ;
+ state->TunerRegs[19].Reg_Val = 0x81 ;
+
+ state->TunerRegs[20].Reg_Num = 35 ;
+ state->TunerRegs[20].Reg_Val = 0xC9 ;
+
+ state->TunerRegs[21].Reg_Num = 36 ;
+ state->TunerRegs[21].Reg_Val = 0x01 ;
+
+ state->TunerRegs[22].Reg_Num = 37 ;
+ state->TunerRegs[22].Reg_Val = 0x00 ;
+
+ state->TunerRegs[23].Reg_Num = 41 ;
+ state->TunerRegs[23].Reg_Val = 0x00 ;
+
+ state->TunerRegs[24].Reg_Num = 42 ;
+ state->TunerRegs[24].Reg_Val = 0xF8 ;
+
+ state->TunerRegs[25].Reg_Num = 43 ;
+ state->TunerRegs[25].Reg_Val = 0x43 ;
+
+ state->TunerRegs[26].Reg_Num = 44 ;
+ state->TunerRegs[26].Reg_Val = 0x20 ;
+
+ state->TunerRegs[27].Reg_Num = 45 ;
+ state->TunerRegs[27].Reg_Val = 0x80 ;
+
+ state->TunerRegs[28].Reg_Num = 46 ;
+ state->TunerRegs[28].Reg_Val = 0x88 ;
+
+ state->TunerRegs[29].Reg_Num = 47 ;
+ state->TunerRegs[29].Reg_Val = 0x86 ;
+
+ state->TunerRegs[30].Reg_Num = 48 ;
+ state->TunerRegs[30].Reg_Val = 0x00 ;
+
+ state->TunerRegs[31].Reg_Num = 49 ;
+ state->TunerRegs[31].Reg_Val = 0x00 ;
+
+ state->TunerRegs[32].Reg_Num = 53 ;
+ state->TunerRegs[32].Reg_Val = 0x94 ;
+
+ state->TunerRegs[33].Reg_Num = 54 ;
+ state->TunerRegs[33].Reg_Val = 0xFA ;
+
+ state->TunerRegs[34].Reg_Num = 55 ;
+ state->TunerRegs[34].Reg_Val = 0x92 ;
+
+ state->TunerRegs[35].Reg_Num = 56 ;
+ state->TunerRegs[35].Reg_Val = 0x80 ;
+
+ state->TunerRegs[36].Reg_Num = 57 ;
+ state->TunerRegs[36].Reg_Val = 0x41 ;
+
+ state->TunerRegs[37].Reg_Num = 58 ;
+ state->TunerRegs[37].Reg_Val = 0xDB ;
+
+ state->TunerRegs[38].Reg_Num = 59 ;
+ state->TunerRegs[38].Reg_Val = 0x00 ;
+
+ state->TunerRegs[39].Reg_Num = 60 ;
+ state->TunerRegs[39].Reg_Val = 0x00 ;
+
+ state->TunerRegs[40].Reg_Num = 61 ;
+ state->TunerRegs[40].Reg_Val = 0x00 ;
+
+ state->TunerRegs[41].Reg_Num = 62 ;
+ state->TunerRegs[41].Reg_Val = 0x00 ;
+
+ state->TunerRegs[42].Reg_Num = 65 ;
+ state->TunerRegs[42].Reg_Val = 0xF8 ;
+
+ state->TunerRegs[43].Reg_Num = 66 ;
+ state->TunerRegs[43].Reg_Val = 0xE4 ;
+
+ state->TunerRegs[44].Reg_Num = 67 ;
+ state->TunerRegs[44].Reg_Val = 0x90 ;
+
+ state->TunerRegs[45].Reg_Num = 68 ;
+ state->TunerRegs[45].Reg_Val = 0xC0 ;
+
+ state->TunerRegs[46].Reg_Num = 69 ;
+ state->TunerRegs[46].Reg_Val = 0x01 ;
+
+ state->TunerRegs[47].Reg_Num = 70 ;
+ state->TunerRegs[47].Reg_Val = 0x50 ;
+
+ state->TunerRegs[48].Reg_Num = 71 ;
+ state->TunerRegs[48].Reg_Val = 0x06 ;
+
+ state->TunerRegs[49].Reg_Num = 72 ;
+ state->TunerRegs[49].Reg_Val = 0x00 ;
+
+ state->TunerRegs[50].Reg_Num = 73 ;
+ state->TunerRegs[50].Reg_Val = 0x20 ;
+
+ state->TunerRegs[51].Reg_Num = 76 ;
+ state->TunerRegs[51].Reg_Val = 0xBB ;
+
+ state->TunerRegs[52].Reg_Num = 77 ;
+ state->TunerRegs[52].Reg_Val = 0x13 ;
+
+ state->TunerRegs[53].Reg_Num = 81 ;
+ state->TunerRegs[53].Reg_Val = 0x04 ;
+
+ state->TunerRegs[54].Reg_Num = 82 ;
+ state->TunerRegs[54].Reg_Val = 0x75 ;
+
+ state->TunerRegs[55].Reg_Num = 83 ;
+ state->TunerRegs[55].Reg_Val = 0x00 ;
+
+ state->TunerRegs[56].Reg_Num = 84 ;
+ state->TunerRegs[56].Reg_Val = 0x00 ;
+
+ state->TunerRegs[57].Reg_Num = 85 ;
+ state->TunerRegs[57].Reg_Val = 0x00 ;
+
+ state->TunerRegs[58].Reg_Num = 91 ;
+ state->TunerRegs[58].Reg_Val = 0x70 ;
+
+ state->TunerRegs[59].Reg_Num = 92 ;
+ state->TunerRegs[59].Reg_Val = 0x00 ;
+
+ state->TunerRegs[60].Reg_Num = 93 ;
+ state->TunerRegs[60].Reg_Val = 0x00 ;
+
+ state->TunerRegs[61].Reg_Num = 94 ;
+ state->TunerRegs[61].Reg_Val = 0x00 ;
+
+ state->TunerRegs[62].Reg_Num = 95 ;
+ state->TunerRegs[62].Reg_Val = 0x0C ;
+
+ state->TunerRegs[63].Reg_Num = 96 ;
+ state->TunerRegs[63].Reg_Val = 0x00 ;
+
+ state->TunerRegs[64].Reg_Num = 97 ;
+ state->TunerRegs[64].Reg_Val = 0x00 ;
+
+ state->TunerRegs[65].Reg_Num = 98 ;
+ state->TunerRegs[65].Reg_Val = 0xE2 ;
+
+ state->TunerRegs[66].Reg_Num = 99 ;
+ state->TunerRegs[66].Reg_Val = 0x00 ;
+
+ state->TunerRegs[67].Reg_Num = 100 ;
+ state->TunerRegs[67].Reg_Val = 0x00 ;
+
+ state->TunerRegs[68].Reg_Num = 101 ;
+ state->TunerRegs[68].Reg_Val = 0x12 ;
+
+ state->TunerRegs[69].Reg_Num = 102 ;
+ state->TunerRegs[69].Reg_Val = 0x80 ;
+
+ state->TunerRegs[70].Reg_Num = 103 ;
+ state->TunerRegs[70].Reg_Val = 0x32 ;
+
+ state->TunerRegs[71].Reg_Num = 104 ;
+ state->TunerRegs[71].Reg_Val = 0xB4 ;
+
+ state->TunerRegs[72].Reg_Num = 105 ;
+ state->TunerRegs[72].Reg_Val = 0x60 ;
+
+ state->TunerRegs[73].Reg_Num = 106 ;
+ state->TunerRegs[73].Reg_Val = 0x83 ;
+
+ state->TunerRegs[74].Reg_Num = 107 ;
+ state->TunerRegs[74].Reg_Val = 0x84 ;
+
+ state->TunerRegs[75].Reg_Num = 108 ;
+ state->TunerRegs[75].Reg_Val = 0x9C ;
+
+ state->TunerRegs[76].Reg_Num = 109 ;
+ state->TunerRegs[76].Reg_Val = 0x02 ;
+
+ state->TunerRegs[77].Reg_Num = 110 ;
+ state->TunerRegs[77].Reg_Val = 0x81 ;
+
+ state->TunerRegs[78].Reg_Num = 111 ;
+ state->TunerRegs[78].Reg_Val = 0xC0 ;
+
+ state->TunerRegs[79].Reg_Num = 112 ;
+ state->TunerRegs[79].Reg_Val = 0x10 ;
+
+ state->TunerRegs[80].Reg_Num = 131 ;
+ state->TunerRegs[80].Reg_Val = 0x8A ;
+
+ state->TunerRegs[81].Reg_Num = 132 ;
+ state->TunerRegs[81].Reg_Val = 0x10 ;
+
+ state->TunerRegs[82].Reg_Num = 133 ;
+ state->TunerRegs[82].Reg_Val = 0x24 ;
+
+ state->TunerRegs[83].Reg_Num = 134 ;
+ state->TunerRegs[83].Reg_Val = 0x00 ;
+
+ state->TunerRegs[84].Reg_Num = 135 ;
+ state->TunerRegs[84].Reg_Val = 0x00 ;
+
+ state->TunerRegs[85].Reg_Num = 136 ;
+ state->TunerRegs[85].Reg_Val = 0x7E ;
+
+ state->TunerRegs[86].Reg_Num = 137 ;
+ state->TunerRegs[86].Reg_Val = 0x40 ;
+
+ state->TunerRegs[87].Reg_Num = 138 ;
+ state->TunerRegs[87].Reg_Val = 0x38 ;
+
+ state->TunerRegs[88].Reg_Num = 146 ;
+ state->TunerRegs[88].Reg_Val = 0xF6 ;
+
+ state->TunerRegs[89].Reg_Num = 147 ;
+ state->TunerRegs[89].Reg_Val = 0x1A ;
+
+ state->TunerRegs[90].Reg_Num = 148 ;
+ state->TunerRegs[90].Reg_Val = 0x62 ;
+
+ state->TunerRegs[91].Reg_Num = 149 ;
+ state->TunerRegs[91].Reg_Val = 0x33 ;
+
+ state->TunerRegs[92].Reg_Num = 150 ;
+ state->TunerRegs[92].Reg_Val = 0x80 ;
+
+ state->TunerRegs[93].Reg_Num = 156 ;
+ state->TunerRegs[93].Reg_Val = 0x56 ;
+
+ state->TunerRegs[94].Reg_Num = 157 ;
+ state->TunerRegs[94].Reg_Val = 0x17 ;
+
+ state->TunerRegs[95].Reg_Num = 158 ;
+ state->TunerRegs[95].Reg_Val = 0xA9 ;
+
+ state->TunerRegs[96].Reg_Num = 159 ;
+ state->TunerRegs[96].Reg_Val = 0x00 ;
+
+ state->TunerRegs[97].Reg_Num = 160 ;
+ state->TunerRegs[97].Reg_Val = 0x00 ;
+
+ state->TunerRegs[98].Reg_Num = 161 ;
+ state->TunerRegs[98].Reg_Val = 0x00 ;
+
+ state->TunerRegs[99].Reg_Num = 162 ;
+ state->TunerRegs[99].Reg_Val = 0x40 ;
+
+ state->TunerRegs[100].Reg_Num = 166 ;
+ state->TunerRegs[100].Reg_Val = 0xAE ;
+
+ state->TunerRegs[101].Reg_Num = 167 ;
+ state->TunerRegs[101].Reg_Val = 0x1B ;
+
+ state->TunerRegs[102].Reg_Num = 168 ;
+ state->TunerRegs[102].Reg_Val = 0xF2 ;
+
+ state->TunerRegs[103].Reg_Num = 195 ;
+ state->TunerRegs[103].Reg_Val = 0x00 ;
+
+ return 0 ;
+}
+
+static u16 MXL5005_ControlInit(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ state->Init_Ctrl_Num = INITCTRL_NUM;
+
+ state->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ;
+ state->Init_Ctrl[0].size = 1 ;
+ state->Init_Ctrl[0].addr[0] = 73;
+ state->Init_Ctrl[0].bit[0] = 7;
+ state->Init_Ctrl[0].val[0] = 0;
+
+ state->Init_Ctrl[1].Ctrl_Num = BB_MODE ;
+ state->Init_Ctrl[1].size = 1 ;
+ state->Init_Ctrl[1].addr[0] = 53;
+ state->Init_Ctrl[1].bit[0] = 2;
+ state->Init_Ctrl[1].val[0] = 1;
+
+ state->Init_Ctrl[2].Ctrl_Num = BB_BUF ;
+ state->Init_Ctrl[2].size = 2 ;
+ state->Init_Ctrl[2].addr[0] = 53;
+ state->Init_Ctrl[2].bit[0] = 1;
+ state->Init_Ctrl[2].val[0] = 0;
+ state->Init_Ctrl[2].addr[1] = 57;
+ state->Init_Ctrl[2].bit[1] = 0;
+ state->Init_Ctrl[2].val[1] = 1;
+
+ state->Init_Ctrl[3].Ctrl_Num = BB_BUF_OA ;
+ state->Init_Ctrl[3].size = 1 ;
+ state->Init_Ctrl[3].addr[0] = 53;
+ state->Init_Ctrl[3].bit[0] = 0;
+ state->Init_Ctrl[3].val[0] = 0;
+
+ state->Init_Ctrl[4].Ctrl_Num = BB_ALPF_BANDSELECT ;
+ state->Init_Ctrl[4].size = 3 ;
+ state->Init_Ctrl[4].addr[0] = 53;
+ state->Init_Ctrl[4].bit[0] = 5;
+ state->Init_Ctrl[4].val[0] = 0;
+ state->Init_Ctrl[4].addr[1] = 53;
+ state->Init_Ctrl[4].bit[1] = 6;
+ state->Init_Ctrl[4].val[1] = 0;
+ state->Init_Ctrl[4].addr[2] = 53;
+ state->Init_Ctrl[4].bit[2] = 7;
+ state->Init_Ctrl[4].val[2] = 1;
+
+ state->Init_Ctrl[5].Ctrl_Num = BB_IQSWAP ;
+ state->Init_Ctrl[5].size = 1 ;
+ state->Init_Ctrl[5].addr[0] = 59;
+ state->Init_Ctrl[5].bit[0] = 0;
+ state->Init_Ctrl[5].val[0] = 0;
+
+ state->Init_Ctrl[6].Ctrl_Num = BB_DLPF_BANDSEL ;
+ state->Init_Ctrl[6].size = 2 ;
+ state->Init_Ctrl[6].addr[0] = 53;
+ state->Init_Ctrl[6].bit[0] = 3;
+ state->Init_Ctrl[6].val[0] = 0;
+ state->Init_Ctrl[6].addr[1] = 53;
+ state->Init_Ctrl[6].bit[1] = 4;
+ state->Init_Ctrl[6].val[1] = 1;
+
+ state->Init_Ctrl[7].Ctrl_Num = RFSYN_CHP_GAIN ;
+ state->Init_Ctrl[7].size = 4 ;
+ state->Init_Ctrl[7].addr[0] = 22;
+ state->Init_Ctrl[7].bit[0] = 4;
+ state->Init_Ctrl[7].val[0] = 0;
+ state->Init_Ctrl[7].addr[1] = 22;
+ state->Init_Ctrl[7].bit[1] = 5;
+ state->Init_Ctrl[7].val[1] = 1;
+ state->Init_Ctrl[7].addr[2] = 22;
+ state->Init_Ctrl[7].bit[2] = 6;
+ state->Init_Ctrl[7].val[2] = 1;
+ state->Init_Ctrl[7].addr[3] = 22;
+ state->Init_Ctrl[7].bit[3] = 7;
+ state->Init_Ctrl[7].val[3] = 0;
+
+ state->Init_Ctrl[8].Ctrl_Num = RFSYN_EN_CHP_HIGAIN ;
+ state->Init_Ctrl[8].size = 1 ;
+ state->Init_Ctrl[8].addr[0] = 22;
+ state->Init_Ctrl[8].bit[0] = 2;
+ state->Init_Ctrl[8].val[0] = 0;
+
+ state->Init_Ctrl[9].Ctrl_Num = AGC_IF ;
+ state->Init_Ctrl[9].size = 4 ;
+ state->Init_Ctrl[9].addr[0] = 76;
+ state->Init_Ctrl[9].bit[0] = 0;
+ state->Init_Ctrl[9].val[0] = 1;
+ state->Init_Ctrl[9].addr[1] = 76;
+ state->Init_Ctrl[9].bit[1] = 1;
+ state->Init_Ctrl[9].val[1] = 1;
+ state->Init_Ctrl[9].addr[2] = 76;
+ state->Init_Ctrl[9].bit[2] = 2;
+ state->Init_Ctrl[9].val[2] = 0;
+ state->Init_Ctrl[9].addr[3] = 76;
+ state->Init_Ctrl[9].bit[3] = 3;
+ state->Init_Ctrl[9].val[3] = 1;
+
+ state->Init_Ctrl[10].Ctrl_Num = AGC_RF ;
+ state->Init_Ctrl[10].size = 4 ;
+ state->Init_Ctrl[10].addr[0] = 76;
+ state->Init_Ctrl[10].bit[0] = 4;
+ state->Init_Ctrl[10].val[0] = 1;
+ state->Init_Ctrl[10].addr[1] = 76;
+ state->Init_Ctrl[10].bit[1] = 5;
+ state->Init_Ctrl[10].val[1] = 1;
+ state->Init_Ctrl[10].addr[2] = 76;
+ state->Init_Ctrl[10].bit[2] = 6;
+ state->Init_Ctrl[10].val[2] = 0;
+ state->Init_Ctrl[10].addr[3] = 76;
+ state->Init_Ctrl[10].bit[3] = 7;
+ state->Init_Ctrl[10].val[3] = 1;
+
+ state->Init_Ctrl[11].Ctrl_Num = IF_DIVVAL ;
+ state->Init_Ctrl[11].size = 5 ;
+ state->Init_Ctrl[11].addr[0] = 43;
+ state->Init_Ctrl[11].bit[0] = 3;
+ state->Init_Ctrl[11].val[0] = 0;
+ state->Init_Ctrl[11].addr[1] = 43;
+ state->Init_Ctrl[11].bit[1] = 4;
+ state->Init_Ctrl[11].val[1] = 0;
+ state->Init_Ctrl[11].addr[2] = 43;
+ state->Init_Ctrl[11].bit[2] = 5;
+ state->Init_Ctrl[11].val[2] = 0;
+ state->Init_Ctrl[11].addr[3] = 43;
+ state->Init_Ctrl[11].bit[3] = 6;
+ state->Init_Ctrl[11].val[3] = 1;
+ state->Init_Ctrl[11].addr[4] = 43;
+ state->Init_Ctrl[11].bit[4] = 7;
+ state->Init_Ctrl[11].val[4] = 0;
+
+ state->Init_Ctrl[12].Ctrl_Num = IF_VCO_BIAS ;
+ state->Init_Ctrl[12].size = 6 ;
+ state->Init_Ctrl[12].addr[0] = 44;
+ state->Init_Ctrl[12].bit[0] = 2;
+ state->Init_Ctrl[12].val[0] = 0;
+ state->Init_Ctrl[12].addr[1] = 44;
+ state->Init_Ctrl[12].bit[1] = 3;
+ state->Init_Ctrl[12].val[1] = 0;
+ state->Init_Ctrl[12].addr[2] = 44;
+ state->Init_Ctrl[12].bit[2] = 4;
+ state->Init_Ctrl[12].val[2] = 0;
+ state->Init_Ctrl[12].addr[3] = 44;
+ state->Init_Ctrl[12].bit[3] = 5;
+ state->Init_Ctrl[12].val[3] = 1;
+ state->Init_Ctrl[12].addr[4] = 44;
+ state->Init_Ctrl[12].bit[4] = 6;
+ state->Init_Ctrl[12].val[4] = 0;
+ state->Init_Ctrl[12].addr[5] = 44;
+ state->Init_Ctrl[12].bit[5] = 7;
+ state->Init_Ctrl[12].val[5] = 0;
+
+ state->Init_Ctrl[13].Ctrl_Num = CHCAL_INT_MOD_IF ;
+ state->Init_Ctrl[13].size = 7 ;
+ state->Init_Ctrl[13].addr[0] = 11;
+ state->Init_Ctrl[13].bit[0] = 0;
+ state->Init_Ctrl[13].val[0] = 1;
+ state->Init_Ctrl[13].addr[1] = 11;
+ state->Init_Ctrl[13].bit[1] = 1;
+ state->Init_Ctrl[13].val[1] = 0;
+ state->Init_Ctrl[13].addr[2] = 11;
+ state->Init_Ctrl[13].bit[2] = 2;
+ state->Init_Ctrl[13].val[2] = 0;
+ state->Init_Ctrl[13].addr[3] = 11;
+ state->Init_Ctrl[13].bit[3] = 3;
+ state->Init_Ctrl[13].val[3] = 1;
+ state->Init_Ctrl[13].addr[4] = 11;
+ state->Init_Ctrl[13].bit[4] = 4;
+ state->Init_Ctrl[13].val[4] = 1;
+ state->Init_Ctrl[13].addr[5] = 11;
+ state->Init_Ctrl[13].bit[5] = 5;
+ state->Init_Ctrl[13].val[5] = 0;
+ state->Init_Ctrl[13].addr[6] = 11;
+ state->Init_Ctrl[13].bit[6] = 6;
+ state->Init_Ctrl[13].val[6] = 0;
+
+ state->Init_Ctrl[14].Ctrl_Num = CHCAL_FRAC_MOD_IF ;
+ state->Init_Ctrl[14].size = 16 ;
+ state->Init_Ctrl[14].addr[0] = 13;
+ state->Init_Ctrl[14].bit[0] = 0;
+ state->Init_Ctrl[14].val[0] = 0;
+ state->Init_Ctrl[14].addr[1] = 13;
+ state->Init_Ctrl[14].bit[1] = 1;
+ state->Init_Ctrl[14].val[1] = 0;
+ state->Init_Ctrl[14].addr[2] = 13;
+ state->Init_Ctrl[14].bit[2] = 2;
+ state->Init_Ctrl[14].val[2] = 0;
+ state->Init_Ctrl[14].addr[3] = 13;
+ state->Init_Ctrl[14].bit[3] = 3;
+ state->Init_Ctrl[14].val[3] = 0;
+ state->Init_Ctrl[14].addr[4] = 13;
+ state->Init_Ctrl[14].bit[4] = 4;
+ state->Init_Ctrl[14].val[4] = 0;
+ state->Init_Ctrl[14].addr[5] = 13;
+ state->Init_Ctrl[14].bit[5] = 5;
+ state->Init_Ctrl[14].val[5] = 0;
+ state->Init_Ctrl[14].addr[6] = 13;
+ state->Init_Ctrl[14].bit[6] = 6;
+ state->Init_Ctrl[14].val[6] = 0;
+ state->Init_Ctrl[14].addr[7] = 13;
+ state->Init_Ctrl[14].bit[7] = 7;
+ state->Init_Ctrl[14].val[7] = 0;
+ state->Init_Ctrl[14].addr[8] = 12;
+ state->Init_Ctrl[14].bit[8] = 0;
+ state->Init_Ctrl[14].val[8] = 0;
+ state->Init_Ctrl[14].addr[9] = 12;
+ state->Init_Ctrl[14].bit[9] = 1;
+ state->Init_Ctrl[14].val[9] = 0;
+ state->Init_Ctrl[14].addr[10] = 12;
+ state->Init_Ctrl[14].bit[10] = 2;
+ state->Init_Ctrl[14].val[10] = 0;
+ state->Init_Ctrl[14].addr[11] = 12;
+ state->Init_Ctrl[14].bit[11] = 3;
+ state->Init_Ctrl[14].val[11] = 0;
+ state->Init_Ctrl[14].addr[12] = 12;
+ state->Init_Ctrl[14].bit[12] = 4;
+ state->Init_Ctrl[14].val[12] = 0;
+ state->Init_Ctrl[14].addr[13] = 12;
+ state->Init_Ctrl[14].bit[13] = 5;
+ state->Init_Ctrl[14].val[13] = 1;
+ state->Init_Ctrl[14].addr[14] = 12;
+ state->Init_Ctrl[14].bit[14] = 6;
+ state->Init_Ctrl[14].val[14] = 1;
+ state->Init_Ctrl[14].addr[15] = 12;
+ state->Init_Ctrl[14].bit[15] = 7;
+ state->Init_Ctrl[14].val[15] = 0;
+
+ state->Init_Ctrl[15].Ctrl_Num = DRV_RES_SEL ;
+ state->Init_Ctrl[15].size = 3 ;
+ state->Init_Ctrl[15].addr[0] = 147;
+ state->Init_Ctrl[15].bit[0] = 2;
+ state->Init_Ctrl[15].val[0] = 0;
+ state->Init_Ctrl[15].addr[1] = 147;
+ state->Init_Ctrl[15].bit[1] = 3;
+ state->Init_Ctrl[15].val[1] = 1;
+ state->Init_Ctrl[15].addr[2] = 147;
+ state->Init_Ctrl[15].bit[2] = 4;
+ state->Init_Ctrl[15].val[2] = 1;
+
+ state->Init_Ctrl[16].Ctrl_Num = I_DRIVER ;
+ state->Init_Ctrl[16].size = 2 ;
+ state->Init_Ctrl[16].addr[0] = 147;
+ state->Init_Ctrl[16].bit[0] = 0;
+ state->Init_Ctrl[16].val[0] = 0;
+ state->Init_Ctrl[16].addr[1] = 147;
+ state->Init_Ctrl[16].bit[1] = 1;
+ state->Init_Ctrl[16].val[1] = 1;
+
+ state->Init_Ctrl[17].Ctrl_Num = EN_AAF ;
+ state->Init_Ctrl[17].size = 1 ;
+ state->Init_Ctrl[17].addr[0] = 147;
+ state->Init_Ctrl[17].bit[0] = 7;
+ state->Init_Ctrl[17].val[0] = 0;
+
+ state->Init_Ctrl[18].Ctrl_Num = EN_3P ;
+ state->Init_Ctrl[18].size = 1 ;
+ state->Init_Ctrl[18].addr[0] = 147;
+ state->Init_Ctrl[18].bit[0] = 6;
+ state->Init_Ctrl[18].val[0] = 0;
+
+ state->Init_Ctrl[19].Ctrl_Num = EN_AUX_3P ;
+ state->Init_Ctrl[19].size = 1 ;
+ state->Init_Ctrl[19].addr[0] = 156;
+ state->Init_Ctrl[19].bit[0] = 0;
+ state->Init_Ctrl[19].val[0] = 0;
+
+ state->Init_Ctrl[20].Ctrl_Num = SEL_AAF_BAND ;
+ state->Init_Ctrl[20].size = 1 ;
+ state->Init_Ctrl[20].addr[0] = 147;
+ state->Init_Ctrl[20].bit[0] = 5;
+ state->Init_Ctrl[20].val[0] = 0;
+
+ state->Init_Ctrl[21].Ctrl_Num = SEQ_ENCLK16_CLK_OUT ;
+ state->Init_Ctrl[21].size = 1 ;
+ state->Init_Ctrl[21].addr[0] = 137;
+ state->Init_Ctrl[21].bit[0] = 4;
+ state->Init_Ctrl[21].val[0] = 0;
+
+ state->Init_Ctrl[22].Ctrl_Num = SEQ_SEL4_16B ;
+ state->Init_Ctrl[22].size = 1 ;
+ state->Init_Ctrl[22].addr[0] = 137;
+ state->Init_Ctrl[22].bit[0] = 7;
+ state->Init_Ctrl[22].val[0] = 0;
+
+ state->Init_Ctrl[23].Ctrl_Num = XTAL_CAPSELECT ;
+ state->Init_Ctrl[23].size = 1 ;
+ state->Init_Ctrl[23].addr[0] = 91;
+ state->Init_Ctrl[23].bit[0] = 5;
+ state->Init_Ctrl[23].val[0] = 1;
+
+ state->Init_Ctrl[24].Ctrl_Num = IF_SEL_DBL ;
+ state->Init_Ctrl[24].size = 1 ;
+ state->Init_Ctrl[24].addr[0] = 43;
+ state->Init_Ctrl[24].bit[0] = 0;
+ state->Init_Ctrl[24].val[0] = 1;
+
+ state->Init_Ctrl[25].Ctrl_Num = RFSYN_R_DIV ;
+ state->Init_Ctrl[25].size = 2 ;
+ state->Init_Ctrl[25].addr[0] = 22;
+ state->Init_Ctrl[25].bit[0] = 0;
+ state->Init_Ctrl[25].val[0] = 1;
+ state->Init_Ctrl[25].addr[1] = 22;
+ state->Init_Ctrl[25].bit[1] = 1;
+ state->Init_Ctrl[25].val[1] = 1;
+
+ state->Init_Ctrl[26].Ctrl_Num = SEQ_EXTSYNTHCALIF ;
+ state->Init_Ctrl[26].size = 1 ;
+ state->Init_Ctrl[26].addr[0] = 134;
+ state->Init_Ctrl[26].bit[0] = 2;
+ state->Init_Ctrl[26].val[0] = 0;
+
+ state->Init_Ctrl[27].Ctrl_Num = SEQ_EXTDCCAL ;
+ state->Init_Ctrl[27].size = 1 ;
+ state->Init_Ctrl[27].addr[0] = 137;
+ state->Init_Ctrl[27].bit[0] = 3;
+ state->Init_Ctrl[27].val[0] = 0;
+
+ state->Init_Ctrl[28].Ctrl_Num = AGC_EN_RSSI ;
+ state->Init_Ctrl[28].size = 1 ;
+ state->Init_Ctrl[28].addr[0] = 77;
+ state->Init_Ctrl[28].bit[0] = 7;
+ state->Init_Ctrl[28].val[0] = 0;
+
+ state->Init_Ctrl[29].Ctrl_Num = RFA_ENCLKRFAGC ;
+ state->Init_Ctrl[29].size = 1 ;
+ state->Init_Ctrl[29].addr[0] = 166;
+ state->Init_Ctrl[29].bit[0] = 7;
+ state->Init_Ctrl[29].val[0] = 1;
+
+ state->Init_Ctrl[30].Ctrl_Num = RFA_RSSI_REFH ;
+ state->Init_Ctrl[30].size = 3 ;
+ state->Init_Ctrl[30].addr[0] = 166;
+ state->Init_Ctrl[30].bit[0] = 0;
+ state->Init_Ctrl[30].val[0] = 0;
+ state->Init_Ctrl[30].addr[1] = 166;
+ state->Init_Ctrl[30].bit[1] = 1;
+ state->Init_Ctrl[30].val[1] = 1;
+ state->Init_Ctrl[30].addr[2] = 166;
+ state->Init_Ctrl[30].bit[2] = 2;
+ state->Init_Ctrl[30].val[2] = 1;
+
+ state->Init_Ctrl[31].Ctrl_Num = RFA_RSSI_REF ;
+ state->Init_Ctrl[31].size = 3 ;
+ state->Init_Ctrl[31].addr[0] = 166;
+ state->Init_Ctrl[31].bit[0] = 3;
+ state->Init_Ctrl[31].val[0] = 1;
+ state->Init_Ctrl[31].addr[1] = 166;
+ state->Init_Ctrl[31].bit[1] = 4;
+ state->Init_Ctrl[31].val[1] = 0;
+ state->Init_Ctrl[31].addr[2] = 166;
+ state->Init_Ctrl[31].bit[2] = 5;
+ state->Init_Ctrl[31].val[2] = 1;
+
+ state->Init_Ctrl[32].Ctrl_Num = RFA_RSSI_REFL ;
+ state->Init_Ctrl[32].size = 3 ;
+ state->Init_Ctrl[32].addr[0] = 167;
+ state->Init_Ctrl[32].bit[0] = 0;
+ state->Init_Ctrl[32].val[0] = 1;
+ state->Init_Ctrl[32].addr[1] = 167;
+ state->Init_Ctrl[32].bit[1] = 1;
+ state->Init_Ctrl[32].val[1] = 1;
+ state->Init_Ctrl[32].addr[2] = 167;
+ state->Init_Ctrl[32].bit[2] = 2;
+ state->Init_Ctrl[32].val[2] = 0;
+
+ state->Init_Ctrl[33].Ctrl_Num = RFA_FLR ;
+ state->Init_Ctrl[33].size = 4 ;
+ state->Init_Ctrl[33].addr[0] = 168;
+ state->Init_Ctrl[33].bit[0] = 0;
+ state->Init_Ctrl[33].val[0] = 0;
+ state->Init_Ctrl[33].addr[1] = 168;
+ state->Init_Ctrl[33].bit[1] = 1;
+ state->Init_Ctrl[33].val[1] = 1;
+ state->Init_Ctrl[33].addr[2] = 168;
+ state->Init_Ctrl[33].bit[2] = 2;
+ state->Init_Ctrl[33].val[2] = 0;
+ state->Init_Ctrl[33].addr[3] = 168;
+ state->Init_Ctrl[33].bit[3] = 3;
+ state->Init_Ctrl[33].val[3] = 0;
+
+ state->Init_Ctrl[34].Ctrl_Num = RFA_CEIL ;
+ state->Init_Ctrl[34].size = 4 ;
+ state->Init_Ctrl[34].addr[0] = 168;
+ state->Init_Ctrl[34].bit[0] = 4;
+ state->Init_Ctrl[34].val[0] = 1;
+ state->Init_Ctrl[34].addr[1] = 168;
+ state->Init_Ctrl[34].bit[1] = 5;
+ state->Init_Ctrl[34].val[1] = 1;
+ state->Init_Ctrl[34].addr[2] = 168;
+ state->Init_Ctrl[34].bit[2] = 6;
+ state->Init_Ctrl[34].val[2] = 1;
+ state->Init_Ctrl[34].addr[3] = 168;
+ state->Init_Ctrl[34].bit[3] = 7;
+ state->Init_Ctrl[34].val[3] = 1;
+
+ state->Init_Ctrl[35].Ctrl_Num = SEQ_EXTIQFSMPULSE ;
+ state->Init_Ctrl[35].size = 1 ;
+ state->Init_Ctrl[35].addr[0] = 135;
+ state->Init_Ctrl[35].bit[0] = 0;
+ state->Init_Ctrl[35].val[0] = 0;
+
+ state->Init_Ctrl[36].Ctrl_Num = OVERRIDE_1 ;
+ state->Init_Ctrl[36].size = 1 ;
+ state->Init_Ctrl[36].addr[0] = 56;
+ state->Init_Ctrl[36].bit[0] = 3;
+ state->Init_Ctrl[36].val[0] = 0;
+
+ state->Init_Ctrl[37].Ctrl_Num = BB_INITSTATE_DLPF_TUNE ;
+ state->Init_Ctrl[37].size = 7 ;
+ state->Init_Ctrl[37].addr[0] = 59;
+ state->Init_Ctrl[37].bit[0] = 1;
+ state->Init_Ctrl[37].val[0] = 0;
+ state->Init_Ctrl[37].addr[1] = 59;
+ state->Init_Ctrl[37].bit[1] = 2;
+ state->Init_Ctrl[37].val[1] = 0;
+ state->Init_Ctrl[37].addr[2] = 59;
+ state->Init_Ctrl[37].bit[2] = 3;
+ state->Init_Ctrl[37].val[2] = 0;
+ state->Init_Ctrl[37].addr[3] = 59;
+ state->Init_Ctrl[37].bit[3] = 4;
+ state->Init_Ctrl[37].val[3] = 0;
+ state->Init_Ctrl[37].addr[4] = 59;
+ state->Init_Ctrl[37].bit[4] = 5;
+ state->Init_Ctrl[37].val[4] = 0;
+ state->Init_Ctrl[37].addr[5] = 59;
+ state->Init_Ctrl[37].bit[5] = 6;
+ state->Init_Ctrl[37].val[5] = 0;
+ state->Init_Ctrl[37].addr[6] = 59;
+ state->Init_Ctrl[37].bit[6] = 7;
+ state->Init_Ctrl[37].val[6] = 0;
+
+ state->Init_Ctrl[38].Ctrl_Num = TG_R_DIV ;
+ state->Init_Ctrl[38].size = 6 ;
+ state->Init_Ctrl[38].addr[0] = 32;
+ state->Init_Ctrl[38].bit[0] = 2;
+ state->Init_Ctrl[38].val[0] = 0;
+ state->Init_Ctrl[38].addr[1] = 32;
+ state->Init_Ctrl[38].bit[1] = 3;
+ state->Init_Ctrl[38].val[1] = 0;
+ state->Init_Ctrl[38].addr[2] = 32;
+ state->Init_Ctrl[38].bit[2] = 4;
+ state->Init_Ctrl[38].val[2] = 0;
+ state->Init_Ctrl[38].addr[3] = 32;
+ state->Init_Ctrl[38].bit[3] = 5;
+ state->Init_Ctrl[38].val[3] = 0;
+ state->Init_Ctrl[38].addr[4] = 32;
+ state->Init_Ctrl[38].bit[4] = 6;
+ state->Init_Ctrl[38].val[4] = 1;
+ state->Init_Ctrl[38].addr[5] = 32;
+ state->Init_Ctrl[38].bit[5] = 7;
+ state->Init_Ctrl[38].val[5] = 0;
+
+ state->Init_Ctrl[39].Ctrl_Num = EN_CHP_LIN_B ;
+ state->Init_Ctrl[39].size = 1 ;
+ state->Init_Ctrl[39].addr[0] = 25;
+ state->Init_Ctrl[39].bit[0] = 3;
+ state->Init_Ctrl[39].val[0] = 1;
+
+
+ state->CH_Ctrl_Num = CHCTRL_NUM ;
+
+ state->CH_Ctrl[0].Ctrl_Num = DN_POLY ;
+ state->CH_Ctrl[0].size = 2 ;
+ state->CH_Ctrl[0].addr[0] = 68;
+ state->CH_Ctrl[0].bit[0] = 6;
+ state->CH_Ctrl[0].val[0] = 1;
+ state->CH_Ctrl[0].addr[1] = 68;
+ state->CH_Ctrl[0].bit[1] = 7;
+ state->CH_Ctrl[0].val[1] = 1;
+
+ state->CH_Ctrl[1].Ctrl_Num = DN_RFGAIN ;
+ state->CH_Ctrl[1].size = 2 ;
+ state->CH_Ctrl[1].addr[0] = 70;
+ state->CH_Ctrl[1].bit[0] = 6;
+ state->CH_Ctrl[1].val[0] = 1;
+ state->CH_Ctrl[1].addr[1] = 70;
+ state->CH_Ctrl[1].bit[1] = 7;
+ state->CH_Ctrl[1].val[1] = 0;
+
+ state->CH_Ctrl[2].Ctrl_Num = DN_CAP_RFLPF ;
+ state->CH_Ctrl[2].size = 9 ;
+ state->CH_Ctrl[2].addr[0] = 69;
+ state->CH_Ctrl[2].bit[0] = 5;
+ state->CH_Ctrl[2].val[0] = 0;
+ state->CH_Ctrl[2].addr[1] = 69;
+ state->CH_Ctrl[2].bit[1] = 6;
+ state->CH_Ctrl[2].val[1] = 0;
+ state->CH_Ctrl[2].addr[2] = 69;
+ state->CH_Ctrl[2].bit[2] = 7;
+ state->CH_Ctrl[2].val[2] = 0;
+ state->CH_Ctrl[2].addr[3] = 68;
+ state->CH_Ctrl[2].bit[3] = 0;
+ state->CH_Ctrl[2].val[3] = 0;
+ state->CH_Ctrl[2].addr[4] = 68;
+ state->CH_Ctrl[2].bit[4] = 1;
+ state->CH_Ctrl[2].val[4] = 0;
+ state->CH_Ctrl[2].addr[5] = 68;
+ state->CH_Ctrl[2].bit[5] = 2;
+ state->CH_Ctrl[2].val[5] = 0;
+ state->CH_Ctrl[2].addr[6] = 68;
+ state->CH_Ctrl[2].bit[6] = 3;
+ state->CH_Ctrl[2].val[6] = 0;
+ state->CH_Ctrl[2].addr[7] = 68;
+ state->CH_Ctrl[2].bit[7] = 4;
+ state->CH_Ctrl[2].val[7] = 0;
+ state->CH_Ctrl[2].addr[8] = 68;
+ state->CH_Ctrl[2].bit[8] = 5;
+ state->CH_Ctrl[2].val[8] = 0;
+
+ state->CH_Ctrl[3].Ctrl_Num = DN_EN_VHFUHFBAR ;
+ state->CH_Ctrl[3].size = 1 ;
+ state->CH_Ctrl[3].addr[0] = 70;
+ state->CH_Ctrl[3].bit[0] = 5;
+ state->CH_Ctrl[3].val[0] = 0;
+
+ state->CH_Ctrl[4].Ctrl_Num = DN_GAIN_ADJUST ;
+ state->CH_Ctrl[4].size = 3 ;
+ state->CH_Ctrl[4].addr[0] = 73;
+ state->CH_Ctrl[4].bit[0] = 4;
+ state->CH_Ctrl[4].val[0] = 0;
+ state->CH_Ctrl[4].addr[1] = 73;
+ state->CH_Ctrl[4].bit[1] = 5;
+ state->CH_Ctrl[4].val[1] = 1;
+ state->CH_Ctrl[4].addr[2] = 73;
+ state->CH_Ctrl[4].bit[2] = 6;
+ state->CH_Ctrl[4].val[2] = 0;
+
+ state->CH_Ctrl[5].Ctrl_Num = DN_IQTNBUF_AMP ;
+ state->CH_Ctrl[5].size = 4 ;
+ state->CH_Ctrl[5].addr[0] = 70;
+ state->CH_Ctrl[5].bit[0] = 0;
+ state->CH_Ctrl[5].val[0] = 0;
+ state->CH_Ctrl[5].addr[1] = 70;
+ state->CH_Ctrl[5].bit[1] = 1;
+ state->CH_Ctrl[5].val[1] = 0;
+ state->CH_Ctrl[5].addr[2] = 70;
+ state->CH_Ctrl[5].bit[2] = 2;
+ state->CH_Ctrl[5].val[2] = 0;
+ state->CH_Ctrl[5].addr[3] = 70;
+ state->CH_Ctrl[5].bit[3] = 3;
+ state->CH_Ctrl[5].val[3] = 0;
+
+ state->CH_Ctrl[6].Ctrl_Num = DN_IQTNGNBFBIAS_BST ;
+ state->CH_Ctrl[6].size = 1 ;
+ state->CH_Ctrl[6].addr[0] = 70;
+ state->CH_Ctrl[6].bit[0] = 4;
+ state->CH_Ctrl[6].val[0] = 1;
+
+ state->CH_Ctrl[7].Ctrl_Num = RFSYN_EN_OUTMUX ;
+ state->CH_Ctrl[7].size = 1 ;
+ state->CH_Ctrl[7].addr[0] = 111;
+ state->CH_Ctrl[7].bit[0] = 4;
+ state->CH_Ctrl[7].val[0] = 0;
+
+ state->CH_Ctrl[8].Ctrl_Num = RFSYN_SEL_VCO_OUT ;
+ state->CH_Ctrl[8].size = 1 ;
+ state->CH_Ctrl[8].addr[0] = 111;
+ state->CH_Ctrl[8].bit[0] = 7;
+ state->CH_Ctrl[8].val[0] = 1;
+
+ state->CH_Ctrl[9].Ctrl_Num = RFSYN_SEL_VCO_HI ;
+ state->CH_Ctrl[9].size = 1 ;
+ state->CH_Ctrl[9].addr[0] = 111;
+ state->CH_Ctrl[9].bit[0] = 6;
+ state->CH_Ctrl[9].val[0] = 1;
+
+ state->CH_Ctrl[10].Ctrl_Num = RFSYN_SEL_DIVM ;
+ state->CH_Ctrl[10].size = 1 ;
+ state->CH_Ctrl[10].addr[0] = 111;
+ state->CH_Ctrl[10].bit[0] = 5;
+ state->CH_Ctrl[10].val[0] = 0;
+
+ state->CH_Ctrl[11].Ctrl_Num = RFSYN_RF_DIV_BIAS ;
+ state->CH_Ctrl[11].size = 2 ;
+ state->CH_Ctrl[11].addr[0] = 110;
+ state->CH_Ctrl[11].bit[0] = 0;
+ state->CH_Ctrl[11].val[0] = 1;
+ state->CH_Ctrl[11].addr[1] = 110;
+ state->CH_Ctrl[11].bit[1] = 1;
+ state->CH_Ctrl[11].val[1] = 0;
+
+ state->CH_Ctrl[12].Ctrl_Num = DN_SEL_FREQ ;
+ state->CH_Ctrl[12].size = 3 ;
+ state->CH_Ctrl[12].addr[0] = 69;
+ state->CH_Ctrl[12].bit[0] = 2;
+ state->CH_Ctrl[12].val[0] = 0;
+ state->CH_Ctrl[12].addr[1] = 69;
+ state->CH_Ctrl[12].bit[1] = 3;
+ state->CH_Ctrl[12].val[1] = 0;
+ state->CH_Ctrl[12].addr[2] = 69;
+ state->CH_Ctrl[12].bit[2] = 4;
+ state->CH_Ctrl[12].val[2] = 0;
+
+ state->CH_Ctrl[13].Ctrl_Num = RFSYN_VCO_BIAS ;
+ state->CH_Ctrl[13].size = 6 ;
+ state->CH_Ctrl[13].addr[0] = 110;
+ state->CH_Ctrl[13].bit[0] = 2;
+ state->CH_Ctrl[13].val[0] = 0;
+ state->CH_Ctrl[13].addr[1] = 110;
+ state->CH_Ctrl[13].bit[1] = 3;
+ state->CH_Ctrl[13].val[1] = 0;
+ state->CH_Ctrl[13].addr[2] = 110;
+ state->CH_Ctrl[13].bit[2] = 4;
+ state->CH_Ctrl[13].val[2] = 0;
+ state->CH_Ctrl[13].addr[3] = 110;
+ state->CH_Ctrl[13].bit[3] = 5;
+ state->CH_Ctrl[13].val[3] = 0;
+ state->CH_Ctrl[13].addr[4] = 110;
+ state->CH_Ctrl[13].bit[4] = 6;
+ state->CH_Ctrl[13].val[4] = 0;
+ state->CH_Ctrl[13].addr[5] = 110;
+ state->CH_Ctrl[13].bit[5] = 7;
+ state->CH_Ctrl[13].val[5] = 1;
+
+ state->CH_Ctrl[14].Ctrl_Num = CHCAL_INT_MOD_RF ;
+ state->CH_Ctrl[14].size = 7 ;
+ state->CH_Ctrl[14].addr[0] = 14;
+ state->CH_Ctrl[14].bit[0] = 0;
+ state->CH_Ctrl[14].val[0] = 0;
+ state->CH_Ctrl[14].addr[1] = 14;
+ state->CH_Ctrl[14].bit[1] = 1;
+ state->CH_Ctrl[14].val[1] = 0;
+ state->CH_Ctrl[14].addr[2] = 14;
+ state->CH_Ctrl[14].bit[2] = 2;
+ state->CH_Ctrl[14].val[2] = 0;
+ state->CH_Ctrl[14].addr[3] = 14;
+ state->CH_Ctrl[14].bit[3] = 3;
+ state->CH_Ctrl[14].val[3] = 0;
+ state->CH_Ctrl[14].addr[4] = 14;
+ state->CH_Ctrl[14].bit[4] = 4;
+ state->CH_Ctrl[14].val[4] = 0;
+ state->CH_Ctrl[14].addr[5] = 14;
+ state->CH_Ctrl[14].bit[5] = 5;
+ state->CH_Ctrl[14].val[5] = 0;
+ state->CH_Ctrl[14].addr[6] = 14;
+ state->CH_Ctrl[14].bit[6] = 6;
+ state->CH_Ctrl[14].val[6] = 0;
+
+ state->CH_Ctrl[15].Ctrl_Num = CHCAL_FRAC_MOD_RF ;
+ state->CH_Ctrl[15].size = 18 ;
+ state->CH_Ctrl[15].addr[0] = 17;
+ state->CH_Ctrl[15].bit[0] = 6;
+ state->CH_Ctrl[15].val[0] = 0;
+ state->CH_Ctrl[15].addr[1] = 17;
+ state->CH_Ctrl[15].bit[1] = 7;
+ state->CH_Ctrl[15].val[1] = 0;
+ state->CH_Ctrl[15].addr[2] = 16;
+ state->CH_Ctrl[15].bit[2] = 0;
+ state->CH_Ctrl[15].val[2] = 0;
+ state->CH_Ctrl[15].addr[3] = 16;
+ state->CH_Ctrl[15].bit[3] = 1;
+ state->CH_Ctrl[15].val[3] = 0;
+ state->CH_Ctrl[15].addr[4] = 16;
+ state->CH_Ctrl[15].bit[4] = 2;
+ state->CH_Ctrl[15].val[4] = 0;
+ state->CH_Ctrl[15].addr[5] = 16;
+ state->CH_Ctrl[15].bit[5] = 3;
+ state->CH_Ctrl[15].val[5] = 0;
+ state->CH_Ctrl[15].addr[6] = 16;
+ state->CH_Ctrl[15].bit[6] = 4;
+ state->CH_Ctrl[15].val[6] = 0;
+ state->CH_Ctrl[15].addr[7] = 16;
+ state->CH_Ctrl[15].bit[7] = 5;
+ state->CH_Ctrl[15].val[7] = 0;
+ state->CH_Ctrl[15].addr[8] = 16;
+ state->CH_Ctrl[15].bit[8] = 6;
+ state->CH_Ctrl[15].val[8] = 0;
+ state->CH_Ctrl[15].addr[9] = 16;
+ state->CH_Ctrl[15].bit[9] = 7;
+ state->CH_Ctrl[15].val[9] = 0;
+ state->CH_Ctrl[15].addr[10] = 15;
+ state->CH_Ctrl[15].bit[10] = 0;
+ state->CH_Ctrl[15].val[10] = 0;
+ state->CH_Ctrl[15].addr[11] = 15;
+ state->CH_Ctrl[15].bit[11] = 1;
+ state->CH_Ctrl[15].val[11] = 0;
+ state->CH_Ctrl[15].addr[12] = 15;
+ state->CH_Ctrl[15].bit[12] = 2;
+ state->CH_Ctrl[15].val[12] = 0;
+ state->CH_Ctrl[15].addr[13] = 15;
+ state->CH_Ctrl[15].bit[13] = 3;
+ state->CH_Ctrl[15].val[13] = 0;
+ state->CH_Ctrl[15].addr[14] = 15;
+ state->CH_Ctrl[15].bit[14] = 4;
+ state->CH_Ctrl[15].val[14] = 0;
+ state->CH_Ctrl[15].addr[15] = 15;
+ state->CH_Ctrl[15].bit[15] = 5;
+ state->CH_Ctrl[15].val[15] = 0;
+ state->CH_Ctrl[15].addr[16] = 15;
+ state->CH_Ctrl[15].bit[16] = 6;
+ state->CH_Ctrl[15].val[16] = 1;
+ state->CH_Ctrl[15].addr[17] = 15;
+ state->CH_Ctrl[15].bit[17] = 7;
+ state->CH_Ctrl[15].val[17] = 1;
+
+ state->CH_Ctrl[16].Ctrl_Num = RFSYN_LPF_R ;
+ state->CH_Ctrl[16].size = 5 ;
+ state->CH_Ctrl[16].addr[0] = 112;
+ state->CH_Ctrl[16].bit[0] = 0;
+ state->CH_Ctrl[16].val[0] = 0;
+ state->CH_Ctrl[16].addr[1] = 112;
+ state->CH_Ctrl[16].bit[1] = 1;
+ state->CH_Ctrl[16].val[1] = 0;
+ state->CH_Ctrl[16].addr[2] = 112;
+ state->CH_Ctrl[16].bit[2] = 2;
+ state->CH_Ctrl[16].val[2] = 0;
+ state->CH_Ctrl[16].addr[3] = 112;
+ state->CH_Ctrl[16].bit[3] = 3;
+ state->CH_Ctrl[16].val[3] = 0;
+ state->CH_Ctrl[16].addr[4] = 112;
+ state->CH_Ctrl[16].bit[4] = 4;
+ state->CH_Ctrl[16].val[4] = 1;
+
+ state->CH_Ctrl[17].Ctrl_Num = CHCAL_EN_INT_RF ;
+ state->CH_Ctrl[17].size = 1 ;
+ state->CH_Ctrl[17].addr[0] = 14;
+ state->CH_Ctrl[17].bit[0] = 7;
+ state->CH_Ctrl[17].val[0] = 0;
+
+ state->CH_Ctrl[18].Ctrl_Num = TG_LO_DIVVAL ;
+ state->CH_Ctrl[18].size = 4 ;
+ state->CH_Ctrl[18].addr[0] = 107;
+ state->CH_Ctrl[18].bit[0] = 3;
+ state->CH_Ctrl[18].val[0] = 0;
+ state->CH_Ctrl[18].addr[1] = 107;
+ state->CH_Ctrl[18].bit[1] = 4;
+ state->CH_Ctrl[18].val[1] = 0;
+ state->CH_Ctrl[18].addr[2] = 107;
+ state->CH_Ctrl[18].bit[2] = 5;
+ state->CH_Ctrl[18].val[2] = 0;
+ state->CH_Ctrl[18].addr[3] = 107;
+ state->CH_Ctrl[18].bit[3] = 6;
+ state->CH_Ctrl[18].val[3] = 0;
+
+ state->CH_Ctrl[19].Ctrl_Num = TG_LO_SELVAL ;
+ state->CH_Ctrl[19].size = 3 ;
+ state->CH_Ctrl[19].addr[0] = 107;
+ state->CH_Ctrl[19].bit[0] = 7;
+ state->CH_Ctrl[19].val[0] = 1;
+ state->CH_Ctrl[19].addr[1] = 106;
+ state->CH_Ctrl[19].bit[1] = 0;
+ state->CH_Ctrl[19].val[1] = 1;
+ state->CH_Ctrl[19].addr[2] = 106;
+ state->CH_Ctrl[19].bit[2] = 1;
+ state->CH_Ctrl[19].val[2] = 1;
+
+ state->CH_Ctrl[20].Ctrl_Num = TG_DIV_VAL ;
+ state->CH_Ctrl[20].size = 11 ;
+ state->CH_Ctrl[20].addr[0] = 109;
+ state->CH_Ctrl[20].bit[0] = 2;
+ state->CH_Ctrl[20].val[0] = 0;
+ state->CH_Ctrl[20].addr[1] = 109;
+ state->CH_Ctrl[20].bit[1] = 3;
+ state->CH_Ctrl[20].val[1] = 0;
+ state->CH_Ctrl[20].addr[2] = 109;
+ state->CH_Ctrl[20].bit[2] = 4;
+ state->CH_Ctrl[20].val[2] = 0;
+ state->CH_Ctrl[20].addr[3] = 109;
+ state->CH_Ctrl[20].bit[3] = 5;
+ state->CH_Ctrl[20].val[3] = 0;
+ state->CH_Ctrl[20].addr[4] = 109;
+ state->CH_Ctrl[20].bit[4] = 6;
+ state->CH_Ctrl[20].val[4] = 0;
+ state->CH_Ctrl[20].addr[5] = 109;
+ state->CH_Ctrl[20].bit[5] = 7;
+ state->CH_Ctrl[20].val[5] = 0;
+ state->CH_Ctrl[20].addr[6] = 108;
+ state->CH_Ctrl[20].bit[6] = 0;
+ state->CH_Ctrl[20].val[6] = 0;
+ state->CH_Ctrl[20].addr[7] = 108;
+ state->CH_Ctrl[20].bit[7] = 1;
+ state->CH_Ctrl[20].val[7] = 0;
+ state->CH_Ctrl[20].addr[8] = 108;
+ state->CH_Ctrl[20].bit[8] = 2;
+ state->CH_Ctrl[20].val[8] = 1;
+ state->CH_Ctrl[20].addr[9] = 108;
+ state->CH_Ctrl[20].bit[9] = 3;
+ state->CH_Ctrl[20].val[9] = 1;
+ state->CH_Ctrl[20].addr[10] = 108;
+ state->CH_Ctrl[20].bit[10] = 4;
+ state->CH_Ctrl[20].val[10] = 1;
+
+ state->CH_Ctrl[21].Ctrl_Num = TG_VCO_BIAS ;
+ state->CH_Ctrl[21].size = 6 ;
+ state->CH_Ctrl[21].addr[0] = 106;
+ state->CH_Ctrl[21].bit[0] = 2;
+ state->CH_Ctrl[21].val[0] = 0;
+ state->CH_Ctrl[21].addr[1] = 106;
+ state->CH_Ctrl[21].bit[1] = 3;
+ state->CH_Ctrl[21].val[1] = 0;
+ state->CH_Ctrl[21].addr[2] = 106;
+ state->CH_Ctrl[21].bit[2] = 4;
+ state->CH_Ctrl[21].val[2] = 0;
+ state->CH_Ctrl[21].addr[3] = 106;
+ state->CH_Ctrl[21].bit[3] = 5;
+ state->CH_Ctrl[21].val[3] = 0;
+ state->CH_Ctrl[21].addr[4] = 106;
+ state->CH_Ctrl[21].bit[4] = 6;
+ state->CH_Ctrl[21].val[4] = 0;
+ state->CH_Ctrl[21].addr[5] = 106;
+ state->CH_Ctrl[21].bit[5] = 7;
+ state->CH_Ctrl[21].val[5] = 1;
+
+ state->CH_Ctrl[22].Ctrl_Num = SEQ_EXTPOWERUP ;
+ state->CH_Ctrl[22].size = 1 ;
+ state->CH_Ctrl[22].addr[0] = 138;
+ state->CH_Ctrl[22].bit[0] = 4;
+ state->CH_Ctrl[22].val[0] = 1;
+
+ state->CH_Ctrl[23].Ctrl_Num = OVERRIDE_2 ;
+ state->CH_Ctrl[23].size = 1 ;
+ state->CH_Ctrl[23].addr[0] = 17;
+ state->CH_Ctrl[23].bit[0] = 5;
+ state->CH_Ctrl[23].val[0] = 0;
+
+ state->CH_Ctrl[24].Ctrl_Num = OVERRIDE_3 ;
+ state->CH_Ctrl[24].size = 1 ;
+ state->CH_Ctrl[24].addr[0] = 111;
+ state->CH_Ctrl[24].bit[0] = 3;
+ state->CH_Ctrl[24].val[0] = 0;
+
+ state->CH_Ctrl[25].Ctrl_Num = OVERRIDE_4 ;
+ state->CH_Ctrl[25].size = 1 ;
+ state->CH_Ctrl[25].addr[0] = 112;
+ state->CH_Ctrl[25].bit[0] = 7;
+ state->CH_Ctrl[25].val[0] = 0;
+
+ state->CH_Ctrl[26].Ctrl_Num = SEQ_FSM_PULSE ;
+ state->CH_Ctrl[26].size = 1 ;
+ state->CH_Ctrl[26].addr[0] = 136;
+ state->CH_Ctrl[26].bit[0] = 7;
+ state->CH_Ctrl[26].val[0] = 0;
+
+ state->CH_Ctrl[27].Ctrl_Num = GPIO_4B ;
+ state->CH_Ctrl[27].size = 1 ;
+ state->CH_Ctrl[27].addr[0] = 149;
+ state->CH_Ctrl[27].bit[0] = 7;
+ state->CH_Ctrl[27].val[0] = 0;
+
+ state->CH_Ctrl[28].Ctrl_Num = GPIO_3B ;
+ state->CH_Ctrl[28].size = 1 ;
+ state->CH_Ctrl[28].addr[0] = 149;
+ state->CH_Ctrl[28].bit[0] = 6;
+ state->CH_Ctrl[28].val[0] = 0;
+
+ state->CH_Ctrl[29].Ctrl_Num = GPIO_4 ;
+ state->CH_Ctrl[29].size = 1 ;
+ state->CH_Ctrl[29].addr[0] = 149;
+ state->CH_Ctrl[29].bit[0] = 5;
+ state->CH_Ctrl[29].val[0] = 1;
+
+ state->CH_Ctrl[30].Ctrl_Num = GPIO_3 ;
+ state->CH_Ctrl[30].size = 1 ;
+ state->CH_Ctrl[30].addr[0] = 149;
+ state->CH_Ctrl[30].bit[0] = 4;
+ state->CH_Ctrl[30].val[0] = 1;
+
+ state->CH_Ctrl[31].Ctrl_Num = GPIO_1B ;
+ state->CH_Ctrl[31].size = 1 ;
+ state->CH_Ctrl[31].addr[0] = 149;
+ state->CH_Ctrl[31].bit[0] = 3;
+ state->CH_Ctrl[31].val[0] = 0;
+
+ state->CH_Ctrl[32].Ctrl_Num = DAC_A_ENABLE ;
+ state->CH_Ctrl[32].size = 1 ;
+ state->CH_Ctrl[32].addr[0] = 93;
+ state->CH_Ctrl[32].bit[0] = 1;
+ state->CH_Ctrl[32].val[0] = 0;
+
+ state->CH_Ctrl[33].Ctrl_Num = DAC_B_ENABLE ;
+ state->CH_Ctrl[33].size = 1 ;
+ state->CH_Ctrl[33].addr[0] = 93;
+ state->CH_Ctrl[33].bit[0] = 0;
+ state->CH_Ctrl[33].val[0] = 0;
+
+ state->CH_Ctrl[34].Ctrl_Num = DAC_DIN_A ;
+ state->CH_Ctrl[34].size = 6 ;
+ state->CH_Ctrl[34].addr[0] = 92;
+ state->CH_Ctrl[34].bit[0] = 2;
+ state->CH_Ctrl[34].val[0] = 0;
+ state->CH_Ctrl[34].addr[1] = 92;
+ state->CH_Ctrl[34].bit[1] = 3;
+ state->CH_Ctrl[34].val[1] = 0;
+ state->CH_Ctrl[34].addr[2] = 92;
+ state->CH_Ctrl[34].bit[2] = 4;
+ state->CH_Ctrl[34].val[2] = 0;
+ state->CH_Ctrl[34].addr[3] = 92;
+ state->CH_Ctrl[34].bit[3] = 5;
+ state->CH_Ctrl[34].val[3] = 0;
+ state->CH_Ctrl[34].addr[4] = 92;
+ state->CH_Ctrl[34].bit[4] = 6;
+ state->CH_Ctrl[34].val[4] = 0;
+ state->CH_Ctrl[34].addr[5] = 92;
+ state->CH_Ctrl[34].bit[5] = 7;
+ state->CH_Ctrl[34].val[5] = 0;
+
+ state->CH_Ctrl[35].Ctrl_Num = DAC_DIN_B ;
+ state->CH_Ctrl[35].size = 6 ;
+ state->CH_Ctrl[35].addr[0] = 93;
+ state->CH_Ctrl[35].bit[0] = 2;
+ state->CH_Ctrl[35].val[0] = 0;
+ state->CH_Ctrl[35].addr[1] = 93;
+ state->CH_Ctrl[35].bit[1] = 3;
+ state->CH_Ctrl[35].val[1] = 0;
+ state->CH_Ctrl[35].addr[2] = 93;
+ state->CH_Ctrl[35].bit[2] = 4;
+ state->CH_Ctrl[35].val[2] = 0;
+ state->CH_Ctrl[35].addr[3] = 93;
+ state->CH_Ctrl[35].bit[3] = 5;
+ state->CH_Ctrl[35].val[3] = 0;
+ state->CH_Ctrl[35].addr[4] = 93;
+ state->CH_Ctrl[35].bit[4] = 6;
+ state->CH_Ctrl[35].val[4] = 0;
+ state->CH_Ctrl[35].addr[5] = 93;
+ state->CH_Ctrl[35].bit[5] = 7;
+ state->CH_Ctrl[35].val[5] = 0;
+
+#ifdef _MXL_PRODUCTION
+ state->CH_Ctrl[36].Ctrl_Num = RFSYN_EN_DIV ;
+ state->CH_Ctrl[36].size = 1 ;
+ state->CH_Ctrl[36].addr[0] = 109;
+ state->CH_Ctrl[36].bit[0] = 1;
+ state->CH_Ctrl[36].val[0] = 1;
+
+ state->CH_Ctrl[37].Ctrl_Num = RFSYN_DIVM ;
+ state->CH_Ctrl[37].size = 2 ;
+ state->CH_Ctrl[37].addr[0] = 112;
+ state->CH_Ctrl[37].bit[0] = 5;
+ state->CH_Ctrl[37].val[0] = 0;
+ state->CH_Ctrl[37].addr[1] = 112;
+ state->CH_Ctrl[37].bit[1] = 6;
+ state->CH_Ctrl[37].val[1] = 0;
+
+ state->CH_Ctrl[38].Ctrl_Num = DN_BYPASS_AGC_I2C ;
+ state->CH_Ctrl[38].size = 1 ;
+ state->CH_Ctrl[38].addr[0] = 65;
+ state->CH_Ctrl[38].bit[0] = 1;
+ state->CH_Ctrl[38].val[0] = 0;
+#endif
+
+ return 0 ;
+}
+
+static void InitTunerControls(struct dvb_frontend *fe)
+{
+ MXL5005_RegisterInit(fe);
+ MXL5005_ControlInit(fe);
+#ifdef _MXL_INTERNAL
+ MXL5005_MXLControlInit(fe);
+#endif
+}
+
+static u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
+ u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */
+ u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */
+ u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */
+ u32 IF_out, /* Desired IF Out Frequency */
+ u32 Fxtal, /* XTAL Frequency */
+ u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */
+ u16 TOP, /* 0: Dual AGC; Value: take over point */
+ u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */
+ u8 CLOCK_OUT, /* 0: turn off clk out; 1: turn on clock out */
+ u8 DIV_OUT, /* 0: Div-1; 1: Div-4 */
+ u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */
+ u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */
+
+ /* Modulation Type; */
+ /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */
+ u8 Mod_Type,
+
+ /* Tracking Filter */
+ /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */
+ u8 TF_Type
+ )
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0;
+
+ state->Mode = Mode;
+ state->IF_Mode = IF_mode;
+ state->Chan_Bandwidth = Bandwidth;
+ state->IF_OUT = IF_out;
+ state->Fxtal = Fxtal;
+ state->AGC_Mode = AGC_Mode;
+ state->TOP = TOP;
+ state->IF_OUT_LOAD = IF_OUT_LOAD;
+ state->CLOCK_OUT = CLOCK_OUT;
+ state->DIV_OUT = DIV_OUT;
+ state->CAPSELECT = CAPSELECT;
+ state->EN_RSSI = EN_RSSI;
+ state->Mod_Type = Mod_Type;
+ state->TF_Type = TF_Type;
+
+ /* Initialize all the controls and registers */
+ InitTunerControls(fe);
+
+ /* Synthesizer LO frequency calculation */
+ MXL_SynthIFLO_Calc(fe);
+
+ return status;
+}
+
+static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ if (state->Mode == 1) /* Digital Mode */
+ state->IF_LO = state->IF_OUT;
+ else /* Analog Mode */ {
+ if (state->IF_Mode == 0) /* Analog Zero IF mode */
+ state->IF_LO = state->IF_OUT + 400000;
+ else /* Analog Low IF mode */
+ state->IF_LO = state->IF_OUT + state->Chan_Bandwidth/2;
+ }
+}
+
+static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+
+ if (state->Mode == 1) /* Digital Mode */ {
+ /* remove 20.48MHz setting for 2.6.10 */
+ state->RF_LO = state->RF_IN;
+ /* change for 2.6.6 */
+ state->TG_LO = state->RF_IN - 750000;
+ } else /* Analog Mode */ {
+ if (state->IF_Mode == 0) /* Analog Zero IF mode */ {
+ state->RF_LO = state->RF_IN - 400000;
+ state->TG_LO = state->RF_IN - 1750000;
+ } else /* Analog Low IF mode */ {
+ state->RF_LO = state->RF_IN - state->Chan_Bandwidth/2;
+ state->TG_LO = state->RF_IN -
+ state->Chan_Bandwidth + 500000;
+ }
+ }
+}
+
+static u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
+{
+ u16 status = 0;
+
+ status += MXL_ControlWrite(fe, OVERRIDE_1, 1);
+ status += MXL_ControlWrite(fe, OVERRIDE_2, 1);
+ status += MXL_ControlWrite(fe, OVERRIDE_3, 1);
+ status += MXL_ControlWrite(fe, OVERRIDE_4, 1);
+
+ return status;
+}
+
+static u16 MXL_BlockInit(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0;
+
+ status += MXL_OverwriteICDefault(fe);
+
+ /* Downconverter Control Dig Ana */
+ status += MXL_ControlWrite(fe, DN_IQTN_AMP_CUT, state->Mode ? 1 : 0);
+
+ /* Filter Control Dig Ana */
+ status += MXL_ControlWrite(fe, BB_MODE, state->Mode ? 0 : 1);
+ status += MXL_ControlWrite(fe, BB_BUF, state->Mode ? 3 : 2);
+ status += MXL_ControlWrite(fe, BB_BUF_OA, state->Mode ? 1 : 0);
+ status += MXL_ControlWrite(fe, BB_IQSWAP, state->Mode ? 0 : 1);
+ status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 0);
+
+ /* Initialize Low-Pass Filter */
+ if (state->Mode) { /* Digital Mode */
+ switch (state->Chan_Bandwidth) {
+ case 8000000:
+ status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 0);
+ break;
+ case 7000000:
+ status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2);
+ break;
+ case 6000000:
+ status += MXL_ControlWrite(fe,
+ BB_DLPF_BANDSEL, 3);
+ break;
+ }
+ } else { /* Analog Mode */
+ switch (state->Chan_Bandwidth) {
+ case 8000000: /* Low Zero */
+ status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
+ (state->IF_Mode ? 0 : 3));
+ break;
+ case 7000000:
+ status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
+ (state->IF_Mode ? 1 : 4));
+ break;
+ case 6000000:
+ status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
+ (state->IF_Mode ? 2 : 5));
+ break;
+ }
+ }
+
+ /* Charge Pump Control Dig Ana */
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, state->Mode ? 5 : 8);
+ status += MXL_ControlWrite(fe,
+ RFSYN_EN_CHP_HIGAIN, state->Mode ? 1 : 1);
+ status += MXL_ControlWrite(fe, EN_CHP_LIN_B, state->Mode ? 0 : 0);
+
+ /* AGC TOP Control */
+ if (state->AGC_Mode == 0) /* Dual AGC */ {
+ status += MXL_ControlWrite(fe, AGC_IF, 15);
+ status += MXL_ControlWrite(fe, AGC_RF, 15);
+ } else /* Single AGC Mode Dig Ana */
+ status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12);
+
+ if (state->TOP == 55) /* TOP == 5.5 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x0);
+
+ if (state->TOP == 72) /* TOP == 7.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x1);
+
+ if (state->TOP == 92) /* TOP == 9.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x2);
+
+ if (state->TOP == 110) /* TOP == 11.0 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x3);
+
+ if (state->TOP == 129) /* TOP == 12.9 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x4);
+
+ if (state->TOP == 147) /* TOP == 14.7 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x5);
+
+ if (state->TOP == 168) /* TOP == 16.8 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x6);
+
+ if (state->TOP == 194) /* TOP == 19.4 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x7);
+
+ if (state->TOP == 212) /* TOP == 21.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0x9);
+
+ if (state->TOP == 232) /* TOP == 23.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xA);
+
+ if (state->TOP == 252) /* TOP == 25.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xB);
+
+ if (state->TOP == 271) /* TOP == 27.1 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xC);
+
+ if (state->TOP == 292) /* TOP == 29.2 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xD);
+
+ if (state->TOP == 317) /* TOP == 31.7 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xE);
+
+ if (state->TOP == 349) /* TOP == 34.9 */
+ status += MXL_ControlWrite(fe, AGC_IF, 0xF);
+
+ /* IF Synthesizer Control */
+ status += MXL_IFSynthInit(fe);
+
+ /* IF UpConverter Control */
+ if (state->IF_OUT_LOAD == 200) {
+ status += MXL_ControlWrite(fe, DRV_RES_SEL, 6);
+ status += MXL_ControlWrite(fe, I_DRIVER, 2);
+ }
+ if (state->IF_OUT_LOAD == 300) {
+ status += MXL_ControlWrite(fe, DRV_RES_SEL, 4);
+ status += MXL_ControlWrite(fe, I_DRIVER, 1);
+ }
+
+ /* Anti-Alias Filtering Control
+ * initialise Anti-Aliasing Filter
+ */
+ if (state->Mode) { /* Digital Mode */
+ if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 6280000UL) {
+ status += MXL_ControlWrite(fe, EN_AAF, 1);
+ status += MXL_ControlWrite(fe, EN_3P, 1);
+ status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
+ status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
+ }
+ if ((state->IF_OUT == 36125000UL) ||
+ (state->IF_OUT == 36150000UL)) {
+ status += MXL_ControlWrite(fe, EN_AAF, 1);
+ status += MXL_ControlWrite(fe, EN_3P, 1);
+ status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
+ status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1);
+ }
+ if (state->IF_OUT > 36150000UL) {
+ status += MXL_ControlWrite(fe, EN_AAF, 0);
+ status += MXL_ControlWrite(fe, EN_3P, 1);
+ status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
+ status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1);
+ }
+ } else { /* Analog Mode */
+ if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 5000000UL) {
+ status += MXL_ControlWrite(fe, EN_AAF, 1);
+ status += MXL_ControlWrite(fe, EN_3P, 1);
+ status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
+ status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
+ }
+ if (state->IF_OUT > 5000000UL) {
+ status += MXL_ControlWrite(fe, EN_AAF, 0);
+ status += MXL_ControlWrite(fe, EN_3P, 0);
+ status += MXL_ControlWrite(fe, EN_AUX_3P, 0);
+ status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
+ }
+ }
+
+ /* Demod Clock Out */
+ if (state->CLOCK_OUT)
+ status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 1);
+ else
+ status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 0);
+
+ if (state->DIV_OUT == 1)
+ status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 1);
+ if (state->DIV_OUT == 0)
+ status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 0);
+
+ /* Crystal Control */
+ if (state->CAPSELECT)
+ status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 1);
+ else
+ status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 0);
+
+ if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL)
+ status += MXL_ControlWrite(fe, IF_SEL_DBL, 1);
+ if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL)
+ status += MXL_ControlWrite(fe, IF_SEL_DBL, 0);
+
+ if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL)
+ status += MXL_ControlWrite(fe, RFSYN_R_DIV, 3);
+ if (state->Fxtal > 22000000UL && state->Fxtal <= 32000000UL)
+ status += MXL_ControlWrite(fe, RFSYN_R_DIV, 0);
+
+ /* Misc Controls */
+ if (state->Mode == 0 && state->IF_Mode == 1) /* Analog LowIF mode */
+ status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 0);
+ else
+ status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 1);
+
+ /* status += MXL_ControlRead(fe, IF_DIVVAL, &IF_DIVVAL_Val); */
+
+ /* Set TG_R_DIV */
+ status += MXL_ControlWrite(fe, TG_R_DIV,
+ MXL_Ceiling(state->Fxtal, 1000000));
+
+ /* Apply Default value to BB_INITSTATE_DLPF_TUNE */
+
+ /* RSSI Control */
+ if (state->EN_RSSI) {
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 3);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
+
+ /* TOP point */
+ status += MXL_ControlWrite(fe, RFA_FLR, 0);
+ status += MXL_ControlWrite(fe, RFA_CEIL, 12);
+ }
+
+ /* Modulation type bit settings
+ * Override the control values preset
+ */
+ if (state->Mod_Type == MXL_DVBT) /* DVB-T Mode */ {
+ state->AGC_Mode = 1; /* Single AGC Mode */
+
+ /* Enable RSSI */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
+
+ /* TOP point */
+ status += MXL_ControlWrite(fe, RFA_FLR, 2);
+ status += MXL_ControlWrite(fe, RFA_CEIL, 13);
+ if (state->IF_OUT <= 6280000UL) /* Low IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
+ else /* High IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
+
+ }
+ if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ {
+ state->AGC_Mode = 1; /* Single AGC Mode */
+
+ /* Enable RSSI */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 4);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
+
+ /* TOP point */
+ status += MXL_ControlWrite(fe, RFA_FLR, 2);
+ status += MXL_ControlWrite(fe, RFA_CEIL, 13);
+ status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 1);
+ /* Low Zero */
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5);
+
+ if (state->IF_OUT <= 6280000UL) /* Low IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
+ else /* High IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
+ }
+ if (state->Mod_Type == MXL_QAM) /* QAM Mode */ {
+ state->Mode = MXL_DIGITAL_MODE;
+
+ /* state->AGC_Mode = 1; */ /* Single AGC Mode */
+
+ /* Disable RSSI */ /* change here for v2.6.5 */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
+ /* change here for v2.6.5 */
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
+
+ if (state->IF_OUT <= 6280000UL) /* Low IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
+ else /* High IF */
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
+#if 1
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2);
+#endif
+
+ }
+ if (state->Mod_Type == MXL_ANALOG_CABLE) {
+ /* Analog Cable Mode */
+ /* state->Mode = MXL_DIGITAL_MODE; */
+
+ state->AGC_Mode = 1; /* Single AGC Mode */
+
+ /* Disable RSSI */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+ /* change for 2.6.3 */
+ status += MXL_ControlWrite(fe, AGC_IF, 1);
+ status += MXL_ControlWrite(fe, AGC_RF, 15);
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
+ }
+
+ if (state->Mod_Type == MXL_ANALOG_OTA) {
+ /* Analog OTA Terrestrial mode add for 2.6.7 */
+ /* state->Mode = MXL_ANALOG_MODE; */
+
+ /* Enable RSSI */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
+ status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
+ }
+
+ /* RSSI disable */
+ if (state->EN_RSSI == 0) {
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+ }
+
+ return status;
+}
+
+static u16 MXL_IFSynthInit(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0 ;
+ u32 Fref = 0 ;
+ u32 Kdbl, intModVal ;
+ u32 fracModVal ;
+ Kdbl = 2 ;
+
+ if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL)
+ Kdbl = 2 ;
+ if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL)
+ Kdbl = 1 ;
+
+ /* IF Synthesizer Control */
+ if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF mode */ {
+ if (state->IF_LO == 41000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 328000000UL ;
+ }
+ if (state->IF_LO == 47000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 376000000UL ;
+ }
+ if (state->IF_LO == 54000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 324000000UL ;
+ }
+ if (state->IF_LO == 60000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 39250000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 314000000UL ;
+ }
+ if (state->IF_LO == 39650000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 317200000UL ;
+ }
+ if (state->IF_LO == 40150000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 321200000UL ;
+ }
+ if (state->IF_LO == 40650000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 325200000UL ;
+ }
+ }
+
+ if (state->Mode || (state->Mode == 0 && state->IF_Mode == 0)) {
+ if (state->IF_LO == 57000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 342000000UL ;
+ }
+ if (state->IF_LO == 44000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 352000000UL ;
+ }
+ if (state->IF_LO == 43750000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 350000000UL ;
+ }
+ if (state->IF_LO == 36650000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 366500000UL ;
+ }
+ if (state->IF_LO == 36150000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 361500000UL ;
+ }
+ if (state->IF_LO == 36000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 35250000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 352500000UL ;
+ }
+ if (state->IF_LO == 34750000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 347500000UL ;
+ }
+ if (state->IF_LO == 6280000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 376800000UL ;
+ }
+ if (state->IF_LO == 5000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 4500000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 4570000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 365600000UL ;
+ }
+ if (state->IF_LO == 4000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 57400000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 344400000UL ;
+ }
+ if (state->IF_LO == 44400000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 355200000UL ;
+ }
+ if (state->IF_LO == 44150000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 353200000UL ;
+ }
+ if (state->IF_LO == 37050000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 370500000UL ;
+ }
+ if (state->IF_LO == 36550000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 365500000UL ;
+ }
+ if (state->IF_LO == 36125000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 361250000UL ;
+ }
+ if (state->IF_LO == 6000000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 360000000UL ;
+ }
+ if (state->IF_LO == 5400000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 324000000UL ;
+ }
+ if (state->IF_LO == 5380000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
+ Fref = 322800000UL ;
+ }
+ if (state->IF_LO == 5200000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 374400000UL ;
+ }
+ if (state->IF_LO == 4900000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 352800000UL ;
+ }
+ if (state->IF_LO == 4400000UL) {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 352000000UL ;
+ }
+ if (state->IF_LO == 4063000UL) /* add for 2.6.8 */ {
+ status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05);
+ status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
+ Fref = 365670000UL ;
+ }
+ }
+ /* CHCAL_INT_MOD_IF */
+ /* CHCAL_FRAC_MOD_IF */
+ intModVal = Fref / (state->Fxtal * Kdbl/2);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_IF, intModVal);
+
+ fracModVal = (2<<15)*(Fref/1000 - (state->Fxtal/1000 * Kdbl/2) *
+ intModVal);
+
+ fracModVal = fracModVal / ((state->Fxtal * Kdbl/2)/1000);
+ status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_IF, fracModVal);
+
+ return status ;
+}
+
+static u32 MXL_GetXtalInt(u32 Xtal_Freq)
+{
+ if ((Xtal_Freq % 1000000) == 0)
+ return (Xtal_Freq / 10000);
+ else
+ return (((Xtal_Freq / 1000000) + 1)*100);
+}
+
+static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0;
+ u32 divider_val, E3, E4, E5, E5A;
+ u32 Fmax, Fmin, FmaxBin, FminBin;
+ u32 Kdbl_RF = 2;
+ u32 tg_divval;
+ u32 tg_lo;
+ u32 Xtal_Int;
+
+ u32 Fref_TG;
+ u32 Fvco;
+
+ Xtal_Int = MXL_GetXtalInt(state->Fxtal);
+
+ state->RF_IN = RF_Freq;
+
+ MXL_SynthRFTGLO_Calc(fe);
+
+ if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL)
+ Kdbl_RF = 2;
+ if (state->Fxtal > 22000000 && state->Fxtal <= 32000000)
+ Kdbl_RF = 1;
+
+ /* Downconverter Controls
+ * Look-Up Table Implementation for:
+ * DN_POLY
+ * DN_RFGAIN
+ * DN_CAP_RFLPF
+ * DN_EN_VHFUHFBAR
+ * DN_GAIN_ADJUST
+ * Change the boundary reference from RF_IN to RF_LO
+ */
+ if (state->RF_LO < 40000000UL)
+ return -1;
+
+ if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 2);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 3);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 423);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1);
+ }
+ if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 3);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 222);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1);
+ }
+ if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 3);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 147);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2);
+ }
+ if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 3);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 9);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2);
+ }
+ if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 3);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3);
+ }
+ if (state->RF_LO > 300000000UL && state->RF_LO <= 650000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 1);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3);
+ }
+ if (state->RF_LO > 650000000UL && state->RF_LO <= 900000000UL) {
+ status += MXL_ControlWrite(fe, DN_POLY, 3);
+ status += MXL_ControlWrite(fe, DN_RFGAIN, 2);
+ status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0);
+ status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0);
+ status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3);
+ }
+ if (state->RF_LO > 900000000UL)
+ return -1;
+
+ /* DN_IQTNBUF_AMP */
+ /* DN_IQTNGNBFBIAS_BST */
+ if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 300000000UL && state->RF_LO <= 400000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 400000000UL && state->RF_LO <= 450000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 450000000UL && state->RF_LO <= 500000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 500000000UL && state->RF_LO <= 550000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 550000000UL && state->RF_LO <= 600000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 600000000UL && state->RF_LO <= 650000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 650000000UL && state->RF_LO <= 700000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 700000000UL && state->RF_LO <= 750000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 750000000UL && state->RF_LO <= 800000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0);
+ }
+ if (state->RF_LO > 800000000UL && state->RF_LO <= 850000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 10);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 1);
+ }
+ if (state->RF_LO > 850000000UL && state->RF_LO <= 900000000UL) {
+ status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 10);
+ status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 1);
+ }
+
+ /*
+ * Set RF Synth and LO Path Control
+ *
+ * Look-Up table implementation for:
+ * RFSYN_EN_OUTMUX
+ * RFSYN_SEL_VCO_OUT
+ * RFSYN_SEL_VCO_HI
+ * RFSYN_SEL_DIVM
+ * RFSYN_RF_DIV_BIAS
+ * DN_SEL_FREQ
+ *
+ * Set divider_val, Fmax, Fmix to use in Equations
+ */
+ FminBin = 28000000UL ;
+ FmaxBin = 42500000UL ;
+ if (state->RF_LO >= 40000000UL && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1);
+ divider_val = 64 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 42500000UL ;
+ FmaxBin = 56000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1);
+ divider_val = 64 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 56000000UL ;
+ FmaxBin = 85000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1);
+ divider_val = 32 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 85000000UL ;
+ FmaxBin = 112000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1);
+ divider_val = 32 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 112000000UL ;
+ FmaxBin = 170000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2);
+ divider_val = 16 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 170000000UL ;
+ FmaxBin = 225000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2);
+ divider_val = 16 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 225000000UL ;
+ FmaxBin = 300000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 4);
+ divider_val = 8 ;
+ Fmax = 340000000UL ;
+ Fmin = FminBin ;
+ }
+ FminBin = 300000000UL ;
+ FmaxBin = 340000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ divider_val = 8 ;
+ Fmax = FmaxBin ;
+ Fmin = 225000000UL ;
+ }
+ FminBin = 340000000UL ;
+ FmaxBin = 450000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 2);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ divider_val = 8 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 450000000UL ;
+ FmaxBin = 680000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ divider_val = 4 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 680000000UL ;
+ FmaxBin = 900000000UL ;
+ if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ divider_val = 4 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+
+ /* CHCAL_INT_MOD_RF
+ * CHCAL_FRAC_MOD_RF
+ * RFSYN_LPF_R
+ * CHCAL_EN_INT_RF
+ */
+ /* Equation E3 RFSYN_VCO_BIAS */
+ E3 = (((Fmax-state->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ;
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, E3);
+
+ /* Equation E4 CHCAL_INT_MOD_RF */
+ E4 = (state->RF_LO*divider_val/1000)/(2*state->Fxtal*Kdbl_RF/1000);
+ MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, E4);
+
+ /* Equation E5 CHCAL_FRAC_MOD_RF CHCAL_EN_INT_RF */
+ E5 = ((2<<17)*(state->RF_LO/10000*divider_val -
+ (E4*(2*state->Fxtal*Kdbl_RF)/10000))) /
+ (2*state->Fxtal*Kdbl_RF/10000);
+
+ status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5);
+
+ /* Equation E5A RFSYN_LPF_R */
+ E5A = (((Fmax - state->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ;
+ status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A);
+
+ /* Euqation E5B CHCAL_EN_INIT_RF */
+ status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0));
+ /*if (E5 == 0)
+ * status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1);
+ *else
+ * status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5);
+ */
+
+ /*
+ * Set TG Synth
+ *
+ * Look-Up table implementation for:
+ * TG_LO_DIVVAL
+ * TG_LO_SELVAL
+ *
+ * Set divider_val, Fmax, Fmix to use in Equations
+ */
+ if (state->TG_LO < 33000000UL)
+ return -1;
+
+ FminBin = 33000000UL ;
+ FmaxBin = 50000000UL ;
+ if (state->TG_LO >= FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x6);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0);
+ divider_val = 36 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 50000000UL ;
+ FmaxBin = 67000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x1);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0);
+ divider_val = 24 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 67000000UL ;
+ FmaxBin = 100000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0xC);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2);
+ divider_val = 18 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 100000000UL ;
+ FmaxBin = 150000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2);
+ divider_val = 12 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 150000000UL ;
+ FmaxBin = 200000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2);
+ divider_val = 8 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 200000000UL ;
+ FmaxBin = 300000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3);
+ divider_val = 6 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 300000000UL ;
+ FmaxBin = 400000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3);
+ divider_val = 4 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 400000000UL ;
+ FmaxBin = 600000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7);
+ divider_val = 3 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+ FminBin = 600000000UL ;
+ FmaxBin = 900000000UL ;
+ if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
+ status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0);
+ status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7);
+ divider_val = 2 ;
+ Fmax = FmaxBin ;
+ Fmin = FminBin ;
+ }
+
+ /* TG_DIV_VAL */
+ tg_divval = (state->TG_LO*divider_val/100000) *
+ (MXL_Ceiling(state->Fxtal, 1000000) * 100) /
+ (state->Fxtal/1000);
+
+ status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval);
+
+ if (state->TG_LO > 600000000UL)
+ status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval + 1);
+
+ Fmax = 1800000000UL ;
+ Fmin = 1200000000UL ;
+
+ /* prevent overflow of 32 bit unsigned integer, use
+ * following equation. Edit for v2.6.4
+ */
+ /* Fref_TF = Fref_TG * 1000 */
+ Fref_TG = (state->Fxtal/1000) / MXL_Ceiling(state->Fxtal, 1000000);
+
+ /* Fvco = Fvco/10 */
+ Fvco = (state->TG_LO/10000) * divider_val * Fref_TG;
+
+ tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
+
+ /* below equation is same as above but much harder to debug.
+ * tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
+ * ((state->TG_LO/10000)*divider_val *
+ * (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
+ * Xtal_Int/100) + 8;
+ */
+
+ status += MXL_ControlWrite(fe, TG_VCO_BIAS , tg_lo);
+
+ /* add for 2.6.5 Special setting for QAM */
+ if (state->Mod_Type == MXL_QAM) {
+ if (state->RF_IN < 680000000)
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
+ else
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2);
+ }
+
+ /* Off Chip Tracking Filter Control */
+ if (state->TF_Type == MXL_TF_OFF) {
+ /* Tracking Filter Off State; turn off all the banks */
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 3, 1); /* Bank1 Off */
+ status += MXL_SetGPIO(fe, 1, 1); /* Bank2 Off */
+ status += MXL_SetGPIO(fe, 4, 1); /* Bank3 Off */
+ }
+
+ if (state->TF_Type == MXL_TF_C) /* Tracking Filter type C */ {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ }
+ if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ }
+ if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ }
+ if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 0);
+ }
+ if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 29);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 0);
+ }
+ if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 0);
+ }
+ if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 16);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ }
+ if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 7);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ }
+ if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_C_H) {
+
+ /* Tracking Filter type C-H for Hauppauge only */
+ status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ }
+ if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ }
+ if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ }
+ if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ }
+ if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ }
+ if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ }
+ if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ }
+ if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ }
+ if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_D) { /* Tracking Filter type D */
+
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_D_L) {
+
+ /* Tracking Filter type D-L for Lumanate ONLY change 2.6.3 */
+ status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
+
+ /* if UHF and terrestrial => Turn off Tracking Filter */
+ if (state->RF_IN >= 471000000 &&
+ (state->RF_IN - 471000000)%6000000 != 0) {
+ /* Turn off all the banks */
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_ControlWrite(fe, AGC_IF, 10);
+ } else {
+ /* if VHF or cable => Turn on Tracking Filter */
+ if (state->RF_IN >= 43000000 &&
+ state->RF_IN < 140000000) {
+
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 140000000 &&
+ state->RF_IN < 240000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 240000000 &&
+ state->RF_IN < 340000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 340000000 &&
+ state->RF_IN < 430000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 430000000 &&
+ state->RF_IN < 470000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 470000000 &&
+ state->RF_IN < 570000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 570000000 &&
+ state->RF_IN < 620000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 620000000 &&
+ state->RF_IN < 760000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 760000000 &&
+ state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_E) /* Tracking Filter type E */ {
+
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_F) {
+
+ /* Tracking Filter type F */
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 160000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 160000000 && state->RF_IN < 210000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 210000000 && state->RF_IN < 300000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 300000000 && state->RF_IN < 390000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 390000000 && state->RF_IN < 515000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 515000000 && state->RF_IN < 650000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 650000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_E_2) {
+
+ /* Tracking Filter type E_2 */
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_G) {
+
+ /* Tracking Filter type G add for v2.6.8 */
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ if (state->RF_IN >= 50000000 && state->RF_IN < 190000000) {
+
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 190000000 && state->RF_IN < 280000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 280000000 && state->RF_IN < 350000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 400000000 && state->RF_IN < 470000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 640000000 && state->RF_IN < 820000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 820000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+
+ if (state->TF_Type == MXL_TF_E_NA) {
+
+ /* Tracking Filter type E-NA for Empia ONLY change for 2.6.8 */
+ status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
+
+ /* if UHF and terrestrial=> Turn off Tracking Filter */
+ if (state->RF_IN >= 471000000 &&
+ (state->RF_IN - 471000000)%6000000 != 0) {
+
+ /* Turn off all the banks */
+ status += MXL_SetGPIO(fe, 3, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+
+ /* 2.6.12 Turn on RSSI */
+ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
+ status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
+ status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
+
+ /* RSSI reference point */
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
+ status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
+
+ /* following parameter is from analog OTA mode,
+ * can be change to seek better performance */
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
+ } else {
+ /* if VHF or Cable => Turn on Tracking Filter */
+
+ /* 2.6.12 Turn off RSSI */
+ status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
+
+ /* change back from above condition */
+ status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5);
+
+
+ if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
+
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 0);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 0);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 0);
+ }
+ if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) {
+ status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
+ status += MXL_SetGPIO(fe, 4, 1);
+ status += MXL_SetGPIO(fe, 1, 1);
+ status += MXL_SetGPIO(fe, 3, 1);
+ }
+ }
+ }
+ return status ;
+}
+
+static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
+{
+ u16 status = 0;
+
+ if (GPIO_Num == 1)
+ status += MXL_ControlWrite(fe, GPIO_1B, GPIO_Val ? 0 : 1);
+
+ /* GPIO2 is not available */
+
+ if (GPIO_Num == 3) {
+ if (GPIO_Val == 1) {
+ status += MXL_ControlWrite(fe, GPIO_3, 0);
+ status += MXL_ControlWrite(fe, GPIO_3B, 0);
+ }
+ if (GPIO_Val == 0) {
+ status += MXL_ControlWrite(fe, GPIO_3, 1);
+ status += MXL_ControlWrite(fe, GPIO_3B, 1);
+ }
+ if (GPIO_Val == 3) { /* tri-state */
+ status += MXL_ControlWrite(fe, GPIO_3, 0);
+ status += MXL_ControlWrite(fe, GPIO_3B, 1);
+ }
+ }
+ if (GPIO_Num == 4) {
+ if (GPIO_Val == 1) {
+ status += MXL_ControlWrite(fe, GPIO_4, 0);
+ status += MXL_ControlWrite(fe, GPIO_4B, 0);
+ }
+ if (GPIO_Val == 0) {
+ status += MXL_ControlWrite(fe, GPIO_4, 1);
+ status += MXL_ControlWrite(fe, GPIO_4B, 1);
+ }
+ if (GPIO_Val == 3) { /* tri-state */
+ status += MXL_ControlWrite(fe, GPIO_4, 0);
+ status += MXL_ControlWrite(fe, GPIO_4B, 1);
+ }
+ }
+
+ return status;
+}
+
+static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
+{
+ u16 status = 0;
+
+ /* Will write ALL Matching Control Name */
+ /* Write Matching INIT Control */
+ status += MXL_ControlWrite_Group(fe, ControlNum, value, 1);
+ /* Write Matching CH Control */
+ status += MXL_ControlWrite_Group(fe, ControlNum, value, 2);
+#ifdef _MXL_INTERNAL
+ /* Write Matching MXL Control */
+ status += MXL_ControlWrite_Group(fe, ControlNum, value, 3);
+#endif
+ return status;
+}
+
+static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
+ u32 value, u16 controlGroup)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 i, j, k;
+ u32 highLimit;
+ u32 ctrlVal;
+
+ if (controlGroup == 1) /* Initial Control */ {
+
+ for (i = 0; i < state->Init_Ctrl_Num; i++) {
+
+ if (controlNum == state->Init_Ctrl[i].Ctrl_Num) {
+
+ highLimit = 1 << state->Init_Ctrl[i].size;
+ if (value < highLimit) {
+ for (j = 0; j < state->Init_Ctrl[i].size; j++) {
+ state->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
+ MXL_RegWriteBit(fe, (u8)(state->Init_Ctrl[i].addr[j]),
+ (u8)(state->Init_Ctrl[i].bit[j]),
+ (u8)((value>>j) & 0x01));
+ }
+ ctrlVal = 0;
+ for (k = 0; k < state->Init_Ctrl[i].size; k++)
+ ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k);
+ } else
+ return -1;
+ }
+ }
+ }
+ if (controlGroup == 2) /* Chan change Control */ {
+
+ for (i = 0; i < state->CH_Ctrl_Num; i++) {
+
+ if (controlNum == state->CH_Ctrl[i].Ctrl_Num) {
+
+ highLimit = 1 << state->CH_Ctrl[i].size;
+ if (value < highLimit) {
+ for (j = 0; j < state->CH_Ctrl[i].size; j++) {
+ state->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
+ MXL_RegWriteBit(fe, (u8)(state->CH_Ctrl[i].addr[j]),
+ (u8)(state->CH_Ctrl[i].bit[j]),
+ (u8)((value>>j) & 0x01));
+ }
+ ctrlVal = 0;
+ for (k = 0; k < state->CH_Ctrl[i].size; k++)
+ ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k);
+ } else
+ return -1;
+ }
+ }
+ }
+#ifdef _MXL_INTERNAL
+ if (controlGroup == 3) /* Maxlinear Control */ {
+
+ for (i = 0; i < state->MXL_Ctrl_Num; i++) {
+
+ if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) {
+
+ highLimit = (1 << state->MXL_Ctrl[i].size);
+ if (value < highLimit) {
+ for (j = 0; j < state->MXL_Ctrl[i].size; j++) {
+ state->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
+ MXL_RegWriteBit(fe, (u8)(state->MXL_Ctrl[i].addr[j]),
+ (u8)(state->MXL_Ctrl[i].bit[j]),
+ (u8)((value>>j) & 0x01));
+ }
+ ctrlVal = 0;
+ for (k = 0; k < state->MXL_Ctrl[i].size; k++)
+ ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k);
+ } else
+ return -1;
+ }
+ }
+ }
+#endif
+ return 0 ; /* successful return */
+}
+
+static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ int i ;
+
+ for (i = 0; i < 104; i++) {
+ if (RegNum == state->TunerRegs[i].Reg_Num) {
+ *RegVal = (u8)(state->TunerRegs[i].Reg_Val);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u32 ctrlVal ;
+ u16 i, k ;
+
+ for (i = 0; i < state->Init_Ctrl_Num ; i++) {
+
+ if (controlNum == state->Init_Ctrl[i].Ctrl_Num) {
+
+ ctrlVal = 0;
+ for (k = 0; k < state->Init_Ctrl[i].size; k++)
+ ctrlVal += state->Init_Ctrl[i].val[k] * (1<<k);
+ *value = ctrlVal;
+ return 0;
+ }
+ }
+
+ for (i = 0; i < state->CH_Ctrl_Num ; i++) {
+
+ if (controlNum == state->CH_Ctrl[i].Ctrl_Num) {
+
+ ctrlVal = 0;
+ for (k = 0; k < state->CH_Ctrl[i].size; k++)
+ ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k);
+ *value = ctrlVal;
+ return 0;
+
+ }
+ }
+
+#ifdef _MXL_INTERNAL
+ for (i = 0; i < state->MXL_Ctrl_Num ; i++) {
+
+ if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) {
+
+ ctrlVal = 0;
+ for (k = 0; k < state->MXL_Ctrl[i].size; k++)
+ ctrlVal += state->MXL_Ctrl[i].val[k] * (1<<k);
+ *value = ctrlVal;
+ return 0;
+
+ }
+ }
+#endif
+ return 1;
+}
+
+static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
+ u8 bitVal)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ int i ;
+
+ const u8 AND_MAP[8] = {
+ 0xFE, 0xFD, 0xFB, 0xF7,
+ 0xEF, 0xDF, 0xBF, 0x7F } ;
+
+ const u8 OR_MAP[8] = {
+ 0x01, 0x02, 0x04, 0x08,
+ 0x10, 0x20, 0x40, 0x80 } ;
+
+ for (i = 0; i < state->TunerRegs_Num; i++) {
+ if (state->TunerRegs[i].Reg_Num == address) {
+ if (bitVal)
+ state->TunerRegs[i].Reg_Val |= OR_MAP[bit];
+ else
+ state->TunerRegs[i].Reg_Val &= AND_MAP[bit];
+ break ;
+ }
+ }
+}
+
+static u32 MXL_Ceiling(u32 value, u32 resolution)
+{
+ return (value/resolution + (value % resolution > 0 ? 1 : 0));
+}
+
+/* Retrieve the Initialzation Registers */
+static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
+ u8 *RegVal, int *count)
+{
+ u16 status = 0;
+ int i ;
+
+ u8 RegAddr[] = {
+ 11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73,
+ 76, 77, 91, 134, 135, 137, 147,
+ 156, 166, 167, 168, 25 };
+
+ *count = sizeof(RegAddr) / sizeof(u8);
+
+ status += MXL_BlockInit(fe);
+
+ for (i = 0 ; i < *count; i++) {
+ RegNum[i] = RegAddr[i];
+ status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
+ }
+
+ return status;
+}
+
+static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal,
+ int *count)
+{
+ u16 status = 0;
+ int i ;
+
+/* add 77, 166, 167, 168 register for 2.6.12 */
+#ifdef _MXL_PRODUCTION
+ u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106,
+ 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ;
+#else
+ u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106,
+ 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ;
+ /*
+ u8 RegAddr[171];
+ for (i = 0; i <= 170; i++)
+ RegAddr[i] = i;
+ */
+#endif
+
+ *count = sizeof(RegAddr) / sizeof(u8);
+
+ for (i = 0 ; i < *count; i++) {
+ RegNum[i] = RegAddr[i];
+ status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
+ }
+
+ return status;
+}
+
+static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
+ u8 *RegVal, int *count)
+{
+ u16 status = 0;
+ int i;
+
+ u8 RegAddr[] = {43, 136};
+
+ *count = sizeof(RegAddr) / sizeof(u8);
+
+ for (i = 0; i < *count; i++) {
+ RegNum[i] = RegAddr[i];
+ status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
+ }
+
+ return status;
+}
+
+static u16 MXL_GetMasterControl(u8 *MasterReg, int state)
+{
+ if (state == 1) /* Load_Start */
+ *MasterReg = 0xF3;
+ if (state == 2) /* Power_Down */
+ *MasterReg = 0x41;
+ if (state == 3) /* Synth_Reset */
+ *MasterReg = 0xB1;
+ if (state == 4) /* Seq_Off */
+ *MasterReg = 0xF1;
+
+ return 0;
+}
+
+#ifdef _MXL_PRODUCTION
+static u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0 ;
+
+ if (VCO_Range == 1) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ if (state->Mode == 0 && state->IF_Mode == 1) {
+ /* Analog Low IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 180224);
+ }
+ if (state->Mode == 0 && state->IF_Mode == 0) {
+ /* Analog Zero IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 222822);
+ }
+ if (state->Mode == 1) /* Digital Mode */ {
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 229376);
+ }
+ }
+
+ if (VCO_Range == 2) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41);
+ if (state->Mode == 0 && state->IF_Mode == 1) {
+ /* Analog Low IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 206438);
+ }
+ if (state->Mode == 0 && state->IF_Mode == 0) {
+ /* Analog Zero IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 206438);
+ }
+ if (state->Mode == 1) /* Digital Mode */ {
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 16384);
+ }
+ }
+
+ if (VCO_Range == 3) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
+ if (state->Mode == 0 && state->IF_Mode == 1) {
+ /* Analog Low IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 173670);
+ }
+ if (state->Mode == 0 && state->IF_Mode == 0) {
+ /* Analog Zero IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 173670);
+ }
+ if (state->Mode == 1) /* Digital Mode */ {
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 245760);
+ }
+ }
+
+ if (VCO_Range == 4) {
+ status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
+ status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
+ status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
+ status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
+ status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
+ if (state->Mode == 0 && state->IF_Mode == 1) {
+ /* Analog Low IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 206438);
+ }
+ if (state->Mode == 0 && state->IF_Mode == 0) {
+ /* Analog Zero IF Mode */
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 206438);
+ }
+ if (state->Mode == 1) /* Digital Mode */ {
+ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
+ status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
+ status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
+ status += MXL_ControlWrite(fe,
+ CHCAL_FRAC_MOD_RF, 212992);
+ }
+ }
+
+ return status;
+}
+
+static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u16 status = 0;
+
+ if (Hystersis == 1)
+ status += MXL_ControlWrite(fe, DN_BYPASS_AGC_I2C, 1);
+
+ return status;
+}
+#endif
+/* End: Reference driver code found in the Realtek driver that
+ * is copyright MaxLinear */
+
+/* ----------------------------------------------------------------
+ * Begin: Everything after here is new code to adapt the
+ * proprietary Realtek driver into a Linux API tuner.
+ * Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+ */
+static int mxl5005s_reset(struct dvb_frontend *fe)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ int ret = 0;
+
+ u8 buf[2] = { 0xff, 0x00 };
+ struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
+ .buf = buf, .len = 2 };
+
+ dprintk(2, "%s()\n", __func__);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "mxl5005s I2C reset failed\n");
+ ret = -EREMOTEIO;
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return ret;
+}
+
+/* Write a single byte to a single reg, latch the value if required by
+ * following the transaction with the latch byte.
+ */
+static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE };
+ struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
+ .buf = buf, .len = 3 };
+
+ if (latch == 0)
+ msg.len = 2;
+
+ dprintk(2, "%s(0x%x, 0x%x, 0x%x)\n", __func__, reg, val, msg.addr);
+
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "mxl5005s I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
+ u8 *datatable, u8 len)
+{
+ int ret = 0, i;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ for (i = 0 ; i < len-1; i++) {
+ ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0);
+ if (ret < 0)
+ break;
+ }
+
+ ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ return ret;
+}
+
+static int mxl5005s_init(struct dvb_frontend *fe)
+{
+ dprintk(1, "%s()\n", __func__);
+ return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
+}
+
+static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type,
+ u32 bandwidth)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+
+ u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
+ u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
+ int TableLen;
+
+ dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth);
+
+ mxl5005s_reset(fe);
+
+ /* Tuner initialization stage 0 */
+ MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
+ AddrTable[0] = MASTER_CONTROL_ADDR;
+ ByteTable[0] |= state->config->AgcMasterByte;
+
+ mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
+
+ mxl5005s_AssignTunerMode(fe, mod_type, bandwidth);
+
+ /* Tuner initialization stage 1 */
+ MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);
+
+ mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
+
+ return 0;
+}
+
+static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
+ u32 bandwidth)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ struct mxl5005s_config *c = state->config;
+
+ InitTunerControls(fe);
+
+ /* Set MxL5005S parameters. */
+ MXL5005_TunerConfig(
+ fe,
+ c->mod_mode,
+ c->if_mode,
+ bandwidth,
+ c->if_freq,
+ c->xtal_freq,
+ c->agc_mode,
+ c->top,
+ c->output_load,
+ c->clock_out,
+ c->div_out,
+ c->cap_select,
+ c->rssi_enable,
+ mod_type,
+ c->tracking_filter);
+
+ return 0;
+}
+
+static int mxl5005s_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ u32 req_mode, req_bw = 0;
+ int ret;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (fe->ops.info.type == FE_ATSC) {
+ switch (params->u.vsb.modulation) {
+ case VSB_8:
+ req_mode = MXL_ATSC; break;
+ default:
+ case QAM_64:
+ case QAM_256:
+ case QAM_AUTO:
+ req_mode = MXL_QAM; break;
+ }
+ } else
+ req_mode = MXL_DVBT;
+
+ /* Change tuner for new modulation type if reqd */
+ if (req_mode != state->current_mode) {
+ switch (req_mode) {
+ case VSB_8:
+ case QAM_64:
+ case QAM_256:
+ case QAM_AUTO:
+ req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ break;
+ default:
+ /* Assume DVB-T */
+ switch (params->u.ofdm.bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ break;
+ case BANDWIDTH_7_MHZ:
+ req_bw = MXL5005S_BANDWIDTH_7MHZ;
+ break;
+ case BANDWIDTH_AUTO:
+ case BANDWIDTH_8_MHZ:
+ req_bw = MXL5005S_BANDWIDTH_8MHZ;
+ break;
+ }
+ }
+
+ state->current_mode = req_mode;
+ ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
+
+ } else
+ ret = 0;
+
+ if (ret == 0) {
+ dprintk(1, "%s() freq=%d\n", __func__, params->frequency);
+ ret = mxl5005s_SetRfFreqHz(fe, params->frequency);
+ }
+
+ return ret;
+}
+
+static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ dprintk(1, "%s()\n", __func__);
+
+ *frequency = state->RF_IN;
+
+ return 0;
+}
+
+static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct mxl5005s_state *state = fe->tuner_priv;
+ dprintk(1, "%s()\n", __func__);
+
+ *bandwidth = state->Chan_Bandwidth;
+
+ return 0;
+}
+
+static int mxl5005s_release(struct dvb_frontend *fe)
+{
+ dprintk(1, "%s()\n", __func__);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
+ .info = {
+ .name = "MaxLinear MXL5005S",
+ .frequency_min = 48000000,
+ .frequency_max = 860000000,
+ .frequency_step = 50000,
+ },
+
+ .release = mxl5005s_release,
+ .init = mxl5005s_init,
+
+ .set_params = mxl5005s_set_params,
+ .get_frequency = mxl5005s_get_frequency,
+ .get_bandwidth = mxl5005s_get_bandwidth,
+};
+
+struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mxl5005s_config *config)
+{
+ struct mxl5005s_state *state = NULL;
+ dprintk(1, "%s()\n", __func__);
+
+ state = kzalloc(sizeof(struct mxl5005s_state), GFP_KERNEL);
+ if (state == NULL)
+ return NULL;
+
+ state->frontend = fe;
+ state->config = config;
+ state->i2c = i2c;
+ state->current_mode = MXL_QAM;
+
+ printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n",
+ config->i2c_address);
+
+ memcpy(&fe->ops.tuner_ops, &mxl5005s_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = state;
+ return fe;
+}
+EXPORT_SYMBOL(mxl5005s_attach);
+
+MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/common/tuners/mxl5005s.h b/linux/drivers/media/common/tuners/mxl5005s.h
new file mode 100644
index 000000000..396db150b
--- /dev/null
+++ b/linux/drivers/media/common/tuners/mxl5005s.h
@@ -0,0 +1,131 @@
+/*
+ MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
+
+ Copyright (C) 2008 MaxLinear
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __MXL5005S_H
+#define __MXL5005S_H
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+struct mxl5005s_config {
+
+ /* 7 bit i2c address */
+ u8 i2c_address;
+
+#define IF_FREQ_4570000HZ 4570000
+#define IF_FREQ_4571429HZ 4571429
+#define IF_FREQ_5380000HZ 5380000
+#define IF_FREQ_36000000HZ 36000000
+#define IF_FREQ_36125000HZ 36125000
+#define IF_FREQ_36166667HZ 36166667
+#define IF_FREQ_44000000HZ 44000000
+ u32 if_freq;
+
+#define CRYSTAL_FREQ_4000000HZ 4000000
+#define CRYSTAL_FREQ_16000000HZ 16000000
+#define CRYSTAL_FREQ_25000000HZ 25000000
+#define CRYSTAL_FREQ_28800000HZ 28800000
+ u32 xtal_freq;
+
+#define MXL_DUAL_AGC 0
+#define MXL_SINGLE_AGC 1
+ u8 agc_mode;
+
+#define MXL_TF_DEFAULT 0
+#define MXL_TF_OFF 1
+#define MXL_TF_C 2
+#define MXL_TF_C_H 3
+#define MXL_TF_D 4
+#define MXL_TF_D_L 5
+#define MXL_TF_E 6
+#define MXL_TF_F 7
+#define MXL_TF_E_2 8
+#define MXL_TF_E_NA 9
+#define MXL_TF_G 10
+ u8 tracking_filter;
+
+#define MXL_RSSI_DISABLE 0
+#define MXL_RSSI_ENABLE 1
+ u8 rssi_enable;
+
+#define MXL_CAP_SEL_DISABLE 0
+#define MXL_CAP_SEL_ENABLE 1
+ u8 cap_select;
+
+#define MXL_DIV_OUT_1 0
+#define MXL_DIV_OUT_4 1
+ u8 div_out;
+
+#define MXL_CLOCK_OUT_DISABLE 0
+#define MXL_CLOCK_OUT_ENABLE 1
+ u8 clock_out;
+
+#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200
+#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300
+ u32 output_load;
+
+#define MXL5005S_TOP_5P5 55
+#define MXL5005S_TOP_7P2 72
+#define MXL5005S_TOP_9P2 92
+#define MXL5005S_TOP_11P0 110
+#define MXL5005S_TOP_12P9 129
+#define MXL5005S_TOP_14P7 147
+#define MXL5005S_TOP_16P8 168
+#define MXL5005S_TOP_19P4 194
+#define MXL5005S_TOP_21P2 212
+#define MXL5005S_TOP_23P2 232
+#define MXL5005S_TOP_25P2 252
+#define MXL5005S_TOP_27P1 271
+#define MXL5005S_TOP_29P2 292
+#define MXL5005S_TOP_31P7 317
+#define MXL5005S_TOP_34P9 349
+ u32 top;
+
+#define MXL_ANALOG_MODE 0
+#define MXL_DIGITAL_MODE 1
+ u8 mod_mode;
+
+#define MXL_ZERO_IF 0
+#define MXL_LOW_IF 1
+ u8 if_mode;
+
+ /* Stuff I don't know what to do with */
+ u8 AgcMasterByte;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || \
+ (defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE))
+extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mxl5005s_config *config);
+#else
+static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct mxl5005s_config *config)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_TUNER_MXL5005S */
+
+#endif /* __MXL5005S_H */
+
diff --git a/linux/drivers/media/dvb/frontends/qt1010.c b/linux/drivers/media/common/tuners/qt1010.c
index 4afed44ab..4afed44ab 100644
--- a/linux/drivers/media/dvb/frontends/qt1010.c
+++ b/linux/drivers/media/common/tuners/qt1010.c
diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/common/tuners/qt1010.h
index 3ab4aa045..807fb7b61 100644
--- a/linux/drivers/media/dvb/frontends/qt1010.h
+++ b/linux/drivers/media/common/tuners/qt1010.h
@@ -36,7 +36,7 @@ struct qt1010_config {
* @param cfg tuner hw based configuration
* @return fe pointer on success, NULL on failure
*/
-#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_QT1010) || (defined(CONFIG_MEDIA_TUNER_QT1010_MODULE) && defined(MODULE))
extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct qt1010_config *cfg);
@@ -45,9 +45,9 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct qt1010_config *cfg)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TUNER_QT1010
+#endif // CONFIG_MEDIA_TUNER_QT1010
#endif
diff --git a/linux/drivers/media/dvb/frontends/qt1010_priv.h b/linux/drivers/media/common/tuners/qt1010_priv.h
index 090cf475f..090cf475f 100644
--- a/linux/drivers/media/dvb/frontends/qt1010_priv.h
+++ b/linux/drivers/media/common/tuners/qt1010_priv.h
diff --git a/linux/drivers/media/dvb/frontends/tda18271-common.c b/linux/drivers/media/common/tuners/tda18271-common.c
index 43c0bec83..1eaff90da 100644
--- a/linux/drivers/media/dvb/frontends/tda18271-common.c
+++ b/linux/drivers/media/common/tuners/tda18271-common.c
@@ -227,9 +227,8 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe,
regs[r_cp] &= ~0x20;
regs[r_cp] |= ((force & 1) << 5);
- tda18271_write_regs(fe, r_cp, 1);
- return 0;
+ return tda18271_write_regs(fe, r_cp, 1);
}
int tda18271_init_regs(struct dvb_frontend *fe)
@@ -555,16 +554,15 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe,
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
- tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
+ if (tda18271_debug & DBG_ADV)
+ tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
regs[R_EP3] |= sm ? (1 << 7) : 0 |
sm_lt ? (1 << 6) : 0 |
sm_xt ? (1 << 5) : 0;
- tda18271_write_regs(fe, R_EP3, 1);
-
- return 0;
+ return tda18271_write_regs(fe, R_EP3, 1);
}
/*---------------------------------------------------------------------*/
@@ -578,7 +576,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
u32 div;
int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_MPD] = (0x77 & pd);
@@ -610,7 +608,7 @@ int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
u32 div;
int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_CPD] = pd;
@@ -634,7 +632,7 @@ int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
u8 val;
int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_EP1] &= ~0x07; /* clear bp filter bits */
@@ -651,7 +649,7 @@ int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
u8 val;
int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_EB13] &= ~0x7c; /* clear k & m bits */
@@ -668,7 +666,7 @@ int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
u8 val;
int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_EP2] &= ~0xe0; /* clear rf band bits */
@@ -685,7 +683,7 @@ int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
u8 val;
int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
@@ -702,7 +700,7 @@ int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
u8 val;
int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
regs[R_EP5] &= ~0x07;
@@ -718,11 +716,11 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
unsigned char *regs = priv->tda18271_regs;
u8 val;
- tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
regs[R_EB14] = val;
- return 0;
+ return ret;
}
/*
diff --git a/linux/drivers/media/dvb/frontends/tda18271-fe.c b/linux/drivers/media/common/tuners/tda18271-fe.c
index 355c37a42..f9e2957bb 100644
--- a/linux/drivers/media/dvb/frontends/tda18271-fe.c
+++ b/linux/drivers/media/common/tuners/tda18271-fe.c
@@ -52,6 +52,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
u32 N;
/* update TV broadcast parameters */
@@ -86,7 +87,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
/* update rf top / if top */
regs[R_EB22] = 0x00;
regs[R_EB22] |= map->rfagc_top;
- tda18271_write_regs(fe, R_EB22, 1);
+ ret = tda18271_write_regs(fe, R_EB22, 1);
+ if (tda_fail(ret))
+ goto fail;
/* --------------------------------------------------------------- */
@@ -122,7 +125,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
/* agc1 has priority on agc2 */
regs[R_EB1] &= ~0x01;
- tda18271_write_regs(fe, R_EB1, 1);
+ ret = tda18271_write_regs(fe, R_EB1, 1);
+ if (tda_fail(ret))
+ goto fail;
/* --------------------------------------------------------------- */
@@ -142,7 +147,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
break;
}
- tda18271_write_regs(fe, R_TM, 7);
+ ret = tda18271_write_regs(fe, R_TM, 7);
+ if (tda_fail(ret))
+ goto fail;
/* force charge pump source */
charge_pump_source(fe, 1);
@@ -159,9 +166,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
regs[R_EP3] &= ~0x04;
else
regs[R_EP3] |= 0x04;
- tda18271_write_regs(fe, R_EP3, 1);
-
- return 0;
+ ret = tda18271_write_regs(fe, R_EP3, 1);
+fail:
+ return ret;
}
static int tda18271_read_thermometer(struct dvb_frontend *fe)
@@ -214,11 +221,13 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
struct tda18271_priv *priv = fe->tuner_priv;
struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
unsigned char *regs = priv->tda18271_regs;
- int tm_current, rfcal_comp, approx, i;
+ int tm_current, rfcal_comp, approx, i, ret;
u8 dc_over_dt, rf_tab;
/* power up */
- tda18271_set_standby_mode(fe, 0, 0, 0);
+ ret = tda18271_set_standby_mode(fe, 0, 0, 0);
+ if (tda_fail(ret))
+ goto fail;
/* read die current temperature */
tm_current = tda18271_read_thermometer(fe);
@@ -229,8 +238,8 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
rf_tab = regs[R_EB14];
i = tda18271_lookup_rf_band(fe, &freq, NULL);
- if (i < 0)
- return -EINVAL;
+ if (tda_fail(i))
+ return i;
if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) {
approx = map[i].rf_a1 *
@@ -251,35 +260,42 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal);
regs[R_EB14] = approx + rfcal_comp;
- tda18271_write_regs(fe, R_EB14, 1);
-
- return 0;
+ ret = tda18271_write_regs(fe, R_EB14, 1);
+fail:
+ return ret;
}
static int tda18271_por(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
/* power up detector 1 */
regs[R_EB12] &= ~0x20;
- tda18271_write_regs(fe, R_EB12, 1);
+ ret = tda18271_write_regs(fe, R_EB12, 1);
+ if (tda_fail(ret))
+ goto fail;
regs[R_EB18] &= ~0x80; /* turn agc1 loop on */
regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
- tda18271_write_regs(fe, R_EB18, 1);
+ ret = tda18271_write_regs(fe, R_EB18, 1);
+ if (tda_fail(ret))
+ goto fail;
regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */
/* POR mode */
- tda18271_set_standby_mode(fe, 1, 0, 0);
+ ret = tda18271_set_standby_mode(fe, 1, 0, 0);
+ if (tda_fail(ret))
+ goto fail;
/* disable 1.5 MHz low pass filter */
regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */
regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */
- tda18271_write_regs(fe, R_EB21, 3);
-
- return 0;
+ ret = tda18271_write_regs(fe, R_EB21, 3);
+fail:
+ return ret;
}
static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
@@ -390,7 +406,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
- int sgn, bcal, count, wait;
+ int sgn, bcal, count, wait, ret;
u8 cid_target;
u16 count_limit;
u32 freq;
@@ -422,7 +438,9 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
tda18271_write_regs(fe, R_EP2, 1);
/* read power detection info, stored in EB10 */
- tda18271_read_extended(fe);
+ ret = tda18271_read_extended(fe);
+ if (tda_fail(ret))
+ return ret;
/* algorithm initialization */
sgn = 1;
@@ -448,7 +466,9 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
tda18271_write_regs(fe, R_EP2, 1);
/* read power detection info, stored in EB10 */
- tda18271_read_extended(fe);
+ ret = tda18271_read_extended(fe);
+ if (tda_fail(ret))
+ return ret;
count += 200;
@@ -479,6 +499,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
/* set standard to digital */
regs[R_EP3] &= ~0x1f; /* clear std bits */
@@ -490,10 +511,14 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
/* update IF output level & IF notch frequency */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
- tda18271_write_regs(fe, R_EP3, 2);
+ ret = tda18271_write_regs(fe, R_EP3, 2);
+ if (tda_fail(ret))
+ goto fail;
regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */
- tda18271_write_regs(fe, R_EB18, 1);
+ ret = tda18271_write_regs(fe, R_EB18, 1);
+ if (tda_fail(ret))
+ goto fail;
regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */
@@ -501,9 +526,9 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */
regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */
- tda18271_write_regs(fe, R_EB21, 3);
-
- return 0;
+ ret = tda18271_write_regs(fe, R_EB21, 3);
+fail:
+ return ret;
}
static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
@@ -522,7 +547,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
i = tda18271_lookup_rf_band(fe, &freq, NULL);
- if (i < 0)
+ if (tda_fail(i))
return i;
rf_default[RF1] = 1000 * map[i].rf1_def;
@@ -536,6 +561,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
/* look for optimized calibration frequency */
bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]);
+ if (tda_fail(bcal))
+ return bcal;
tda18271_calc_rf_cal(fe, &rf_freq[rf]);
prog_tab[rf] = regs[R_EB14];
@@ -576,22 +603,29 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned int i;
+ int ret;
tda_info("tda18271: performing RF tracking filter calibration\n");
/* wait for die temperature stabilization */
msleep(200);
- tda18271_powerscan_init(fe);
+ ret = tda18271_powerscan_init(fe);
+ if (tda_fail(ret))
+ goto fail;
/* rf band calibration */
- for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++)
+ for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) {
+ ret =
tda18271_rf_tracking_filters_init(fe, 1000 *
priv->rf_cal_state[i].rfmax);
+ if (tda_fail(ret))
+ goto fail;
+ }
priv->tm_rfcal = tda18271_read_thermometer(fe);
-
- return 0;
+fail:
+ return ret;
}
/* ------------------------------------------------------------------ */
@@ -600,6 +634,7 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
/* test RF_CAL_OK to see if we need init */
if ((regs[R_EP1] & 0x10) == 0)
@@ -608,15 +643,22 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
if (priv->cal_initialized)
return 0;
- tda18271_calc_rf_filter_curve(fe);
+ ret = tda18271_calc_rf_filter_curve(fe);
+ if (tda_fail(ret))
+ goto fail;
- tda18271_por(fe);
+ ret = tda18271_por(fe);
+ if (tda_fail(ret))
+ goto fail;
tda_info("tda18271: RF tracking filter calibration complete\n");
priv->cal_initialized = true;
-
- return 0;
+ goto end;
+fail:
+ tda_info("tda18271: RF tracking filter calibration failed!\n");
+end:
+ return ret;
}
static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
@@ -624,6 +666,7 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
u32 N = 0;
/* calculate bp filter */
@@ -672,7 +715,10 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
tda18271_calc_main_pll(fe, N);
- tda18271_write_regs(fe, R_EP3, 11);
+ ret = tda18271_write_regs(fe, R_EP3, 11);
+ if (tda_fail(ret))
+ return ret;
+
msleep(5); /* RF tracking filter calibration initialization */
/* search for K,M,CO for RF calibration */
@@ -720,45 +766,56 @@ static int tda18271_ir_cal_init(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
+ int ret;
- tda18271_read_regs(fe);
+ ret = tda18271_read_regs(fe);
+ if (tda_fail(ret))
+ goto fail;
/* test IR_CAL_OK to see if we need init */
if ((regs[R_EP1] & 0x08) == 0)
- tda18271_init_regs(fe);
-
- return 0;
+ ret = tda18271_init_regs(fe);
+fail:
+ return ret;
}
static int tda18271_init(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
+ int ret;
mutex_lock(&priv->lock);
/* power up */
- tda18271_set_standby_mode(fe, 0, 0, 0);
+ ret = tda18271_set_standby_mode(fe, 0, 0, 0);
+ if (tda_fail(ret))
+ goto fail;
/* initialization */
- tda18271_ir_cal_init(fe);
+ ret = tda18271_ir_cal_init(fe);
+ if (tda_fail(ret))
+ goto fail;
if (priv->id == TDA18271HDC2)
tda18271c2_rf_cal_init(fe);
-
+fail:
mutex_unlock(&priv->lock);
- return 0;
+ return ret;
}
static int tda18271_tune(struct dvb_frontend *fe,
struct tda18271_std_map_item *map, u32 freq, u32 bw)
{
struct tda18271_priv *priv = fe->tuner_priv;
+ int ret;
tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
freq, map->if_freq, bw, map->agc_mode, map->std);
- tda18271_init(fe);
+ ret = tda18271_init(fe);
+ if (tda_fail(ret))
+ goto fail;
mutex_lock(&priv->lock);
@@ -770,11 +827,11 @@ static int tda18271_tune(struct dvb_frontend *fe,
tda18271c2_rf_tracking_filters_correction(fe, freq);
break;
}
- tda18271_channel_configuration(fe, map, freq, bw);
+ ret = tda18271_channel_configuration(fe, map, freq, bw);
mutex_unlock(&priv->lock);
-
- return 0;
+fail:
+ return ret;
}
/* ------------------------------------------------------------------ */
@@ -838,7 +895,7 @@ static int tda18271_set_params(struct dvb_frontend *fe,
ret = tda18271_tune(fe, map, freq, bw);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
priv->frequency = freq;
@@ -894,7 +951,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
ret = tda18271_tune(fe, map, freq, 0);
- if (ret < 0)
+ if (tda_fail(ret))
goto fail;
priv->frequency = freq;
@@ -906,16 +963,17 @@ fail:
static int tda18271_sleep(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
+ int ret;
mutex_lock(&priv->lock);
/* standby mode w/ slave tuner output
* & loop thru & xtal oscillator on */
- tda18271_set_standby_mode(fe, 1, 0, 0);
+ ret = tda18271_set_standby_mode(fe, 1, 0, 0);
mutex_unlock(&priv->lock);
- return 0;
+ return ret;
}
static int tda18271_release(struct dvb_frontend *fe)
@@ -1096,10 +1154,10 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
if (cfg)
priv->small_i2c = cfg->small_i2c;
- if (tda18271_get_id(fe) < 0)
+ if (tda_fail(tda18271_get_id(fe)))
goto fail;
- if (tda18271_assign_map_layout(fe) < 0)
+ if (tda_fail(tda18271_assign_map_layout(fe)))
goto fail;
mutex_lock(&priv->lock);
diff --git a/linux/drivers/media/dvb/frontends/tda18271-tables.c b/linux/drivers/media/common/tuners/tda18271-maps.c
index 83e756196..ab14ceb9e 100644
--- a/linux/drivers/media/dvb/frontends/tda18271-tables.c
+++ b/linux/drivers/media/common/tuners/tda18271-maps.c
@@ -1,5 +1,5 @@
/*
- tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
+ tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
diff --git a/linux/drivers/media/dvb/frontends/tda18271-priv.h b/linux/drivers/media/common/tuners/tda18271-priv.h
index 808b89c40..2ed61a31f 100644
--- a/linux/drivers/media/dvb/frontends/tda18271-priv.h
+++ b/linux/drivers/media/common/tuners/tda18271-priv.h
@@ -148,7 +148,7 @@ extern int tda18271_debug;
#define DBG_CAL 16
#define tda_printk(kern, fmt, arg...) \
- printk(kern "%s: " fmt, __FUNCTION__, ##arg)
+ printk(kern "%s: " fmt, __func__, ##arg)
#define dprintk(kern, lvl, fmt, arg...) do {\
if (tda18271_debug & lvl) \
@@ -162,6 +162,15 @@ extern int tda18271_debug;
#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg)
#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg)
+#define tda_fail(ret) \
+({ \
+ int __ret; \
+ __ret = (ret < 0); \
+ if (__ret) \
+ tda_printk(KERN_ERR, "error %d on line %d\n", ret, __LINE__);\
+ __ret; \
+})
+
/*---------------------------------------------------------------------*/
enum tda18271_map_type {
diff --git a/linux/drivers/media/dvb/frontends/tda18271.h b/linux/drivers/media/common/tuners/tda18271.h
index b547318c9..7db9831c0 100644
--- a/linux/drivers/media/dvb/frontends/tda18271.h
+++ b/linux/drivers/media/common/tuners/tda18271.h
@@ -81,7 +81,7 @@ struct tda18271_config {
unsigned int small_i2c:1;
};
-#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE))
extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
struct i2c_adapter *i2c,
struct tda18271_config *cfg);
@@ -91,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct tda18271_config *cfg)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/dvb/frontends/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c
index 2d39f9be5..763b0dd95 100644
--- a/linux/drivers/media/dvb/frontends/tda827x.c
+++ b/linux/drivers/media/common/tuners/tda827x.c
@@ -419,13 +419,13 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
unsigned char buf[] = {0x22, 0x01};
int arg;
int gp_func;
- struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
if (NULL == priv->cfg) {
dprintk("tda827x_config not defined, cannot set LNA gain!\n");
return;
}
+ msg.addr = priv->cfg->switch_addr;
if (priv->cfg->config) {
if (high)
dprintk("setting LNA to high gain\n");
diff --git a/linux/drivers/media/dvb/frontends/tda827x.h b/linux/drivers/media/common/tuners/tda827x.h
index cd3032f98..7850a9a1d 100644
--- a/linux/drivers/media/dvb/frontends/tda827x.h
+++ b/linux/drivers/media/common/tuners/tda827x.h
@@ -51,7 +51,7 @@ struct tda827x_config
* @param cfg optional callback function pointers.
* @return FE pointer on success, NULL on failure.
*/
-#if defined(CONFIG_DVB_TDA827X) || (defined(CONFIG_DVB_TDA827X_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA827X) || (defined(CONFIG_MEDIA_TUNER_TDA827X_MODULE) && defined(MODULE))
extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
struct i2c_adapter *i2c,
struct tda827x_config *cfg);
@@ -61,9 +61,9 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct tda827x_config *cfg)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TDA827X
+#endif // CONFIG_MEDIA_TUNER_TDA827X
#endif // __DVB_TDA827X_H__
diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c
index 789548828..9bda53be5 100644
--- a/linux/drivers/media/video/tda8290.c
+++ b/linux/drivers/media/common/tuners/tda8290.c
@@ -389,7 +389,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
set_audio(fe, params);
- tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
+ tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
tda8295_power(fe, 1);
tda8295_agc1_out(fe, 1);
@@ -604,16 +604,16 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
if ((data == 0x83) || (data == 0x84)) {
priv->ver |= TDA18271;
- tda18271_attach(fe, priv->tda827x_addr,
- priv->i2c_props.adap,
- &tda829x_tda18271_config);
+ dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
+ priv->i2c_props.adap, &tda829x_tda18271_config);
} else {
if ((data & 0x3c) == 0)
priv->ver |= TDA8275;
else
priv->ver |= TDA8275A;
- tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
+ dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
+ priv->i2c_props.adap, &priv->cfg);
priv->cfg.switch_addr = priv->i2c_props.addr;
}
if (fe->ops.tuner_ops.init)
@@ -639,7 +639,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props)
if (tda8290_id[1] == TDA8290_ID) {
if (debug)
printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
- __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+ __func__, i2c_adapter_id(i2c_props->adap),
i2c_props->addr);
return 0;
}
@@ -659,7 +659,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
if (tda8295_id[1] == TDA8295_ID) {
if (debug)
printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
- __FUNCTION__, i2c_adapter_id(i2c_props->adap),
+ __func__, i2c_adapter_id(i2c_props->adap),
i2c_props->addr);
return 0;
}
diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/common/tuners/tda8290.h
index 9dd8b73eb..aa074f3f0 100644
--- a/linux/drivers/media/video/tda8290.h
+++ b/linux/drivers/media/common/tuners/tda8290.h
@@ -29,7 +29,7 @@ struct tda829x_config {
#define TDA829X_DONT_PROBE 1
};
-#if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
#else
static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -EINVAL;
}
@@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
struct tda829x_config *cfg)
{
printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __FUNCTION__);
+ __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/common/tuners/tda9887.c
index e98de7d40..e98de7d40 100644
--- a/linux/drivers/media/video/tda9887.c
+++ b/linux/drivers/media/common/tuners/tda9887.c
diff --git a/linux/drivers/media/video/tda9887.h b/linux/drivers/media/common/tuners/tda9887.h
index 8f873a8e6..acc419e8c 100644
--- a/linux/drivers/media/video/tda9887.h
+++ b/linux/drivers/media/common/tuners/tda9887.h
@@ -21,7 +21,7 @@
#include "dvb_frontend.h"
/* ------------------------------------------------------------------------ */
-#if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA9887) || (defined(CONFIG_MEDIA_TUNER_TDA9887_MODULE) && defined(MODULE))
extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c_adap,
u8 i2c_addr);
@@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c_adap,
u8 i2c_addr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/video/tea5761.c b/linux/drivers/media/common/tuners/tea5761.c
index fa1d12d6f..f5fadcd4b 100644
--- a/linux/drivers/media/video/tea5761.c
+++ b/linux/drivers/media/common/tuners/tea5761.c
@@ -248,14 +248,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
- return EINVAL;
+ return -EINVAL;
}
- if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
- printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
- return EINVAL;
+ if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
+ printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
+ " It is not a TEA5761\n",
+ buffer[13], buffer[14], buffer[15]);
+ return -EINVAL;
}
- printk(KERN_WARNING "TEA5761 detected.\n");
+ printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
+ "Manufacturer ID= 0x%02x\n",
+ buffer[14], buffer[15], buffer[13]);
+
return 0;
}
@@ -296,7 +301,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
{
struct tea5761_priv *priv = NULL;
- if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
+ if (tea5761_autodetection(i2c_adap, i2c_addr) != 0)
return NULL;
priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
diff --git a/linux/drivers/media/video/tea5761.h b/linux/drivers/media/common/tuners/tea5761.h
index 73a03b427..2e2ff82c9 100644
--- a/linux/drivers/media/video/tea5761.h
+++ b/linux/drivers/media/common/tuners/tea5761.h
@@ -20,7 +20,7 @@
#include <linux/i2c.h>
#include "dvb_frontend.h"
-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_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,
@@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
u8 i2c_addr)
{
printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
@@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
struct i2c_adapter* i2c_adap,
u8 i2c_addr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/video/tea5767.c b/linux/drivers/media/common/tuners/tea5767.c
index c4f39a5d3..5990a63ef 100644
--- a/linux/drivers/media/video/tea5767.c
+++ b/linux/drivers/media/common/tuners/tea5767.c
@@ -380,14 +380,14 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
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;
+ 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]) {
printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
- return EINVAL;
+ return -EINVAL;
}
/* Status bytes:
@@ -397,14 +397,16 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
*/
if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
- return EINVAL;
+ return -EINVAL;
}
+#if 0 /* Not working for TEA5767 in Beholder Columbus card */
/* It seems that tea5767 returns 0xff after the 5th byte */
if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
- return EINVAL;
+ return -EINVAL;
}
+#endif
#if 0 /*Sometimes, this code doesn't work */
/* Sets tuner at some freq (87.5 MHz) and see if it is ok */
@@ -423,7 +425,7 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
if (5 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 5))) {
printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
- return EINVAL;
+ return -EINVAL;
}
/* Initial freq for 32.768KHz clock */
@@ -431,7 +433,7 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
printk(KERN_WARNING "It is not a TEA5767. div=%d, Return: %02x %02x %02x %02x %02x\n",
div,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
tea5767_status_dump(buffer);
- return EINVAL;
+ return -EINVAL;
}
#endif
return 0;
@@ -488,8 +490,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
struct tea5767_priv *priv = NULL;
#if 0 /* By removing autodetection allows forcing TEA chip */
- if (tea5767_autodetection(i2c_adap, i2c_addr) == EINVAL)
- return EINVAL;
+ if (tea5767_autodetection(i2c_adap, i2c_addr) == -EINVAL)
+ return -EINVAL;
#endif
priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
if (priv == NULL)
diff --git a/linux/drivers/media/video/tea5767.h b/linux/drivers/media/common/tuners/tea5767.h
index a44451f61..d30ab1b48 100644
--- a/linux/drivers/media/video/tea5767.h
+++ b/linux/drivers/media/common/tuners/tea5767.h
@@ -39,7 +39,7 @@ struct tea5767_ctrl {
enum tea5767_xtal xtal_freq;
};
-#if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5767) || (defined(CONFIG_MEDIA_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,
@@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
u8 i2c_addr)
{
printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __FUNCTION__);
+ __func__);
return -EINVAL;
}
@@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
struct i2c_adapter* i2c_adap,
u8 i2c_addr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/video/tuner-i2c.h b/linux/drivers/media/common/tuners/tuner-i2c.h
index 3ad6c8e0b..cb1c7141f 100644
--- a/linux/drivers/media/video/tuner-i2c.h
+++ b/linux/drivers/media/common/tuners/tuner-i2c.h
@@ -170,4 +170,12 @@ __fail: \
__ret; \
})
+#define hybrid_tuner_report_instance_count(state) \
+({ \
+ int __ret = 0; \
+ if (state) \
+ __ret = state->i2c_props.count; \
+ __ret; \
+})
+
#endif /* __TUNER_I2C_H__ */
diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c
index 772bfefbe..c9d70e4b2 100644
--- a/linux/drivers/media/video/tuner-simple.c
+++ b/linux/drivers/media/common/tuners/tuner-simple.c
@@ -1034,7 +1034,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
if (type >= tuner_count) {
printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
- __FUNCTION__, type, tuner_count-1);
+ __func__, type, tuner_count-1);
return NULL;
}
@@ -1053,8 +1053,10 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 1);
if (1 != i2c_transfer(i2c_adap, &msg, 1))
- tuner_warn("unable to probe %s, proceeding anyway.",
- tuners[type].name);
+ printk(KERN_WARNING "tuner-simple %d-%04x: "
+ "unable to probe %s, proceeding anyway.",
+ i2c_adapter_id(i2c_adap), i2c_addr,
+ tuners[type].name);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
diff --git a/linux/drivers/media/video/tuner-simple.h b/linux/drivers/media/common/tuners/tuner-simple.h
index bf425f325..381fa5d35 100644
--- a/linux/drivers/media/video/tuner-simple.h
+++ b/linux/drivers/media/common/tuners/tuner-simple.h
@@ -20,7 +20,7 @@
#include <linux/i2c.h>
#include "dvb_frontend.h"
-#if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_SIMPLE) || (defined(CONFIG_MEDIA_TUNER_SIMPLE_MODULE) && defined(MODULE))
extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c_adap,
u8 i2c_addr,
@@ -31,7 +31,7 @@ static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
u8 i2c_addr,
unsigned int type)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c
index b3f0f62e0..b3f0f62e0 100644
--- a/linux/drivers/media/video/tuner-types.c
+++ b/linux/drivers/media/common/tuners/tuner-types.c
diff --git a/linux/drivers/media/video/tuner-xc2028-types.h b/linux/drivers/media/common/tuners/tuner-xc2028-types.h
index d0057fbf0..216665c2c 100644
--- a/linux/drivers/media/video/tuner-xc2028-types.h
+++ b/linux/drivers/media/common/tuners/tuner-xc2028-types.h
@@ -1,6 +1,9 @@
/* tuner-xc2028_types
*
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This file includes internal tipes to be used inside tuner-xc2028.
+ * Shouldn't be included outside tuner-xc2028
+ *
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
* This code is placed under the terms of the GNU General Public License v2
*/
@@ -54,11 +57,13 @@
/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
There are variants both with and without NOGD
+ Those firmwares produce better result with LCD displays
*/
#define LCD (1<<12)
/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
+ The NOGD firmwares don't have group delay compensation filter
*/
#define NOGD (1<<13)
@@ -85,11 +90,31 @@
/* This flag identifies that the scode table has a new format */
#define HAS_IF (1 << 30)
-#define SCODE_TYPES (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
+#if 0
+/* The current seek algorithm doesn'use those flags. Instead, this is
+ currently useful only for debug process, since this is a HINT table
+ associating an alias to an IF table that can be used by that digital
+ video standard (in the case of DTV6/7/78/8, QAM and ATSC), or to a
+ particular demod type
+ */
+#define SCODE_TYPES (DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \
DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
-
-/* Newer types to be moved to videodev2.h */
+#else
+/* There are different scode tables for MTS and non-MTS.
+ The MTS firmwares support mono only
+ */
+#define SCODE_TYPES (SCODE | MTS)
+#endif
+
+
+/* Newer types not defined on videodev2.h.
+ The original idea were to move all those types to videodev2.h, but
+ it seemed overkill, since, with the exception of SECAM/K3, the other
+ types seem to be autodetected.
+ It is not clear where secam/k3 is used, nor we have a feedback of this
+ working or being autodetected by the standard secam firmware.
+ */
#define V4L2_STD_SECAM_K3 (0x04000000)
diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c
index 0ab0cbeca..6a9742552 100644
--- a/linux/drivers/media/video/tuner-xc2028.c
+++ b/linux/drivers/media/common/tuners/tuner-xc2028.c
@@ -1,6 +1,6 @@
/* tuner-xc2028
*
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
*
* Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
* - frontend interface
@@ -57,7 +57,7 @@ module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
"default firmware name\n");
-static LIST_HEAD(xc2028_list);
+static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(xc2028_list_mutex);
/* struct for storing firmware table */
@@ -79,12 +79,11 @@ struct firmware_properties {
};
struct xc2028_data {
- struct list_head xc2028_list;
+ struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props;
int (*tuner_callback) (void *dev,
int command, int arg);
void *video_dev;
- int count;
__u32 frequency;
struct firmware_description *firm;
@@ -145,12 +144,12 @@ struct xc2028_data {
_rc; \
})
-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
{
unsigned char buf[2];
unsigned char ibuf[2];
- tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
+ tuner_dbg("%s %04x called\n", __func__, reg);
buf[0] = reg >> 8;
buf[1] = (unsigned char) reg;
@@ -250,6 +249,7 @@ static v4l2_std_id parse_audio_std_option(void)
static void free_firmware(struct xc2028_data *priv)
{
int i;
+ tuner_dbg("%s called\n", __func__);
if (!priv->firm)
return;
@@ -275,7 +275,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
char name[33];
char *fname;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
if (!firmware_name[0])
fname = priv->ctrl.fname;
@@ -418,9 +418,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
{
struct xc2028_data *priv = fe->tuner_priv;
int i, best_i = -1, best_nr_matches = 0;
- unsigned int ign_firm_type_mask = 0;
+ unsigned int type_mask = 0;
- tuner_dbg("%s called, want type=", __FUNCTION__);
+ tuner_dbg("%s called, want type=", __func__);
if (debug) {
dump_firm_type(type);
printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -435,18 +435,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
*id = V4L2_STD_PAL;
if (type & BASE)
- type &= BASE_TYPES;
+ type_mask = BASE_TYPES;
else if (type & SCODE) {
type &= SCODE_TYPES;
- ign_firm_type_mask = HAS_IF;
+ type_mask = SCODE_TYPES & ~HAS_IF;
} else if (type & DTV_TYPES)
- type &= DTV_TYPES;
+ type_mask = DTV_TYPES;
else if (type & STD_SPECIFIC_TYPES)
- type &= STD_SPECIFIC_TYPES;
+ type_mask = STD_SPECIFIC_TYPES;
+
+ type &= type_mask;
+
+ if (!(type & SCODE))
+ type_mask = ~0;
/* Seek for exact match */
for (i = 0; i < priv->firm_size; i++) {
- if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
+ if ((type == (priv->firm[i].type & type_mask)) &&
(*id == priv->firm[i].id))
goto found;
}
@@ -456,7 +461,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
v4l2_std_id match_mask;
int nr_matches;
- if (type != (priv->firm[i].type & ~ign_firm_type_mask))
+ if (type != (priv->firm[i].type & type_mask))
continue;
match_mask = *id & priv->firm[i].id;
@@ -506,7 +511,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
int pos, rc;
unsigned char *p, *endp, buf[priv->ctrl.max_len];
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
pos = seek_firmware(fe, type, id);
if (pos < 0)
@@ -609,7 +614,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
int pos, rc;
unsigned char *p;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
if (!int_freq) {
pos = seek_firmware(fe, type, id);
@@ -673,7 +678,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
u16 version, hwmodel;
v4l2_std_id std0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
if (!priv->firm) {
if (!priv->ctrl.fname) {
@@ -793,10 +798,10 @@ check_device:
goto fail;
}
- tuner_info("Device is Xceive %d version %d.%d, "
- "firmware version %d.%d\n",
- hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
- (version & 0xf0) >> 4, version & 0xf);
+ tuner_dbg("Device is Xceive %d version %d.%d, "
+ "firmware version %d.%d\n",
+ hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+ (version & 0xf0) >> 4, version & 0xf);
/* Check firmware version against what we downloaded. */
if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
@@ -847,27 +852,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
u16 frq_lock, signal = 0;
int rc;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
mutex_lock(&priv->lock);
/* Sync Lock Indicator */
rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
- if (rc < 0 || frq_lock == 0)
+ if (rc < 0)
goto ret;
- /* Frequency is locked. Return signal quality */
+ /* Frequency is locked */
+ if (frq_lock == 1)
+ signal = 32768;
/* Get SNR of the video signal */
rc = xc2028_get_reg(priv, 0x0040, &signal);
if (rc < 0)
- signal = -frq_lock;
+ goto ret;
+
+ /* Use both frq_lock and signal to generate the result */
+ signal = signal || ((signal & 0x07) << 12);
ret:
mutex_unlock(&priv->lock);
*strength = signal;
+ tuner_dbg("signal strength is %d\n", signal);
+
return rc;
}
@@ -884,7 +896,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
unsigned char buf[4];
u32 div, offset = 0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
mutex_lock(&priv->lock);
@@ -967,7 +979,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
struct xc2028_data *priv = fe->tuner_priv;
unsigned int type=0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
if (p->mode == V4L2_TUNER_RADIO) {
type |= FM;
@@ -1000,7 +1012,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
fe_bandwidth_t bw = BANDWIDTH_8_MHZ;
u16 demod = 0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
if (priv->ctrl.d2633)
type |= D2633;
@@ -1065,12 +1077,16 @@ static int xc2028_set_params(struct dvb_frontend *fe,
T_DIGITAL_TV, type, 0, demod);
}
+#if 0
+/* This is needed at sleep (S1/S3), but not at fe_standby. Otherwise,
+ firmware will be loaded on every open()
+ */
static int xc2028_sleep(struct dvb_frontend *fe)
{
struct xc2028_data *priv = fe->tuner_priv;
int rc = 0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
mutex_lock(&priv->lock);
@@ -1085,30 +1101,29 @@ static int xc2028_sleep(struct dvb_frontend *fe)
return rc;
}
-
+#endif
static int xc2028_dvb_release(struct dvb_frontend *fe)
{
struct xc2028_data *priv = fe->tuner_priv;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
mutex_lock(&xc2028_list_mutex);
- priv->count--;
-
- if (!priv->count) {
- list_del(&priv->xc2028_list);
-
+ /* only perform final cleanup if this is the last instance */
+ if (hybrid_tuner_report_instance_count(priv) == 1) {
kfree(priv->ctrl.fname);
-
free_firmware(priv);
- kfree(priv);
- fe->tuner_priv = NULL;
}
+ if (priv)
+ hybrid_tuner_release_state(priv);
+
mutex_unlock(&xc2028_list_mutex);
+ fe->tuner_priv = NULL;
+
return 0;
}
@@ -1116,7 +1131,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct xc2028_data *priv = fe->tuner_priv;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
*frequency = priv->frequency;
@@ -1129,25 +1144,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
struct xc2028_ctrl *p = priv_cfg;
int rc = 0;
- tuner_dbg("%s called\n", __FUNCTION__);
+ tuner_dbg("%s called\n", __func__);
mutex_lock(&priv->lock);
- kfree(priv->ctrl.fname);
- free_firmware(priv);
-
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
- priv->ctrl.fname = NULL;
+ if (priv->ctrl.max_len < 9)
+ priv->ctrl.max_len = 13;
if (p->fname) {
+ if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
+ kfree(priv->ctrl.fname);
+ free_firmware(priv);
+ }
+
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
if (priv->ctrl.fname == NULL)
rc = -ENOMEM;
}
- if (priv->ctrl.max_len < 9)
- priv->ctrl.max_len = 13;
-
mutex_unlock(&priv->lock);
return rc;
@@ -1167,8 +1182,9 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
.get_frequency = xc2028_get_frequency,
.get_rf_strength = xc2028_signal,
.set_params = xc2028_set_params,
+#if 0
.sleep = xc2028_sleep,
-
+#endif
#if 0
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
int (*get_status)(struct dvb_frontend *fe, u32 *status);
@@ -1179,7 +1195,7 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
struct xc2028_config *cfg)
{
struct xc2028_data *priv;
- void *video_dev;
+ int instance;
if (debug)
printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
@@ -1192,48 +1208,40 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
return NULL;
}
- video_dev = cfg->i2c_adap->algo_data;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
-
mutex_lock(&xc2028_list_mutex);
- list_for_each_entry(priv, &xc2028_list, xc2028_list) {
- if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
- video_dev = NULL;
- if (debug)
- printk(KERN_DEBUG "xc2028: reusing device\n");
-
- break;
- }
- }
-
- if (video_dev) {
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- mutex_unlock(&xc2028_list_mutex);
- return NULL;
- }
-
- priv->i2c_props.addr = cfg->i2c_addr;
- priv->i2c_props.adap = cfg->i2c_adap;
- priv->i2c_props.name = "xc2028";
-
- priv->video_dev = video_dev;
+ instance = hybrid_tuner_request_state(struct xc2028_data, priv,
+ hybrid_tuner_instance_list,
+ cfg->i2c_adap, cfg->i2c_addr,
+ "xc2028");
+ switch (instance) {
+ case 0:
+ /* memory allocation failure */
+ goto fail;
+ break;
+ case 1:
+ /* new tuner instance */
priv->tuner_callback = cfg->callback;
priv->ctrl.max_len = 13;
mutex_init(&priv->lock);
- list_add_tail(&priv->xc2028_list, &xc2028_list);
- }
-
- fe->tuner_priv = priv;
- priv->count++;
+ /* analog side (tuner-core) uses i2c_adap->algo_data.
+ * digital side is not guaranteed to have algo_data defined.
+ *
+ * digital side will always have fe->dvb defined.
+ * analog side (tuner-core) doesn't (yet) define fe->dvb.
+ */
+ priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
+ fe->dvb->priv : cfg->i2c_adap->algo_data;
- if (debug)
- printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+ fe->tuner_priv = priv;
+ break;
+ case 2:
+ /* existing tuner instance */
+ fe->tuner_priv = priv;
+ break;
+ }
memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
sizeof(xc2028_dvb_tuner_ops));
@@ -1246,6 +1254,11 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
mutex_unlock(&xc2028_list_mutex);
return fe;
+fail:
+ mutex_unlock(&xc2028_list_mutex);
+
+ xc2028_dvb_release(fe);
+ return NULL;
}
EXPORT_SYMBOL(xc2028_attach);
diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/common/tuners/tuner-xc2028.h
index 3eb842037..216025cf5 100644
--- a/linux/drivers/media/video/tuner-xc2028.h
+++ b/linux/drivers/media/common/tuners/tuner-xc2028.h
@@ -1,6 +1,6 @@
/* tuner-xc2028
*
- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
* This code is placed under the terms of the GNU General Public License v2
*/
@@ -12,7 +12,7 @@
#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
/* Dmoduler IF (kHz) */
-#define XC3028_FE_DEFAULT 0
+#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
#define XC3028_FE_LG60 6000
#define XC3028_FE_ATI638 6380
#define XC3028_FE_OREN538 5380
@@ -47,7 +47,7 @@ struct xc2028_config {
#define XC2028_TUNER_RESET 0
#define XC2028_RESET_CLK 1
-#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
struct xc2028_config *cfg);
#else
@@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
struct xc2028_config *cfg)
{
printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __FUNCTION__);
+ __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/dvb/frontends/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c
index e50924d97..b35640824 100644
--- a/linux/drivers/media/dvb/frontends/xc5000.c
+++ b/linux/drivers/media/common/tuners/xc5000.c
@@ -209,10 +209,10 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (priv->cfg->tuner_callback) {
- ret = priv->cfg->tuner_callback(priv->cfg->priv,
+ ret = priv->cfg->tuner_callback(priv->devptr,
XC5000_TUNER_RESET, 0);
if (ret)
printk(KERN_ERR "xc5000: reset failed\n");
@@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
static int xc_initialize(struct xc5000_priv *priv)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
return xc_write_reg(priv, XREG_INIT, 0);
}
@@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
u16 VideoMode, u16 AudioMode)
{
int ret;
- dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
+ dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
dprintk(1, "%s() Standard = %s\n",
- __FUNCTION__,
+ __func__,
XC5000_Standard[priv->video_standard].Name);
ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
@@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv)
static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
{
- dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
+ dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
@@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
rf_mode = XC_RF_MODE_CABLE;
printk(KERN_ERR
"%s(), Invalid mode, defaulting to CABLE",
- __FUNCTION__);
+ __func__);
}
return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
}
@@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
{
u16 freq_code;
- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+ dprintk(1, "%s(%u)\n", __func__, freq_hz);
if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
(freq_hz < xc5000_tuner_ops.info.frequency_min))
@@ -415,7 +415,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
{
u32 freq_code = (freq_khz * 1024)/1000;
dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
- __FUNCTION__, freq_khz, freq_code);
+ __func__, freq_khz, freq_code);
return xc_write_reg(priv, XREG_IF_OUT, freq_code);
}
@@ -507,7 +507,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
{
int found = 0;
- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
+ dprintk(1, "%s(%u)\n", __func__, freq_hz);
if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
return 0;
@@ -646,12 +646,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
- dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
+ dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
switch(params->u.vsb.modulation) {
case VSB_8:
case VSB_16:
- dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
+ dprintk(1, "%s() VSB modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_AIR;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -660,7 +660,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
case QAM_64:
case QAM_256:
case QAM_AUTO:
- dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
+ dprintk(1, "%s() QAM modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_CABLE;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
@@ -671,7 +671,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
}
dprintk(1, "%s() frequency=%d (compensated)\n",
- __FUNCTION__, priv->freq_hz);
+ __func__, priv->freq_hz);
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
@@ -716,7 +716,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
xc_load_fw_and_init_tuner(fe);
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
- __FUNCTION__, params->frequency);
+ __func__, params->frequency);
priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
@@ -794,7 +794,7 @@ tune_channel:
static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
*freq = priv->freq_hz;
return 0;
}
@@ -802,7 +802,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
{
struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
*bw = priv->bandwidth;
return 0;
@@ -815,7 +815,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
xc_get_lock_status(priv, &lock_status);
- dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
+ dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
*status = lock_status;
@@ -855,7 +855,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
* once shutdown without reloading the driver. Maybe I am not
@@ -867,7 +867,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
if(ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: %s() unable to shutdown tuner\n",
- __FUNCTION__);
+ __func__);
return -EREMOTEIO;
}
else {
@@ -879,7 +879,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
static int xc5000_init(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
@@ -894,7 +894,7 @@ static int xc5000_init(struct dvb_frontend *fe)
static int xc5000_release(struct dvb_frontend *fe)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
@@ -919,14 +919,14 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
.get_status = xc5000_get_status
};
-struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct xc5000_config *cfg)
+struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct xc5000_config *cfg, void *devptr)
{
struct xc5000_priv *priv = NULL;
u16 id = 0;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
if (priv == NULL)
@@ -935,6 +935,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
priv->cfg = cfg;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->i2c = i2c;
+ priv->devptr = devptr;
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware.
diff --git a/linux/drivers/media/dvb/frontends/xc5000.h b/linux/drivers/media/common/tuners/xc5000.h
index 32a5f1c86..c910715ad 100644
--- a/linux/drivers/media/dvb/frontends/xc5000.h
+++ b/linux/drivers/media/common/tuners/xc5000.h
@@ -31,33 +31,35 @@ struct xc5000_config {
u8 i2c_address;
u32 if_khz;
- /* For each bridge framework, when it attaches either analog or digital,
- * it has to store a reference back to its _core equivalent structure,
- * so that it can service the hardware by steering gpio's etc.
- * Each bridge implementation is different so cast priv accordingly.
- * The xc5000 driver cares not for this value, other than ensuring
- * it's passed back to a bridge during tuner_callback().
- */
- void *priv;
int (*tuner_callback) (void *priv, int command, int arg);
};
/* xc5000 callback command */
#define XC5000_TUNER_RESET 0
-#if defined(CONFIG_DVB_TUNER_XC5000) || \
- (defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE))
+/* For each bridge framework, when it attaches either analog or digital,
+ * it has to store a reference back to its _core equivalent structure,
+ * so that it can service the hardware by steering gpio's etc.
+ * Each bridge implementation is different so cast devptr accordingly.
+ * The xc5000 driver cares not for this value, other than ensuring
+ * it's passed back to a bridge during tuner_callback().
+ */
+
+#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
+ (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
- struct xc5000_config *cfg);
+ struct xc5000_config *cfg,
+ void *devptr);
#else
static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
- struct xc5000_config *cfg)
+ struct xc5000_config *cfg,
+ void *devptr)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TUNER_XC5000
+#endif // CONFIG_MEDIA_TUNER_XC5000
#endif // __XC5000_H__
diff --git a/linux/drivers/media/dvb/frontends/xc5000_priv.h b/linux/drivers/media/common/tuners/xc5000_priv.h
index 13b2d1934..ecebfe474 100644
--- a/linux/drivers/media/dvb/frontends/xc5000_priv.h
+++ b/linux/drivers/media/common/tuners/xc5000_priv.h
@@ -31,6 +31,8 @@ struct xc5000_priv {
u8 video_standard;
u8 rf_mode;
u8 fwloaded;
+
+ void *devptr;
};
#endif
diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig
index 03ef88acd..7b21b49f1 100644
--- a/linux/drivers/media/dvb/Kconfig
+++ b/linux/drivers/media/dvb/Kconfig
@@ -1,9 +1,7 @@
#
-# Multimedia device configuration
+# DVB device configuration
#
-source "drivers/media/dvb/dvb-core/Kconfig"
-
menuconfig DVB_CAPTURE_DRIVERS
bool "DVB/ATSC adapters"
depends on DVB_CORE
diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig
index 8193d88d1..73dc2ee9b 100644
--- a/linux/drivers/media/dvb/b2c2/Kconfig
+++ b/linux/drivers/media/dvb/b2c2/Kconfig
@@ -9,7 +9,9 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
- select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select DVB_S5H1420 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE
help
diff --git a/linux/drivers/media/dvb/b2c2/Makefile b/linux/drivers/media/dvb/b2c2/Makefile
index 870e2848c..d9db066f9 100644
--- a/linux/drivers/media/dvb/b2c2/Makefile
+++ b/linux/drivers/media/dvb/b2c2/Makefile
@@ -14,4 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/video/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-dma.c b/linux/drivers/media/dvb/b2c2/flexcop-dma.c
index f0b134a16..1df246a7f 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
{
flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
- deb_info("%s\n",__FUNCTION__);
+ deb_info("%s\n",__func__);
v.dma_0xc.remap_enable = onoff;
fc->write_ibi_reg(fc,r,v);
return 0;
@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
flexcop_dma_remap(fc,dma_idx,0);
- deb_info("%s\n",__FUNCTION__);
+ deb_info("%s\n",__func__);
v.dma_0x4_write.dmatimer = cycles;
fc->write_ibi_reg(fc,r,v);
return 0;
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 6759c3ad2..f9d087669 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -19,6 +19,9 @@
#include "dvb-pll.h"
#include "tuner-simple.h"
+#include "s5h1420.h"
+#include "itd1000.h"
+
#include "cx24123.h"
#include "cx24113.h"
@@ -249,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
.mclk = 88000000UL,
.invert = 0,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_LK,
+ .lock_output = STV0299_LOCKOUTPUT_LK,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
@@ -482,6 +485,18 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
};
+/* SkyStar2 rev2.7 (a/u) */
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+ .demod_address = 0x53,
+ .invert = 1,
+ .repeated_start_workaround = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+ .i2c_address = 0x61,
+};
+
+/* SkyStar2 rev2.8 */
static struct cx24123_config skystar2_rev2_8_cx24123_config = {
.demod_address = 0x55,
.dont_use_pll = 1,
@@ -500,6 +515,39 @@ int flexcop_frontend_init(struct flexcop_device *fc)
struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
struct i2c_adapter *i2c_tuner;
+ /* enable no_base_addr - no repeated start when reading */
+ fc->fc_i2c_adap[0].no_base_addr = 1;
+ fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
+ if (fc->fe != NULL) {
+ flexcop_ibi_value r108;
+ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+ ops = &fc->fe->ops;
+
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
+
+ fc->dev_type = FC_SKY_REV27;
+
+ /* enable no_base_addr - no repeated start when reading */
+ fc->fc_i2c_adap[2].no_base_addr = 1;
+ if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
+ err("ISL6421 could NOT be attached");
+ else
+ info("ISL6421 successfully attached");
+
+ /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
+ r108.raw = 0x00000506;
+ fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+ if (i2c_tuner) {
+ if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
+ err("ITD1000 could NOT be attached");
+ else
+ info("ITD1000 successfully attached");
+ }
+ goto fe_found;
+ }
+ fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
+
/* try the sky v2.8 (cx24123, isl6421) */
fc->fe = dvb_attach(cx24123_attach,
&skystar2_rev2_8_cx24123_config, i2c);
@@ -586,7 +634,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
}
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
- fc->fe = dvb_attach(vp310_mt312_attach,
+ fc->fe = dvb_attach(mt312_attach,
&skystar23_samsung_tbdu18132_config, i2c);
if (fc->fe != NULL) {
ops = &fc->fe->ops;
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-sram.c b/linux/drivers/media/dvb/b2c2/flexcop-sram.c
index 4d978c01e..cfb196ef7 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-sram.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-sram.c
@@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
};
if (retries == 0)
- printk("%s: SRAM timeout\n", __FUNCTION__);
+ printk("%s: SRAM timeout\n", __func__);
write_reg_dw(adapter, 0x700, command);
@@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
};
if (retries == 0)
- printk("%s: SRAM timeout\n", __FUNCTION__);
+ printk("%s: SRAM timeout\n", __func__);
write_reg_dw(adapter, 0x700, command);
@@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
};
if (retries == 0)
- printk("%s: SRAM timeout\n", __FUNCTION__);
+ printk("%s: SRAM timeout\n", __func__);
value = read_reg_dw(adapter, 0x700) >> 0x10;
@@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter)
adapter->dw_sram_type = tmp & 0x30000;
- ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
} else {
adapter->dw_sram_type = 0x10000;
- ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
}
/* return value is never used? */
@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
{
u8 tmp1, tmp2;
- dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+ dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
sram_set_size(adapter, mask);
sram_init(adapter);
@@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
sram_read(adapter, addr, &tmp2, 1);
sram_read(adapter, addr, &tmp2, 1);
- dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
+ dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
if (tmp2 != 0xa5)
return 0;
@@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
sram_read(adapter, addr, &tmp2, 1);
sram_read(adapter, addr, &tmp2, 1);
- dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
+ dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
if (tmp2 != 0x5a)
return 0;
@@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
tmp3 = read_reg_dw(adapter, 0x71c);
- dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+ dprintk("%s: tmp3 = %x\n", __func__, tmp3);
write_reg_dw(adapter, 0x71c, tmp2);
@@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp);
- dprintk("%s: sram size = 32K\n", __FUNCTION__);
+ dprintk("%s: sram size = 32K\n", __func__);
return 32;
}
@@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp);
- dprintk("%s: sram size = 128K\n", __FUNCTION__);
+ dprintk("%s: sram size = 128K\n", __func__);
return 128;
}
@@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp);
- dprintk("%s: sram size = 64K\n", __FUNCTION__);
+ dprintk("%s: sram size = 64K\n", __func__);
return 64;
}
@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp);
- dprintk("%s: sram size = 32K\n", __FUNCTION__);
+ dprintk("%s: sram size = 32K\n", __func__);
return 32;
}
@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp);
- dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+ dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
return 0;
}
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-usb.c b/linux/drivers/media/dvb/b2c2/flexcop-usb.c
index 683217b0f..d523dd5bf 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -383,7 +383,7 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
{
- u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+ u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
int buffer_offset = 0;
diff --git a/linux/drivers/media/dvb/b2c2/flexcop.c b/linux/drivers/media/dvb/b2c2/flexcop.c
index 205146c24..5f79c8dc3 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop.c
@@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
#undef DEBSTATUS
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/* global zero for ibi values */
flexcop_ibi_value ibi_zero;
@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
static int flexcop_dvb_init(struct flexcop_device *fc)
{
- int ret;
- if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
+ int ret = dvb_register_adapter(&fc->dvb_adapter,
+ "FlexCop Digital TV device", fc->owner,
+ fc->dev, adapter_nr);
+ if (ret < 0) {
err("error registering DVB adapter");
return ret;
}
diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig
index 902c762e0..7588db131 100644
--- a/linux/drivers/media/dvb/bt8xx/Kconfig
+++ b/linux/drivers/media/dvb/bt8xx/Kconfig
@@ -1,6 +1,7 @@
config DVB_BT8XX
tristate "BT8xx based PCI cards"
depends on DVB_CORE && PCI && I2C && VIDEO_BT848
+ depends on HOTPLUG # due to FW_LOADER
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_SP887X if !DVB_FE_CUSTOMISE
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
@@ -8,7 +9,7 @@ config DVB_BT8XX
select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
select FW_LOADER
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
diff --git a/linux/drivers/media/dvb/bt8xx/Makefile b/linux/drivers/media/dvb/bt8xx/Makefile
index 9d3e68b5d..d98f1d49f 100644
--- a/linux/drivers/media/dvb/bt8xx/Makefile
+++ b/linux/drivers/media/dvb/bt8xx/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c
index 307ff35bd..a7637562e 100644
--- a/linux/drivers/media/dvb/bt8xx/dst.c
+++ b/linux/drivers/media/dvb/bt8xx/dst.c
@@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state)
{
int retval;
u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
- //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+ //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
state->decode_lock = state->decode_strength = state->decode_snr = 0;
return 0;
@@ -1714,7 +1714,7 @@ static void dst_release(struct dvb_frontend *fe)
struct dst_state *state = fe->demodulator_priv;
if (state->dst_ca) {
dvb_unregister_device(state->dst_ca);
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
symbol_put(dst_ca_attach);
#endif
}
diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c
index ce64629fc..0b462e7bb 100644
--- a/linux/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c
@@ -36,13 +36,13 @@
#define dprintk(x, y, z, format, arg...) do { \
if (z) { \
if ((x > DST_CA_ERROR) && (x > y)) \
- printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((x > DST_CA_NOTICE) && (x > y)) \
- printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((x > DST_CA_INFO) && (x > y)) \
- printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((x > DST_CA_DEBUG) && (x > y)) \
- printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (x > y) \
printk(format, ## arg); \
@@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state)
dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
state->messages[7], (state->messages[8] << 8) | state->messages[9],
- (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+ (state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
// Transform dst message to correct application_info message
diff --git a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index de0de894b..27d092448 100644
--- a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -41,6 +41,8 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define dprintk( args... ) \
do { \
if (debug) printk(KERN_DEBUG args); \
@@ -672,7 +674,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
state->dst_ca = NULL;
/* DST is not a frontend, attaching the ASIC */
if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
- printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
+ printk("%s: Could not find a Twinhan DST.\n", __func__);
break;
}
/* Attach other DST peripherals if any */
@@ -718,7 +720,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
+ result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
+ THIS_MODULE, &card->bt->dev->dev,
+ adapter_nr);
+ if (result < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
}
diff --git a/linux/drivers/media/dvb/cinergyT2/Kconfig b/linux/drivers/media/dvb/cinergyT2/Kconfig
index 3d778c5ab..c03513b2c 100644
--- a/linux/drivers/media/dvb/cinergyT2/Kconfig
+++ b/linux/drivers/media/dvb/cinergyT2/Kconfig
@@ -1,6 +1,6 @@
config DVB_CINERGYT2
tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && INPUT
help
Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c
index c33afb6ea..651df056e 100644
--- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -61,6 +61,8 @@ static int debug;
module_param_named(debug, debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
#define dprintk(level, args...) \
do { \
@@ -74,7 +76,7 @@ do { \
do { \
if ((debug & level)) { \
printk("%s: %s(): ", KBUILD_MODNAME, \
- __FUNCTION__); \
+ __func__); \
printk(args); } \
} while (0)
#endif
@@ -93,22 +95,22 @@ enum cinergyt2_ep1_cmd {
struct dvbt_set_parameters_msg {
uint8_t cmd;
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
} __attribute__((packed));
struct dvbt_get_status_msg {
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
- uint16_t gain;
+ __le16 gain;
uint8_t snr;
- uint32_t viterbi_error_rate;
- uint32_t rs_error_rate;
- uint32_t uncorrected_block_count;
+ __le32 viterbi_error_rate;
+ __le32 rs_error_rate;
+ __le32 uncorrected_block_count;
uint8_t lock_bits;
uint8_t prev_lock_bits;
} __attribute__((packed));
@@ -156,6 +158,7 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
int disconnect_pending;
+ unsigned int uncorrected_block_count;
atomic_t inuse;
void *streambuf;
@@ -171,7 +174,7 @@ struct cinergyt2 {
struct delayed_work rc_query_work;
#endif
int rc_input_event;
- u32 rc_last_code;
+ __le32 rc_last_code;
unsigned long last_event_jiffies;
#endif
};
@@ -184,7 +187,7 @@ enum {
struct cinergyt2_rc_event {
char type;
- uint32_t value;
+ __le32 value;
} __attribute__((packed));
static const uint32_t rc_keys[] = {
@@ -651,8 +654,11 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
{
uint32_t unc_count;
- unc_count = stat->uncorrected_block_count;
- stat->uncorrected_block_count = 0;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+ unc_count = cinergyt2->uncorrected_block_count;
+ cinergyt2->uncorrected_block_count = 0;
+ mutex_unlock(&cinergyt2->sem);
/* UNC are already converted to host byte order... */
return put_user(unc_count,(__u32 __user *) arg);
@@ -809,7 +815,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
}
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
}
goto out;
}
@@ -820,7 +826,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
- rc_events[n].value == ~0) {
+ rc_events[n].value == cpu_to_le32(~0)) {
/* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
@@ -835,7 +841,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
if (cinergyt2->rc_input_event != KEY_MAX) {
if (rc_events[n].value == cinergyt2->rc_last_code &&
- cinergyt2->rc_last_code != ~0) {
+ cinergyt2->rc_last_code != cpu_to_le32(~0)) {
/* emit a key-up so the double event is recognized */
dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
@@ -869,7 +875,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
cinergyt2->rc_input_event = KEY_MAX;
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
#else
@@ -884,8 +890,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
input_dev->id.bustype = BUS_USB;
- input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
- input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
+ input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor);
+ input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct);
input_dev->id.version = 1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
input_dev->dev.parent = &cinergyt2->udev->dev;
@@ -949,18 +955,16 @@ static void cinergyt2_query (struct work_struct *work)
char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
struct dvbt_get_status_msg *s = &cinergyt2->status;
uint8_t lock_bits;
- uint32_t unc;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return;
- unc = s->uncorrected_block_count;
lock_bits = s->lock_bits;
cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s));
- unc += le32_to_cpu(s->uncorrected_block_count);
- s->uncorrected_block_count = unc;
+ cinergyt2->uncorrected_block_count +=
+ le32_to_cpu(s->uncorrected_block_count);
if (lock_bits != s->lock_bits) {
wake_up_interruptible(&cinergyt2->poll_wq);
@@ -1004,7 +1008,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
return -ENOMEM;
}
- if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
+ err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
+ THIS_MODULE, &cinergyt2->udev->dev,
+ adapter_nr);
+ if (err < 0) {
kfree(cinergyt2);
return err;
}
diff --git a/linux/drivers/media/dvb/dvb-core/Kconfig b/linux/drivers/media/dvb/dvb-core/Kconfig
deleted file mode 100644
index e3e6839f8..000000000
--- a/linux/drivers/media/dvb/dvb-core/Kconfig
+++ /dev/null
@@ -1,34 +0,0 @@
-config DVB_CORE
- tristate "DVB for Linux"
- depends on NET && INET
- select CRC32
- help
- Support Digital Video Broadcasting hardware. Enable this if you
- own a DVB adapter and want to use it or if you compile Linux for
- a digital SetTopBox.
-
- DVB core utility functions for device handling, software fallbacks etc.
- Say Y when you have a DVB card and want to use it. Say Y if your want
- to build your drivers outside the kernel, but need the DVB core. All
- in-kernel drivers will select this automatically if needed.
-
- API specs and user tools are available from <http://www.linuxtv.org/>.
-
- Please report problems regarding this driver to the LinuxDVB
- mailing list.
-
- If unsure say N.
-
-config DVB_CORE_ATTACH
- bool "Load and attach frontend modules as needed"
- depends on DVB_CORE
- depends on MODULES
- help
- Remove the static dependency of DVB card drivers on all
- frontend modules for all possible card variants. Instead,
- allow the card drivers to only load the frontend modules
- they require. This saves several KBytes of memory.
-
- Note: You will need module-init-tools v3.2 or later for this feature.
-
- If unsure say Y.
diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c
index 716735f03..df5bef6a2 100644
--- a/linux/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c
@@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
struct dmxdev *dmxdev = dvbdev->priv;
struct dmx_frontend *front;
- dprintk("function : %s\n", __FUNCTION__);
+ dprintk("function : %s\n", __func__);
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
@@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
return ret;
}
+static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
+ unsigned long size)
+{
+ struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
+ void *newmem;
+ void *oldmem;
+
+ dprintk("function : %s\n", __func__);
+
+ if (buf->size == size)
+ return 0;
+ if (!size)
+ return -EINVAL;
+
+ newmem = vmalloc(size);
+ if (!newmem)
+ return -ENOMEM;
+
+ oldmem = buf->data;
+
+ spin_lock_irq(&dmxdev->lock);
+ buf->data = newmem;
+ buf->size = size;
+
+ /* reset and not flush in case the buffer shrinks */
+ dvb_ringbuffer_reset(buf);
+ spin_unlock_irq(&dmxdev->lock);
+
+ vfree(oldmem);
+
+ return 0;
+}
+
static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
*dmxdevfilter, int state)
{
@@ -271,28 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
unsigned long size)
{
struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
- void *mem;
+ void *newmem;
+ void *oldmem;
if (buf->size == size)
return 0;
+ if (!size)
+ return -EINVAL;
if (dmxdevfilter->state >= DMXDEV_STATE_GO)
return -EBUSY;
+
+ newmem = vmalloc(size);
+ if (!newmem)
+ return -ENOMEM;
+
+ oldmem = buf->data;
+
spin_lock_irq(&dmxdevfilter->dev->lock);
- mem = buf->data;
- buf->data = NULL;
+ buf->data = newmem;
buf->size = size;
- dvb_ringbuffer_flush(buf);
+
+ /* reset and not flush in case the buffer shrinks */
+ dvb_ringbuffer_reset(buf);
spin_unlock_irq(&dmxdevfilter->dev->lock);
- vfree(mem);
- if (buf->size) {
- mem = vmalloc(dmxdevfilter->buffer.size);
- if (!mem)
- return -ENOMEM;
- spin_lock_irq(&dmxdevfilter->dev->lock);
- buf->data = mem;
- spin_unlock_irq(&dmxdevfilter->dev->lock);
- }
+ vfree(oldmem);
+
return 0;
}
@@ -551,7 +588,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
dvb_dmxdev_section_callback);
if (ret < 0) {
printk("DVB (%s): could not alloc feed\n",
- __FUNCTION__);
+ __func__);
return ret;
}
@@ -559,7 +596,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
if (ret < 0) {
printk("DVB (%s): could not set feed\n",
- __FUNCTION__);
+ __func__);
dvb_dmxdev_feed_restart(filter);
return ret;
}
@@ -734,7 +771,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter,
struct dmx_sct_filter_params *params)
{
- dprintk("function : %s\n", __FUNCTION__);
+ dprintk("function : %s\n", __func__);
dvb_dmxdev_filter_stop(dmxdevfilter);
@@ -1009,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
{
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
+ unsigned long arg = (unsigned long)parg;
int ret;
if (mutex_lock_interruptible(&dmxdev->mutex))
@@ -1016,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case DMX_SET_BUFFER_SIZE:
- // FIXME: implement
- ret = 0;
+ ret = dvb_dvr_set_buffer_size(dmxdev, arg);
break;
default:
@@ -1040,7 +1077,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
struct dmxdev *dmxdev = dvbdev->priv;
unsigned int mask = 0;
- dprintk("function : %s\n", __FUNCTION__);
+ dprintk("function : %s\n", __func__);
poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 588a12597..02d902fdf 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -251,7 +251,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
unsigned long timeout;
unsigned long start;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* loop until timeout elapsed */
start = jiffies;
@@ -264,7 +264,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
/* if we got the flags, it was successful! */
if (res & waitfor) {
- dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
+ dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
return 0;
}
@@ -277,7 +277,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
msleep(1);
}
- dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
+ dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
/* if we get here, we've timed out */
return -ETIMEDOUT;
@@ -298,7 +298,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
int buf_size;
u8 buf[2];
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* we'll be determining these during this function */
ca->slot_info[slot].da_irq_supported = 0;
@@ -550,7 +550,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
{
int configoption;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* set the config option */
ca->pub->write_attribute_mem(ca->pub, slot,
@@ -588,7 +588,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
u8 buf[HOST_LINK_BUF_SIZE];
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* check if we have space for a link buf in the rx_buffer */
if (ebuf == NULL) {
@@ -709,7 +709,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
int status;
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// sanity check
@@ -786,7 +786,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
*/
static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
ca->pub->slot_shutdown(ca->pub, slot);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
@@ -893,7 +893,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
ca->wakeup = 1;
mb();
@@ -911,15 +911,21 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
int curdelay = 100000000;
int slot;
+ /* Beware of too high polling frequency, because one polling
+ * call might take several hundred milliseconds until timeout!
+ */
for (slot = 0; slot < ca->slot_count; slot++) {
switch (ca->slot_info[slot].slot_state) {
default:
case DVB_CA_SLOTSTATE_NONE:
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ * 5; /* 5s */
+ break;
case DVB_CA_SLOTSTATE_INVALID:
- delay = HZ * 60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ / 10;
- }
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ / 10; /* 100ms */
break;
case DVB_CA_SLOTSTATE_UNINITIALISED:
@@ -927,19 +933,17 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
case DVB_CA_SLOTSTATE_VALIDATE:
case DVB_CA_SLOTSTATE_WAITFR:
case DVB_CA_SLOTSTATE_LINKINIT:
- delay = HZ / 10;
+ delay = HZ / 10; /* 100ms */
break;
case DVB_CA_SLOTSTATE_RUNNING:
- delay = HZ * 60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ / 10;
- }
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ / 10; /* 100ms */
if (ca->open) {
if ((!ca->slot_info[slot].da_irq_supported) ||
- (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) {
- delay = HZ / 10;
- }
+ (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA)))
+ delay = HZ / 10; /* 100ms */
}
break;
}
@@ -965,7 +969,7 @@ static int dvb_ca_en50221_thread(void *data)
int pktcount;
void *rxbuf;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* choose the correct initial delay */
dvb_ca_en50221_thread_update_delay(ca);
@@ -1173,7 +1177,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
int err = 0;
int slot;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
switch (cmd) {
case CA_RESET:
@@ -1267,7 +1271,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
unsigned long timeout;
int written;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
if (count < 2)
@@ -1402,7 +1406,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
int pktlen;
int dispose = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
if (count < 2)
@@ -1491,7 +1495,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
int err;
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (!try_module_get(ca->pub->owner))
return -EIO;
@@ -1535,7 +1539,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
struct dvb_ca_private *ca = dvbdev->priv;
int err;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* mark the CA device as closed */
ca->open = 0;
@@ -1565,7 +1569,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
int slot;
int result = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
mask |= POLLIN;
@@ -1627,7 +1631,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
struct dvb_ca_private *ca = NULL;
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (slot_count < 1)
return -EINVAL;
@@ -1705,7 +1709,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
struct dvb_ca_private *ca = pubca->private;
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* shutdown the thread if there was one */
kthread_stop(ca->thread);
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
index 988d14302..934e15fff 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __func__, feed->type, feed->state, feed->pid);
goto out;
}
@@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
spin_lock_irq(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
- __FUNCTION__, feed->type, feed->state, feed->pid);
+ __func__, feed->type, feed->state, feed->pid);
goto out;
}
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 54cc2637b..8a9c2283f 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -140,7 +140,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
struct dvb_frontend_event *e;
int wp;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (mutex_lock_interruptible (&events->mtx))
return;
@@ -176,7 +176,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_fe_events *events = &fepriv->events;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (events->overflow) {
events->overflow = 0;
@@ -242,7 +242,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
{
int q2;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (locked)
(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
@@ -334,7 +334,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
dprintk("%s: drift:%i inversion:%i auto_step:%i "
"auto_sub_step:%i started_auto_step:%i\n",
- __FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
+ __func__, fepriv->lnb_drift, fepriv->inversion,
fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
/* set the frontend itself */
@@ -516,7 +516,7 @@ static int dvb_frontend_thread(void *data)
fe_status_t s;
struct dvb_frontend_parameters *params;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
fepriv->check_wrapped = 0;
fepriv->quality = 0;
@@ -608,7 +608,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
fepriv->exit = 1;
mb();
@@ -676,7 +676,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct task_struct *fe_thread;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (fepriv->thread) {
if (!fepriv->exit)
@@ -774,7 +774,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int err = -EOPNOTSUPP;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (fepriv->exit)
return -ENODEV;
@@ -906,7 +906,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
+ printk("%s switch command: 0x%04lx\n", __func__, cmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -930,7 +930,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
}
if (dvb_frontend_debug) {
printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
- __FUNCTION__, fe->dvb->num);
+ __func__, fe->dvb->num);
for (i = 1; i < 10; i++)
printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
}
@@ -1048,7 +1048,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
poll_wait (file, &fepriv->events.wait_queue, wait);
@@ -1065,7 +1065,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int ret;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
@@ -1106,7 +1106,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int ret;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
fepriv->release_jiffies = jiffies;
@@ -1146,7 +1146,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
.kernel_ioctl = dvb_frontend_ioctl
};
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (mutex_lock_interruptible(&frontend_mutex))
return -ERESTARTSYS;
@@ -1180,7 +1180,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
int dvb_unregister_frontend(struct dvb_frontend* fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
mutex_lock(&frontend_mutex);
dvb_frontend_stop (fe);
@@ -1200,7 +1200,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
}
EXPORT_SYMBOL(dvb_unregister_frontend);
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
void dvb_frontend_detach(struct dvb_frontend* fe)
{
void *ptr;
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c
index 627096688..04b207fd7 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c
@@ -177,7 +177,7 @@ struct dvb_net_priv {
* stolen from eth.c out of the linux kernel, hacked for dvb-device
* by Michael Holzt <kju@debian.org>
*/
-static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
+static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
struct ethhdr *eth;
@@ -290,10 +290,10 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if(ext_len >= 0) {
p->ule_next_hdr += ext_len;
if (!p->ule_bridged) {
- p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+ p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr);
p->ule_next_hdr += 2;
} else {
- p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+ p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
/* This assures the extension handling loop will terminate. */
}
}
@@ -307,7 +307,7 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if (ule_optional_ext_handlers[htype])
(void)ule_optional_ext_handlers[htype]( p );
p->ule_next_hdr += ext_len;
- p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+ p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) );
/*
* note: the length of the next header type is included in the
* length of THIS optional extension header
@@ -607,8 +607,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Check for complete payload. */
if (priv->ule_sndu_remain <= 0) {
/* Check CRC32, we've got it in our skb already. */
- unsigned short ulen = htons(priv->ule_sndu_len);
- unsigned short utype = htons(priv->ule_sndu_type);
+ __be16 ulen = htons(priv->ule_sndu_len);
+ __be16 utype = htons(priv->ule_sndu_type);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
const u8 *tail;
#endif
@@ -810,8 +810,8 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct net_device *dev = feed->priv;
- if (buffer2 != 0)
- printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);
+ if (buffer2)
+ printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2);
if (buffer1_len > 32768)
printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
@@ -991,17 +991,17 @@ static int dvb_net_feed_start(struct net_device *dev)
struct dmx_demux *demux = priv->demux;
unsigned char *mac = (unsigned char *) dev->dev_addr;
- dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
+ dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
mutex_lock(&priv->mutex);
if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
- printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
+ printk("%s: BUG %d\n", __func__, __LINE__);
priv->secfeed=NULL;
priv->secfilter=NULL;
priv->tsfeed = NULL;
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
- dprintk("%s: alloc secfeed\n", __FUNCTION__);
+ dprintk("%s: alloc secfeed\n", __func__);
ret=demux->allocate_section_feed(demux, &priv->secfeed,
dvb_net_sec_callback);
if (ret<0) {
@@ -1019,38 +1019,38 @@ static int dvb_net_feed_start(struct net_device *dev)
}
if (priv->rx_mode != RX_MODE_PROMISC) {
- dprintk("%s: set secfilter\n", __FUNCTION__);
+ dprintk("%s: set secfilter\n", __func__);
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
}
switch (priv->rx_mode) {
case RX_MODE_MULTI:
for (i = 0; i < priv->multi_num; i++) {
- dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
+ dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
priv->multi_macs[i], mask_normal);
}
break;
case RX_MODE_ALL_MULTI:
priv->multi_num=1;
- dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+ dprintk("%s: set multi_secfilter[0]\n", __func__);
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
mac_allmulti, mask_allmulti);
break;
case RX_MODE_PROMISC:
priv->multi_num=0;
- dprintk("%s: set secfilter\n", __FUNCTION__);
+ dprintk("%s: set secfilter\n", __func__);
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
break;
}
- dprintk("%s: start filtering\n", __FUNCTION__);
+ dprintk("%s: start filtering\n", __func__);
priv->secfeed->start_filtering(priv->secfeed);
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
struct timespec timeout = { 0, 10000000 }; // 10 msec
/* we have payloads encapsulated in TS */
- dprintk("%s: alloc tsfeed\n", __FUNCTION__);
+ dprintk("%s: alloc tsfeed\n", __func__);
ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
if (ret < 0) {
printk("%s: could not allocate ts feed\n", dev->name);
@@ -1074,7 +1074,7 @@ static int dvb_net_feed_start(struct net_device *dev)
goto error;
}
- dprintk("%s: start filtering\n", __FUNCTION__);
+ dprintk("%s: start filtering\n", __func__);
priv->tsfeed->start_filtering(priv->tsfeed);
} else
ret = -EINVAL;
@@ -1089,17 +1089,17 @@ static int dvb_net_feed_stop(struct net_device *dev)
struct dvb_net_priv *priv = dev->priv;
int i, ret = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
mutex_lock(&priv->mutex);
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
if (priv->secfeed) {
if (priv->secfeed->is_filtering) {
- dprintk("%s: stop secfeed\n", __FUNCTION__);
+ dprintk("%s: stop secfeed\n", __func__);
priv->secfeed->stop_filtering(priv->secfeed);
}
if (priv->secfilter) {
- dprintk("%s: release secfilter\n", __FUNCTION__);
+ dprintk("%s: release secfilter\n", __func__);
priv->secfeed->release_filter(priv->secfeed,
priv->secfilter);
priv->secfilter=NULL;
@@ -1108,7 +1108,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
for (i=0; i<priv->multi_num; i++) {
if (priv->multi_secfilter[i]) {
dprintk("%s: release multi_filter[%d]\n",
- __FUNCTION__, i);
+ __func__, i);
priv->secfeed->release_filter(priv->secfeed,
priv->multi_secfilter[i]);
priv->multi_secfilter[i] = NULL;
@@ -1122,7 +1122,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
if (priv->tsfeed) {
if (priv->tsfeed->is_filtering) {
- dprintk("%s: stop tsfeed\n", __FUNCTION__);
+ dprintk("%s: stop tsfeed\n", __func__);
priv->tsfeed->stop_filtering(priv->tsfeed);
}
priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index ac9d93cf8..872985b79 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
rbuf->error = 0;
}
-
+void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
+{
+ rbuf->pread = rbuf->pwrite = 0;
+ rbuf->error = 0;
+}
void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
{
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index d97714e75..890826262 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -69,6 +69,7 @@ struct dvb_ringbuffer {
** to lock read or write operations.
** Two or more readers must be locked against each other.
** Flushing the buffer counts as a read operation.
+** Resetting the buffer counts as a read and write operation.
** Two or more writers must be locked against each other.
*/
@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
+/*
+** Reset the read and write pointers to zero and flush the buffer
+** This counts as a read and write operation
+*/
+extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
+
+
/* read routines & macros */
/* ---------------------- */
/* flush buffer */
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c
index c70cee304..3439ccec6 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c
@@ -52,7 +52,6 @@ static const char * const dnames[] = {
"net", "osd"
};
-#define DVB_MAX_ADAPTERS 8
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
@@ -211,7 +210,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
if ((id = dvbdev_get_free_id (adap, type)) < 0){
mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
- printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
+ printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
return -ENFILE;
}
@@ -250,7 +249,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
"dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
- __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+ __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
return PTR_ERR(clsdev);
}
@@ -277,18 +276,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
}
EXPORT_SYMBOL(dvb_unregister_device);
+static int dvbdev_check_free_adapter_num(int num)
+{
+ struct list_head *entry;
+ list_for_each(entry, &dvb_adapter_list) {
+ struct dvb_adapter *adap;
+ adap = list_entry(entry, struct dvb_adapter, list_head);
+ if (adap->num == num)
+ return 0;
+ }
+ return 1;
+}
static int dvbdev_get_free_adapter_num (void)
{
int num = 0;
while (num < DVB_MAX_ADAPTERS) {
- struct dvb_adapter *adap;
- list_for_each_entry(adap, &dvb_adapter_list, list_head)
- if (adap->num == num)
- goto skip;
- return num;
-skip:
+ if (dvbdev_check_free_adapter_num(num))
+ return num;
num++;
}
@@ -296,13 +302,28 @@ skip:
}
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+ struct module *module, struct device *device,
+ short *adapter_nums)
{
- int num;
+ int i, num;
mutex_lock(&dvbdev_register_lock);
- if ((num = dvbdev_get_free_adapter_num ()) < 0) {
+ for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
+ num = adapter_nums[i];
+ if (num >= 0 && num < DVB_MAX_ADAPTERS) {
+ /* use the one the driver asked for */
+ if (dvbdev_check_free_adapter_num(num))
+ break;
+ } else {
+ num = dvbdev_get_free_adapter_num();
+ break;
+ }
+ num = -1;
+ }
+
+ if (num < 0) {
mutex_unlock(&dvbdev_register_lock);
return -ENFILE;
}
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h
index 6dff10ebf..89d12dc47 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h
@@ -31,6 +31,10 @@
#define DVB_MAJOR 212
+#define DVB_MAX_ADAPTERS 8
+
+#define DVB_UNSET (-1)
+
#define DVB_DEVICE_VIDEO 0
#define DVB_DEVICE_AUDIO 1
#define DVB_DEVICE_SEC 2
@@ -41,6 +45,11 @@
#define DVB_DEVICE_NET 7
#define DVB_DEVICE_OSD 8
+#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
+ static short adapter_nr[] = \
+ {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
+ module_param_array(adapter_nr, short, NULL, 0444); \
+ MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
struct dvb_adapter {
int num;
@@ -78,7 +87,9 @@ struct dvb_device {
};
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
+extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+ struct module *module, struct device *device,
+ short *adapter_nums);
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
@@ -104,7 +115,7 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
/** generic DVB attach function. */
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
#define dvb_attach(FUNCTION, ARGS...) ({ \
void *__r = NULL; \
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index 3c8493d20..3f7b9b632 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -1,6 +1,7 @@
config DVB_USB
tristate "Support for various USB DVB devices"
- depends on DVB_CORE && USB && I2C
+ depends on DVB_CORE && USB && I2C && INPUT
+ depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
help
By enabling this you will be able to choose the various supported
@@ -25,7 +26,7 @@ config DVB_USB_A800
tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
depends on DVB_USB
select DVB_DIB3000MC
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_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.
@@ -35,7 +36,7 @@ config DVB_USB_DIBUSB_MB
depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MB
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -56,7 +57,7 @@ config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB
select DVB_DIB3000MC
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
Support for USB2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -73,8 +74,8 @@ config DVB_USB_DIB0700
select DVB_DIB7000P
select DVB_DIB7000M
select DVB_DIB3000MC
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
- select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_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
@@ -93,7 +94,7 @@ config DVB_USB_UMT_010
depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MC
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
@@ -105,7 +106,7 @@ config DVB_USB_CXUSB
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -118,7 +119,7 @@ config DVB_USB_M920X
tristate "Uli m920x DVB-T USB2.0 support"
depends on DVB_USB
select DVB_MT352 if !DVB_FE_CUSTOMISE
- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of
@@ -129,7 +130,7 @@ config DVB_USB_GL861
tristate "Genesys Logic GL861 USB2.0 support"
depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
help
Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
receiver with USB ID 0db0:5581.
@@ -138,7 +139,7 @@ config DVB_USB_AU6610
tristate "Alcor Micro AU6610 USB2.0 support"
depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
- select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
help
Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
@@ -190,7 +191,7 @@ config DVB_USB_NOVA_T_USB2
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
depends on DVB_USB
select DVB_DIB3000MC
- select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_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.
@@ -227,8 +228,8 @@ config DVB_USB_OPERA1
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
+ select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+ select MEDIA_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)
@@ -240,3 +241,12 @@ config DVB_USB_AF9005_REMOTE
Say Y here to support the default remote control decoding for the
Afatech AF9005 based receiver.
+config DVB_USB_ANYSEE
+ tristate "Anysee DVB-T/C USB2.0 support"
+ depends on DVB_USB
+ select DVB_MT352 if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Anysee E30, Anysee E30 Plus or
+ Anysee E30 C Plus DVB USB2.0 receiver.
diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile
index 60a910052..44c11e45e 100644
--- a/linux/drivers/media/dvb/dvb-usb/Makefile
+++ b/linux/drivers/media/dvb/dvb-usb/Makefile
@@ -61,7 +61,10 @@ 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
+dvb-usb-anysee-objs = anysee.o
+obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/dvb/dvb-usb/a800.c b/linux/drivers/media/dvb/dvb-usb/a800.c
index 16df0a3f9..de7194ee7 100644
--- a/linux/drivers/media/dvb/dvb-usb/a800.c
+++ b/linux/drivers/media/dvb/dvb-usb/a800.c
@@ -18,6 +18,9 @@
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define deb_rc(args...) dprintk(debug,0x01,args)
static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
@@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties;
static int a800_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
+ return dvb_usb_device_init(intf, &a800_properties,
+ THIS_MODULE, NULL, adapter_nr);
}
/* do not change the order of the ID table */
diff --git a/linux/drivers/media/dvb/dvb-usb/af9005.c b/linux/drivers/media/dvb/dvb-usb/af9005.c
index 042bccd0e..04270dd3d 100644
--- a/linux/drivers/media/dvb/dvb-usb/af9005.c
+++ b/linux/drivers/media/dvb/dvb-usb/af9005.c
@@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0;
module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/* remote control decoder */
int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
int *state);
@@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties;
static int af9005_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
+ return dvb_usb_device_init(intf, &af9005_properties,
+ THIS_MODULE, NULL, adapter_nr);
}
static struct usb_device_id af9005_usb_table[] = {
diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.c b/linux/drivers/media/dvb/dvb-usb/anysee.c
new file mode 100644
index 000000000..89675dbf7
--- /dev/null
+++ b/linux/drivers/media/dvb/dvb-usb/anysee.c
@@ -0,0 +1,558 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implented. This
+ * module registers serial interface that can be used to comminicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#include "anysee.h"
+#include "tda1002x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "zl10353.h"
+
+/* debug */
+static int dvb_usb_anysee_debug;
+module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct mutex anysee_usb_mutex;
+
+static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
+ u8 *rbuf, u8 rlen)
+{
+ struct anysee_state *state = d->priv;
+ int act_len, ret;
+ u8 buf[64];
+
+ if (slen > sizeof(buf))
+ slen = sizeof(buf);
+ memcpy(&buf[0], sbuf, slen);
+ buf[60] = state->seq++;
+
+ if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
+ return -EAGAIN;
+
+ /* We need receive one message more after dvb_usb_generic_rw due
+ to weird transaction flow, which is 1 x send + 2 x receive. */
+ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
+
+ if (!ret) {
+ /* receive 2nd answer */
+ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
+ &act_len, 2000);
+ if (ret)
+ err("%s: recv bulk message failed: %d", __func__, ret);
+ else {
+ deb_xfer("<<< ");
+ debug_dump(buf, act_len, deb_xfer);
+ }
+ }
+
+ /* read request, copy returned data to return buf */
+ if (!ret && rbuf && rlen)
+ memcpy(rbuf, buf, rlen);
+
+ mutex_unlock(&anysee_usb_mutex);
+
+ return ret;
+}
+
+static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
+{
+ u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
+ int ret;
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
+ deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
+ return ret;
+}
+
+static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
+{
+ u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
+ deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
+{
+ u8 buf[] = {CMD_GET_HW_INFO};
+ return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
+}
+
+static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
+ deb_info("%s: onoff:%02x\n", __func__, onoff);
+ return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
+{
+ u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
+ deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
+{
+ u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
+ deb_info("%s: onoff:%02x\n", __func__, onoff);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_init(struct dvb_usb_device *d)
+{
+ int ret;
+ /* LED light */
+ ret = anysee_led_ctrl(d, 0x01, 0x03);
+ if (ret)
+ return ret;
+
+ /* enable IR */
+ ret = anysee_ir_ctrl(d, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* I2C */
+static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret, inc, i = 0;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ while (i < num) {
+ if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+ u8 buf[6];
+ buf[0] = CMD_I2C_READ;
+ buf[1] = msg[i].addr + 1;
+ buf[2] = msg[i].buf[0];
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x01;
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
+ msg[i+1].len);
+ inc = 2;
+ } else {
+ u8 buf[4+msg[i].len];
+ buf[0] = CMD_I2C_WRITE;
+ buf[1] = msg[i].addr;
+ buf[2] = msg[i].len;
+ buf[3] = 0x01;
+ memcpy(&buf[4], msg[i].buf, msg[i].len);
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+ inc = 1;
+ }
+ if (ret)
+ return ret;
+
+ i += inc;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+
+ return i;
+}
+
+static u32 anysee_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm anysee_i2c_algo = {
+ .master_xfer = anysee_master_xfer,
+ .functionality = anysee_i2c_func,
+};
+
+static int anysee_mt352_demod_init(struct dvb_frontend *fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+/* Callbacks for DVB USB */
+static struct tda10023_config anysee_tda10023_config = {
+ .demod_address = 0x1a,
+ .invert = 0,
+ .xtal = 16000000,
+ .pll_m = 11,
+ .pll_p = 3,
+ .pll_n = 1,
+ .deltaf = 0xfed6,
+};
+
+static struct mt352_config anysee_mt352_config = {
+ .demod_address = 0x1e,
+ .demod_init = anysee_mt352_demod_init,
+};
+
+static struct zl10353_config anysee_zl10353_config = {
+ .demod_address = 0x1e,
+ .parallel_ts = 1,
+};
+
+static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ int ret;
+ struct anysee_state *state = adap->dev->priv;
+ u8 hw_info[3];
+ u8 io_d; /* IO port D */
+
+ /* check which hardware we have
+ We must do this call two times to get reliable values (hw bug). */
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ return ret;
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ return ret;
+
+ /* Meaning of these info bytes are guessed. */
+ info("firmware version:%d.%d.%d hardware id:%d",
+ 0, hw_info[1], hw_info[2], hw_info[0]);
+
+ ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
+ if (ret)
+ return ret;
+ deb_info("%s: IO port D:%02x\n", __func__, io_d);
+
+ /* Select demod using trial and error method. */
+
+ /* Try to attach demodulator in following order:
+ model demod hw firmware
+ 1. E30 MT352 02 0.2.1
+ 2. E30 ZL10353 02 0.2.1
+ 3. E30 Plus ZL10353 06 0.1.0
+ 4. E30C Plus TDA10023 0a 0.1.0
+ E30C Plus TDA10023 0f 0.1.2 (not working)
+ */
+
+ /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
+ adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+ adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* connect demod on IO port D for TDA10023 & ZL10353 */
+ ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
+ if (ret)
+ return ret;
+
+ /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+ adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* known not working (E30C Plus v0.1.2) */
+ if (hw_info[0] == 0x0f) {
+ info("this version of Anysee is not supported yet");
+ /* return IO port D to init value for safe */
+ ret = anysee_write_reg(adap->dev, 0xb0, io_d);
+ return -ENODEV;
+ }
+
+ /* Philips TDA10023 DVB-C demod */
+ adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
+ &adap->dev->i2c_adap, 0x48);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
+ return 0;
+ }
+
+ /* return IO port D to init value for safe */
+ ret = anysee_write_reg(adap->dev, 0xb0, io_d);
+ if (ret)
+ return ret;
+
+ err("Unkown Anysee version: %02x %02x %02x. "\
+ "Please report the <linux-dvb@linuxtv.org>.",
+ hw_info[0], hw_info[1], hw_info[2]);
+
+ return -ENODEV;
+}
+
+static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct anysee_state *state = adap->dev->priv;
+ deb_info("%s: \n", __func__);
+
+ switch (state->tuner) {
+ case DVB_PLL_THOMSON_DTT7579:
+ /* Thomson dtt7579 (not sure) PLL inside of:
+ Samsung DNOS404ZH102A NIM
+ Samsung DNOS404ZH103A NIM */
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+ NULL, DVB_PLL_THOMSON_DTT7579);
+ break;
+ case DVB_PLL_SAMSUNG_DTOS403IH102A:
+ /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
+ dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+ &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+ break;
+ }
+
+ return 0;
+}
+
+static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 buf[] = {CMD_GET_IR_CODE};
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[2];
+ int i, ret;
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2);
+ if (ret)
+ return ret;
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[0] &&
+ keymap[i].data == ircode[1]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static struct dvb_usb_rc_key anysee_rc_keys[] = {
+ { 0x01, 0x00, KEY_0 },
+ { 0x01, 0x01, KEY_1 },
+ { 0x01, 0x02, KEY_2 },
+ { 0x01, 0x03, KEY_3 },
+ { 0x01, 0x04, KEY_4 },
+ { 0x01, 0x05, KEY_5 },
+ { 0x01, 0x06, KEY_6 },
+ { 0x01, 0x07, KEY_7 },
+ { 0x01, 0x08, KEY_8 },
+ { 0x01, 0x09, KEY_9 },
+ { 0x01, 0x0a, KEY_POWER },
+ { 0x01, 0x0b, KEY_DOCUMENTS }, /* * */
+ { 0x01, 0x19, KEY_FAVORITES },
+ { 0x01, 0x20, KEY_SLEEP },
+ { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */
+ { 0x01, 0x22, KEY_ZOOM },
+ { 0x01, 0x47, KEY_TEXT },
+ { 0x01, 0x16, KEY_TV }, /* TV / radio select */
+ { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */
+ { 0x01, 0x1a, KEY_SUBTITLE },
+ { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */
+ { 0x01, 0x42, KEY_MUTE },
+ { 0x01, 0x0e, KEY_MENU },
+ { 0x01, 0x0f, KEY_EPG },
+ { 0x01, 0x17, KEY_INFO },
+ { 0x01, 0x10, KEY_EXIT },
+ { 0x01, 0x13, KEY_VOLUMEUP },
+ { 0x01, 0x12, KEY_VOLUMEDOWN },
+ { 0x01, 0x11, KEY_CHANNELUP },
+ { 0x01, 0x14, KEY_CHANNELDOWN },
+ { 0x01, 0x15, KEY_OK },
+ { 0x01, 0x1d, KEY_RED },
+ { 0x01, 0x1f, KEY_GREEN },
+ { 0x01, 0x1c, KEY_YELLOW },
+ { 0x01, 0x44, KEY_BLUE },
+ { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */
+ { 0x01, 0x48, KEY_STOP },
+ { 0x01, 0x50, KEY_PLAY },
+ { 0x01, 0x51, KEY_PAUSE },
+ { 0x01, 0x49, KEY_RECORD },
+ { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */
+ { 0x01, 0x0d, KEY_NEXT }, /* >>| */
+ { 0x01, 0x24, KEY_PROG1 }, /* F1 */
+ { 0x01, 0x25, KEY_PROG2 }, /* F2 */
+};
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties anysee_properties;
+
+static int anysee_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct dvb_usb_device *d;
+ struct usb_host_interface *alt;
+ int ret;
+
+ mutex_init(&anysee_usb_mutex);
+
+ /* There is one interface with two alternate settings.
+ Alternate setting 0 is for bulk transfer.
+ Alternate setting 1 is for isochronous transfer.
+ We use bulk transfer (alternate setting 0). */
+ if (intf->num_altsetting < 1)
+ return -ENODEV;
+
+ ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
+ adapter_nr);
+ if (ret)
+ return ret;
+
+ alt = usb_altnum_to_altsetting(intf, 0);
+ if (alt == NULL) {
+ deb_info("%s: no alt found!\n", __func__);
+ return -ENODEV;
+ }
+
+ ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+ alt->desc.bAlternateSetting);
+ if (ret)
+ return ret;
+
+ if (d)
+ ret = anysee_init(d);
+
+ return ret;
+}
+
+static struct usb_device_id anysee_table [] = {
+ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
+ { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, anysee_table);
+
+static struct dvb_usb_device_properties anysee_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+
+ .size_of_priv = sizeof(struct anysee_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = anysee_streaming_ctrl,
+ .frontend_attach = anysee_frontend_attach,
+ .tuner_attach = anysee_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 512,
+ }
+ }
+ },
+ }
+ },
+
+ .rc_key_map = anysee_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys),
+ .rc_query = anysee_rc_query,
+ .rc_interval = 200, /* windows driver uses 500ms */
+
+ .i2c_algo = &anysee_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 1,
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ .name = "Anysee DVB USB2.0",
+ .cold_ids = {NULL},
+ .warm_ids = {&anysee_table[0],
+ &anysee_table[1], NULL},
+ },
+ }
+};
+
+static struct usb_driver anysee_driver = {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
+ .owner = THIS_MODULE,
+#endif
+ .name = "dvb_usb_anysee",
+ .probe = anysee_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = anysee_table,
+};
+
+/* module stuff */
+static int __init anysee_module_init(void)
+{
+ int ret;
+
+ ret = usb_register(&anysee_driver);
+ if (ret)
+ err("%s: usb_register failed. Error number %d", __func__, ret);
+
+ return ret;
+}
+
+static void __exit anysee_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&anysee_driver);
+}
+
+module_init(anysee_module_init);
+module_exit(anysee_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.h b/linux/drivers/media/dvb/dvb-usb/anysee.h
new file mode 100644
index 000000000..48da3949e
--- /dev/null
+++ b/linux/drivers/media/dvb/dvb-usb/anysee.h
@@ -0,0 +1,304 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implented. This
+ * module registers serial interface that can be used to comminicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#ifndef _DVB_USB_ANYSEE_H_
+#define _DVB_USB_ANYSEE_H_
+
+#define DVB_USB_LOG_PREFIX "anysee"
+#include "dvb-usb.h"
+
+#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
+#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
+#define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args)
+#define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args)
+#define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args)
+#define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args)
+
+enum cmd {
+ CMD_I2C_READ = 0x33,
+ CMD_I2C_WRITE = 0x31,
+ CMD_REG_READ = 0xb0,
+ CMD_REG_WRITE = 0xb1,
+ CMD_STREAMING_CTRL = 0x12,
+ CMD_LED_AND_IR_CTRL = 0x16,
+ CMD_GET_IR_CODE = 0x41,
+ CMD_GET_HW_INFO = 0x19,
+ CMD_SMARTCARD = 0x34,
+};
+
+struct anysee_state {
+ u8 tuner;
+ u8 seq;
+};
+
+#endif
+
+/***************************************************************************
+ * USB API description (reverse engineered)
+ ***************************************************************************
+
+Transaction flow:
+=================
+BULK[00001] >>> REQUEST PACKET 64 bytes
+BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY)
+BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY)
+
+General reply packet(s) are always used if not own reply defined.
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY)
+============================================================================
+| 00 | reply data (if any) from previous transaction
+| | Just same reply packet as returned during previous transaction.
+| | Needed only if reply is missed in previous transaction.
+| | Just skip normally.
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY)
+============================================================================
+| 00 | reply data (if any)
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C WRITE REQUEST PACKET
+============================================================================
+| 00 | 0x31 I2C write command
+----------------------------------------------------------------------------
+| 01 | i2c address
+----------------------------------------------------------------------------
+| 02 | data length
+| | 0x02 (for typical I2C reg / val pair)
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04- | data
+----------------------------------------------------------------------------
+| -59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C READ REQUEST PACKET
+============================================================================
+| 00 | 0x33 I2C read command
+----------------------------------------------------------------------------
+| 01 | i2c address + 1
+----------------------------------------------------------------------------
+| 02 | register
+----------------------------------------------------------------------------
+| 03 | 0x00
+----------------------------------------------------------------------------
+| 04 | 0x00
+----------------------------------------------------------------------------
+| 05 | 0x01
+----------------------------------------------------------------------------
+| 06-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET
+============================================================================
+| 00 | 0xb1 register write command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04 | value
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET
+============================================================================
+| 00 | 0xb0 register read command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | LED CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+| 01 | 0x01 (LED)
+----------------------------------------------------------------------------
+| 03 | 0x00 blink
+| | 0x01 lights continuously
+----------------------------------------------------------------------------
+| 04 | blink interval
+| | 0x00 fastest (looks like LED lights continuously)
+| | 0xff slowest
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | IR CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+| 01 | 0x02 (IR)
+----------------------------------------------------------------------------
+| 03 | 0x00 IR disabled
+| | 0x01 IR enabled
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | STREAMING CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x12 streaming control command
+----------------------------------------------------------------------------
+| 01 | 0x00 streaming disabled
+| | 0x01 streaming enabled
+----------------------------------------------------------------------------
+| 02 | 0x00
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x41 remote control command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REPLY PACKET
+============================================================================
+| 00 | 0x00 code not received
+| | 0x01 code received
+----------------------------------------------------------------------------
+| 01 | remote control code
+----------------------------------------------------------------------------
+| 02-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REQUEST PACKET
+============================================================================
+| 00 | 0x19 get hardware info command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REPLY PACKET
+============================================================================
+| 00 | hardware id
+----------------------------------------------------------------------------
+| 01-02 | firmware version
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | SMART CARD READER PACKET
+============================================================================
+| 00 | 0x34 smart card reader command
+----------------------------------------------------------------------------
+| xx |
+----------------------------------------------------------------------------
+| xx-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+*/
diff --git a/linux/drivers/media/dvb/dvb-usb/au6610.c b/linux/drivers/media/dvb/dvb-usb/au6610.c
index 4800a5004..fc3375c60 100644
--- a/linux/drivers/media/dvb/dvb-usb/au6610.c
+++ b/linux/drivers/media/dvb/dvb-usb/au6610.c
@@ -1,23 +1,32 @@
-/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
*
* Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation, version 2.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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 "au6610.h"
-
#include "zl10353.h"
#include "qt1010.h"
/* debug */
static int dvb_usb_au6610_debug;
module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
@@ -40,9 +49,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
}
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
- USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf,
- sizeof(usb_buf), AU6610_USB_TIMEOUT);
-
+ USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
+ usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
if (ret < 0)
return ret;
@@ -114,15 +122,6 @@ static struct i2c_algorithm au6610_i2c_algo = {
};
/* Callbacks for DVB USB */
-static int au6610_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc,
- int *cold)
-{
- *cold = 0;
- return 0;
-}
-
static struct zl10353_config au6610_zl10353_config = {
.demod_address = 0x0f,
.no_tuner = 1,
@@ -131,12 +130,12 @@ static struct zl10353_config au6610_zl10353_config = {
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
- if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
- &adap->dev->i2c_adap)) != NULL) {
- return 0;
- }
+ adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe == NULL)
+ return -ENODEV;
- return -EIO;
+ return 0;
}
static struct qt1010_config au6610_qt1010_config = {
@@ -163,11 +162,13 @@ static int au6610_probe(struct usb_interface *intf,
if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
return -ENODEV;
- if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
+ adapter_nr);
+ if (ret == 0) {
alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
if (alt == NULL) {
- deb_rc("no alt found!\n");
+ deb_info("%s: no alt found!\n", __func__);
return -ENODEV;
}
ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
@@ -177,18 +178,19 @@ static int au6610_probe(struct usb_interface *intf,
return ret;
}
-
static struct usb_device_id au6610_table [] = {
{ USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, au6610_table);
+MODULE_DEVICE_TABLE(usb, au6610_table);
static struct dvb_usb_device_properties au6610_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
.usb_ctrl = DEVICE_SPECIFIC,
- .size_of_priv = 0,
- .identify_state = au6610_identify_state,
+
+ .size_of_priv = 0,
+
.num_adapters = 1,
.adapter = {
{
@@ -202,26 +204,28 @@ static struct dvb_usb_device_properties au6610_properties = {
.u = {
.isoc = {
.framesperurb = 40,
- .framesize = 942, /* maximum packet size */
- .interval = 1.25, /* 125 us */
+ .framesize = 942,
+ .interval = 1,
}
}
},
}
},
+
.i2c_algo = &au6610_i2c_algo,
+
.num_device_descs = 1,
.devices = {
{
- "Sigmatek DVB-110 DVB-T USB2.0",
- { &au6610_table[0], NULL },
- { NULL },
+ .name = "Sigmatek DVB-110 DVB-T USB2.0",
+ .cold_ids = {NULL},
+ .warm_ids = {&au6610_table[0], NULL},
},
}
};
static struct usb_driver au6610_driver = {
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
.owner = THIS_MODULE,
#endif
.name = "dvb_usb_au6610",
@@ -235,12 +239,11 @@ static int __init au6610_module_init(void)
{
int ret;
- if ((ret = usb_register(&au6610_driver))) {
+ ret = usb_register(&au6610_driver);
+ if (ret)
err("usb_register failed. Error number %d", ret);
- return ret;
- }
- return 0;
+ return ret;
}
static void __exit au6610_module_exit(void)
@@ -249,10 +252,10 @@ static void __exit au6610_module_exit(void)
usb_deregister(&au6610_driver);
}
-module_init (au6610_module_init);
-module_exit (au6610_module_exit);
+module_init(au6610_module_init);
+module_exit(au6610_module_exit);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610");
+MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dvb-usb/au6610.h b/linux/drivers/media/dvb/dvb-usb/au6610.h
index 4161b054c..7849abe2c 100644
--- a/linux/drivers/media/dvb/dvb-usb/au6610.h
+++ b/linux/drivers/media/dvb/dvb-usb/au6610.h
@@ -1,10 +1,30 @@
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
+ *
+ * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DVB_USB_AU6610_H_
#define _DVB_USB_AU6610_H_
#define DVB_USB_LOG_PREFIX "au6610"
#include "dvb-usb.h"
-#define deb_rc(args...) dprintk(dvb_usb_au6610_debug,0x01,args)
+#define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args)
#define AU6610_REQ_I2C_WRITE 0x14
#define AU6610_REQ_I2C_READ 0x13
diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c
index 84d8a915d..ddfa0cff7 100644
--- a/linux/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c
@@ -33,13 +33,15 @@
#include "mt352_priv.h"
#include "zl10353.h"
#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
#include "tuner-simple.h"
/* debug */
static int dvb_usb_cxusb_debug;
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
dprintk(dvb_usb_cxusb_debug,0x01,args)
@@ -492,14 +494,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
switch (command) {
case XC2028_TUNER_RESET:
- deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+ deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
cxusb_bluebird_gpio_pulse(d, 0x01, 1);
break;
case XC2028_RESET_CLK:
- deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+ deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
break;
default:
- deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
+ deb_info("%s: unknown command %d, arg %d\n", __func__,
command, arg);
return -EINVAL;
}
@@ -518,7 +520,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
static struct xc2028_ctrl ctl = {
.fname = "xc3028-dvico-au-01.fw",
.max_len = 64,
- .scode_table = ZARLINK456,
+ .scode_table = XC3028_FE_ZARLINK456,
};
fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
@@ -723,16 +725,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
+ if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &cxusb_bluebird_nano2_needsfirmware_properties,
+ THIS_MODULE, NULL, adapter_nr))
return 0;
- }
return -EINVAL;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
index 9d3217983..a2162fda5 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -17,6 +17,8 @@ int dvb_usb_dib0700_ir_proto = 1;
module_param(dvb_usb_dib0700_ir_proto, int, 0644);
MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{
@@ -289,7 +291,8 @@ static int dib0700_probe(struct usb_interface *intf,
#endif
for (i = 0; i < dib0700_device_count; i++)
- if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
+ if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
+ &dev, adapter_nr) == 0)
{
dib0700_rc_setup(dev);
return 0;
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 6477fc66c..c4d40fe01 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -111,8 +111,8 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
@@ -299,7 +299,7 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
}
/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
-struct dibx000_agc_config xc3028_agc_config = {
+static struct dibx000_agc_config xc3028_agc_config = {
BAND_VHF | BAND_UHF, /* band_caps */
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
@@ -342,7 +342,7 @@ struct dibx000_agc_config xc3028_agc_config = {
};
/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
-struct dibx000_bandwidth_config xc3028_bw_config = {
+static struct dibx000_bandwidth_config xc3028_bw_config = {
60000, 30000, /* internal, sampling */
1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
@@ -402,8 +402,8 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
- if (desc->idVendor == USB_VID_PINNACLE &&
- desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
+ if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -845,8 +845,8 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c;
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
@@ -990,11 +990,12 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
/* STK7070P */
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
{
- if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ 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);
diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 0d0edece8..2ac86685d 100644
--- a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -14,6 +14,8 @@
*/
#include "dibusb.h"
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
@@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties;
static int dibusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
+ if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
+ THIS_MODULE, NULL, adapter_nr))
return 0;
return -EINVAL;
diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c
index 8fa2b6908..b1658ac6b 100644
--- a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -14,13 +14,16 @@
*/
#include "dibusb.h"
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/* USB Driver stuff */
static struct dvb_usb_device_properties dibusb_mc_properties;
static int dibusb_mc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
+ return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
+ NULL, adapter_nr);
}
/* do not change the order of the ID table */
diff --git a/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c
index 382ffaa1e..1394b3e6b 100644
--- a/linux/drivers/media/dvb/dvb-usb/digitv.c
+++ b/linux/drivers/media/dvb/dvb-usb/digitv.c
@@ -20,6 +20,9 @@
static int dvb_usb_digitv_debug;
module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
static int digitv_ctrl_msg(struct dvb_usb_device *d,
@@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct dvb_usb_device *d;
- int ret;
- if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+ int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
+ adapter_nr);
+ if (ret == 0) {
u8 b[4] = { 0 };
if (d != NULL) { /* do that only when the firmware is loaded */
diff --git a/linux/drivers/media/dvb/dvb-usb/dtt200u.c b/linux/drivers/media/dvb/dvb-usb/dtt200u.c
index 24ccd5a4d..5fcae7925 100644
--- a/linux/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/linux/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug;
module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 b = SET_INIT;
@@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
+ if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &wt220u_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
+ THIS_MODULE, NULL, adapter_nr))
return 0;
return -ENODEV;
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h
index 35ab68f6d..6b7b2a892 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
extern int dvb_usb_i2c_init(struct dvb_usb_device *);
extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
+ short *adapter_nums);
extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 4561a672d..ce8cd0c5d 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
return dvb_usb_ctrl_feed(dvbdmxfeed,0);
}
-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
+int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
{
- int ret;
+ int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+ adap->dev->owner, &adap->dev->udev->dev,
+ adapter_nums);
- if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
- adap->dev->owner, &adap->dev->udev->dev)) < 0) {
+ if (ret < 0) {
deb_info("dvb_register_adapter failed: error %d", ret);
goto err;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index e1112e39f..733a7ff7b 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -127,7 +127,7 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
if ((*pos + hx->len + 4) >= fw->size)
return -EINVAL;
- hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->addr = b[1] | (b[2] << 8);
hx->type = b[3];
if (hx->type == 0x04) {
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 34245d1b7..e6b43fb3a 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -14,6 +14,7 @@
#define USB_VID_AFATECH 0x15a4
#define USB_VID_ALCOR_MICRO 0x058f
#define USB_VID_ALINK 0x05e3
+#define USB_VID_AMT 0x1c73
#define USB_VID_ANCHOR 0x0547
#define USB_VID_ANSONIC 0x10b9
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
@@ -57,6 +58,7 @@
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
+#define USB_PID_ANYSEE 0x861f
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index cdd717c3f..e331db8c7 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage;
module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
{
struct dvb_usb_adapter *adap;
int ret,n;
@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d)
}
if ((ret = dvb_usb_adapter_stream_init(adap)) ||
- (ret = dvb_usb_adapter_dvb_init(adap)) ||
+ (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
(ret = dvb_usb_adapter_frontend_init(adap))) {
return ret;
}
@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
return 0;
}
-static int dvb_usb_init(struct dvb_usb_device *d)
+static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
{
int ret = 0;
@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
dvb_usb_device_power_ctrl(d, 1);
if ((ret = dvb_usb_i2c_init(d)) ||
- (ret = dvb_usb_adapter_init(d))) {
+ (ret = dvb_usb_adapter_init(d, adapter_nums))) {
dvb_usb_exit(d);
return ret;
}
@@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
/*
* USB
*/
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
- *props, struct module *owner,struct dvb_usb_device **du)
+int dvb_usb_device_init(struct usb_interface *intf,
+ struct dvb_usb_device_properties *props,
+ struct module *owner, struct dvb_usb_device **du,
+ short *adapter_nums)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_device *d = NULL;
@@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper
if (du != NULL)
*du = d;
- ret = dvb_usb_init(d);
+ ret = dvb_usb_init(d, adapter_nums);
if (ret == 0)
info("%s successfully initialized and connected.",desc->name);
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
index cc5d432bc..f8528bf74 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -387,7 +387,10 @@ struct dvb_usb_device {
void *priv;
};
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
+extern int dvb_usb_device_init(struct usb_interface *,
+ struct dvb_usb_device_properties *,
+ struct module *, struct dvb_usb_device **,
+ short *adapter_nums);
extern void dvb_usb_device_exit(struct usb_interface *);
/* the generic read/write method for device control */
diff --git a/linux/drivers/media/dvb/dvb-usb/gl861.c b/linux/drivers/media/dvb/dvb-usb/gl861.c
index 8f26ede0c..cc90a3054 100644
--- a/linux/drivers/media/dvb/dvb-usb/gl861.c
+++ b/linux/drivers/media/dvb/dvb-usb/gl861.c
@@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug;
module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{
@@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf,
if (intf->num_altsetting < 2)
return -ENODEV;
- if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
+ adapter_nr);
+ if (ret == 0) {
alt = usb_altnum_to_altsetting(intf, 0);
if (alt == NULL) {
diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index e37142d92..262a858c3 100644
--- a/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
{
struct gp8psk_fe_state *st = fe->demodulator_priv;
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
m->msg, m->msg_len)) {
@@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
struct gp8psk_fe_state *st = fe->demodulator_priv;
u8 cmd;
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
/* These commands are certainly wrong */
cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c
index 54ecee36d..0a152fcb5 100644
--- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug;
module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
{
int ret = 0,try = 0;
@@ -144,24 +146,24 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
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;
+ return -EINVAL;
if (! (status & bmIntersilOn)) /* LNB Power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
&buf, 1))
- return EINVAL;
+ return -EINVAL;
/* 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;
+ return -EINVAL;
/* Abort possible TS (if previous tune crashed) */
if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
- return EINVAL;
+ return -EINVAL;
} else {
/* Turn off LNB power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
- return EINVAL;
+ return -EINVAL;
/* Turn off 8psk power */
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
return -EINVAL;
@@ -208,7 +210,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
{
int ret;
struct usb_device *udev = interface_to_usbdev(intf);
- ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+ ret = dvb_usb_device_init(intf, &gp8psk_properties,
+ THIS_MODULE, NULL, adapter_nr);
if (ret == 0) {
info("found Genpix USB device pID = %x (hex)",
le16_to_cpu(udev->descriptor.idProduct));
diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c
index 503598127..5a7766fab 100644
--- a/linux/drivers/media/dvb/dvb-usb/m920x.c
+++ b/linux/drivers/media/dvb/dvb-usb/m920x.c
@@ -16,12 +16,15 @@
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
+#include <asm/unaligned.h>
/* debug */
static int dvb_usb_m920x_debug;
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
@@ -345,13 +348,13 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
for (pass = 0; pass < 2; pass++) {
for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
- value = le16_to_cpu(*(u16 *)(fw->data + i));
+ value = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- index = le16_to_cpu(*(u16 *)(fw->data + i));
+ index = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- size = le16_to_cpu(*(u16 *)(fw->data + i));
+ size = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
if (pass == 1) {
@@ -477,7 +480,7 @@ static struct qt1010_config m920x_qt1010_config = {
/* Callbacks for DVB USB */
static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if ((adap->fe = dvb_attach(mt352_attach,
&m920x_mt352_config,
@@ -489,7 +492,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if ((adap->fe = dvb_attach(tda10046_attach,
&m920x_tda10046_08_config,
@@ -501,7 +504,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if ((adap->fe = dvb_attach(tda10046_attach,
&m920x_tda10046_0b_config,
@@ -513,7 +516,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
return -ENODEV;
@@ -523,7 +526,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
@@ -533,7 +536,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
{
- deb("%s\n",__FUNCTION__);
+ deb("%s\n",__func__);
if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
return -ENODEV;
@@ -618,27 +621,31 @@ static int m920x_probe(struct usb_interface *intf,
* multi-tuner device
*/
- if ((ret = dvb_usb_device_init(intf, &megasky_properties,
- THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &megasky_properties,
+ THIS_MODULE, &d, adapter_nr);
+ if (ret == 0) {
rc_init_seq = megasky_rc_init;
goto found;
}
- if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
- THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+ THIS_MODULE, &d, adapter_nr);
+ if (ret == 0) {
/* No remote control, so no rc_init_seq */
goto found;
}
/* This configures both tuners on the TV Walker Twin */
- if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
- THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+ THIS_MODULE, &d, adapter_nr);
+ if (ret == 0) {
rc_init_seq = tvwalkertwin_rc_init;
goto found;
}
- if ((ret = dvb_usb_device_init(intf, &dposh_properties,
- THIS_MODULE, &d)) == 0) {
+ ret = dvb_usb_device_init(intf, &dposh_properties,
+ THIS_MODULE, &d, adapter_nr);
+ if (ret == 0) {
/* Remote controller not supported yet. */
goto found;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index f0aadc8a2..a346040ca 100644
--- a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -15,6 +15,8 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define deb_rc(args...) dprintk(debug,0x01,args)
#define deb_ee(args...) dprintk(debug,0x02,args)
@@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties;
static int nova_t_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
+ return dvb_usb_device_init(intf, &nova_t_properties,
+ THIS_MODULE, NULL, adapter_nr);
}
/* do not change the order of the ID table */
diff --git a/linux/drivers/media/dvb/dvb-usb/opera1.c b/linux/drivers/media/dvb/dvb-usb/opera1.c
index 78f55fd69..cba064615 100644
--- a/linux/drivers/media/dvb/dvb-usb/opera1.c
+++ b/linux/drivers/media/dvb/dvb-usb/opera1.c
@@ -45,6 +45,9 @@ module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
MODULE_PARM_DESC(debug,
"set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#if 0
struct mutex mymutex;
#endif
@@ -254,7 +257,7 @@ static struct stv0299_config opera1_stv0299_config = {
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_0,
+ .lock_output = STV0299_LOCKOUTPUT_0,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.inittab = opera1_inittab,
.set_symbol_rate = opera1_stv0299_set_symbol_rate,
@@ -559,7 +562,8 @@ static int opera1_probe(struct usb_interface *intf,
return -EINVAL;
}
- if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
+ if (0 != dvb_usb_device_init(intf, &opera1_properties,
+ THIS_MODULE, NULL, adapter_nr))
return -EINVAL;
return 0;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/ttusb2.c b/linux/drivers/media/dvb/dvb-usb/ttusb2.c
index 572760414..e79a26473 100644
--- a/linux/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/linux/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug;
module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
struct ttusb2_state {
u8 id;
};
@@ -151,6 +153,7 @@ static struct tda10086_config tda10086_config = {
.demod_address = 0x0e,
.invert = 0,
.diseqc_tone = 1,
+ .xtal_freq = TDA10086_XTAL_16M,
};
static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
@@ -187,8 +190,10 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400;
static int ttusb2_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf, &ttusb2_properties, THIS_MODULE, NULL) == 0 ||
- dvb_usb_device_init(intf, &ttusb2_properties_s2400, THIS_MODULE, NULL) == 0)
+ if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
+ THIS_MODULE, NULL, adapter_nr))
return 0;
return -ENODEV;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/umt-010.c b/linux/drivers/media/dvb/dvb-usb/umt-010.c
index f0aff4b0d..ca850d266 100644
--- a/linux/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/linux/drivers/media/dvb/dvb-usb/umt-010.c
@@ -13,6 +13,8 @@
#include "mt352.h"
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static int umt_mt352_demod_init(struct dvb_frontend *fe)
{
static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
@@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties;
static int umt_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
+ if (0 == dvb_usb_device_init(intf, &umt_properties,
+ THIS_MODULE, NULL, adapter_nr))
return 0;
return -EINVAL;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/vp702x-fe.c b/linux/drivers/media/dvb/dvb-usb/vp702x-fe.c
index c3fdc7cd0..ccc7e4452 100644
--- a/linux/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/linux/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
vp702x_fe_refresh_state(st);
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
if (st->lock == 0)
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
@@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
{
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
tune->min_delay_ms = 2000;
return 0;
}
@@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
static int vp702x_fe_init(struct dvb_frontend *fe)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
return 0;
}
static int vp702x_fe_sleep(struct dvb_frontend *fe)
{
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
return 0;
}
static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
return 0;
}
@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
u8 cmd[8],ibuf[10];
memset(cmd,0,8);
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
if (m->msg_len > 4)
return -EINVAL;
@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
return 0;
}
@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 ibuf[10];
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
st->tone_mode = tone;
@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 ibuf[10];
- deb_fe("%s\n",__FUNCTION__);
+ deb_fe("%s\n",__func__);
st->voltage = voltage;
diff --git a/linux/drivers/media/dvb/dvb-usb/vp702x.c b/linux/drivers/media/dvb/dvb-usb/vp702x.c
index 28b7011f2..9d286d430 100644
--- a/linux/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/linux/drivers/media/dvb/dvb-usb/vp702x.c
@@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug;
module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
struct vp702x_state {
int pid_filter_count;
int pid_filter_can_bypass;
@@ -285,7 +287,8 @@ static struct dvb_usb_device_properties vp702x_properties;
static int vp702x_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+ return dvb_usb_device_init(intf, &vp702x_properties,
+ THIS_MODULE, NULL, adapter_nr);
}
static struct usb_device_id vp702x_usb_table [] = {
diff --git a/linux/drivers/media/dvb/dvb-usb/vp7045.c b/linux/drivers/media/dvb/dvb-usb/vp7045.c
index 9d244e603..b45498911 100644
--- a/linux/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/linux/drivers/media/dvb/dvb-usb/vp7045.c
@@ -18,6 +18,9 @@
static int dvb_usb_vp7045_debug;
module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
@@ -227,7 +230,8 @@ static struct dvb_usb_device_properties vp7045_properties;
static int vp7045_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
+ return dvb_usb_device_init(intf, &vp7045_properties,
+ THIS_MODULE, NULL, adapter_nr);
}
static struct usb_device_id vp7045_usb_table [] = {
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig
index 0209644f2..fa7f0c563 100644
--- a/linux/drivers/media/dvb/frontends/Kconfig
+++ b/linux/drivers/media/dvb/frontends/Kconfig
@@ -15,22 +15,36 @@ config DVB_FE_CUSTOMISE
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
-config DVB_STV0299
- tristate "ST STV0299 based"
+config DVB_CX24110
+ tristate "Conexant CX24110 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_CX24110
- tristate "Conexant CX24110 based"
+config DVB_CX24123
+ tristate "Conexant CX24123 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_CX24123
- tristate "Conexant CX24123 based"
+config DVB_MT312
+ tristate "Zarlink VP310/MT312/ZL10313 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_S5H1420
+ tristate "Samsung S5H1420 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STV0299
+ tristate "ST STV0299 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
@@ -43,8 +57,8 @@ config DVB_TDA8083
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_MT312
- tristate "Zarlink VP310/MT312 based"
+config DVB_TDA10086
+ tristate "Philips TDA10086 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
@@ -57,26 +71,33 @@ config DVB_VES1X93
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_S5H1420
- tristate "Samsung S5H1420 based"
+config DVB_TUNER_ITD1000
+ tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
-config DVB_TDA10086
- tristate "Philips TDA10086 based"
+config DVB_TDA826X
+ tristate "Philips TDA826X silicon tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
- A DVB-S tuner module. Say Y when you want to support this frontend.
+ A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_TUA6100
+ tristate "Infineon TUA6100 PLL"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S PLL chip.
comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
config DVB_SP8870
tristate "Spase sp8870 based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -89,7 +110,7 @@ config DVB_SP8870
config DVB_SP887X
tristate "Spase sp887x based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -114,6 +135,20 @@ config DVB_CX22702
help
A DVB-T tuner module. Say Y when you want to support this frontend.
+config DVB_DRX397XD
+ tristate "Micronas DRX3975D/DRX3977D based"
+ depends on DVB_CORE && I2C && HOTPLUG
+ default m if DVB_FE_CUSTOMISE
+ select FW_LOADER
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
+
+ TODO:
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_L64781
tristate "LSI L64781"
depends on DVB_CORE && I2C
@@ -123,7 +158,7 @@ config DVB_L64781
config DVB_TDA1004X
tristate "Philips TDA10045H/TDA10046H based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -188,6 +223,14 @@ config DVB_DIB7000P
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
+config DVB_TDA10048
+ tristate "Philips TDA10048HN based"
+ depends on DVB_CORE && I2C && HOTPLUG
+ default m if DVB_FE_CUSTOMISE
+ select FW_LOADER
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
+
comment "DVB-C (cable) frontends"
depends on DVB_CORE
@@ -224,7 +267,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
config DVB_NXT200X
tristate "NxtWave Communications NXT2002/NXT2004 based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -239,7 +282,7 @@ config DVB_NXT200X
config DVB_OR51211
tristate "Oren OR51211 based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -252,7 +295,7 @@ config DVB_OR51211
config DVB_OR51132
tristate "Oren OR51132 based"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -268,7 +311,7 @@ config DVB_OR51132
config DVB_BCM3510
tristate "Broadcom BCM3510"
- depends on DVB_CORE && I2C
+ depends on DVB_CORE && I2C && HOTPLUG
default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
@@ -291,65 +334,32 @@ config DVB_S5H1409
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
-
-config DVB_PLL
- tristate "Generic I2C PLL based tuners"
- depends on DVB_CORE && I2C
- default m if DVB_FE_CUSTOMISE
- help
- 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
- tristate "Philips TDA826X silicon tuner"
+config DVB_AU8522
+ tristate "Auvitek AU8522 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
- A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
-config DVB_TDA827X
- tristate "Philips TDA827X silicon tuner"
+config DVB_S5H1411
+ tristate "Samsung S5H1411 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
- A DVB-T silicon tuner module. Say Y when you want to support this tuner.
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
-config DVB_TDA18271
- tristate "NXP TDA18271 silicon tuner"
- depends on I2C
- default m if DVB_FE_CUSTOMISE
- help
- A silicon tuner module. Say Y when you want to support this tuner.
+comment "Digital terrestrial only tuners/PLL"
+ depends on DVB_CORE
-config DVB_TUNER_QT1010
- tristate "Quantek QT1010 silicon tuner"
+config DVB_PLL
+ tristate "Generic I2C PLL based tuners"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
- A driver for the silicon tuner QT1010 from Quantek.
-
-config DVB_TUNER_MT2060
- tristate "Microtune MT2060 silicon IF tuner"
- depends on I2C
- default m if DVB_FE_CUSTOMISE
- 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.
+ 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_TUNER_DIB0070
tristate "DiBcom DiB0070 silicon base-band tuner"
@@ -360,16 +370,7 @@ config DVB_TUNER_DIB0070
This device is only used inside a SiP called togther with a
demodulator for now.
-config DVB_TUNER_XC5000
- tristate "Xceive XC5000 silicon tuner"
- depends on I2C
- default m if DVB_FE_CUSTOMISE
- help
- A driver for the silicon tuner XC5000 from Xceive.
- This device is only used inside a SiP called togther with a
- demodulator for now.
-
-comment "Miscellaneous devices"
+comment "SEC control devices for DVB-S"
depends on DVB_CORE
config DVB_LNBP21
@@ -393,11 +394,4 @@ config DVB_ISL6421
help
An SEC control chip.
-config DVB_TUA6100
- tristate "TUA6100 PLL"
- depends on DVB_CORE && I2C
- default m if DVB_FE_CUSTOMISE
- help
- A DVBS PLL chip.
-
endmenu
diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile
index 23304b377..028da5561 100644
--- a/linux/drivers/media/dvb/frontends/Makefile
+++ b/linux/drivers/media/dvb/frontends/Makefile
@@ -3,9 +3,7 @@
#
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/video/
-
-tda18271-objs := tda18271-tables.o tda18271-common.o tda18271-fe.o
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -27,6 +25,7 @@ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_ZL10353) += zl10353.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o
+obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_TDA10023) += tda10023.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
@@ -42,13 +41,10 @@ obj-$(CONFIG_DVB_ISL6405) += isl6405.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
-obj-$(CONFIG_DVB_TDA827X) += tda827x.o
-obj-$(CONFIG_DVB_TDA18271) += tda18271.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
-obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
+obj-$(CONFIG_DVB_AU8522) += au8522.o
+obj-$(CONFIG_DVB_TDA10048) += tda10048.o
+obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
diff --git a/linux/drivers/media/dvb/frontends/au8522.c b/linux/drivers/media/dvb/frontends/au8522.c
new file mode 100644
index 000000000..3e1b0d96f
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/au8522.c
@@ -0,0 +1,697 @@
+/*
+ Auvitek AU8522 QAM/8VSB demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "au8522.h"
+
+struct au8522_state {
+
+ struct i2c_adapter *i2c;
+
+ /* configuration settings */
+ const struct au8522_config *config;
+
+ struct dvb_frontend frontend;
+
+ u32 current_frequency;
+ fe_modulation_t current_modulation;
+
+};
+
+static int debug;
+
+#define dprintk(arg...) do { \
+ if (debug) \
+ printk(arg); \
+ } while (0)
+
+/* 16 bit registers, 8 bit values */
+static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+ int ret;
+ u8 buf [] = { reg >> 8, reg & 0xff, data };
+
+ struct i2c_msg msg = { .addr = state->config->demod_address,
+ .flags = 0, .buf = buf, .len = 3 };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+}
+
+static u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+ int ret;
+ u8 b0 [] = { reg >> 8, reg & 0xff };
+ u8 b1 [] = { 0 };
+
+ struct i2c_msg msg [] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 2 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 } };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
+ return b1[0];
+}
+
+static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __func__, enable);
+
+ if (enable)
+ return au8522_writereg(state, 0x106, 1);
+ else
+ return au8522_writereg(state, 0x106, 0);
+}
+
+struct mse2snr_tab {
+ u16 val;
+ u16 data;
+};
+
+/* VSB SNR lookup table */
+static struct mse2snr_tab vsb_mse2snr_tab[] = {
+ { 0, 270 },
+ { 2, 250 },
+ { 3, 240 },
+ { 5, 230 },
+ { 7, 220 },
+ { 9, 210 },
+ { 12, 200 },
+ { 13, 195 },
+ { 15, 190 },
+ { 17, 185 },
+ { 19, 180 },
+ { 21, 175 },
+ { 24, 170 },
+ { 27, 165 },
+ { 31, 160 },
+ { 32, 158 },
+ { 33, 156 },
+ { 36, 152 },
+ { 37, 150 },
+ { 39, 148 },
+ { 40, 146 },
+ { 41, 144 },
+ { 43, 142 },
+ { 44, 140 },
+ { 48, 135 },
+ { 50, 130 },
+ { 43, 142 },
+ { 53, 125 },
+ { 56, 120 },
+ { 256, 115 },
+};
+
+/* QAM64 SNR lookup table */
+static struct mse2snr_tab qam64_mse2snr_tab[] = {
+ { 15, 0 },
+ { 16, 290 },
+ { 17, 288 },
+ { 18, 286 },
+ { 19, 284 },
+ { 20, 282 },
+ { 21, 281 },
+ { 22, 279 },
+ { 23, 277 },
+ { 24, 275 },
+ { 25, 273 },
+ { 26, 271 },
+ { 27, 269 },
+ { 28, 268 },
+ { 29, 266 },
+ { 30, 264 },
+ { 31, 262 },
+ { 32, 260 },
+ { 33, 259 },
+ { 34, 258 },
+ { 35, 256 },
+ { 36, 255 },
+ { 37, 254 },
+ { 38, 252 },
+ { 39, 251 },
+ { 40, 250 },
+ { 41, 249 },
+ { 42, 248 },
+ { 43, 246 },
+ { 44, 245 },
+ { 45, 244 },
+ { 46, 242 },
+ { 47, 241 },
+ { 48, 240 },
+ { 50, 239 },
+ { 51, 238 },
+ { 53, 237 },
+ { 54, 236 },
+ { 56, 235 },
+ { 57, 234 },
+ { 59, 233 },
+ { 60, 232 },
+ { 62, 231 },
+ { 63, 230 },
+ { 65, 229 },
+ { 67, 228 },
+ { 68, 227 },
+ { 70, 226 },
+ { 71, 225 },
+ { 73, 224 },
+ { 74, 223 },
+ { 76, 222 },
+ { 78, 221 },
+ { 80, 220 },
+ { 82, 219 },
+ { 85, 218 },
+ { 88, 217 },
+ { 90, 216 },
+ { 92, 215 },
+ { 93, 214 },
+ { 94, 212 },
+ { 95, 211 },
+ { 97, 210 },
+ { 99, 209 },
+ { 101, 208 },
+ { 102, 207 },
+ { 104, 206 },
+ { 107, 205 },
+ { 111, 204 },
+ { 114, 203 },
+ { 118, 202 },
+ { 122, 201 },
+ { 125, 200 },
+ { 128, 199 },
+ { 130, 198 },
+ { 132, 197 },
+ { 256, 190 },
+};
+
+/* QAM256 SNR lookup table */
+static struct mse2snr_tab qam256_mse2snr_tab[] = {
+ { 16, 0 },
+ { 17, 400 },
+ { 18, 398 },
+ { 19, 396 },
+ { 20, 394 },
+ { 21, 392 },
+ { 22, 390 },
+ { 23, 388 },
+ { 24, 386 },
+ { 25, 384 },
+ { 26, 382 },
+ { 27, 380 },
+ { 28, 379 },
+ { 29, 378 },
+ { 30, 377 },
+ { 31, 376 },
+ { 32, 375 },
+ { 33, 374 },
+ { 34, 373 },
+ { 35, 372 },
+ { 36, 371 },
+ { 37, 370 },
+ { 38, 362 },
+ { 39, 354 },
+ { 40, 346 },
+ { 41, 338 },
+ { 42, 330 },
+ { 43, 328 },
+ { 44, 326 },
+ { 45, 324 },
+ { 46, 322 },
+ { 47, 320 },
+ { 48, 319 },
+ { 49, 318 },
+ { 50, 317 },
+ { 51, 316 },
+ { 52, 315 },
+ { 53, 314 },
+ { 54, 313 },
+ { 55, 312 },
+ { 56, 311 },
+ { 57, 310 },
+ { 58, 308 },
+ { 59, 306 },
+ { 60, 304 },
+ { 61, 302 },
+ { 62, 300 },
+ { 63, 298 },
+ { 65, 295 },
+ { 68, 294 },
+ { 70, 293 },
+ { 73, 292 },
+ { 76, 291 },
+ { 78, 290 },
+ { 79, 289 },
+ { 81, 288 },
+ { 82, 287 },
+ { 83, 286 },
+ { 84, 285 },
+ { 85, 284 },
+ { 86, 283 },
+ { 88, 282 },
+ { 89, 281 },
+ { 256, 280 },
+};
+
+static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
+ u16 *snr)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __func__);
+
+ for (i = 0; i < sz; i++) {
+ if (mse < tab[i].val) {
+ *snr = tab[i].data;
+ ret = 0;
+ break;
+ }
+ }
+ dprintk("%s() snr=%d\n", __func__, *snr);
+ return ret;
+}
+
+/* VSB Modulation table */
+static struct {
+ u16 reg;
+ u16 data;
+} VSB_mod_tab[] = {
+ { 0x8090, 0x84 },
+ { 0x4092, 0x11 },
+ { 0x2005, 0x00 },
+ { 0x8091, 0x80 },
+ { 0x80a3, 0x0c },
+ { 0x80a4, 0xe8 },
+ { 0x8081, 0xc4 },
+ { 0x80a5, 0x40 },
+ { 0x80a7, 0x40 },
+ { 0x80a6, 0x67 },
+ { 0x8262, 0x20 },
+ { 0x821c, 0x30 },
+ { 0x80d8, 0x1a },
+ { 0x8227, 0xa0 },
+ { 0x8121, 0xff },
+ { 0x80a8, 0xf0 },
+ { 0x80a9, 0x05 },
+ { 0x80aa, 0x77 },
+ { 0x80ab, 0xf0 },
+ { 0x80ac, 0x05 },
+ { 0x80ad, 0x77 },
+ { 0x80ae, 0x41 },
+ { 0x80af, 0x66 },
+ { 0x821b, 0xcc },
+ { 0x821d, 0x80 },
+ { 0x80b5, 0xfb },
+ { 0x80b6, 0x8e },
+ { 0x80b7, 0x39 },
+ { 0x80a4, 0xe8 },
+ { 0x8231, 0x13 },
+};
+
+/* QAM Modulation table */
+static struct {
+ u16 reg;
+ u16 data;
+} QAM_mod_tab[] = {
+ { 0x80a3, 0x09 },
+ { 0x80a4, 0x00 },
+ { 0x8081, 0xc4 },
+ { 0x80a5, 0x40 },
+ { 0x80b5, 0xfb },
+ { 0x80b6, 0x8e },
+ { 0x80b7, 0x39 },
+ { 0x80aa, 0x77 },
+ { 0x80ad, 0x77 },
+ { 0x80a6, 0x67 },
+ { 0x8262, 0x20 },
+ { 0x821c, 0x30 },
+ { 0x80b8, 0x3e },
+ { 0x80b9, 0xf0 },
+ { 0x80ba, 0x01 },
+ { 0x80bb, 0x18 },
+ { 0x80bc, 0x50 },
+ { 0x80bd, 0x00 },
+ { 0x80be, 0xea },
+ { 0x80bf, 0xef },
+ { 0x80c0, 0xfc },
+ { 0x80c1, 0xbd },
+ { 0x80c2, 0x1f },
+ { 0x80c3, 0xfc },
+ { 0x80c4, 0xdd },
+ { 0x80c5, 0xaf },
+ { 0x80c6, 0x00 },
+ { 0x80c7, 0x38 },
+ { 0x80c8, 0x30 },
+ { 0x80c9, 0x05 },
+ { 0x80ca, 0x4a },
+ { 0x80cb, 0xd0 },
+ { 0x80cc, 0x01 },
+ { 0x80cd, 0xd9 },
+ { 0x80ce, 0x6f },
+ { 0x80cf, 0xf9 },
+ { 0x80d0, 0x70 },
+ { 0x80d1, 0xdf },
+ { 0x80d2, 0xf7 },
+ { 0x80d3, 0xc2 },
+ { 0x80d4, 0xdf },
+ { 0x80d5, 0x02 },
+ { 0x80d6, 0x9a },
+ { 0x80d7, 0xd0 },
+ { 0x8250, 0x0d },
+ { 0x8251, 0xcd },
+ { 0x8252, 0xe0 },
+ { 0x8253, 0x05 },
+ { 0x8254, 0xa7 },
+ { 0x8255, 0xff },
+ { 0x8256, 0xed },
+ { 0x8257, 0x5b },
+ { 0x8258, 0xae },
+ { 0x8259, 0xe6 },
+ { 0x825a, 0x3d },
+ { 0x825b, 0x0f },
+ { 0x825c, 0x0d },
+ { 0x825d, 0xea },
+ { 0x825e, 0xf2 },
+ { 0x825f, 0x51 },
+ { 0x8260, 0xf5 },
+ { 0x8261, 0x06 },
+ { 0x821a, 0x00 },
+ { 0x8546, 0x40 },
+ { 0x8210, 0x26 },
+ { 0x8211, 0xf6 },
+ { 0x8212, 0x84 },
+ { 0x8213, 0x02 },
+ { 0x8502, 0x01 },
+ { 0x8121, 0x04 },
+ { 0x8122, 0x04 },
+ { 0x852e, 0x10 },
+ { 0x80a4, 0xca },
+ { 0x80a7, 0x40 },
+ { 0x8526, 0x01 },
+};
+
+static int au8522_enable_modulation(struct dvb_frontend *fe,
+ fe_modulation_t m)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ int i;
+
+ dprintk("%s(0x%08x)\n", __func__, m);
+
+ switch (m) {
+ case VSB_8:
+ dprintk("%s() VSB_8\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
+ au8522_writereg(state,
+ VSB_mod_tab[i].reg,
+ VSB_mod_tab[i].data);
+ break;
+ case QAM_64:
+ case QAM_256:
+ dprintk("%s() QAM 64/256\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+ au8522_writereg(state,
+ QAM_mod_tab[i].reg,
+ QAM_mod_tab[i].data);
+ break;
+ default:
+ dprintk("%s() Invalid modulation\n", __func__);
+ return -EINVAL;
+ }
+
+ state->current_modulation = m;
+
+ return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int au8522_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+ state->current_frequency = p->frequency;
+
+ au8522_enable_modulation(fe, p->u.vsb.modulation);
+
+ /* Allow the demod to settle */
+ msleep(100);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+ to a default state. */
+static int au8522_init(struct dvb_frontend *fe)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ dprintk("%s()\n", __func__);
+
+ au8522_writereg(state, 0xa4, 1 << 5);
+
+ au8522_i2c_gate_ctrl(fe, 1);
+
+ return 0;
+}
+
+static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ u8 reg;
+ u32 tuner_status = 0;
+
+ *status = 0;
+
+ if (state->current_modulation == VSB_8) {
+ dprintk("%s() Checking VSB_8\n", __func__);
+ reg = au8522_readreg(state, 0x4088);
+ if (reg & 0x01)
+ *status |= FE_HAS_VITERBI;
+ if (reg & 0x02)
+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+ } else {
+ dprintk("%s() Checking QAM\n", __func__);
+ reg = au8522_readreg(state, 0x4541);
+ if (reg & 0x80)
+ *status |= FE_HAS_VITERBI;
+ if (reg & 0x20)
+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+ }
+
+ switch (state->config->status_mode) {
+ case AU8522_DEMODLOCKING:
+ dprintk("%s() DEMODLOCKING\n", __func__);
+ if (*status & FE_HAS_VITERBI)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ break;
+ case AU8522_TUNERLOCKING:
+ /* Get the tuner status */
+ dprintk("%s() TUNERLOCKING\n", __func__);
+ if (fe->ops.tuner_ops.get_status) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (tuner_status)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ break;
+ }
+
+ dprintk("%s() status 0x%08x\n", __func__, *status);
+
+ return 0;
+}
+
+static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ int ret = -EINVAL;
+
+ dprintk("%s()\n", __func__);
+
+ if (state->current_modulation == QAM_256)
+ ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
+ ARRAY_SIZE(qam256_mse2snr_tab),
+ au8522_readreg(state, 0x4522),
+ snr);
+ else if (state->current_modulation == QAM_64)
+ ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
+ ARRAY_SIZE(qam64_mse2snr_tab),
+ au8522_readreg(state, 0x4522),
+ snr);
+ else /* VSB_8 */
+ ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
+ ARRAY_SIZE(vsb_mse2snr_tab),
+ au8522_readreg(state, 0x4311),
+ snr);
+
+ return ret;
+}
+
+static int au8522_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ return au8522_read_snr(fe, signal_strength);
+}
+
+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ if (state->current_modulation == VSB_8)
+ *ucblocks = au8522_readreg(state, 0x4087);
+ else
+ *ucblocks = au8522_readreg(state, 0x4543);
+
+ return 0;
+}
+
+static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ return au8522_read_ucblocks(fe, ber);
+}
+
+static int au8522_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ p->frequency = state->current_frequency;
+ p->u.vsb.modulation = state->current_modulation;
+
+ return 0;
+}
+
+static int au8522_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void au8522_release(struct dvb_frontend *fe)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops au8522_ops;
+
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct au8522_state *state = NULL;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+#if 0
+ /* check if the demod exists */
+ reg = au8522_readreg(state, 0x04);
+ if ((reg != 0x0066) && (reg != 0x007f))
+ goto error;
+#endif
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &au8522_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ if (au8522_init(&state->frontend) != 0) {
+ printk(KERN_ERR "%s: Failed to initialize correctly\n",
+ __func__);
+ goto error;
+ }
+
+ /* Note: Leaving the I2C gate open here. */
+ au8522_i2c_gate_ctrl(&state->frontend, 1);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(au8522_attach);
+
+static struct dvb_frontend_ops au8522_ops = {
+
+ .info = {
+ .name = "Auvitek AU8522 QAM/8VSB Frontend",
+ .type = FE_ATSC,
+ .frequency_min = 54000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 62500,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+
+ .init = au8522_init,
+ .i2c_gate_ctrl = au8522_i2c_gate_ctrl,
+ .set_frontend = au8522_set_frontend,
+ .get_frontend = au8522_get_frontend,
+ .get_tune_settings = au8522_get_tune_settings,
+ .read_status = au8522_read_status,
+ .read_ber = au8522_read_ber,
+ .read_signal_strength = au8522_read_signal_strength,
+ .read_snr = au8522_read_snr,
+ .read_ucblocks = au8522_read_ucblocks,
+ .release = au8522_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/au8522.h b/linux/drivers/media/dvb/frontends/au8522.h
new file mode 100644
index 000000000..d7affa3cd
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/au8522.h
@@ -0,0 +1,56 @@
+/*
+ Auvitek AU8522 QAM/8VSB demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __AU8522_H__
+#define __AU8522_H__
+
+#include <linux/dvb/frontend.h>
+
+struct au8522_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* Return lock status based on tuner lock, or demod lock */
+#define AU8522_TUNERLOCKING 0
+#define AU8522_DEMODLOCKING 1
+ u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_AU8522) || \
+ (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_AU8522 */
+
+#endif /* __AU8522_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/linux/drivers/media/dvb/frontends/bcm3510.c b/linux/drivers/media/dvb/frontends/bcm3510.c
index 0e2253dd6..ca9a55ae9 100644
--- a/linux/drivers/media/dvb/frontends/bcm3510.c
+++ b/linux/drivers/media/dvb/frontends/bcm3510.c
@@ -98,7 +98,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, reg, err);
+ __func__, state->config->demod_address, reg, err);
return -EREMOTEIO;
}
@@ -117,7 +117,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, reg, err);
+ __func__, state->config->demod_address, reg, err);
return -EREMOTEIO;
}
deb_i2c("i2c rd %02x: ",reg);
diff --git a/linux/drivers/media/dvb/frontends/bcm3510.h b/linux/drivers/media/dvb/frontends/bcm3510.h
index 7e4f95e17..f4575c0cc 100644
--- a/linux/drivers/media/dvb/frontends/bcm3510.h
+++ b/linux/drivers/media/dvb/frontends/bcm3510.h
@@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_BCM3510
diff --git a/linux/drivers/media/dvb/frontends/bsbe1.h b/linux/drivers/media/dvb/frontends/bsbe1.h
index d8f65738e..5e431ebd0 100644
--- a/linux/drivers/media/dvb/frontends/bsbe1.h
+++ b/linux/drivers/media/dvb/frontends/bsbe1.h
@@ -1,5 +1,5 @@
/*
- * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c)
+ * bsbe1.h - ALPS BSBE1 tuner support
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,44 +26,24 @@
#define BSBE1_H
static u8 alps_bsbe1_inittab[] = {
- 0x01, 0x15,
- 0x02, 0x30,
- 0x03, 0x00,
+ 0x01, 0x15, /* XTAL = 4MHz, VCO = 352 MHz */
+ 0x02, 0x30, /* MCLK = 88 MHz */
+ 0x03, 0x00, /* ACR output 0 */
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
- 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
- 0x06, 0x40, /* DAC not used, set to high impendance mode */
- 0x07, 0x00, /* DAC LSB */
+ 0x05, 0x05, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+ 0x06, 0x00, /* DAC output 0 */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
- 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
- 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
- 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
- 0x10, 0x3f, // AGC2 0x3d
- 0x11, 0x84,
- 0x12, 0xb9,
- 0x15, 0xc9, // lock detector threshold
- 0x16, 0x00,
- 0x17, 0x00,
- 0x18, 0x00,
- 0x19, 0x00,
- 0x1a, 0x00,
- 0x1f, 0x50,
- 0x20, 0x00,
- 0x21, 0x00,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
- 0x29, 0x1e, // 1/2 threshold
- 0x2a, 0x14, // 2/3 threshold
- 0x2b, 0x0f, // 3/4 threshold
- 0x2c, 0x09, // 5/6 threshold
- 0x2d, 0x05, // 7/8 threshold
- 0x2e, 0x01,
- 0x31, 0x1f, // test all FECs
- 0x32, 0x19, // viterbi and synchro search
- 0x33, 0xfc, // rs control
- 0x34, 0x93, // error control
- 0x0f, 0x92,
+ 0x0c, 0x51, /* OP1/OP0 normal, val = 1 (LNB power on) */
+ 0x0d, 0x82, /* DC offset compensation = on, beta_agc1 = 2 */
+ 0x0f, 0x92, /* AGC1R */
+ 0x10, 0x34, /* AGC2O */
+ 0x11, 0x84, /* TLSR */
+ 0x12, 0xb9, /* CFD */
+ 0x15, 0xc9, /* lock detector threshold */
+ 0x28, 0x00, /* out imp: normal, type: parallel, FEC mode: QPSK */
+ 0x33, 0xfc, /* RS control */
+ 0x34, 0x93, /* count viterbi bit errors per 2E18 bytes */
0xff, 0xff
};
@@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
- div = (params->frequency + (125 - 1)) / 125; // round correctly
+ div = params->frequency / 1000;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
- data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
- data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+ data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
+ data[3] = 0xe0;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
diff --git a/linux/drivers/media/dvb/frontends/bsru6.h b/linux/drivers/media/dvb/frontends/bsru6.h
index e231cd84b..45a6dfd8e 100644
--- a/linux/drivers/media/dvb/frontends/bsru6.h
+++ b/linux/drivers/media/dvb/frontends/bsru6.h
@@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = {
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c
index 11a4968f1..ace5cb171 100644
--- a/linux/drivers/media/dvb/frontends/cx22700.c
+++ b/linux/drivers/media/dvb/frontends/cx22700.c
@@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
u8 buf [] = { reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
ret = i2c_transfer (state->i2c, &msg, 1);
if (ret != 1)
printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- __FUNCTION__, reg, data, ret);
+ __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
@@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg)
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
ret = i2c_transfer (state->i2c, msg, 2);
@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
{
u8 val;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
switch (inversion) {
case INVERSION_AUTO:
@@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
u8 val;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
return -EINVAL;
@@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
FEC_5_6, FEC_7_8 };
u8 val;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (!(cx22700_readreg(state, 0x07) & 0x20)) /* tps valid? */
return -EAGAIN;
diff --git a/linux/drivers/media/dvb/frontends/cx22700.h b/linux/drivers/media/dvb/frontends/cx22700.h
index 7ac33690c..4757a930c 100644
--- a/linux/drivers/media/dvb/frontends/cx22700.h
+++ b/linux/drivers/media/dvb/frontends/cx22700.h
@@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_CX22700
diff --git a/linux/drivers/media/dvb/frontends/cx22702.c b/linux/drivers/media/dvb/frontends/cx22702.c
index 406c4cfa8..cc1db4e37 100644
--- a/linux/drivers/media/dvb/frontends/cx22702.c
+++ b/linux/drivers/media/dvb/frontends/cx22702.c
@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
if (ret != 1)
printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- __FUNCTION__, reg, data, ret);
+ __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
@@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ printk("%s: readreg error (ret == %i)\n", __func__, ret);
return b1[0];
}
@@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct cx22702_state* state = fe->demodulator_priv;
- dprintk ("%s(%d)\n", __FUNCTION__, enable);
+ dprintk ("%s(%d)\n", __func__, enable);
if (enable)
return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
else
@@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
break;
default:
- dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
+ dprintk ("%s: invalid bandwidth\n",__func__);
return -EINVAL;
}
@@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
- dprintk("%s: Autodetecting\n",__FUNCTION__);
+ dprintk("%s: Autodetecting\n",__func__);
return 0;
}
@@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
case QAM_16: val = (val&0xe7)|0x08; break;
case QAM_64: val = (val&0xe7)|0x10; break;
default:
- dprintk ("%s: invalid constellation\n",__FUNCTION__);
+ dprintk ("%s: invalid constellation\n",__func__);
return -EINVAL;
}
switch(p->u.ofdm.hierarchy_information) {
@@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
case HIERARCHY_2: val = (val&0xf8)|2; break;
case HIERARCHY_4: val = (val&0xf8)|3; break;
default:
- dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
+ dprintk ("%s: invalid hierarchy\n",__func__);
return -EINVAL;
}
cx22702_writereg (state, 0x06, val);
@@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
case FEC_5_6: val = (val&0xc7)|0x18; break;
case FEC_7_8: val = (val&0xc7)|0x20; break;
default:
- dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__);
+ dprintk ("%s: invalid code_rate_HP\n",__func__);
return -EINVAL;
}
switch(p->u.ofdm.code_rate_LP) {
@@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
case FEC_5_6: val = (val&0xf8)|3; break;
case FEC_7_8: val = (val&0xf8)|4; break;
default:
- dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
+ dprintk ("%s: invalid code_rate_LP\n",__func__);
return -EINVAL;
}
cx22702_writereg (state, 0x07, val);
@@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
case GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
case GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
default:
- dprintk ("%s: invalid guard_interval\n",__FUNCTION__);
+ dprintk ("%s: invalid guard_interval\n",__func__);
return -EINVAL;
}
switch(p->u.ofdm.transmission_mode) {
case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
default:
- dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
+ dprintk ("%s: invalid transmission_mode\n",__func__);
return -EINVAL;
}
cx22702_writereg(state, 0x08, val);
@@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
reg23 = cx22702_readreg (state, 0x23);
dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
- ,__FUNCTION__,reg0A,reg23);
+ ,__func__,reg0A,reg23);
if(reg0A & 0x10) {
*status |= FE_HAS_LOCK;
diff --git a/linux/drivers/media/dvb/frontends/cx22702.h b/linux/drivers/media/dvb/frontends/cx22702.h
index 9cd64da6e..8af766a31 100644
--- a/linux/drivers/media/dvb/frontends/cx22702.h
+++ b/linux/drivers/media/dvb/frontends/cx22702.h
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_CX22702
diff --git a/linux/drivers/media/dvb/frontends/cx24110.c b/linux/drivers/media/dvb/frontends/cx24110.c
index b03d8283c..87ae29db0 100644
--- a/linux/drivers/media/dvb/frontends/cx24110.c
+++ b/linux/drivers/media/dvb/frontends/cx24110.c
@@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
- " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ " data == 0x%02x)\n", __func__, err, reg, data);
return -EREMOTEIO;
}
@@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
int i;
- dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+ dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
if (srate>90999000UL/2)
srate=90999000UL/2;
if (srate<500000)
@@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
/* fixme (low): error handling */
int i;
- dprintk("%s: init chip\n", __FUNCTION__);
+ dprintk("%s: init chip\n", __func__);
for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
diff --git a/linux/drivers/media/dvb/frontends/cx24110.h b/linux/drivers/media/dvb/frontends/cx24110.h
index 0ca3af4db..1792adb23 100644
--- a/linux/drivers/media/dvb/frontends/cx24110.h
+++ b/linux/drivers/media/dvb/frontends/cx24110.h
@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_CX24110
diff --git a/linux/drivers/media/dvb/frontends/dib0070.h b/linux/drivers/media/dvb/frontends/dib0070.h
index 786e37d33..3eedfdf50 100644
--- a/linux/drivers/media/dvb/frontends/dib0070.h
+++ b/linux/drivers/media/dvb/frontends/dib0070.h
@@ -37,7 +37,20 @@ struct dib0070_config {
u8 flip_chip;
};
-extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
+#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg);
+#else
+static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
diff --git a/linux/drivers/media/dvb/frontends/dib3000.h b/linux/drivers/media/dvb/frontends/dib3000.h
index a6d3854a6..ba917359f 100644
--- a/linux/drivers/media/dvb/frontends/dib3000.h
+++ b/linux/drivers/media/dvb/frontends/dib3000.h
@@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config
static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_DIB3000MB
diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.h b/linux/drivers/media/dvb/frontends/dib3000mc.h
index 72d475760..4142ed7a4 100644
--- a/linux/drivers/media/dvb/frontends/dib3000mc.h
+++ b/linux/drivers/media/dvb/frontends/dib3000mc.h
@@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i
#else
static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_DIB3000MC
diff --git a/linux/drivers/media/dvb/frontends/dib7000p.c b/linux/drivers/media/dvb/frontends/dib7000p.c
index 9b6702b70..c74d373b6 100644
--- a/linux/drivers/media/dvb/frontends/dib7000p.c
+++ b/linux/drivers/media/dvb/frontends/dib7000p.c
@@ -1194,7 +1194,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
ret = dib7000p_tune(fe, fep);
/* make this a config parameter */
- dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+ dib7000p_set_output_mode(state, state->cfg.output_mode);
return ret;
}
@@ -1356,6 +1356,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
st->gpio_val = cfg->gpio_val;
st->gpio_dir = cfg->gpio_dir;
+ /* Ensure the output mode remains at the previous default if it's
+ * not specifically set by the caller.
+ */
+ if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
+ st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
demod = &st->demod;
demod->demodulator_priv = st;
memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
diff --git a/linux/drivers/media/dvb/frontends/dib7000p.h b/linux/drivers/media/dvb/frontends/dib7000p.h
index eefcac8b5..07c4d12ed 100644
--- a/linux/drivers/media/dvb/frontends/dib7000p.h
+++ b/linux/drivers/media/dvb/frontends/dib7000p.h
@@ -31,11 +31,26 @@ struct dib7000p_config {
u8 spur_protect;
int (*agc_control) (struct dvb_frontend *, u8 before);
+
+ u8 output_mode;
};
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg);
+#else
+static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
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);
diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c
new file mode 100644
index 000000000..327fff4b8
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/drx397xD.c
@@ -0,0 +1,1583 @@
+/*
+ * Driver for Micronas drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DEBUG /* uncomment if you want debugging output */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drx397xD.h"
+#include "compat.h"
+
+static const char mod_name[] = "drx397xD";
+
+#define MAX_CLOCK_DRIFT 200 /* maximal 200 PPM allowed */
+
+#define F_SET_0D0h 1
+#define F_SET_0D4h 2
+
+typedef enum fw_ix {
+#define _FW_ENTRY(a, b) b
+#include "drx397xD_fw.h"
+} fw_ix_t;
+
+/* chip specifics */
+struct drx397xD_state {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend frontend;
+ struct drx397xD_config config;
+ fw_ix_t chip_rev;
+ int flags;
+ u32 bandwidth_parm; /* internal bandwidth conversions */
+ u32 f_osc; /* w90: actual osc frequency [Hz] */
+};
+
+/*******************************************************************************
+ * Firmware
+ ******************************************************************************/
+
+static const char *blob_name[] = {
+#define _BLOB_ENTRY(a, b) a
+#include "drx397xD_fw.h"
+};
+
+typedef enum blob_ix {
+#define _BLOB_ENTRY(a, b) b
+#include "drx397xD_fw.h"
+} blob_ix_t;
+
+static struct {
+ const char *name;
+ const struct firmware *file;
+ rwlock_t lock;
+ int refcnt;
+ u8 *data[ARRAY_SIZE(blob_name)];
+} fw[] = {
+#define _FW_ENTRY(a, b) { \
+ .name = a, \
+ .file = 0, \
+ .lock = RW_LOCK_UNLOCKED, \
+ .refcnt = 0, \
+ .data = { } }
+#include "drx397xD_fw.h"
+};
+
+/* use only with writer lock aquired */
+static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+ memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+ if (fw[ix].file)
+ release_firmware(fw[ix].file);
+}
+
+static void drx_release_fw(struct drx397xD_state *s)
+{
+ fw_ix_t ix = s->chip_rev;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ write_lock(&fw[ix].lock);
+ if (fw[ix].refcnt) {
+ fw[ix].refcnt--;
+ if (fw[ix].refcnt == 0)
+ _drx_release_fw(s, ix);
+ }
+ write_unlock(&fw[ix].lock);
+}
+
+static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+ u8 *data;
+ size_t size, len;
+ int i = 0, j, rc = -EINVAL;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (ix < 0 || ix >= ARRAY_SIZE(fw))
+ return -EINVAL;
+ s->chip_rev = ix;
+
+ write_lock(&fw[ix].lock);
+ if (fw[ix].file) {
+ rc = 0;
+ goto exit_ok;
+ }
+ memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+
+ if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
+ printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
+ mod_name, fw[ix].name);
+ rc = -ENOENT;
+ goto exit_err;
+ }
+
+ if (!fw[ix].file->data || fw[ix].file->size < 10)
+ goto exit_corrupt;
+
+ data = fw[ix].file->data;
+ size = fw[ix].file->size;
+
+ if (data[i++] != 2) /* check firmware version */
+ goto exit_corrupt;
+
+ do {
+ switch (data[i++]) {
+ case 0x00: /* bytecode */
+ if (i >= size)
+ break;
+ i += data[i];
+ case 0x01: /* reset */
+ case 0x02: /* sleep */
+ i++;
+ break;
+ case 0xfe: /* name */
+ len = strnlen(&data[i], size - i);
+ if (i + len + 1 >= size)
+ goto exit_corrupt;
+ if (data[i + len + 1] != 0)
+ goto exit_corrupt;
+ for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
+ if (strcmp(blob_name[j], &data[i]) == 0) {
+ fw[ix].data[j] = &data[i + len + 1];
+ pr_debug("Loading %s\n", blob_name[j]);
+ }
+ }
+ i += len + 1;
+ break;
+ case 0xff: /* file terminator */
+ if (i == size) {
+ rc = 0;
+ goto exit_ok;
+ }
+ default:
+ goto exit_corrupt;
+ }
+ } while (i < size);
+ exit_corrupt:
+ printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
+ exit_err:
+ _drx_release_fw(s, ix);
+ fw[ix].refcnt--;
+ exit_ok:
+ fw[ix].refcnt++;
+ write_unlock(&fw[ix].lock);
+ return rc;
+}
+
+/*******************************************************************************
+ * i2c bus IO
+ ******************************************************************************/
+
+static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+{
+ struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
+ u8 *data;
+ int len, rc = 0, i = 0;
+
+ if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
+ pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+
+ read_lock(&fw[s->chip_rev].lock);
+ data = fw[s->chip_rev].data[ix];
+ if (!data) {
+ rc = -EINVAL;
+ goto exit_rc;
+ }
+
+ for (;;) {
+ switch (data[i++]) {
+ case 0: /* bytecode */
+ len = data[i++];
+ msg.len = len;
+ msg.buf = &data[i];
+ if (i2c_transfer(s->i2c, &msg, 1) != 1) {
+ rc = -EIO;
+ goto exit_rc;
+ }
+ i += len;
+ break;
+ case 1: /* reset */
+ case 2: /* sleep */
+ i++;
+ break;
+ default:
+ goto exit_rc;
+ }
+ }
+ exit_rc:
+ read_unlock(&fw[s->chip_rev].lock);
+ return 0;
+}
+
+/* Function is not endian safe, use the RD16 wrapper below */
+static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+{
+ int rc;
+ u8 a[4];
+ u16 v;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = s->config.demod_address,
+ .flags = 0,
+ .buf = a,
+ .len = sizeof(a)
+ }
+ , {
+ .addr = s->config.demod_address,
+ .flags = I2C_M_RD,
+ .buf = (u8 *) & v,
+ .len = sizeof(v)
+ }
+ };
+
+ *(u32 *) a = i2c_adr;
+
+ rc = i2c_transfer(s->i2c, msg, 2);
+ if (rc != 2)
+ return -EIO;
+
+ return le16_to_cpu(v);
+}
+
+/* Function is not endian safe, use the WR16.. wrappers below */
+static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+{
+ u8 a[6];
+ int rc;
+ struct i2c_msg msg = {
+ .addr = s->config.demod_address,
+ .flags = 0,
+ .buf = a,
+ .len = sizeof(a)
+ };
+
+ *(u32 *) a = i2c_adr;
+ *(u16 *) & a[4] = val;
+
+ rc = i2c_transfer(s->i2c, &msg, 1);
+ if (rc != 1)
+ return -EIO;
+ return 0;
+}
+
+#define WR16(ss,adr, val) \
+ _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
+#define WR16_E0(ss,adr, val) \
+ _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
+#define RD16(ss,adr) \
+ _read16(ss, I2C_ADR_C0(adr))
+
+#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
+
+/*******************************************************************************
+ * Tuner callback
+ ******************************************************************************/
+
+static int PLL_Set(struct drx397xD_state *s,
+ struct dvb_frontend_parameters *fep, int *df_tuner)
+{
+ struct dvb_frontend *fe = &s->frontend;
+ u32 f_tuner, f = fep->frequency;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
+ (f < s->frontend.ops.tuner_ops.info.frequency_min))
+ return -EINVAL;
+
+ *df_tuner = 0;
+ if (!s->frontend.ops.tuner_ops.set_params ||
+ !s->frontend.ops.tuner_ops.get_frequency)
+ return -ENOSYS;
+
+ rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
+ if (rc < 0)
+ return rc;
+
+ rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
+ if (rc < 0)
+ return rc;
+
+ *df_tuner = f_tuner - f;
+ pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+ f_tuner);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Demodulator helper functions
+ ******************************************************************************/
+
+static int SC_WaitForReady(struct drx397xD_state *s)
+{
+ int cnt = 1000;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ while (cnt--) {
+ rc = RD16(s, 0x820043);
+ if (rc == 0)
+ return 0;
+ }
+ return -1;
+}
+
+static int SC_SendCommand(struct drx397xD_state *s, int cmd)
+{
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ WR16(s, 0x820043, cmd);
+ SC_WaitForReady(s);
+ rc = RD16(s, 0x820042);
+ if ((rc & 0xffff) == 0xffff)
+ return -1;
+ return 0;
+}
+
+static int HI_Command(struct drx397xD_state *s, u16 cmd)
+{
+ int rc, cnt = 1000;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ rc = WR16(s, 0x420032, cmd);
+ if (rc < 0)
+ return rc;
+
+ do {
+ rc = RD16(s, 0x420032);
+ if (rc == 0) {
+ rc = RD16(s, 0x420031);
+ return rc;
+ }
+ if (rc < 0)
+ return rc;
+ } while (--cnt);
+ return rc;
+}
+
+static int HI_CfgCommand(struct drx397xD_state *s)
+{
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ WR16(s, 0x420033, 0x3973);
+ WR16(s, 0x420034, s->config.w50); // code 4, log 4
+ WR16(s, 0x420035, s->config.w52); // code 15, log 9
+ WR16(s, 0x420036, s->config.demod_address << 1);
+ WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1
+// WR16(s, 0x420033, 0x3973);
+ if ((s->config.w56 & 8) == 0)
+ return HI_Command(s, 3);
+ return WR16(s, 0x420032, 0x3);
+}
+
+static const u8 fastIncrDecLUT_15273[] = {
+ 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
+};
+
+static const u8 slowIncrDecLUT_15272[] = {
+ 3, 4, 4, 5, 6
+};
+
+static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
+{
+ u16 w06 = agc->w06;
+ u16 w08 = agc->w08;
+ u16 w0A = agc->w0A;
+ u16 w0C = agc->w0C;
+ int quot, rem, i, rc = -EINVAL;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (agc->w04 > 0x3ff)
+ goto exit_rc;
+
+ if (agc->d00 == 1) {
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= ~0x10;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
+ }
+
+ if (agc->d00 != 0)
+ goto exit_rc;
+ if (w0A < w08)
+ goto exit_rc;
+ if (w0A > 0x3ff)
+ goto exit_rc;
+ if (w0C > 0x3ff)
+ goto exit_rc;
+ if (w06 > 0x3ff)
+ goto exit_rc;
+
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc |= 0x10;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+
+ EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
+ EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
+ EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
+
+ quot = w0C / 113;
+ rem = w0C % 113;
+ if (quot <= 8) {
+ quot = 8 - quot;
+ } else {
+ quot = 0;
+ rem += 113;
+ }
+
+ EXIT_RC(WR16(s, 0x0c20024, quot));
+
+ i = fastIncrDecLUT_15273[rem / 8];
+ EXIT_RC(WR16(s, 0x0c2002d, i));
+ EXIT_RC(WR16(s, 0x0c2002e, i));
+
+ i = slowIncrDecLUT_15272[rem / 28];
+ EXIT_RC(WR16(s, 0x0c2002b, i));
+ rc = WR16(s, 0x0c2002c, i);
+ exit_rc:
+ return rc;
+}
+
+static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
+{
+ u16 w04 = agc->w04;
+ u16 w06 = agc->w06;
+ int rc = -1;
+
+ pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+
+ if (w04 > 0x3ff)
+ goto exit_rc;
+
+ switch (agc->d00) {
+ case 1:
+ if (w04 == 0x3ff)
+ w04 = 0x400;
+
+ EXIT_RC(WR16(s, 0x0c20036, w04));
+ s->config.w9C &= ~2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc &= ~2;
+ break;
+ case 0:
+ // loc_8000659
+ s->config.w9C &= ~2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ rc |= 0x4000;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc &= ~2;
+ break;
+ default:
+ s->config.w9C |= 2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+
+ EXIT_RC(WR16(s, 0x0c20036, 0));
+
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc |= 2;
+ }
+ rc = WR16(s, 0x0c20013, rc);
+ exit_rc:
+ return rc;
+}
+
+static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
+{
+ int rc;
+
+ *lockstat = 0;
+
+ rc = RD16(s, 0x082004b);
+ if (rc < 0)
+ return rc;
+
+ if (s->config.d60 != 2)
+ return 0;
+
+ if ((rc & 7) == 7)
+ *lockstat |= 1;
+ if ((rc & 3) == 3)
+ *lockstat |= 2;
+ if (rc & 1)
+ *lockstat |= 4;
+ return 0;
+}
+
+static int CorrectSysClockDeviation(struct drx397xD_state *s)
+{
+ int rc = -EINVAL;
+ int lockstat;
+ u32 clk, clk_limit;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (s->config.d5C == 0) {
+ EXIT_RC(WR16(s, 0x08200e8, 0x010));
+ EXIT_RC(WR16(s, 0x08200e9, 0x113));
+ s->config.d5C = 1;
+ return rc;
+ }
+ if (s->config.d5C != 1)
+ goto exit_rc;
+
+ rc = RD16(s, 0x0820048);
+
+ rc = GetLockStatus(s, &lockstat);
+ if (rc < 0)
+ goto exit_rc;
+ if ((lockstat & 1) == 0)
+ goto exit_rc;
+
+ EXIT_RC(WR16(s, 0x0420033, 0x200));
+ EXIT_RC(WR16(s, 0x0420034, 0xc5));
+ EXIT_RC(WR16(s, 0x0420035, 0x10));
+ EXIT_RC(WR16(s, 0x0420036, 0x1));
+ EXIT_RC(WR16(s, 0x0420037, 0xa));
+ EXIT_RC(HI_Command(s, 6));
+ EXIT_RC(RD16(s, 0x0420040));
+ clk = rc;
+ EXIT_RC(RD16(s, 0x0420041));
+ clk |= rc << 16;
+
+ if (clk <= 0x26ffff)
+ goto exit_rc;
+ if (clk > 0x610000)
+ goto exit_rc;
+
+ if (!s->bandwidth_parm)
+ return -EINVAL;
+
+ /* round & convert to Hz */
+ clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
+ clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
+
+ if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
+ s->f_osc = clk;
+ pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+ s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
+ }
+ rc = WR16(s, 0x08200e8, 0);
+ exit_rc:
+ return rc;
+}
+
+static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
+{
+ int rc, si, bp;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ si = s->config.wA0;
+ if (s->config.w98 == 0) {
+ si |= 1;
+ bp = 0;
+ } else {
+ si &= ~1;
+ bp = 0x200;
+ }
+ if (s->config.w9A == 0) {
+ si |= 0x80;
+ } else {
+ si &= ~0x80;
+ }
+
+ EXIT_RC(WR16(s, 0x2150045, 0));
+ EXIT_RC(WR16(s, 0x2150010, si));
+ EXIT_RC(WR16(s, 0x2150011, bp));
+ rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
+ exit_rc:
+ return rc;
+}
+
+static int drx_tune(struct drx397xD_state *s,
+ struct dvb_frontend_parameters *fep)
+{
+ u16 v22 = 0;
+ u16 v1C = 0;
+ u16 v1A = 0;
+ u16 v18 = 0;
+ u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
+ u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
+
+ int rc, df_tuner;
+ int a, b, c, d;
+ pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+
+ if (s->config.d60 != 2)
+ goto set_tuner;
+ rc = CorrectSysClockDeviation(s);
+ if (rc < 0)
+ goto set_tuner;
+
+ s->config.d60 = 1;
+ rc = ConfigureMPEGOutput(s, 0);
+ if (rc < 0)
+ goto set_tuner;
+#if 0
+
+ if (s->chip_rev != DRXD_FW_B1) {
+ rc = WR16(s, 0x2150000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x2110000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x0800000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x2800000, 0);
+ } else {
+ rc = WR16(s, 0x0800000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x2800000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x1000000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x1400000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x1800000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x1c00000, 0);
+ if (rc < 0)
+ goto loc_800111A;
+ rc = WR16(s, 0x2000000, 0);
+ }
+ loc_800111A:
+#endif
+ set_tuner:
+
+ rc = PLL_Set(s, fep, &df_tuner);
+ if (rc < 0) {
+ printk(KERN_ERR "Error in pll_set\n");
+ goto exit_rc;
+ }
+ msleep(200);
+
+ a = rc = RD16(s, 0x2150016);
+ if (rc < 0)
+ goto exit_rc;
+ b = rc = RD16(s, 0x2150010);
+ if (rc < 0)
+ goto exit_rc;
+ c = rc = RD16(s, 0x2150034);
+ if (rc < 0)
+ goto exit_rc;
+ d = rc = RD16(s, 0x2150035);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2150014, c);
+ rc = WR16(s, 0x2150015, d);
+ rc = WR16(s, 0x2150010, 0);
+ rc = WR16(s, 0x2150000, 2);
+ rc = WR16(s, 0x2150036, 0x0fff);
+ rc = WR16(s, 0x2150016, a);
+
+ rc = WR16(s, 0x2150010, 2);
+ rc = WR16(s, 0x2150007, 0);
+ rc = WR16(s, 0x2150000, 1);
+ rc = WR16(s, 0x2110000, 0);
+ rc = WR16(s, 0x0800000, 0);
+ rc = WR16(s, 0x2800000, 0);
+ rc = WR16(s, 0x2110010, 0x664);
+
+ rc = write_fw(s, DRXD_ResetECRAM);
+ rc = WR16(s, 0x2110000, 1);
+
+ rc = write_fw(s, DRXD_InitSC);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = SetCfgIfAgc(s, &s->config.ifagc);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = SetCfgRfAgc(s, &s->config.rfagc);
+ if (rc < 0)
+ goto exit_rc;
+
+ if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
+ v22 = 1;
+ switch (fep->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_8K:
+ edi = 1;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x2010010, 0);
+ if (rc < 0)
+ break;
+ v1C = 0x63;
+ v1A = 0x53;
+ v18 = 0x43;
+ break;
+ default:
+ edi = 0;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x2010010, 1);
+ if (rc < 0)
+ break;
+
+ v1C = 0x61;
+ v1A = 0x47;
+ v18 = 0x41;
+ }
+
+ switch (fep->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_4:
+ edi |= 0x0c;
+ break;
+ case GUARD_INTERVAL_1_8:
+ edi |= 0x08;
+ break;
+ case GUARD_INTERVAL_1_16:
+ edi |= 0x04;
+ break;
+ case GUARD_INTERVAL_1_32:
+ break;
+ default:
+ v22 |= 2;
+ }
+
+ ebx = 0;
+ ebp = 0;
+ v20 = 0;
+ v1E = 0;
+ v16 = 0;
+ v14 = 0;
+ v12 = 0;
+ v10 = 0;
+ v0E = 0;
+
+ switch (fep->u.ofdm.hierarchy_information) {
+ case HIERARCHY_1:
+ edi |= 0x40;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 1);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x19f;
+ ebp = 0x1fb;
+ v20 = 0x0c0;
+ v1E = 0x195;
+ v16 = 0x1d6;
+ v14 = 0x1ef;
+ v12 = 4;
+ v10 = 5;
+ v0E = 5;
+ break;
+ case HIERARCHY_2:
+ edi |= 0x80;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 2);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x08f;
+ ebp = 0x12f;
+ v20 = 0x0c0;
+ v1E = 0x11e;
+ v16 = 0x1d6;
+ v14 = 0x15e;
+ v12 = 4;
+ v10 = 5;
+ v0E = 5;
+ break;
+ case HIERARCHY_4:
+ edi |= 0xc0;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 3);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 3);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x14d;
+ ebp = 0x197;
+ v20 = 0x0c0;
+ v1E = 0x1ce;
+ v16 = 0x1d6;
+ v14 = 0x11a;
+ v12 = 4;
+ v10 = 6;
+ v0E = 5;
+ break;
+ default:
+ v22 |= 8;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 0);
+ if (rc < 0)
+ goto exit_rc;
+ // QPSK QAM16 QAM64
+ ebx = 0x19f; // 62
+ ebp = 0x1fb; // 15
+ v20 = 0x16a; // 62
+ v1E = 0x195; // 62
+ v16 = 0x1bb; // 15
+ v14 = 0x1ef; // 15
+ v12 = 5; // 16
+ v10 = 5; // 16
+ v0E = 5; // 16
+ }
+
+ switch (fep->u.ofdm.constellation) {
+ default:
+ v22 |= 4;
+ case QPSK:
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x1c10046, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x10);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, v20);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v1C);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, v16);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v12);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ case QAM_16:
+ edi |= 0x10;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x1c10046, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x10);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 4);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, v1E);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v1A);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, v14);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v10);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ case QAM_64:
+ edi |= 0x20;
+ rc = WR16(s, 0x1c10046, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x20);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 8);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, ebx);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v18);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, ebp);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v0E);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ }
+
+ if (s->config.s20d24 == 1) {
+ rc = WR16(s, 0x2010013, 0);
+ } else {
+ rc = WR16(s, 0x2010013, 1);
+ edi |= 0x1000;
+ }
+
+ switch (fep->u.ofdm.code_rate_HP) {
+ default:
+ v22 |= 0x10;
+ case FEC_1_2:
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 0);
+ break;
+ case FEC_2_3:
+ edi |= 0x200;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 1);
+ break;
+ case FEC_3_4:
+ edi |= 0x400;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 2);
+ break;
+ case FEC_5_6: /* 5 */
+ edi |= 0x600;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 3);
+ break;
+ case FEC_7_8: /* 7 */
+ edi |= 0x800;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 4);
+ break;
+ };
+ if (rc < 0)
+ goto exit_rc;
+
+ switch (fep->u.ofdm.bandwidth) {
+ default:
+ rc = -EINVAL;
+ goto exit_rc;
+ case BANDWIDTH_8_MHZ: /* 0 */
+ case BANDWIDTH_AUTO:
+ rc = WR16(s, 0x0c2003f, 0x32);
+ s->bandwidth_parm = ebx = 0x8b8249; // 9142857
+ edx = 0;
+ break;
+ case BANDWIDTH_7_MHZ:
+ rc = WR16(s, 0x0c2003f, 0x3b);
+ s->bandwidth_parm = ebx = 0x7a1200; // 8000000
+ edx = 0x4807;
+ break;
+ case BANDWIDTH_6_MHZ:
+ rc = WR16(s, 0x0c2003f, 0x47);
+ s->bandwidth_parm = ebx = 0x68a1b6; // 6857142
+ edx = 0x0f07;
+ break;
+ };
+
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = WR16(s, 0x08200ec, edx);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = RD16(s, 0x0820050);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x0820050, rc);
+
+ {
+ /* Configure bandwidth specific factor */
+ ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
+ (u64)ebx) - 0x800000;
+ EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
+ EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
+
+ /* drx397xD oscillator calibration */
+ ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
+ (s->f_osc >> 1), (u64)s->f_osc);
+ }
+ ebx &= 0xfffffff;
+ if (fep->inversion == INVERSION_ON)
+ ebx = 0x10000000 - ebx;
+
+ EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
+ EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
+
+ EXIT_RC(WR16(s, 0x0800000, 1));
+ EXIT_RC(RD16(s, 0x0800000));
+
+#if 0
+ rc = WR16(s, 0x0810000, 1);
+ if (rc < 0)
+ goto exit_rc;
+#endif
+
+ EXIT_RC(SC_WaitForReady(s));
+ EXIT_RC(WR16(s, 0x0820042, 0));
+ EXIT_RC(WR16(s, 0x0820041, v22));
+ EXIT_RC(WR16(s, 0x0820040, edi));
+ EXIT_RC(SC_SendCommand(s, 3));
+
+ rc = RD16(s, 0x0800000);
+
+ SC_WaitForReady(s);
+ WR16(s, 0x0820042, 0);
+ WR16(s, 0x0820041, 1);
+ WR16(s, 0x0820040, 1);
+ SC_SendCommand(s, 1);
+
+// rc = WR16(s, 0x2150000, 1);
+// if (rc < 0) goto exit_rc;
+
+ rc = WR16(s, 0x2150000, 2);
+ rc = WR16(s, 0x2150016, a);
+ rc = WR16(s, 0x2150010, 4);
+ rc = WR16(s, 0x2150036, 0);
+ rc = WR16(s, 0x2150000, 1);
+ s->config.d60 = 2;
+ exit_rc:
+ return rc;
+}
+
+/*******************************************************************************
+ * DVB interface
+ ******************************************************************************/
+
+static int drx397x_init(struct dvb_frontend *fe)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ s->config.rfagc.d00 = 2; /* 0x7c */
+ s->config.rfagc.w04 = 0;
+ s->config.rfagc.w06 = 0x3ff;
+
+ s->config.ifagc.d00 = 0; /* 0x68 */
+ s->config.ifagc.w04 = 0;
+ s->config.ifagc.w06 = 140;
+ s->config.ifagc.w08 = 0;
+ s->config.ifagc.w0A = 0x3ff;
+ s->config.ifagc.w0C = 0x388;
+
+ /* for signal strenght calculations */
+ s->config.ss76 = 820;
+ s->config.ss78 = 2200;
+ s->config.ss7A = 150;
+
+ /* HI_CfgCommand */
+ s->config.w50 = 4;
+ s->config.w52 = 9; // 0xf;
+
+ s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */
+ s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */
+ s->config.w92 = 12000; // 20000;
+
+ s->config.w9C = 0x000e;
+ s->config.w9E = 0x0000;
+
+ /* ConfigureMPEGOutput params */
+ s->config.wA0 = 4;
+ s->config.w98 = 1; // 0;
+ s->config.w9A = 1;
+
+ /* get chip revision */
+ rc = RD16(s, 0x2410019);
+ if (rc < 0)
+ return -ENODEV;
+
+ if (rc == 0) {
+ printk(KERN_INFO "%s: chip revision A2\n", mod_name);
+ rc = drx_load_fw(s, DRXD_FW_A2);
+ } else {
+
+ rc = (rc >> 12) - 3;
+ switch (rc) {
+ case 1:
+ s->flags |= F_SET_0D4h;
+ case 0:
+ case 4:
+ s->flags |= F_SET_0D0h;
+ break;
+ case 2:
+ case 5:
+ break;
+ case 3:
+ s->flags |= F_SET_0D4h;
+ break;
+ default:
+ return -ENODEV;
+ };
+ printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
+ rc = drx_load_fw(s, DRXD_FW_B1);
+ }
+ if (rc < 0)
+ goto error;
+
+ rc = WR16(s, 0x0420033, 0x3973);
+ if (rc < 0)
+ goto error;
+
+ rc = HI_Command(s, 2);
+
+ msleep(1);
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = WR16(s, 0x043012d, 0x47F);
+ if (rc < 0)
+ goto error;
+ }
+ rc = WR16_E0(s, 0x0400000, 0);
+ if (rc < 0)
+ goto error;
+
+ if (s->config.w92 > 20000 || s->config.w92 % 4000) {
+ printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
+ rc = -1;
+ goto error;
+ }
+
+ rc = WR16(s, 0x2410010, 1);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x2410011, 0x15);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x2410012, s->config.w92 / 4000);
+ if (rc < 0)
+ goto error;
+#ifdef ORIG_FW
+ rc = WR16(s, 0x2410015, 2);
+ if (rc < 0)
+ goto error;
+#endif
+ rc = WR16(s, 0x2410017, 0x3973);
+ if (rc < 0)
+ goto error;
+
+ s->f_osc = s->config.f_osc * 1000; /* initial estimator */
+#if 0
+ {
+ int deviation, val, edi;
+
+ /* osc_deviation(struct state *x, int deviation, int io)
+ *
+ * io == 0 : read_deviation from eeprom
+ * io != 0 : write deviation to eeprom
+ */
+ s->config.w64 = x->osc_deviation(x, 0, 0);
+ val = s->config.w64 * s->config.w66;
+ deviation = val / 1000000;
+
+ edi = 2;
+ if (val <= 0)
+ edi = -2;
+ val = val % 1000000;
+ if (edi * val > 1000000)
+ deviation += edi >> 1;
+ s->clk_if_corrected += deviation;
+ }
+#endif
+
+ s->config.w56 = 1;
+
+ rc = HI_CfgCommand(s);
+ if (rc < 0)
+ goto error;
+
+ rc = write_fw(s, DRXD_InitAtomicRead);
+ if (rc < 0)
+ goto error;
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = WR16(s, 0x2150013, 0);
+ if (rc < 0)
+ goto error;
+ }
+
+ rc = WR16_E0(s, 0x0400002, 0);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x0400002, 0);
+ if (rc < 0)
+ goto error;
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = write_fw(s, DRXD_ResetCEFR);
+ if (rc < 0)
+ goto error;
+ }
+ rc = write_fw(s, DRXD_microcode);
+ if (rc < 0)
+ goto error;
+
+ s->config.w9C = 0x0e;
+ if (s->flags & F_SET_0D0h) {
+ s->config.w9C = 0;
+ rc = RD16(s, 0x0c20010);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc &= ~0x1000;
+ rc = WR16(s, 0x0c20010, rc);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc = RD16(s, 0x0c20011);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc &= ~0x8;
+ rc = WR16(s, 0x0c20011, rc);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc = WR16(s, 0x0c20012, 1);
+ }
+
+ write_DRXD_InitFE_1:
+
+ rc = write_fw(s, DRXD_InitFE_1);
+ if (rc < 0)
+ goto error;
+
+ rc = 1;
+ if (s->chip_rev == DRXD_FW_B1) {
+ if (s->flags & F_SET_0D0h)
+ rc = 0;
+ } else {
+ if (s->flags & F_SET_0D0h)
+ rc = 4;
+ }
+
+ rc = WR16(s, 0x0C20012, rc);
+ if (rc < 0)
+ goto error;
+
+ rc = WR16(s, 0x0C20013, s->config.w9E);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x0C20015, s->config.w9C);
+ if (rc < 0)
+ goto error;
+
+ rc = write_fw(s, DRXD_InitFE_2);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitFT);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitCP);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitCE);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitEQ);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitEC);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitSC);
+ if (rc < 0)
+ goto error;
+
+ rc = SetCfgIfAgc(s, &s->config.ifagc);
+ if (rc < 0)
+ goto error;
+
+ rc = SetCfgRfAgc(s, &s->config.rfagc);
+ if (rc < 0)
+ goto error;
+
+#if 1
+ rc = ConfigureMPEGOutput(s, 1);
+ rc = WR16(s, 0x08201fe, 0x0017);
+ rc = WR16(s, 0x08201ff, 0x0101);
+
+ s->config.d5C = 0;
+#else
+ s->config.d5C = 0;
+ rc = CorrectSysClockDeviation(s);
+ if (rc < 0)
+ goto error;
+
+// rc = ConfigureWR16(s, 0x0420033, 0x200);
+
+ rc = WR16(s, 0x0800000, 0);
+ if (rc < 0)
+ goto error;
+
+ rc = WR16(s, 0x2800000, 0);
+#endif
+ s->config.d60 = 1;
+ s->config.d48 = 1;
+ error:
+ return rc;
+}
+
+static int drx397x_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ return 0;
+}
+
+static int drx397x_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+
+ s->config.s20d24 = 1; // 0;
+ return drx_tune(s, params);
+}
+
+static int drx397x_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings
+ *fe_tune_settings)
+{
+ fe_tune_settings->min_delay_ms = 10000;
+ fe_tune_settings->step_size = 0;
+ fe_tune_settings->max_drift = 0;
+ return 0;
+}
+
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int lockstat;
+
+ GetLockStatus(s, &lockstat);
+ /* TODO */
+// if (lockstat & 1)
+// CorrectSysClockDeviation(s);
+
+ *status = 0;
+ if (lockstat & 2) {
+ CorrectSysClockDeviation(s);
+ ConfigureMPEGOutput(s, 1);
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
+ }
+ if (lockstat & 4) {
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ }
+
+ return 0;
+}
+
+static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
+{
+ *ber = 0;
+ return 0;
+}
+
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+ *snr = 0;
+ return 0;
+}
+
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int rc;
+
+ if (s->config.ifagc.d00 == 2) {
+ *strength = 0xffff;
+ return 0;
+ }
+ rc = RD16(s, 0x0c20035);
+ if (rc < 0) {
+ *strength = 0;
+ return 0;
+ }
+ rc &= 0x3ff;
+ /* Signal strength is calculated using the following formula:
+ *
+ * a = 2200 * 150 / (2200 + 150);
+ * a = a * 3300 / (a + 820);
+ * b = 2200 * 3300 / (2200 + 820);
+ * c = (((b-a) * rc) >> 10 + a) << 4;
+ * strength = ~c & 0xffff;
+ *
+ * The following does the same but with less rounding errors:
+ */
+ *strength = ~(7720 + (rc * 30744 >> 10));
+ return 0;
+}
+
+static int drx397x_read_ucblocks(struct dvb_frontend *fe,
+ unsigned int *ucblocks)
+{
+ *ucblocks = 0;
+ return 0;
+}
+
+static int drx397x_sleep(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+static void drx397x_release(struct dvb_frontend *fe)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ printk(KERN_INFO "%s: release demodulator\n", mod_name);
+ if (s) {
+ drx_release_fw(s);
+ kfree(s);
+ }
+
+}
+
+static struct dvb_frontend_ops drx397x_ops = {
+
+ .info = {
+ .name = "Micronas DRX397xD DVB-T Frontend",
+ .type = FE_OFDM,
+ .frequency_min = 47125000,
+ .frequency_max = 855250000,
+ .frequency_stepsize = 166667,
+ .frequency_tolerance = 0,
+ .caps = /* 0x0C01B2EAE */
+ FE_CAN_FEC_1_2 | // = 0x2,
+ FE_CAN_FEC_2_3 | // = 0x4,
+ FE_CAN_FEC_3_4 | // = 0x8,
+ FE_CAN_FEC_5_6 | // = 0x20,
+ FE_CAN_FEC_7_8 | // = 0x80,
+ FE_CAN_FEC_AUTO | // = 0x200,
+ FE_CAN_QPSK | // = 0x400,
+ FE_CAN_QAM_16 | // = 0x800,
+ FE_CAN_QAM_64 | // = 0x2000,
+ FE_CAN_QAM_AUTO | // = 0x10000,
+ FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000,
+ FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000,
+ FE_CAN_HIERARCHY_AUTO | // = 0x100000,
+ FE_CAN_RECOVER | // = 0x40000000,
+ FE_CAN_MUTE_TS // = 0x80000000
+ },
+
+ .release = drx397x_release,
+ .init = drx397x_init,
+ .sleep = drx397x_sleep,
+
+ .set_frontend = drx397x_set_frontend,
+ .get_tune_settings = drx397x_get_tune_settings,
+ .get_frontend = drx397x_get_frontend,
+
+ .read_status = drx397x_read_status,
+ .read_snr = drx397x_read_snr,
+ .read_signal_strength = drx397x_read_signal_strength,
+ .read_ber = drx397x_read_ber,
+ .read_ucblocks = drx397x_read_ucblocks,
+};
+
+struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct drx397xD_state *s = NULL;
+
+ /* allocate memory for the internal state */
+ s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+
+ /* setup the state */
+ s->i2c = i2c;
+ memcpy(&s->config, config, sizeof(struct drx397xD_config));
+
+ /* check if the demod is there */
+ if (RD16(s, 0x2410019) < 0)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
+ s->frontend.demodulator_priv = s;
+
+ return &s->frontend;
+ error:
+ kfree(s);
+ return NULL;
+}
+
+MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
+MODULE_AUTHOR("Henk Vergonet");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(drx397xD_attach);
diff --git a/linux/drivers/media/dvb/frontends/drx397xD.h b/linux/drivers/media/dvb/frontends/drx397xD.h
new file mode 100644
index 000000000..ddc7a0797
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/drx397xD.h
@@ -0,0 +1,130 @@
+/*
+ * Driver for Micronas DVB-T drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk vergonet <Henk.Vergonet@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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 _DRX397XD_H_INCLUDED
+#define _DRX397XD_H_INCLUDED
+
+#include <linux/dvb/frontend.h>
+
+#define DRX_F_STEPSIZE 166667
+#define DRX_F_OFFSET 36000000
+
+#define I2C_ADR_C0(x) \
+( (u32)cpu_to_le32( \
+ (u32)( \
+ (((u32)(x) & (u32)0x000000ffUL) ) | \
+ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+ (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
+ ( (u32)0x00c00000UL) \
+ )) \
+)
+
+#define I2C_ADR_E0(x) \
+( (u32)cpu_to_le32( \
+ (u32)( \
+ (((u32)(x) & (u32)0x000000ffUL) ) | \
+ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+ (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
+ ( (u32)0x00e00000UL) \
+ )) \
+)
+
+struct drx397xD_CfgRfAgc /* 0x7c */
+{
+ int d00; /* 2 */
+ u16 w04;
+ u16 w06;
+};
+
+struct drx397xD_CfgIfAgc /* 0x68 */
+{
+ int d00; /* 0 */
+ u16 w04; /* 0 */
+ u16 w06;
+ u16 w08;
+ u16 w0A;
+ u16 w0C;
+};
+
+struct drx397xD_s20 {
+ int d04;
+ u32 d18;
+ u32 d1C;
+ u32 d20;
+ u32 d14;
+ u32 d24;
+ u32 d0C;
+ u32 d08;
+};
+
+struct drx397xD_config
+{
+ /* demodulator's I2C address */
+ u8 demod_address; /* 0x0f */
+
+ struct drx397xD_CfgIfAgc ifagc; /* 0x68 */
+ struct drx397xD_CfgRfAgc rfagc; /* 0x7c */
+ u32 s20d24;
+
+ /* HI_CfgCommand parameters */
+ u16 w50, w52, /* w54, */ w56;
+
+ int d5C;
+ int d60;
+ int d48;
+ int d28;
+
+ u32 f_if; /* d14: intermediate frequency [Hz] */
+ /* 36000000 on Cinergy 2400i DT */
+ /* 42800000 on Pinnacle Hybrid PRO 330e */
+
+ u16 f_osc; /* s66: 48000 oscillator frequency [kHz] */
+
+ u16 w92; /* 20000 */
+
+ u16 wA0;
+ u16 w98;
+ u16 w9A;
+
+ u16 w9C; /* 0xe0 */
+ u16 w9E; /* 0x00 */
+
+ /* used for signal strength calculations in
+ drx397x_read_signal_strength
+ */
+ u16 ss78; // 2200
+ u16 ss7A; // 150
+ u16 ss76; // 820
+};
+
+#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
+extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_DRX397XD */
+
+#endif /* _DRX397XD_H_INCLUDED */
diff --git a/linux/drivers/media/dvb/frontends/drx397xD_fw.h b/linux/drivers/media/dvb/frontends/drx397xD_fw.h
new file mode 100644
index 000000000..01de02a81
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/drx397xD_fw.h
@@ -0,0 +1,40 @@
+/*
+ * Firmware definitions for Micronas drx397xD
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef _FW_ENTRY
+ _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0 ),
+ _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1 ),
+#undef _FW_ENTRY
+#endif /* _FW_ENTRY */
+
+#ifdef _BLOB_ENTRY
+ _BLOB_ENTRY("InitAtomicRead", DRXD_InitAtomicRead = 0 ),
+ _BLOB_ENTRY("InitCE", DRXD_InitCE ),
+ _BLOB_ENTRY("InitCP", DRXD_InitCP ),
+ _BLOB_ENTRY("InitEC", DRXD_InitEC ),
+ _BLOB_ENTRY("InitEQ", DRXD_InitEQ ),
+ _BLOB_ENTRY("InitFE_1", DRXD_InitFE_1 ),
+ _BLOB_ENTRY("InitFE_2", DRXD_InitFE_2 ),
+ _BLOB_ENTRY("InitFT", DRXD_InitFT ),
+ _BLOB_ENTRY("InitSC", DRXD_InitSC ),
+ _BLOB_ENTRY("ResetCEFR", DRXD_ResetCEFR ),
+ _BLOB_ENTRY("ResetECRAM", DRXD_ResetECRAM ),
+ _BLOB_ENTRY("microcode", DRXD_microcode ),
+#undef _BLOB_ENTRY
+#endif /* _BLOB_ENTRY */
diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c
index 93785eef2..bb3e35373 100644
--- a/linux/drivers/media/dvb/frontends/dvb-pll.c
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.c
@@ -344,6 +344,52 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
}
};
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ struct i2c_msg msg = {
+ .addr = priv->pll_i2c_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 4
+ };
+ int result;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ result = i2c_transfer(priv->i2c, &msg, 1);
+ if (result != 1)
+ printk(KERN_ERR "%s: i2c_transfer failed:%d",
+ __func__, result);
+
+ buf[2] = 0x9e;
+ buf[3] = 0x90;
+
+ return;
+}
+
+/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
+static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
+ .name = "Samsung DTOS403IH102A",
+ .min = 44250000,
+ .max = 858000000,
+ .iffreq = 36125000,
+ .count = 8,
+ .set = samsung_dtos403ih102a_set,
+ .entries = {
+ { 135000000, 62500, 0xbe, 0x01 },
+ { 177000000, 62500, 0xf6, 0x01 },
+ { 370000000, 62500, 0xbe, 0x02 },
+ { 450000000, 62500, 0xf6, 0x02 },
+ { 466000000, 62500, 0xfe, 0x02 },
+ { 538000000, 62500, 0xbe, 0x08 },
+ { 826000000, 62500, 0xf6, 0x08 },
+ { 999999999, 62500, 0xfe, 0x08 },
+ }
+};
+
/* ----------------------------------------------------------- */
static struct dvb_pll_desc *pll_list[] = {
@@ -361,6 +407,7 @@ static struct dvb_pll_desc *pll_list[] = {
[DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
[DVB_PLL_OPERA1] = &dvb_pll_opera1,
+ [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a,
};
/* ----------------------------------------------------------- */
diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h
index 435146d9f..05239f579 100644
--- a/linux/drivers/media/dvb/frontends/dvb-pll.h
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.h
@@ -22,6 +22,7 @@
#define DVB_PLL_SAMSUNG_TBMV 11
#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
#define DVB_PLL_OPERA1 13
+#define DVB_PLL_SAMSUNG_DTOS403IH102A 14
/**
* Attach a dvb-pll to the supplied frontend structure.
@@ -43,7 +44,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
unsigned int pll_desc_id)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
diff --git a/linux/drivers/media/dvb/frontends/isl6405.h b/linux/drivers/media/dvb/frontends/isl6405.h
index 9d4001a22..1c793d375 100644
--- a/linux/drivers/media/dvb/frontends/isl6405.h
+++ b/linux/drivers/media/dvb/frontends/isl6405.h
@@ -66,7 +66,7 @@ static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_ISL6405 */
diff --git a/linux/drivers/media/dvb/frontends/isl6421.h b/linux/drivers/media/dvb/frontends/isl6421.h
index ea7f78a7d..47e4518a0 100644
--- a/linux/drivers/media/dvb/frontends/isl6421.h
+++ b/linux/drivers/media/dvb/frontends/isl6421.h
@@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a
static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_ISL6421
diff --git a/linux/drivers/media/dvb/frontends/itd1000.c b/linux/drivers/media/dvb/frontends/itd1000.c
new file mode 100644
index 000000000..3e37beb14
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/itd1000.c
@@ -0,0 +1,408 @@
+/*
+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ * Copyright (c) 2007-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "itd1000.h"
+#include "itd1000_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define deb(args...) do { \
+ if (debug) { \
+ printk(KERN_DEBUG "ITD1000: " args);\
+ printk("\n"); \
+ } \
+} while (0)
+
+#define warn(args...) do { \
+ printk(KERN_WARNING "ITD1000: " args); \
+ printk("\n"); \
+} while (0)
+
+#define info(args...) do { \
+ printk(KERN_INFO "ITD1000: " args); \
+ printk("\n"); \
+} while (0)
+
+/* don't write more than one byte with flexcop behind */
+static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
+{
+ u8 buf[1+len];
+ struct i2c_msg msg = {
+ .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
+ };
+ buf[0] = reg;
+ memcpy(&buf[1], v, len);
+
+ /* deb("wr %02x: %02x", reg, v[0]); */
+
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "itd1000 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
+{
+ u8 val;
+ struct i2c_msg msg[2] = {
+ { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
+ };
+
+ /* ugly flexcop workaround */
+ itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
+
+ if (i2c_transfer(state->i2c, msg, 2) != 2) {
+ warn("itd1000 I2C read failed");
+ return -EREMOTEIO;
+ }
+ return val;
+}
+
+static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
+{
+ int ret = itd1000_write_regs(state, r, &v, 1);
+ state->shadow[r] = v;
+ return ret;
+}
+
+#if 0
+static void reg_dump(struct itd1000_state *state)
+{
+ int i;
+ for (i = 0x65; i < 0x9c; i++)
+ printk(KERN_DEBUG "ITD: %02x: %02x\n", i, itd1000_read_reg(state, i));
+}
+#endif
+
+static struct {
+ u32 symbol_rate;
+ u8 pgaext : 4; /* PLLFH */
+ u8 bbgvmin : 4; /* BBGVMIN */
+} itd1000_lpf_pga[] = {
+ { 0, 0x8, 0x3 },
+ { 5200000, 0x8, 0x3 },
+ { 12200000, 0x4, 0x3 },
+ { 15400000, 0x2, 0x3 },
+ { 19800000, 0x2, 0x3 },
+ { 21500000, 0x2, 0x3 },
+ { 24500000, 0x2, 0x3 },
+ { 28400000, 0x2, 0x3 },
+ { 33400000, 0x2, 0x3 },
+ { 34400000, 0x1, 0x4 },
+ { 34400000, 0x1, 0x4 },
+ { 38400000, 0x1, 0x4 },
+ { 38400000, 0x1, 0x4 },
+ { 40400000, 0x1, 0x4 },
+ { 45400000, 0x1, 0x4 },
+};
+
+static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
+{
+ u8 i;
+ u8 con1 = itd1000_read_reg(state, CON1) & 0xfd;
+ u8 pllfh = itd1000_read_reg(state, PLLFH) & 0x0f;
+ u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
+ u8 bw = itd1000_read_reg(state, BW) & 0xf0;
+
+ deb("symbol_rate = %d", symbol_rate);
+
+ /* not sure what is that ? - starting to download the table */
+ itd1000_write_reg(state, CON1, con1 | (1 << 1));
+
+ for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
+ if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
+ deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+ itd1000_write_reg(state, PLLFH, pllfh | (itd1000_lpf_pga[i].pgaext << 4));
+ itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
+ itd1000_write_reg(state, BW, bw | (i & 0x0f));
+ break;
+ }
+
+ itd1000_write_reg(state, CON1, con1 | (0 << 1));
+}
+
+static struct {
+ u8 vcorg;
+ u32 fmax_rg;
+} itd1000_vcorg[] = {
+ { 1, 920000 },
+ { 2, 971000 },
+ { 3, 1031000 },
+ { 4, 1091000 },
+ { 5, 1171000 },
+ { 6, 1281000 },
+ { 7, 1381000 },
+ { 8, 500000 }, /* this is intentional. */
+ { 9, 1451000 },
+ { 10, 1531000 },
+ { 11, 1631000 },
+ { 12, 1741000 },
+ { 13, 1891000 },
+ { 14, 2071000 },
+ { 15, 2250000 },
+};
+
+static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
+{
+ u8 i;
+ u8 gvbb_i2c = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
+ u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
+ u8 adcout;
+
+ /* reserved bit again (reset ?) */
+ itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
+
+ for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
+ if (freq_khz < itd1000_vcorg[i].fmax_rg) {
+ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
+ msleep(1);
+
+ adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
+
+ deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+
+ if (adcout > 13) {
+ if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
+ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
+ } else if (adcout < 2) {
+ if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
+ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
+ }
+ break;
+ }
+ }
+}
+
+static const struct {
+ u32 freq;
+ u8 values[10]; /* RFTR, RFST1 - RFST9 */
+} itd1000_fre_values[] = {
+ { 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+ { 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+ { 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+ { 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+ { 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+ { 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+ { 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+ { 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
+ { 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
+ { 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
+};
+
+
+#define FREF 16
+
+static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
+{
+ int i, j;
+ u32 plln, pllf;
+ u64 tmp;
+
+ plln = (freq_khz * 1000) / 2 / FREF;
+
+ /* Compute the factional part times 1000 */
+ tmp = plln % 1000000;
+ plln /= 1000000;
+
+ tmp *= 1048576;
+ do_div(tmp, 1000000);
+ pllf = (u32) tmp;
+
+ state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
+ deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
+
+ itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+ itd1000_write_reg(state, PLLNL, plln & 0xff);
+ itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
+ itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
+ itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
+
+ for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
+ if (freq_khz <= itd1000_fre_values[i].freq) {
+ deb("fre_values: %d", i);
+ itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
+ for (j = 0; j < 9; j++)
+ itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
+ break;
+ }
+ }
+
+ itd1000_set_vco(state, freq_khz);
+}
+
+static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct itd1000_state *state = fe->tuner_priv;
+ u8 pllcon1;
+
+ itd1000_set_lo(state, p->frequency);
+ itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
+
+ pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
+ itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
+ itd1000_write_reg(state, PLLCON1, pllcon1);
+
+ return 0;
+}
+
+static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct itd1000_state *state = fe->tuner_priv;
+ *frequency = state->frequency;
+ return 0;
+}
+
+static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ return 0;
+}
+
+static u8 itd1000_init_tab[][2] = {
+ { PLLCON1, 0x65 }, /* Register does not change */
+ { PLLNH, 0x80 }, /* Bits [7:6] do not change */
+ { RESERVED_0X6D, 0x3b },
+ { VCO_CHP2_I2C, 0x12 },
+ { 0x72, 0xf9 }, /* No such regsister defined */
+ { RESERVED_0X73, 0xff },
+ { RESERVED_0X74, 0xb2 },
+ { RESERVED_0X75, 0xc7 },
+ { EXTGVBBRF, 0xf0 },
+ { DIVAGCCK, 0x80 },
+ { BBTR, 0xa0 },
+ { RESERVED_0X7E, 0x4f },
+ { 0x82, 0x88 }, /* No such regsister defined */
+ { 0x83, 0x80 }, /* No such regsister defined */
+ { 0x84, 0x80 }, /* No such regsister defined */
+ { RESERVED_0X85, 0x74 },
+ { RESERVED_0X86, 0xff },
+ { RESERVED_0X88, 0x02 },
+ { RESERVED_0X89, 0x16 },
+ { RFST0, 0x1f },
+ { RESERVED_0X94, 0x66 },
+ { RESERVED_0X95, 0x66 },
+ { RESERVED_0X96, 0x77 },
+ { RESERVED_0X97, 0x99 },
+ { RESERVED_0X98, 0xff },
+ { RESERVED_0X99, 0xfc },
+ { RESERVED_0X9A, 0xba },
+ { RESERVED_0X9B, 0xaa },
+};
+
+static u8 itd1000_reinit_tab[][2] = {
+ { VCO_CHP1_I2C, 0x8a },
+ { BW, 0x87 },
+ { GVBB_I2C, 0x03 },
+ { BBGVMIN, 0x03 },
+ { CON1, 0x2e },
+};
+
+
+static int itd1000_init(struct dvb_frontend *fe)
+{
+ struct itd1000_state *state = fe->tuner_priv;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
+ itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
+
+ for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
+ itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
+
+ return 0;
+}
+
+static int itd1000_sleep(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+static int itd1000_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static const struct dvb_tuner_ops itd1000_tuner_ops = {
+ .info = {
+ .name = "Integrant ITD1000",
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_step = 125, /* kHz for QPSK frontends */
+ },
+
+ .release = itd1000_release,
+
+ .init = itd1000_init,
+ .sleep = itd1000_sleep,
+
+ .set_params = itd1000_set_parameters,
+ .get_frequency = itd1000_get_frequency,
+ .get_bandwidth = itd1000_get_bandwidth
+};
+
+
+struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+ struct itd1000_state *state = NULL;
+ u8 i = 0;
+
+ state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
+ if (state == NULL)
+ return NULL;
+
+ state->cfg = cfg;
+ state->i2c = i2c;
+
+ i = itd1000_read_reg(state, 0);
+ if (i != 0) {
+ kfree(state);
+ return NULL;
+ }
+ info("successfully identified (ID: %d)", i);
+
+ memset(state->shadow, 0xff, sizeof(state->shadow));
+ for (i = 0x65; i < 0x9c; i++)
+ state->shadow[i] = itd1000_read_reg(state, i);
+
+ memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = state;
+
+ return fe;
+}
+EXPORT_SYMBOL(itd1000_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("Integrant ITD1000 driver");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/itd1000.h b/linux/drivers/media/dvb/frontends/itd1000.h
new file mode 100644
index 000000000..5e18df071
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/itd1000.h
@@ -0,0 +1,42 @@
+/*
+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ * Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_H
+#define ITD1000_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct itd1000_config {
+ u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
+#else
+static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/itd1000_priv.h b/linux/drivers/media/dvb/frontends/itd1000_priv.h
new file mode 100644
index 000000000..8cdc54e57
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/itd1000_priv.h
@@ -0,0 +1,88 @@
+/*
+ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ * Copyright (c) 2007 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef ITD1000_PRIV_H
+#define ITD1000_PRIV_H
+
+struct itd1000_state {
+ struct itd1000_config *cfg;
+ struct i2c_adapter *i2c;
+
+ u32 frequency; /* contains the value resulting from the LO-setting */
+
+ /* ugly workaround for flexcop's incapable i2c-controller
+ * FIXME, if possible
+ */
+ u8 shadow[255];
+};
+
+enum itd1000_register {
+ VCO_CHP1 = 0x65,
+ VCO_CHP2,
+ PLLCON1,
+ PLLNH,
+ PLLNL,
+ PLLFH,
+ PLLFM,
+ PLLFL,
+ RESERVED_0X6D,
+ PLLLOCK,
+ VCO_CHP2_I2C,
+ VCO_CHP1_I2C,
+ BW,
+ RESERVED_0X73 = 0x73,
+ RESERVED_0X74,
+ RESERVED_0X75,
+ GVBB,
+ GVRF,
+ GVBB_I2C,
+ EXTGVBBRF,
+ DIVAGCCK,
+ BBTR,
+ RFTR,
+ BBGVMIN,
+ RESERVED_0X7E,
+ RESERVED_0X85 = 0x85,
+ RESERVED_0X86,
+ CON1,
+ RESERVED_0X88,
+ RESERVED_0X89,
+ RFST0,
+ RFST1,
+ RFST2,
+ RFST3,
+ RFST4,
+ RFST5,
+ RFST6,
+ RFST7,
+ RFST8,
+ RFST9,
+ RESERVED_0X94,
+ RESERVED_0X95,
+ RESERVED_0X96,
+ RESERVED_0X97,
+ RESERVED_0X98,
+ RESERVED_0X99,
+ RESERVED_0X9A,
+ RESERVED_0X9B,
+};
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/l64781.c b/linux/drivers/media/dvb/frontends/l64781.c
index 443d9045d..e1e70e9e0 100644
--- a/linux/drivers/media/dvb/frontends/l64781.c
+++ b/linux/drivers/media/dvb/frontends/l64781.c
@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
- __FUNCTION__, reg, ret);
+ __func__, reg, ret);
return (ret != 1) ? -1 : 0;
}
diff --git a/linux/drivers/media/dvb/frontends/l64781.h b/linux/drivers/media/dvb/frontends/l64781.h
index cd15f76ff..1305a9e7f 100644
--- a/linux/drivers/media/dvb/frontends/l64781.h
+++ b/linux/drivers/media/dvb/frontends/l64781.h
@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_L64781
diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.c b/linux/drivers/media/dvb/frontends/lgdt330x.c
index 033b5a18d..3a3658238 100644
--- a/linux/drivers/media/dvb/frontends/lgdt330x.c
+++ b/linux/drivers/media/dvb/frontends/lgdt330x.c
@@ -89,7 +89,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
for (i=0; i<len-1; i+=2){
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
+ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
if (err < 0)
return err;
else
@@ -118,7 +118,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
int ret;
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
- printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
+ printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
} else {
ret = 0;
}
@@ -257,7 +257,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
err = -ENODEV;
}
- dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
+ dprintk("%s entered as %s\n", __func__, chip_name);
if (err < 0)
return err;
return lgdt330x_SwReset(state);
@@ -335,7 +335,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
if (state->current_modulation != param->u.vsb.modulation) {
switch(param->u.vsb.modulation) {
case VSB_8:
- dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
+ dprintk("%s: VSB_8 MODE\n", __func__);
/* Select VSB mode */
top_ctrl_cfg[1] = 0x03;
@@ -351,7 +351,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
break;
case QAM_64:
- dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
+ dprintk("%s: QAM_64 MODE\n", __func__);
/* Select QAM_64 mode */
top_ctrl_cfg[1] = 0x00;
@@ -367,7 +367,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
break;
case QAM_256:
- dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
+ dprintk("%s: QAM_256 MODE\n", __func__);
/* Select QAM_256 mode */
top_ctrl_cfg[1] = 0x01;
@@ -382,7 +382,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
}
break;
default:
- printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
+ printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
return -1;
}
/*
@@ -432,7 +432,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* AGC status register */
i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
if ((buf[0] & 0x0c) == 0x8){
/* Test signal does not exist flag */
/* as well as the AGC lock flag. */
@@ -446,7 +446,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
*/
/* signal status */
i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
- dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
+ dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
#if 0
/* Alternative method to check for a signal */
@@ -468,7 +468,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Carrier Recovery Lock Status Register */
i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
switch (state->current_modulation) {
case QAM_256:
case QAM_64:
@@ -481,7 +481,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
*status |= FE_HAS_CARRIER;
break;
default:
- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
}
return 0;
@@ -500,7 +500,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
if (err < 0)
return err;
- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
if ((buf[0] & 0x21) == 0x01){
/* Test input signal does not exist flag */
/* as well as the AGC lock flag. */
@@ -509,7 +509,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Carrier Recovery Lock Status Register */
i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
switch (state->current_modulation) {
case QAM_256:
case QAM_64:
@@ -540,7 +540,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
break;
default:
- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
+ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
}
return 0;
}
@@ -614,14 +614,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
break;
default:
printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
- __FUNCTION__);
+ __func__);
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
state->snr = calculate_snr(noise, c);
*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
@@ -658,14 +658,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
break;
default:
printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
- __FUNCTION__);
+ __func__);
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
state->snr = calculate_snr(noise, c);
*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
return 0;
@@ -750,7 +750,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
error:
kfree(state);
- dprintk("%s: ERROR\n",__FUNCTION__);
+ dprintk("%s: ERROR\n",__func__);
return NULL;
}
diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.h b/linux/drivers/media/dvb/frontends/lgdt330x.h
index 995059004..9012504f0 100644
--- a/linux/drivers/media/dvb/frontends/lgdt330x.h
+++ b/linux/drivers/media/dvb/frontends/lgdt330x.h
@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_LGDT330X
diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h
index 68906acf7..8fe094bd9 100644
--- a/linux/drivers/media/dvb/frontends/lnbp21.h
+++ b/linux/drivers/media/dvb/frontends/lnbp21.h
@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
#else
static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_LNBP21
diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c
index 1638301fb..5ac9b1592 100644
--- a/linux/drivers/media/dvb/frontends/mt312.c
+++ b/linux/drivers/media/dvb/frontends/mt312.c
@@ -1,7 +1,8 @@
/*
- Driver for Zarlink VP310/MT312 Satellite Channel Decoder
+ Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
+ Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -43,7 +44,8 @@ struct mt312_state {
struct dvb_frontend frontend;
u8 id;
- u8 frequency;
+ unsigned long xtal;
+ u8 freq_mult;
};
static int debug;
@@ -53,12 +55,11 @@ static int debug;
printk(KERN_DEBUG "mt312: " args); \
} while (0)
-#define MT312_SYS_CLK 90000000UL /* 90 MHz */
-#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
#define MT312_PLL_CLK 10000000UL /* 10 MHz */
+#define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */
static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
- void *buf, const size_t count)
+ u8 *buf, const size_t count)
{
int ret;
struct i2c_msg msg[2];
@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
- printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
+ printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
return -EREMOTEIO;
}
@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
int i;
dprintk("R(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
- printk(" %02x", ((const u8 *) buf)[i]);
+ printk(" %02x", buf[i]);
printk("\n");
}
@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
}
static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
- const void *src, const size_t count)
+ const u8 *src, const size_t count)
{
int ret;
u8 buf[count + 1];
@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
int i;
dprintk("W(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
- printk(" %02x", ((const u8 *) src)[i]);
+ printk(" %02x", src[i]);
printk("\n");
}
@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1) {
- dprintk("%s: ret == %d\n", __FUNCTION__, ret);
+ dprintk("%s: ret == %d\n", __func__, ret);
return -EREMOTEIO;
}
@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
dprintk("sym_rat_op=%d dec_ratio=%d\n",
sym_rat_op, dec_ratio);
dprintk("*sr(manual) = %lu\n",
- (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
+ (((state->xtal * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
}
@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
/* wake up */
ret = mt312_writereg(state, CONFIG,
- (state->frequency == 60 ? 0x88 : 0x8c));
+ (state->freq_mult == 6 ? 0x88 : 0x8c));
if (ret < 0)
return ret;
@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
return ret;
}
+ switch (state->id) {
+ case ID_ZL10313:
+ /* enable ADC */
+ ret = mt312_writereg(state, GPP_CTRL, 0x80);
+ if (ret < 0)
+ return ret;
+
+ /* configure ZL10313 for optimal ADC performance */
+ buf[0] = 0x80;
+ buf[1] = 0xB0;
+ ret = mt312_write(state, HW_CTRL, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ /* enable MPEG output and ADCs */
+ ret = mt312_writereg(state, HW_CTRL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = mt312_writereg(state, MPEG_CTRL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ break;
+ }
+
/* SYS_CLK */
- buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
- MT312_SYS_CLK) * 2, 1000000);
+ buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
/* DISEQC_RATIO */
- buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
+ buf[1] = mt312_div(state->xtal, 22000 * 4);
ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
if (ret < 0)
@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
if (ret < 0)
return ret;
- ret = mt312_writereg(state, OP_CTRL, 0x53);
+ /* different MOCLK polarity */
+ switch (state->id) {
+ case ID_ZL10313:
+ buf[0] = 0x33;
+ break;
+ default:
+ buf[0] = 0x53;
+ break;
+ }
+
+ ret = mt312_writereg(state, OP_CTRL, buf[0]);
if (ret < 0)
return ret;
@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
if (ret < 0)
return ret;
+ /* is there a better way to wait for message to be transmitted */
+ msleep(100);
+
/* set DISEQC_MODE[2:0] to zero if a return message is expected */
if (c->msg[0] & 0x02) {
ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
+ u8 val;
if (v > SEC_VOLTAGE_OFF)
return -EINVAL;
- return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
+ val = volt_tab[v];
+ if (state->config->voltage_inverted)
+ val ^= 0x40;
+
+ return mt312_writereg(state, DISEQC_MODE, val);
}
static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
int ret;
u8 buf[2];
- ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
+ ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
int ret;
u8 buf[2];
- ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
+ ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
{ 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
- dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
+ dprintk("%s: Freq %d\n", __func__, p->frequency);
if ((p->frequency < fe->ops.info.frequency_min)
|| (p->frequency > fe->ops.info.frequency_max))
@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
return ret;
if (p->u.qpsk.symbol_rate >= 30000000) {
/* Note that 30MS/s should use 90MHz */
- if ((config_val & 0x0c) == 0x08) {
+ if (state->freq_mult == 6) {
/* We are running 60MHz */
- state->frequency = 90;
+ state->freq_mult = 9;
ret = mt312_initfe(fe);
if (ret < 0)
return ret;
}
} else {
- if ((config_val & 0x0c) == 0x0C) {
+ if (state->freq_mult == 9) {
/* We are running 90MHz */
- state->frequency = 60;
+ state->freq_mult = 6;
ret = mt312_initfe(fe);
if (ret < 0)
return ret;
@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
break;
case ID_MT312:
+ case ID_ZL10313:
break;
default:
@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct mt312_state *state = fe->demodulator_priv;
- if (enable) {
- return mt312_writereg(state, GPP_CTRL, 0x40);
- } else {
- return mt312_writereg(state, GPP_CTRL, 0x00);
+ u8 val = 0x00;
+ int ret;
+
+ switch (state->id) {
+ case ID_ZL10313:
+ ret = mt312_readreg(state, GPP_CTRL, &val);
+ if (ret < 0)
+ goto error;
+
+ /* preserve this bit to not accidently shutdown ADC */
+ val &= 0x80;
+ break;
}
+
+ if (enable)
+ val |= 0x40;
+ else
+ val &= ~0x40;
+
+ ret = mt312_writereg(state, GPP_CTRL, val);
+
+error:
+ return ret;
}
static int mt312_sleep(struct dvb_frontend *fe)
@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
if (ret < 0)
return ret;
+ if (state->id == ID_ZL10313) {
+ /* reset ADC */
+ ret = mt312_writereg(state, GPP_CTRL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ /* full shutdown of ADCs, mpeg bus tristated */
+ ret = mt312_writereg(state, HW_CTRL, 0x0d);
+ if (ret < 0)
+ return ret;
+ }
+
ret = mt312_readreg(state, CONFIG, &config);
if (ret < 0)
return ret;
@@ -661,15 +736,16 @@ static void mt312_release(struct dvb_frontend *fe)
kfree(state);
}
-static struct dvb_frontend_ops vp310_mt312_ops = {
+#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+static struct dvb_frontend_ops mt312_ops = {
.info = {
.name = "Zarlink ???? DVB-S",
.type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
- .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
- .symbol_rate_min = MT312_SYS_CLK / 128,
+ .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
+ .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
.symbol_rate_max = MT312_SYS_CLK / 2,
.caps =
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
@@ -700,7 +776,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.set_voltage = mt312_set_voltage,
};
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c)
{
struct mt312_state *state = NULL;
@@ -719,21 +795,28 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
goto error;
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &vp310_mt312_ops,
+ memcpy(&state->frontend.ops, &mt312_ops,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
switch (state->id) {
case ID_VP310:
strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
- state->frequency = 90;
+ state->xtal = MT312_PLL_CLK;
+ state->freq_mult = 9;
break;
case ID_MT312:
strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
- state->frequency = 60;
+ state->xtal = MT312_PLL_CLK;
+ state->freq_mult = 6;
+ break;
+ case ID_ZL10313:
+ strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+ state->xtal = MT312_PLL_CLK_10_111;
+ state->freq_mult = 9;
break;
default:
- printk(KERN_WARNING "Only Zarlink VP310/MT312"
+ printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
" are supported chips.\n");
goto error;
}
@@ -744,12 +827,13 @@ error:
kfree(state);
return NULL;
}
-EXPORT_SYMBOL(vp310_mt312_attach);
+EXPORT_SYMBOL(mt312_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
+MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/mt312.h b/linux/drivers/media/dvb/frontends/mt312.h
index f17cb93ba..29e3bb549 100644
--- a/linux/drivers/media/dvb/frontends/mt312.h
+++ b/linux/drivers/media/dvb/frontends/mt312.h
@@ -31,16 +31,19 @@
struct mt312_config {
/* the demodulator's i2c address */
u8 demod_address;
+
+ /* inverted voltage setting */
+ unsigned int voltage_inverted:1;
};
#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend *vp310_mt312_attach(
+static inline struct dvb_frontend *mt312_attach(
const struct mt312_config *config, struct i2c_adapter *i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_MT312 */
diff --git a/linux/drivers/media/dvb/frontends/mt312_priv.h b/linux/drivers/media/dvb/frontends/mt312_priv.h
index 5e0b95b53..a3959f94d 100644
--- a/linux/drivers/media/dvb/frontends/mt312_priv.h
+++ b/linux/drivers/media/dvb/frontends/mt312_priv.h
@@ -110,6 +110,8 @@ enum mt312_reg_addr {
VIT_ERRPER_H = 83,
VIT_ERRPER_M = 84,
VIT_ERRPER_L = 85,
+ HW_CTRL = 84, /* ZL10313 only */
+ MPEG_CTRL = 85, /* ZL10313 only */
VIT_SETUP = 86,
VIT_REF0 = 87,
VIT_REF1 = 88,
@@ -156,7 +158,8 @@ enum mt312_reg_addr {
enum mt312_model_id {
ID_VP310 = 1,
- ID_MT312 = 3
+ ID_MT312 = 3,
+ ID_ZL10313 = 5,
};
#endif /* DVB_FRONTENDS_MT312_PRIV */
diff --git a/linux/drivers/media/dvb/frontends/mt352.c b/linux/drivers/media/dvb/frontends/mt352.c
index f9eb120c0..0bc03d9c7 100644
--- a/linux/drivers/media/dvb/frontends/mt352.c
+++ b/linux/drivers/media/dvb/frontends/mt352.c
@@ -96,7 +96,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
if (ret != 2) {
printk("%s: readreg error (reg=%d, ret==%i)\n",
- __FUNCTION__, reg, ret);
+ __func__, reg, ret);
return ret;
}
@@ -136,7 +136,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
value = 64 * bw * (1<<16) / (7 * 8);
value = value * 1000 / adc_clock;
dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
- __FUNCTION__, bw, adc_clock, value);
+ __func__, bw, adc_clock, value);
buf[0] = msb(value);
buf[1] = lsb(value);
}
@@ -162,7 +162,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
}
value = -16374 * ife / adc_clock;
dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
- __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
+ __func__, if2, ife, adc_clock, value, value & 0x3fff);
buf[0] = msb(value);
buf[1] = lsb(value);
}
@@ -522,7 +522,7 @@ static int mt352_init(struct dvb_frontend* fe)
static u8 mt352_reset_attach [] = { RESET, 0xC0 };
- dprintk("%s: hello\n",__FUNCTION__);
+ dprintk("%s: hello\n",__func__);
if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
(mt352_read_register(state, CONFIG) & 0x20) == 0) {
diff --git a/linux/drivers/media/dvb/frontends/mt352.h b/linux/drivers/media/dvb/frontends/mt352.h
index e9964081f..595092f9f 100644
--- a/linux/drivers/media/dvb/frontends/mt352.h
+++ b/linux/drivers/media/dvb/frontends/mt352.h
@@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_MT352
diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c
index 8808d781f..9172843dd 100644
--- a/linux/drivers/media/dvb/frontends/nxt200x.c
+++ b/linux/drivers/media/dvb/frontends/nxt200x.c
@@ -75,7 +75,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
- __FUNCTION__, addr, err);
+ __func__, addr, err);
return -EREMOTEIO;
}
return 0;
@@ -88,7 +88,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
- __FUNCTION__, addr, err);
+ __func__, addr, err);
return -EREMOTEIO;
}
return 0;
@@ -105,7 +105,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
+ __func__, state->config->demod_address, err);
return -EREMOTEIO;
}
return 0;
@@ -122,7 +122,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le
if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
+ __func__, state->config->demod_address, err);
return -EREMOTEIO;
}
return 0;
@@ -147,7 +147,7 @@ static u16 nxt200x_crc(u16 crc, u8 c)
static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
{
u8 attr, len2, buf;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* set mutli register register */
nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -208,7 +208,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
{
int i;
u8 buf, len2, attr;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* set mutli register register */
nxt200x_writebytes(state, 0x35, &reg, 1);
@@ -255,7 +255,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
{
u8 buf, stopval, counter = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* set correct stop value */
switch (state->demod_chip) {
@@ -288,7 +288,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
static void nxt200x_microcontroller_start (struct nxt200x_state* state)
{
u8 buf;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
buf = 0x00;
nxt200x_writebytes(state, 0x22, &buf, 1);
@@ -298,7 +298,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
{
u8 buf[9];
u8 counter = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
buf[0] = 0x00;
nxt200x_writebytes(state, 0x2b, buf, 1);
@@ -329,7 +329,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
{
u8 buf, count = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
@@ -388,7 +388,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
static void nxt200x_agc_reset(struct nxt200x_state* state)
{
u8 buf;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
switch (state->demod_chip) {
case NXT2002:
@@ -417,7 +417,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
u8 buf[3], written = 0, chunkpos = 0;
u16 rambase, position, crc = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dprintk("Firmware is %zu bytes\n", fw->size);
/* Get the RAM base for this nxt2002 */
@@ -484,7 +484,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
u8 buf[3];
u16 rambase, position, crc=0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dprintk("Firmware is %zu bytes\n", fw->size);
/* set rambase */
diff --git a/linux/drivers/media/dvb/frontends/nxt200x.h b/linux/drivers/media/dvb/frontends/nxt200x.h
index bb0ef58d7..f3c845837 100644
--- a/linux/drivers/media/dvb/frontends/nxt200x.h
+++ b/linux/drivers/media/dvb/frontends/nxt200x.h
@@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_NXT200X
diff --git a/linux/drivers/media/dvb/frontends/nxt6000.h b/linux/drivers/media/dvb/frontends/nxt6000.h
index 13d225183..878eb38a0 100644
--- a/linux/drivers/media/dvb/frontends/nxt6000.h
+++ b/linux/drivers/media/dvb/frontends/nxt6000.h
@@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_NXT6000
diff --git a/linux/drivers/media/dvb/frontends/or51132.c b/linux/drivers/media/dvb/frontends/or51132.c
index 1d2d28ce8..5ed32544d 100644
--- a/linux/drivers/media/dvb/frontends/or51132.c
+++ b/linux/drivers/media/dvb/frontends/or51132.c
@@ -91,7 +91,7 @@ static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
Less code and more efficient that loading a buffer on the stack with
the bytes to send and then calling or51132_writebuf() on that. */
#define or51132_writebytes(state, data...) \
- ({ const static u8 _data[] = {data}; \
+ ({ static const u8 _data[] = {data}; \
or51132_writebuf(state, _data, sizeof(_data)); })
/* Read data from demod into buffer. Returns 0 on success. */
@@ -126,13 +126,13 @@ static int or51132_readreg(struct or51132_state *state, u8 reg)
reg, err);
return -EREMOTEIO;
}
- return le16_to_cpup((u16*)buf);
+ return buf[0] | (buf[1] << 8);
}
static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
{
struct or51132_state* state = fe->demodulator_priv;
- const static u8 run_buf[] = {0x7F,0x01};
+ static const u8 run_buf[] = {0x7F,0x01};
u8 rec_buf[8];
u32 firmwareAsize, firmwareBsize;
int i,ret;
@@ -140,9 +140,9 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
dprintk("Firmware is %Zd bytes\n",fw->size);
/* Get size of firmware A and B */
- firmwareAsize = le32_to_cpu(*((u32*)fw->data));
+ firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
dprintk("FirmwareA is %i bytes\n",firmwareAsize);
- firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
+ firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
dprintk("FirmwareB is %i bytes\n",firmwareBsize);
/* Upload firmware */
@@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
*status = 0;
return -EREMOTEIO;
}
- dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
+ dprintk("%s: read_status %04x\n", __func__, reg);
if (reg & 0x0100) /* Receiver Lock */
*status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
@@ -504,14 +504,14 @@ start:
if (retry--) goto start;
return -EREMOTEIO;
}
- dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
+ dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
reg&0xff, reg&0x1000?"n":"ff");
/* Calculate SNR using noise, c, and NTSC rejection correction */
state->snr = calculate_snr(noise, c) - usK;
*snr = (state->snr) >> 16;
- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
diff --git a/linux/drivers/media/dvb/frontends/or51132.h b/linux/drivers/media/dvb/frontends/or51132.h
index add24f0a7..1b8e04d97 100644
--- a/linux/drivers/media/dvb/frontends/or51132.h
+++ b/linux/drivers/media/dvb/frontends/or51132.h
@@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_OR51132
diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c
index 6a6b0d727..7eaa47655 100644
--- a/linux/drivers/media/dvb/frontends/or51211.c
+++ b/linux/drivers/media/dvb/frontends/or51211.c
@@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
printk(KERN_WARNING "%s: error writing snr reg\n",
- __FUNCTION__);
+ __func__);
return -1;
}
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
printk(KERN_WARNING "%s: read_status read error\n",
- __FUNCTION__);
+ __func__);
return -1;
}
state->snr = calculate_snr(rec_buf[0], 89599047);
*snr = (state->snr) >> 16;
- dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
+ dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
diff --git a/linux/drivers/media/dvb/frontends/or51211.h b/linux/drivers/media/dvb/frontends/or51211.h
index 8aad8402d..3ce0508b8 100644
--- a/linux/drivers/media/dvb/frontends/or51211.h
+++ b/linux/drivers/media/dvb/frontends/or51211.h
@@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_OR51211
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c
index 1ca250378..5ddb2dca3 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.c
+++ b/linux/drivers/media/dvb/frontends/s5h1409.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "s5h1409.h"
struct s5h1409_state {
@@ -312,7 +311,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
if (ret != 1)
printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
- "ret == %i)\n", __FUNCTION__, reg, data, ret);
+ "ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
@@ -332,7 +331,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ printk("%s: readreg error (ret == %i)\n", __func__, ret);
return (b1[0] << 8) | b1[1];
}
@@ -340,7 +339,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
s5h1409_writereg(state, 0xf5, 0);
s5h1409_writereg(state, 0xf5, 1);
@@ -356,7 +355,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
+ dprintk("%s(%d KHz)\n", __func__, KHz);
switch (KHz) {
case 4000:
@@ -381,7 +380,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(%d)\n", __FUNCTION__, inverted);
+ dprintk("%s(%d)\n", __func__, inverted);
if(inverted == 1)
return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
@@ -394,25 +393,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(0x%08x)\n", __FUNCTION__, m);
+ dprintk("%s(0x%08x)\n", __func__, m);
switch(m) {
case VSB_8:
- dprintk("%s() VSB_8\n", __FUNCTION__);
+ dprintk("%s() VSB_8\n", __func__);
if (state->if_freq != S5H1409_VSB_IF_FREQ)
s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
s5h1409_writereg(state, 0xf4, 0);
break;
case QAM_64:
case QAM_256:
- dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
+ dprintk("%s() QAM_AUTO (64/256)\n", __func__);
if (state->if_freq != S5H1409_QAM_IF_FREQ)
s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
s5h1409_writereg(state, 0xf4, 1);
s5h1409_writereg(state, 0x85, 0x110);
break;
default:
- dprintk("%s() Invalid modulation\n", __FUNCTION__);
+ dprintk("%s() Invalid modulation\n", __func__);
return -EINVAL;
}
@@ -426,7 +425,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(%d)\n", __FUNCTION__, enable);
+ dprintk("%s(%d)\n", __func__, enable);
if (enable)
return s5h1409_writereg(state, 0xf3, 1);
@@ -438,7 +437,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(%d)\n", __FUNCTION__, enable);
+ dprintk("%s(%d)\n", __func__, enable);
if (enable)
return s5h1409_writereg(state, 0xe3,
@@ -452,7 +451,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(%d)\n", __FUNCTION__, enable);
+ dprintk("%s(%d)\n", __func__, enable);
return s5h1409_writereg(state, 0xf2, enable);
}
@@ -461,7 +460,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
return s5h1409_writereg(state, 0xfa, 0);
}
@@ -534,7 +533,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
{
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
s5h1409_softreset(fe);
@@ -565,7 +564,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
struct s5h1409_state *state = fe->demodulator_priv;
u16 val;
- dprintk("%s(%d)\n", __FUNCTION__, mode);
+ dprintk("%s(%d)\n", __func__, mode);
val = s5h1409_readreg(state, 0xac) & 0xcfff;
switch (mode) {
@@ -573,7 +572,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
val |= 0x0000;
break;
case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
- dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
+ dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
val |= 0x1000;
break;
case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
@@ -597,7 +596,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
int i;
struct s5h1409_state* state = fe->demodulator_priv;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
s5h1409_sleep(fe, 0);
s5h1409_register_reset(fe);
@@ -663,7 +662,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
break;
}
- dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
+ dprintk("%s() status 0x%08x\n", __func__, *status);
return 0;
}
@@ -671,7 +670,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
{
int i, ret = -EINVAL;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
if (v < qam256_snr_tab[i].val) {
@@ -686,7 +685,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
{
int i, ret = -EINVAL;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
if (v < qam64_snr_tab[i].val) {
@@ -701,7 +700,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
{
int i, ret = -EINVAL;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
if (v > vsb_snr_tab[i].val) {
@@ -710,7 +709,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
break;
}
}
- dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
+ dprintk("%s() snr=%d\n", __func__, *snr);
return ret;
}
@@ -718,7 +717,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct s5h1409_state* state = fe->demodulator_priv;
u16 reg;
- dprintk("%s()\n", __FUNCTION__);
+ dprintk("%s()\n", __func__);
switch(state->current_modulation) {
case QAM_64:
@@ -812,7 +811,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
if (s5h1409_init(&state->frontend) != 0) {
printk(KERN_ERR "%s: Failed to initialize correctly\n",
- __FUNCTION__);
+ __func__);
goto error;
}
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.h b/linux/drivers/media/dvb/frontends/s5h1409.h
index f0bb13fe8..59f433596 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.h
+++ b/linux/drivers/media/dvb/frontends/s5h1409.h
@@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_S5H1409 */
diff --git a/linux/drivers/media/dvb/frontends/s5h1411.c b/linux/drivers/media/dvb/frontends/s5h1411.c
new file mode 100644
index 000000000..cff360ce1
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s5h1411.c
@@ -0,0 +1,887 @@
+/*
+ Samsung S5H1411 VSB/QAM demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s5h1411.h"
+
+struct s5h1411_state {
+
+ struct i2c_adapter *i2c;
+
+ /* configuration settings */
+ const struct s5h1411_config *config;
+
+ struct dvb_frontend frontend;
+
+ fe_modulation_t current_modulation;
+
+ u32 current_frequency;
+ int if_freq;
+
+ u8 inversion;
+};
+
+static int debug;
+
+#define dprintk(arg...) do { \
+ if (debug) \
+ printk(arg); \
+ } while (0)
+
+/* Register values to initialise the demod, defaults to VSB */
+static struct init_tab {
+ u8 addr;
+ u8 reg;
+ u16 data;
+} init_tab[] = {
+ { S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
+ { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
+ { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
+ { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
+ { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
+ { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
+ { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
+ { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
+ { S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
+ { S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
+ { S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
+ { S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
+ { S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
+ { S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
+ { S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
+ { S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
+ { S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
+ { S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
+ { S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
+ { S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
+ { S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
+ { S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
+ { S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
+ { S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
+ { S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
+ { S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
+ { S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
+ { S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
+ { S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
+ { S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
+ { S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
+ { S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
+ { S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
+ { S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
+ { S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
+ { S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
+ { S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
+ { S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
+ { S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
+ { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
+ { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
+ { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
+ { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
+ { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
+ { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
+ { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
+ { S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
+ { S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
+ { S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
+ { S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
+ { S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
+ { S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
+ { S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
+ { S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
+ { S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
+ { S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
+ { S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
+ { S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
+ { S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
+ { S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
+ { S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
+ { S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
+ { S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
+ { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
+ { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
+ { S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
+ { S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
+ { S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
+ { S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
+ { S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
+ { S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
+ { S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
+ { S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
+ { S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
+ { S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
+ { S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
+ { S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
+ { S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
+ { S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
+ { S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
+ { S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+ u16 val;
+ u16 data;
+} vsb_snr_tab[] = {
+ { 0x39f, 300, },
+ { 0x39b, 295, },
+ { 0x397, 290, },
+ { 0x394, 285, },
+ { 0x38f, 280, },
+ { 0x38b, 275, },
+ { 0x387, 270, },
+ { 0x382, 265, },
+ { 0x37d, 260, },
+ { 0x377, 255, },
+ { 0x370, 250, },
+ { 0x36a, 245, },
+ { 0x364, 240, },
+ { 0x35b, 235, },
+ { 0x353, 230, },
+ { 0x349, 225, },
+ { 0x340, 320, },
+ { 0x337, 215, },
+ { 0x327, 210, },
+ { 0x31b, 205, },
+ { 0x310, 200, },
+ { 0x302, 195, },
+ { 0x2f3, 190, },
+ { 0x2e4, 185, },
+ { 0x2d7, 180, },
+ { 0x2cd, 175, },
+ { 0x2bb, 170, },
+ { 0x2a9, 165, },
+ { 0x29e, 160, },
+ { 0x284, 155, },
+ { 0x27a, 150, },
+ { 0x260, 145, },
+ { 0x23a, 140, },
+ { 0x224, 135, },
+ { 0x213, 130, },
+ { 0x204, 125, },
+ { 0x1fe, 120, },
+ { 0, 0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+ u16 val;
+ u16 data;
+} qam64_snr_tab[] = {
+ { 0x0001, 0, },
+ { 0x0af0, 300, },
+ { 0x0d80, 290, },
+ { 0x10a0, 280, },
+ { 0x14b5, 270, },
+ { 0x1590, 268, },
+ { 0x1680, 266, },
+ { 0x17b0, 264, },
+ { 0x18c0, 262, },
+ { 0x19b0, 260, },
+ { 0x1ad0, 258, },
+ { 0x1d00, 256, },
+ { 0x1da0, 254, },
+ { 0x1ef0, 252, },
+ { 0x2050, 250, },
+ { 0x20f0, 249, },
+ { 0x21d0, 248, },
+ { 0x22b0, 247, },
+ { 0x23a0, 246, },
+ { 0x2470, 245, },
+ { 0x24f0, 244, },
+ { 0x25a0, 243, },
+ { 0x26c0, 242, },
+ { 0x27b0, 241, },
+ { 0x28d0, 240, },
+ { 0x29b0, 239, },
+ { 0x2ad0, 238, },
+ { 0x2ba0, 237, },
+ { 0x2c80, 236, },
+ { 0x2d20, 235, },
+ { 0x2e00, 234, },
+ { 0x2f10, 233, },
+ { 0x3050, 232, },
+ { 0x3190, 231, },
+ { 0x3300, 230, },
+ { 0x3340, 229, },
+ { 0x3200, 228, },
+ { 0x3550, 227, },
+ { 0x3610, 226, },
+ { 0x3600, 225, },
+ { 0x3700, 224, },
+ { 0x3800, 223, },
+ { 0x3920, 222, },
+ { 0x3a20, 221, },
+ { 0x3b30, 220, },
+ { 0x3d00, 219, },
+ { 0x3e00, 218, },
+ { 0x4000, 217, },
+ { 0x4100, 216, },
+ { 0x4300, 215, },
+ { 0x4400, 214, },
+ { 0x4600, 213, },
+ { 0x4700, 212, },
+ { 0x4800, 211, },
+ { 0x4a00, 210, },
+ { 0x4b00, 209, },
+ { 0x4d00, 208, },
+ { 0x4f00, 207, },
+ { 0x5050, 206, },
+ { 0x5200, 205, },
+ { 0x53c0, 204, },
+ { 0x5450, 203, },
+ { 0x5650, 202, },
+ { 0x5820, 201, },
+ { 0x6000, 200, },
+ { 0xffff, 0, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+ u16 val;
+ u16 data;
+} qam256_snr_tab[] = {
+ { 0x0001, 0, },
+ { 0x0970, 400, },
+ { 0x0a90, 390, },
+ { 0x0b90, 380, },
+ { 0x0d90, 370, },
+ { 0x0ff0, 360, },
+ { 0x1240, 350, },
+ { 0x1345, 348, },
+ { 0x13c0, 346, },
+ { 0x14c0, 344, },
+ { 0x1500, 342, },
+ { 0x1610, 340, },
+ { 0x1700, 338, },
+ { 0x1800, 336, },
+ { 0x18b0, 334, },
+ { 0x1900, 332, },
+ { 0x1ab0, 330, },
+ { 0x1bc0, 328, },
+ { 0x1cb0, 326, },
+ { 0x1db0, 324, },
+ { 0x1eb0, 322, },
+ { 0x2030, 320, },
+ { 0x2200, 318, },
+ { 0x2280, 316, },
+ { 0x2410, 314, },
+ { 0x25b0, 312, },
+ { 0x27a0, 310, },
+ { 0x2840, 308, },
+ { 0x29d0, 306, },
+ { 0x2b10, 304, },
+ { 0x2d30, 302, },
+ { 0x2f20, 300, },
+ { 0x30c0, 298, },
+ { 0x3260, 297, },
+ { 0x32c0, 296, },
+ { 0x3300, 295, },
+ { 0x33b0, 294, },
+ { 0x34b0, 293, },
+ { 0x35a0, 292, },
+ { 0x3650, 291, },
+ { 0x3800, 290, },
+ { 0x3900, 289, },
+ { 0x3a50, 288, },
+ { 0x3b30, 287, },
+ { 0x3cb0, 286, },
+ { 0x3e20, 285, },
+ { 0x3fa0, 284, },
+ { 0x40a0, 283, },
+ { 0x41c0, 282, },
+ { 0x42f0, 281, },
+ { 0x44a0, 280, },
+ { 0x4600, 279, },
+ { 0x47b0, 278, },
+ { 0x4900, 277, },
+ { 0x4a00, 276, },
+ { 0x4ba0, 275, },
+ { 0x4d00, 274, },
+ { 0x4f00, 273, },
+ { 0x5000, 272, },
+ { 0x51f0, 272, },
+ { 0x53a0, 270, },
+ { 0x5520, 269, },
+ { 0x5700, 268, },
+ { 0x5800, 267, },
+ { 0x5a00, 266, },
+ { 0x5c00, 265, },
+ { 0x5d00, 264, },
+ { 0x5f00, 263, },
+ { 0x6000, 262, },
+ { 0x6200, 261, },
+ { 0x6400, 260, },
+ { 0xffff, 0, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1411_writereg(struct s5h1411_state *state,
+ u8 addr, u8 reg, u16 data)
+{
+ int ret;
+ u8 buf [] = { reg, data >> 8, data & 0xff };
+
+ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
+ "ret == %i)\n", __func__, addr, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
+{
+ int ret;
+ u8 b0 [] = { reg };
+ u8 b1 [] = { 0, 0 };
+
+ struct i2c_msg msg [] = {
+ { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
+ return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1411_softreset(struct dvb_frontend *fe)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __func__);
+
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
+ return 0;
+}
+
+static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s(%d KHz)\n", __func__, KHz);
+
+ switch (KHz) {
+ case 3250:
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
+ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
+ break;
+ case 3500:
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
+ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
+ break;
+ case 4000:
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
+ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
+ break;
+ default:
+ dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
+ __func__, KHz);
+ /* no break, need to continue */
+ case 5380:
+ case 44000:
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
+ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
+ break;
+ }
+
+ state->if_freq = KHz;
+
+ return 0;
+}
+
+static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 val;
+
+ dprintk("%s(%d)\n", __func__, mode);
+
+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
+ switch (mode) {
+ case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
+ val |= 0x0000;
+ break;
+ case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+ dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+ val |= 0x1000;
+ break;
+ case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+ val |= 0x2000;
+ break;
+ case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
+ val |= 0x3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Configure MPEG Signal Timing charactistics */
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
+}
+
+static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 val;
+
+ dprintk("%s(%d)\n", __func__, inversion);
+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
+
+ if (inversion == 1)
+ val |= 0x1000; /* Inverted */
+ else
+ val |= 0x0000;
+
+ state->inversion = inversion;
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
+}
+
+static int s5h1411_enable_modulation(struct dvb_frontend *fe,
+ fe_modulation_t m)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s(0x%08x)\n", __func__, m);
+
+ switch (m) {
+ case VSB_8:
+ dprintk("%s() VSB_8\n", __func__);
+ s5h1411_set_if_freq(fe, state->config->vsb_if);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
+ break;
+ case QAM_64:
+ case QAM_256:
+ dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+ s5h1411_set_if_freq(fe, state->config->qam_if);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
+ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
+ break;
+ default:
+ dprintk("%s() Invalid modulation\n", __func__);
+ return -EINVAL;
+ }
+
+ state->current_modulation = m;
+ s5h1411_softreset(fe);
+
+ return 0;
+}
+
+static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __func__, enable);
+
+ if (enable)
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+ else
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
+}
+
+static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 val;
+
+ dprintk("%s(%d)\n", __func__, enable);
+
+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
+
+ if (enable)
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
+ val | 0x02);
+ else
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
+}
+
+static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __func__, enable);
+
+ if (enable)
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
+ else {
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
+ s5h1411_softreset(fe);
+ }
+
+ return 0;
+}
+
+static int s5h1411_register_reset(struct dvb_frontend *fe)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s()\n", __func__);
+
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1411_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+ s5h1411_softreset(fe);
+
+ state->current_frequency = p->frequency;
+
+ s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+
+ /* Allow the demod to settle */
+ msleep(100);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ fe->ops.tuner_ops.set_params(fe, p);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+ to a default state. */
+static int s5h1411_init(struct dvb_frontend *fe)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ int i;
+
+ dprintk("%s()\n", __func__);
+
+ s5h1411_sleep(fe, 0);
+ s5h1411_register_reset(fe);
+
+ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+ s5h1411_writereg(state, init_tab[i].addr,
+ 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 == S5H1411_SERIAL_OUTPUT)
+ /* Serial */
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+ else
+ /* Parallel */
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+
+ s5h1411_set_spectralinversion(fe, state->config->inversion);
+ s5h1411_set_if_freq(fe, state->config->vsb_if);
+ s5h1411_set_gpio(fe, state->config->gpio);
+ s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
+ s5h1411_softreset(fe);
+
+ /* Note: Leaving the I2C gate closed. */
+ s5h1411_i2c_gate_ctrl(fe, 0);
+
+ return 0;
+}
+
+static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 reg;
+ u32 tuner_status = 0;
+
+ *status = 0;
+
+ /* Get the demodulator status */
+ reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
+ & 0x0001;
+ if (reg)
+ *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+ switch (state->current_modulation) {
+ case QAM_64:
+ case QAM_256:
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
+ if (reg & 0x100)
+ *status |= FE_HAS_VITERBI;
+ if (reg & 0x10)
+ *status |= FE_HAS_SYNC;
+ break;
+ case VSB_8:
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
+ if (reg & 0x0001)
+ *status |= FE_HAS_SYNC;
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
+ if (reg & 0x1000)
+ *status |= FE_HAS_VITERBI;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (state->config->status_mode) {
+ case S5H1411_DEMODLOCKING:
+ if (*status & FE_HAS_VITERBI)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ break;
+ case S5H1411_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", __func__, *status);
+
+ return 0;
+}
+
+static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __func__);
+
+ 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 s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __func__);
+
+ 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 s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+ int i, ret = -EINVAL;
+ dprintk("%s()\n", __func__);
+
+ 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", __func__, *snr);
+ return ret;
+}
+
+static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 reg;
+ dprintk("%s()\n", __func__);
+
+ switch (state->current_modulation) {
+ case QAM_64:
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+ return s5h1411_qam64_lookup_snr(fe, snr, reg);
+ case QAM_256:
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+ return s5h1411_qam256_lookup_snr(fe, snr, reg);
+ case VSB_8:
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
+ 0xf2) & 0x3ff;
+ return s5h1411_vsb_lookup_snr(fe, snr, reg);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ return s5h1411_read_snr(fe, signal_strength);
+}
+
+static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
+
+ return 0;
+}
+
+static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ return s5h1411_read_ucblocks(fe, ber);
+}
+
+static int s5h1411_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+
+ p->frequency = state->current_frequency;
+ p->u.vsb.modulation = state->current_modulation;
+
+ return 0;
+}
+
+static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void s5h1411_release(struct dvb_frontend *fe)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1411_ops;
+
+struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct s5h1411_state *state = NULL;
+ u16 reg;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->current_modulation = VSB_8;
+ state->inversion = state->config->inversion;
+
+ /* check if the demod exists */
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
+ if (reg != 0x0066)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &s5h1411_ops,
+ sizeof(struct dvb_frontend_ops));
+
+ state->frontend.demodulator_priv = state;
+
+ if (s5h1411_init(&state->frontend) != 0) {
+ printk(KERN_ERR "%s: Failed to initialize correctly\n",
+ __func__);
+ goto error;
+ }
+
+ /* Note: Leaving the I2C gate open here. */
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(s5h1411_attach);
+
+static struct dvb_frontend_ops s5h1411_ops = {
+
+ .info = {
+ .name = "Samsung S5H1411 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 = s5h1411_init,
+ .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl,
+ .set_frontend = s5h1411_set_frontend,
+ .get_frontend = s5h1411_get_frontend,
+ .get_tune_settings = s5h1411_get_tune_settings,
+ .read_status = s5h1411_read_status,
+ .read_ber = s5h1411_read_ber,
+ .read_signal_strength = s5h1411_read_signal_strength,
+ .read_snr = s5h1411_read_snr,
+ .read_ucblocks = s5h1411_read_ucblocks,
+ .release = s5h1411_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/linux/drivers/media/dvb/frontends/s5h1411.h b/linux/drivers/media/dvb/frontends/s5h1411.h
new file mode 100644
index 000000000..1855f64ed
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s5h1411.h
@@ -0,0 +1,90 @@
+/*
+ Samsung S5H1411 VSB/QAM demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __S5H1411_H__
+#define __S5H1411_H__
+
+#include <linux/dvb/frontend.h>
+
+#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
+#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
+
+struct s5h1411_config {
+
+ /* serial/parallel output */
+#define S5H1411_PARALLEL_OUTPUT 0
+#define S5H1411_SERIAL_OUTPUT 1
+ u8 output_mode;
+
+ /* GPIO Setting */
+#define S5H1411_GPIO_OFF 0
+#define S5H1411_GPIO_ON 1
+ u8 gpio;
+
+ /* MPEG signal timing */
+#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK 0
+#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 1
+#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2
+#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+ u16 mpeg_timing;
+
+ /* IF Freq for QAM and VSB in KHz */
+#define S5H1411_IF_2500 2500
+#define S5H1411_IF_3500 3500
+#define S5H1411_IF_4000 4000
+#define S5H1411_IF_5380 5380
+#define S5H1411_IF_44000 44000
+#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
+#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
+ u16 qam_if;
+ u16 vsb_if;
+
+ /* Spectral Inversion */
+#define S5H1411_INVERSION_OFF 0
+#define S5H1411_INVERSION_ON 1
+ u8 inversion;
+
+ /* Return lock status based on tuner lock, or demod lock */
+#define S5H1411_TUNERLOCKING 0
+#define S5H1411_DEMODLOCKING 1
+ u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1411) || \
+ (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1411_attach(
+ const struct s5h1411_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_S5H1411 */
+
+#endif /* __S5H1411_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/linux/drivers/media/dvb/frontends/s5h1420.c b/linux/drivers/media/dvb/frontends/s5h1420.c
index 7c64af91e..996f37704 100644
--- a/linux/drivers/media/dvb/frontends/s5h1420.c
+++ b/linux/drivers/media/dvb/frontends/s5h1420.c
@@ -1,24 +1,26 @@
/*
-Driver for Samsung S5H1420 QPSK Demodulator
-
-Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Driver for
+ * Samsung S5H1420 and
+ * PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include <linux/jiffies.h>
#include <asm/div64.h>
-#include "dvb_frontend.h"
-#include "s5h1420.h"
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "s5h1420.h"
+#include "s5h1420_priv.h"
#define TONE_FREQ 22000
struct s5h1420_state {
struct i2c_adapter* i2c;
const struct s5h1420_config* config;
+
struct dvb_frontend frontend;
+ struct i2c_adapter tuner_i2c_adapter;
+
+ u8 CON_1_val;
u8 postlocked:1;
u32 fclk;
u32 tunedfreq;
fe_code_rate_t fec_inner;
u32 symbol_rate;
+
+ /* FIXME: ugly workaround for flexcop's incapable i2c-controller
+ * it does not support repeated-start, workaround: write addr-1
+ * and then read
+ */
+ u8 shadow[255];
};
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
@@ -54,43 +68,65 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
static int debug;
-#define dprintk if (debug) printk
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debugging");
+
+#define dprintk(x...) do { \
+ if (debug) \
+ printk(KERN_DEBUG "S5H1420: " x); \
+} while (0)
+
+static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
+{
+ int ret;
+ u8 b[2];
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
+ { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
+ };
+
+ b[0] = (reg - 1) & 0xff;
+ b[1] = state->shadow[(reg - 1) & 0xff];
+
+ if (state->config->repeated_start_workaround) {
+ ret = i2c_transfer(state->i2c, msg, 3);
+ if (ret != 3)
+ return ret;
+ } else {
+ ret = i2c_transfer(state->i2c, &msg[1], 2);
+ if (ret != 2)
+ return ret;
+ }
+
+ /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
+
+ return b[0];
+}
static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
{
- u8 buf [] = { reg, data };
+ u8 buf[] = { reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
int err;
- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
+ err = i2c_transfer(state->i2c, &msg, 1);
+ if (err != 1) {
+ dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
return -EREMOTEIO;
}
+ state->shadow[reg] = data;
return 0;
}
-static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
-{
- int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
- struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
- struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
-
- if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
- return ret;
-
- if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
- return ret;
-
- return b1[0];
-}
-
static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct s5h1420_state* state = fe->demodulator_priv;
+ dprintk("enter %s\n", __func__);
+
switch(voltage) {
case SEC_VOLTAGE_13:
s5h1420_writereg(state, 0x3c,
@@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
break;
}
+ dprintk("leave %s\n", __func__);
return 0;
}
@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct s5h1420_state* state = fe->demodulator_priv;
+ dprintk("enter %s\n", __func__);
switch(tone) {
case SEC_TONE_ON:
s5h1420_writereg(state, 0x3b,
@@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
(s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
break;
}
+ dprintk("leave %s\n", __func__);
return 0;
}
@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
unsigned long timeout;
int result = 0;
+ dprintk("enter %s\n", __func__);
if (cmd->msg_len > 8)
return -EINVAL;
@@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
/* restore original settings */
s5h1420_writereg(state, 0x3b, val);
msleep(15);
+ dprintk("leave %s\n", __func__);
return result;
}
@@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
struct s5h1420_state* state = fe->demodulator_priv;
u8 val;
+ dprintk("enter %s\n", __func__);
+
if (status == NULL)
return -EINVAL;
@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
the inversion, wait a bit and check again */
- if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
- val = s5h1420_readreg(state, 0x32);
+ if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
+ val = s5h1420_readreg(state, Vit10);
if ((val & 0x07) == 0x03) {
if (val & 0x08)
- s5h1420_writereg(state, 0x31, 0x13);
+ s5h1420_writereg(state, Vit09, 0x13);
else
- s5h1420_writereg(state, 0x31, 0x1b);
+ s5h1420_writereg(state, Vit09, 0x1b);
/* wait a bit then update lock status */
mdelay(200);
@@ -312,68 +355,77 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
/* perform post lock setup */
- if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
+ if ((*status & FE_HAS_LOCK) && !state->postlocked) {
/* calculate the data rate */
u32 tmp = s5h1420_getsymbolrate(state);
- switch(s5h1420_readreg(state, 0x32) & 0x07) {
- case 0:
- tmp = (tmp * 2 * 1) / 2;
- break;
-
- case 1:
- tmp = (tmp * 2 * 2) / 3;
- break;
-
- case 2:
- tmp = (tmp * 2 * 3) / 4;
- break;
-
- case 3:
- tmp = (tmp * 2 * 5) / 6;
- break;
-
- case 4:
- tmp = (tmp * 2 * 6) / 7;
- break;
-
- case 5:
- tmp = (tmp * 2 * 7) / 8;
- break;
+ switch (s5h1420_readreg(state, Vit10) & 0x07) {
+ case 0: tmp = (tmp * 2 * 1) / 2; break;
+ case 1: tmp = (tmp * 2 * 2) / 3; break;
+ case 2: tmp = (tmp * 2 * 3) / 4; break;
+ case 3: tmp = (tmp * 2 * 5) / 6; break;
+ case 4: tmp = (tmp * 2 * 6) / 7; break;
+ case 5: tmp = (tmp * 2 * 7) / 8; break;
}
+
if (tmp == 0) {
- printk("s5h1420: avoided division by 0\n");
+ printk(KERN_ERR "s5h1420: avoided division by 0\n");
tmp = 1;
}
tmp = state->fclk / tmp;
+
/* set the MPEG_CLK_INTL for the calculated data rate */
- if (tmp < 4)
+ if (tmp < 2)
val = 0x00;
- else if (tmp < 8)
+ else if (tmp < 5)
val = 0x01;
- else if (tmp < 12)
+ else if (tmp < 9)
val = 0x02;
- else if (tmp < 16)
+ else if (tmp < 13)
val = 0x03;
- else if (tmp < 24)
+ else if (tmp < 17)
val = 0x04;
- else if (tmp < 32)
+ else if (tmp < 25)
val = 0x05;
- else
+ else if (tmp < 33)
val = 0x06;
- s5h1420_writereg(state, 0x22, val);
-
- /* DC freeze */
- s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
-
- /* kicker disable + remove DC offset */
- s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
+ else
+ val = 0x07;
+ dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
+
+ s5h1420_writereg(state, FEC01, 0x18);
+ s5h1420_writereg(state, FEC01, 0x10);
+ s5h1420_writereg(state, FEC01, val);
+
+ /* Enable "MPEG_Out" */
+ val = s5h1420_readreg(state, Mpeg02);
+ s5h1420_writereg(state, Mpeg02, val | (1 << 6));
+
+ /* kicker disable */
+ val = s5h1420_readreg(state, QPSK01) & 0x7f;
+ s5h1420_writereg(state, QPSK01, val);
+
+ /* DC freeze TODO it was never activated by default or it can stay activated */
+#if 0
+ val = s5h1420_readreg(state, 0x1f);
+ s5h1420_writereg(state, 0x1f, val | 0x01);
+#endif
+
+ if (s5h1420_getsymbolrate(state) >= 20000000) {
+ s5h1420_writereg(state, Loop04, 0x8a);
+ s5h1420_writereg(state, Loop05, 0x6a);
+ } else {
+ s5h1420_writereg(state, Loop04, 0x58);
+ s5h1420_writereg(state, Loop05, 0x27);
+ }
/* post-lock processing has been done! */
state->postlocked = 1;
}
+ dprintk("leave %s\n", __func__);
+
return 0;
}
@@ -414,6 +466,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static void s5h1420_reset(struct s5h1420_state* state)
{
+ dprintk("%s\n", __func__);
s5h1420_writereg (state, 0x01, 0x08);
s5h1420_writereg (state, 0x01, 0x00);
udelay(10);
@@ -422,54 +475,79 @@ static void s5h1420_reset(struct s5h1420_state* state)
static void s5h1420_setsymbolrate(struct s5h1420_state* state,
struct dvb_frontend_parameters *p)
{
+ u8 v;
u64 val;
+ dprintk("enter %s\n", __func__);
+
val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
- if (p->u.qpsk.symbol_rate <= 21000000) {
+ if (p->u.qpsk.symbol_rate < 29000000)
val *= 2;
- }
do_div(val, (state->fclk / 1000));
- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
- s5h1420_writereg(state, 0x11, val >> 16);
- s5h1420_writereg(state, 0x12, val >> 8);
- s5h1420_writereg(state, 0x13, val & 0xff);
- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
+ dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
+
+ v = s5h1420_readreg(state, Loop01);
+ s5h1420_writereg(state, Loop01, v & 0x7f);
+ s5h1420_writereg(state, Tnco01, val >> 16);
+ s5h1420_writereg(state, Tnco02, val >> 8);
+ s5h1420_writereg(state, Tnco03, val & 0xff);
+ s5h1420_writereg(state, Loop01, v | 0x80);
+ dprintk("leave %s\n", __func__);
}
static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
{
+#if 0
+ /* TODO getsymbolrate gives strange values - something is wrong with
+ * configuring the read
+ */
+
u64 val = 0;
+ u8 v;
int sampling = 2;
- if (s5h1420_readreg(state, 0x05) & 0x2)
- sampling = 1;
+ v = s5h1420_readreg(state, QPSK02);
+ s5h1420_writereg(state, QPSK02, v | 0x08);
+ val = s5h1420_readreg(state, Tnco01) << 16;
+ val |= s5h1420_readreg(state, Tnco02) << 8;
+ val |= s5h1420_readreg(state, Tnco03);
+ s5h1420_writereg(state, QPSK02, v & 0xf7);
- s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
- val = s5h1420_readreg(state, 0x11) << 16;
- val |= s5h1420_readreg(state, 0x12) << 8;
- val |= s5h1420_readreg(state, 0x13);
- s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+ dprintk("get_symbolrate: raw: %x\n", val);
- val *= (state->fclk / 1000ULL);
- do_div(val, ((1<<24) * sampling));
+ val *= (state->fclk / 1000);
+ if (s5h1420_readreg(state, QPSK01) & 0x2)
+ do_div(val, 1 << 24);
+ else
+ do_div(val, 1 << 25);
+ dprintk("get_symbolrate: %d\n", (u32) (val * 1000ULL));
return (u32) (val * 1000ULL);
+#endif
+ return state->symbol_rate;
}
static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
{
int val;
+ u8 v;
+
+ dprintk("enter %s\n", __func__);
/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
* divide fclk by 1000000 to get the correct value. */
val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
- s5h1420_writereg(state, 0x0e, val >> 16);
- s5h1420_writereg(state, 0x0f, val >> 8);
- s5h1420_writereg(state, 0x10, val & 0xff);
- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
+ dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
+
+ v = s5h1420_readreg(state, Loop01);
+ s5h1420_writereg(state, Loop01, v & 0xbf);
+ s5h1420_writereg(state, Pnco01, val >> 16);
+ s5h1420_writereg(state, Pnco02, val >> 8);
+ s5h1420_writereg(state, Pnco03, val & 0xff);
+ s5h1420_writereg(state, Loop01, v | 0x40);
+ dprintk("leave %s\n", __func__);
}
static int s5h1420_getfreqoffset(struct s5h1420_state* state)
@@ -496,52 +574,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
struct dvb_frontend_parameters *p)
{
u8 inversion = 0;
+ u8 vit08, vit09;
+
+ dprintk("enter %s\n", __func__);
- if (p->inversion == INVERSION_OFF) {
+ if (p->inversion == INVERSION_OFF)
inversion = state->config->invert ? 0x08 : 0;
- } else if (p->inversion == INVERSION_ON) {
+ else if (p->inversion == INVERSION_ON)
inversion = state->config->invert ? 0 : 0x08;
- }
if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
- s5h1420_writereg(state, 0x30, 0x3f);
- s5h1420_writereg(state, 0x31, 0x00 | inversion);
+ vit08 = 0x3f;
+ vit09 = 0;
} else {
switch(p->u.qpsk.fec_inner) {
case FEC_1_2:
- s5h1420_writereg(state, 0x30, 0x01);
- s5h1420_writereg(state, 0x31, 0x10 | inversion);
+ vit08 = 0x01; vit09 = 0x10;
break;
case FEC_2_3:
- s5h1420_writereg(state, 0x30, 0x02);
- s5h1420_writereg(state, 0x31, 0x11 | inversion);
+ vit08 = 0x02; vit09 = 0x11;
break;
case FEC_3_4:
- s5h1420_writereg(state, 0x30, 0x04);
- s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ vit08 = 0x04; vit09 = 0x12;
break;
case FEC_5_6:
- s5h1420_writereg(state, 0x30, 0x08);
- s5h1420_writereg(state, 0x31, 0x13 | inversion);
+ vit08 = 0x08; vit09 = 0x13;
break;
case FEC_6_7:
- s5h1420_writereg(state, 0x30, 0x10);
- s5h1420_writereg(state, 0x31, 0x14 | inversion);
+ vit08 = 0x10; vit09 = 0x14;
break;
case FEC_7_8:
- s5h1420_writereg(state, 0x30, 0x20);
- s5h1420_writereg(state, 0x31, 0x15 | inversion);
+ vit08 = 0x20; vit09 = 0x15;
break;
default:
return;
}
}
+ vit09 |= inversion;
+ dprintk("fec: %02x %02x\n", vit08, vit09);
+ s5h1420_writereg(state, Vit08, vit08);
+ s5h1420_writereg(state, Vit09, vit09);
+ dprintk("leave %s\n", __func__);
}
static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
@@ -583,16 +662,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
struct s5h1420_state* state = fe->demodulator_priv;
int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
+ uint8_t clock_settting;
+
+ dprintk("enter %s\n", __func__);
/* check if we should do a fast-tune */
memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
s5h1420_get_tune_settings(fe, &fesettings);
frequency_delta = p->frequency - state->tunedfreq;
if ((frequency_delta > -fesettings.max_drift) &&
- (frequency_delta < fesettings.max_drift) &&
- (frequency_delta != 0) &&
- (state->fec_inner == p->u.qpsk.fec_inner) &&
- (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+ (frequency_delta < fesettings.max_drift) &&
+ (frequency_delta != 0) &&
+ (state->fec_inner == p->u.qpsk.fec_inner) &&
+ (state->symbol_rate == p->u.qpsk.symbol_rate)) {
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
@@ -606,54 +688,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
} else {
s5h1420_setfreqoffset(state, 0);
}
+ dprintk("simple tune\n");
return 0;
}
+ dprintk("tuning demod\n");
/* first of all, software reset */
s5h1420_reset(state);
/* set s5h1420 fclk PLL according to desired symbol rate */
- if (p->u.qpsk.symbol_rate > 28000000) {
- state->fclk = 88000000;
- s5h1420_writereg(state, 0x03, 0x50);
- s5h1420_writereg(state, 0x04, 0x40);
- s5h1420_writereg(state, 0x05, 0xae);
- } else if (p->u.qpsk.symbol_rate > 21000000) {
+ if (p->u.qpsk.symbol_rate > 33000000)
+ state->fclk = 80000000;
+ else if (p->u.qpsk.symbol_rate > 28500000)
state->fclk = 59000000;
- s5h1420_writereg(state, 0x03, 0x33);
- s5h1420_writereg(state, 0x04, 0x40);
- s5h1420_writereg(state, 0x05, 0xae);
- } else {
+ else if (p->u.qpsk.symbol_rate > 25000000)
+ state->fclk = 86000000;
+ else if (p->u.qpsk.symbol_rate > 1900000)
state->fclk = 88000000;
- s5h1420_writereg(state, 0x03, 0x50);
- s5h1420_writereg(state, 0x04, 0x40);
- s5h1420_writereg(state, 0x05, 0xac);
+ else
+ state->fclk = 44000000;
+
+ /* Clock */
+ switch (state->fclk) {
+ default:
+ case 88000000:
+ clock_settting = 80;
+ break;
+ case 86000000:
+ clock_settting = 78;
+ break;
+ case 80000000:
+ clock_settting = 72;
+ break;
+ case 59000000:
+ clock_settting = 51;
+ break;
+ case 44000000:
+ clock_settting = 36;
+ break;
}
+ dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+ s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
+ s5h1420_writereg(state, PLL02, 0x40);
+ s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
- /* set misc registers */
- s5h1420_writereg(state, 0x02, 0x00);
- s5h1420_writereg(state, 0x06, 0x00);
- s5h1420_writereg(state, 0x07, 0xb0);
- s5h1420_writereg(state, 0x0a, 0xe7);
- s5h1420_writereg(state, 0x0b, 0x78);
- s5h1420_writereg(state, 0x0c, 0x48);
- s5h1420_writereg(state, 0x0d, 0x6b);
- s5h1420_writereg(state, 0x2e, 0x8e);
- s5h1420_writereg(state, 0x35, 0x33);
- s5h1420_writereg(state, 0x38, 0x01);
- s5h1420_writereg(state, 0x39, 0x7d);
- s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
- s5h1420_writereg(state, 0x3c, 0x00);
- s5h1420_writereg(state, 0x45, 0x61);
- s5h1420_writereg(state, 0x46, 0x1d);
+ /* TODO DC offset removal, config parameter ? */
+ if (p->u.qpsk.symbol_rate > 29000000)
+ s5h1420_writereg(state, QPSK01, 0xae | 0x10);
+ else
+ s5h1420_writereg(state, QPSK01, 0xac | 0x10);
- /* start QPSK */
- s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
+ /* set misc registers */
+ s5h1420_writereg(state, CON_1, 0x00);
+ s5h1420_writereg(state, QPSK02, 0x00);
+ s5h1420_writereg(state, Pre01, 0xb0);
+
+ s5h1420_writereg(state, Loop01, 0xF0);
+ s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
+ s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
+ if (p->u.qpsk.symbol_rate > 20000000)
+ s5h1420_writereg(state, Loop04, 0x79);
+ else
+ s5h1420_writereg(state, Loop04, 0x58);
+ s5h1420_writereg(state, Loop05, 0x6b);
+
+ if (p->u.qpsk.symbol_rate >= 8000000)
+ s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
+ else if (p->u.qpsk.symbol_rate >= 4000000)
+ s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
+ else
+ s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
+
+ s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
+
+ s5h1420_writereg(state, Sync01, 0x33);
+ s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
+ s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
+ s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
+
+ s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
+ s5h1420_writereg(state, DiS03, 0x00);
+ s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
/* set tuner PLL */
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
s5h1420_setfreqoffset(state, 0);
}
@@ -661,10 +782,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
s5h1420_setsymbolrate(state, p);
s5h1420_setfec_inversion(state, p);
+ /* start QPSK */
+ s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
+
state->fec_inner = p->u.qpsk.fec_inner;
state->symbol_rate = p->u.qpsk.symbol_rate;
state->postlocked = 0;
state->tunedfreq = p->frequency;
+
+ dprintk("leave %s\n", __func__);
return 0;
}
@@ -717,11 +843,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct s5h1420_state* state = fe->demodulator_priv;
- if (enable) {
- return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- } else {
- return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
- }
+ if (enable)
+ return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
+ else
+ return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
}
static int s5h1420_init (struct dvb_frontend* fe)
@@ -729,7 +854,8 @@ static int s5h1420_init (struct dvb_frontend* fe)
struct s5h1420_state* state = fe->demodulator_priv;
/* disable power down and do reset */
- s5h1420_writereg(state, 0x02, 0x10);
+ state->CON_1_val = 0x10;
+ s5h1420_writereg(state, 0x02, state->CON_1_val);
msleep(10);
s5h1420_reset(state);
@@ -739,26 +865,60 @@ static int s5h1420_init (struct dvb_frontend* fe)
static int s5h1420_sleep(struct dvb_frontend* fe)
{
struct s5h1420_state* state = fe->demodulator_priv;
-
- return s5h1420_writereg(state, 0x02, 0x12);
+ state->CON_1_val = 0x12;
+ return s5h1420_writereg(state, 0x02, state->CON_1_val);
}
static void s5h1420_release(struct dvb_frontend* fe)
{
struct s5h1420_state* state = fe->demodulator_priv;
+ i2c_del_adapter(&state->tuner_i2c_adapter);
kfree(state);
}
-static struct dvb_frontend_ops s5h1420_ops;
+static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+ struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
+ struct i2c_msg m[1 + num];
+ u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
+
+ memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
+
+ m[0].addr = state->config->demod_address;
+ m[0].buf = tx_open;
+ m[0].len = 2;
+
+ memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
- struct i2c_adapter* i2c)
+ return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
+ .master_xfer = s5h1420_tuner_i2c_tuner_xfer,
+ .functionality = s5h1420_tuner_i2c_func,
+};
+
+struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
- struct s5h1420_state* state = NULL;
- u8 identity;
+ struct s5h1420_state *state = fe->demodulator_priv;
+ return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops s5h1420_ops;
+struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+ struct i2c_adapter *i2c)
+{
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+ struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+ u8 i;
+
if (state == NULL)
goto error;
@@ -772,24 +932,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
state->symbol_rate = 0;
/* check if the demod is there + identify it */
- identity = s5h1420_readreg(state, 0x00);
- if (identity != 0x03)
+ i = s5h1420_readreg(state, ID01);
+ if (i != 0x03)
goto error;
+ memset(state->shadow, 0xff, sizeof(state->shadow));
+
+ for (i = 0; i < 0x50; i++)
+ state->shadow[i] = s5h1420_readreg(state, i);
+
/* create dvb_frontend */
memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
+
+ /* create tuner i2c adapter */
+ strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
+ state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL,
+ state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo;
+ state->tuner_i2c_adapter.algo_data = NULL;
+ i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+ if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+ printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
+ goto error;
+ }
+
return &state->frontend;
error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(s5h1420_attach);
static struct dvb_frontend_ops s5h1420_ops = {
.info = {
- .name = "Samsung S5H1420 DVB-S",
+ .name = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
.type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
@@ -826,10 +1004,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
.set_voltage = s5h1420_set_voltage,
};
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
-MODULE_AUTHOR("Andrew de Quincey");
+MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(s5h1420_attach);
diff --git a/linux/drivers/media/dvb/frontends/s5h1420.h b/linux/drivers/media/dvb/frontends/s5h1420.h
index 1555870f7..4c913f142 100644
--- a/linux/drivers/media/dvb/frontends/s5h1420.h
+++ b/linux/drivers/media/dvb/frontends/s5h1420.h
@@ -1,25 +1,26 @@
/*
- Driver for S5H1420 QPSK Demodulators
-
- Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
+ * Driver for
+ * Samsung S5H1420 and
+ * PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef S5H1420_H
#define S5H1420_H
@@ -31,17 +32,26 @@ struct s5h1420_config
u8 demod_address;
/* does the inversion require inversion? */
- u8 invert:1;
+ u8 invert : 1;
+
+ u8 repeated_start_workaround : 1;
+ u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
};
#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
- struct i2c_adapter* i2c);
+extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+ struct i2c_adapter *i2c);
+extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
#else
-static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_S5H1420
diff --git a/linux/drivers/media/dvb/frontends/s5h1420_priv.h b/linux/drivers/media/dvb/frontends/s5h1420_priv.h
new file mode 100644
index 000000000..7962bbfb6
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s5h1420_priv.h
@@ -0,0 +1,380 @@
+/*
+ * Driver for
+ * Samsung S5H1420 and
+ * PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005 Patrick Boettcher <pb@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
+ * Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef S5H1420_PRIV
+#define S5H1420_PRIV
+
+#include <asm/types.h>
+
+enum s5h1420_register {
+ ID01 = 0x00,
+ CON_0 = 0x01,
+ CON_1 = 0x02,
+ PLL01 = 0x03,
+ PLL02 = 0x04,
+ QPSK01 = 0x05,
+ QPSK02 = 0x06,
+ Pre01 = 0x07,
+ Post01 = 0x08,
+ Loop01 = 0x09,
+ Loop02 = 0x0a,
+ Loop03 = 0x0b,
+ Loop04 = 0x0c,
+ Loop05 = 0x0d,
+ Pnco01 = 0x0e,
+ Pnco02 = 0x0f,
+ Pnco03 = 0x10,
+ Tnco01 = 0x11,
+ Tnco02 = 0x12,
+ Tnco03 = 0x13,
+ Monitor01 = 0x14,
+ Monitor02 = 0x15,
+ Monitor03 = 0x16,
+ Monitor04 = 0x17,
+ Monitor05 = 0x18,
+ Monitor06 = 0x19,
+ Monitor07 = 0x1a,
+ Monitor12 = 0x1f,
+
+ FEC01 = 0x22,
+ Soft01 = 0x23,
+ Soft02 = 0x24,
+ Soft03 = 0x25,
+ Soft04 = 0x26,
+ Soft05 = 0x27,
+ Soft06 = 0x28,
+ Vit01 = 0x29,
+ Vit02 = 0x2a,
+ Vit03 = 0x2b,
+ Vit04 = 0x2c,
+ Vit05 = 0x2d,
+ Vit06 = 0x2e,
+ Vit07 = 0x2f,
+ Vit08 = 0x30,
+ Vit09 = 0x31,
+ Vit10 = 0x32,
+ Vit11 = 0x33,
+ Vit12 = 0x34,
+ Sync01 = 0x35,
+ Sync02 = 0x36,
+ Rs01 = 0x37,
+ Mpeg01 = 0x38,
+ Mpeg02 = 0x39,
+ DiS01 = 0x3a,
+ DiS02 = 0x3b,
+ DiS03 = 0x3c,
+ DiS04 = 0x3d,
+ DiS05 = 0x3e,
+ DiS06 = 0x3f,
+ DiS07 = 0x40,
+ DiS08 = 0x41,
+ DiS09 = 0x42,
+ DiS10 = 0x43,
+ DiS11 = 0x44,
+ Rf01 = 0x45,
+ Err01 = 0x46,
+ Err02 = 0x47,
+ Err03 = 0x48,
+ Err04 = 0x49,
+};
+
+#if 0
+
+regsiter mapping follows
+
+/* ID01 */
+#define PN1010_ID 7, 0
+
+/* CON_0 */
+#define QPSK_ONLY 4, 4
+#define SOFT_RST 3, 3 /* System soft reset mode (active high) [1] Enable [0] Disable */
+#define CLK_MODE 2, 2
+#define BPSK_QPSK 1, 1
+#define DSS_DVB 0, 0 /* DSS/DVB mode selection [1] DSS [0] DVB */
+
+/* CON_1 */
+#define ADC_SPD 6, 6
+#define PLL_OEN 5, 5
+#define SER_SEL 4, 4
+#define XTAL_OEN 3, 3
+#define Q_TEST 2, 2
+#define PWR_DN 1, 1 /* Power down mode [1] Power down enable, [0] Power down disable */
+#define I2C_RPT 0, 0 /* I2C repeater control [1] I2C repeater enable, [0] I2C repeater disable.
+ * Note: The master should be set this bit to "1" in order to interface with the tuner.
+ * When the master is not communicated with the tuner, this bit should be set to "0" */
+
+/* PLL programming information
+ * Fout = ((M+8)*Fin)/((P+2)*2^S), Fin = 4 MHz */
+/* PLL01 */
+#define M 7, 0
+
+/* PLL02 */
+#define P 5, 0
+#define S 7, 6
+
+/* QPSK01 */
+#define KICK_EN 7, 7 /* [1] PLL Kicker enable [0] Disable */
+#define ROLL_OFF 6, 6
+#define SCALE_EN 5, 5
+#define DC_EN 4, 4 /* DC offset remove [1] Enable [0] Disable */
+#define VMODE 3, 3
+#define TGL_MSB 2, 2
+#define MODE_QPSK 1, 1 /* QPSK operation mode [1] 1 sampling/1 symbol [0] 2 sampling/1 symbol */
+#define Q_SRESET_N 0, 0 /* QPSK start signal [1] Start [0] Idle */
+
+/* QPSK02 */
+#define DUMP_ACC 3, 3 /* Dump phase loop filter & timing loop filter accumulator [0 and then 1]
+ * The read operation enabled, when user set DUMP_ACC "0" and then "1". */
+#define DC_WIN 2, 0 /* Window position from MSB (0 <= DC_WIN <= 7) */
+
+/* AGC Controls */
+/* Pre01 */
+#define PRE_TH 4, 0 /* PRE-AGC threshold */
+#define INV_PULSE 7, 7 /* PWM signal is reversed [1] PWM signal active low [0] PWM signal active high */
+
+/* Post01 */
+#define RRC_SCALE 7, 6
+#define POST_TH 5, 0 /* POST-AGC threshold */
+
+/* Loop Controls */
+/* Loop01 */
+#define WT_TNCO 7, 7 /* Write TNCO center frequency [0 and then 1] The write operation enabled, when user set WT_TNCO "0" and then "1" */
+#define WT_PNCO 6, 6 /* Write PNCO center frequency [0 and then 1] The write operation enabled, when user set WT_PNCO "0" and then "1" */
+
+/* Loop02 */
+#define LOOP_OUT 7, 7 /* Loop filter monitoring selection [1] Loop filter accumulator + NCO [0] Loop filter accumulator */
+#define KICK_VAL 6, 4 /* The value that gets injected into the accumulator when a "kick" is needed. */
+#define KICK_MUL 3, 0 /* The number of bits KICK_VAL is up-shifted (2^N) before it is injected into the accumulator. */
+
+/* Loop03 */
+#define IGA_PLF 7, 4 /* Phase loop, integral gain (2^IGA_PLF) in the acquisition mode */
+#define PGA_PLF 3, 0 /* Phase loop, proportional gain (2^PGA_PLF) in the acquisition mode (default +8 added) */
+
+/* Loop04 */
+#define IGT_PLF 7, 4 /* Integral gain in the tracking mode */
+#define PGT_PLF 3, 0 /* Phase loop, proportional gain in the tracking mode (default +8 added) */
+
+/* Loop 05 */
+#define IG_TLF 7, 4 /* Timing loop, integral gain */
+#define PG_TLF 3, 0 /* Timing loop, proportional gain (default +8 added) */
+
+/* NCO controls
+ * LOOP_OUT [1] Read PLF accumulator + PNCO, LOOP_OUT [0] Read PLF accumulator */
+/* Pnco01 */
+#define PNCO0 7, 0
+/* Pnco02 */
+#define PNCO1 7, 0
+/* Pnco03 */
+#define PNCO2 7, 0
+
+/* LOOP_OUT [1], Read TLF accumulator + TNCO, LOOP_OUT [0], Read TLF accumulator */
+/* Tnco01 */
+#define TNCO0 7, 0
+/* Tnco02 */
+#define TNCO1 7, 0
+/* Tnco03 */
+#define TNCO2 7, 0
+
+/* Monitor01 */
+#define A_SCL 3, 3
+#define TLOCK 1, 1 /* Timing loop lock (Symbol sync) [1] Timing loop has locked [0] Timing loop has not locked */
+#define PLOCK 0, 0 /* Phase loop lock (Carrier sync) [1] Phase loop has locked [0] Phase loop has not locked */
+
+/* Monitor02 */
+#define PRE_LEVEL 7, 0 /* PRE-AGC gain level */
+
+/* Monitor03 */
+#define POST_LEVEL 7, 0 /* POST-AGC gain level */
+
+/* Monitor04 */
+#define DC_I_LEVEL 7, 0 /* DC offset of I samples */
+
+/* Monitor05 */
+#define DC_Q_LEVEL 7, 0 /* DC offset of Q samples */
+
+/* Monitor06 */
+#define PLOCK_CNT 7, 0
+
+/* Monitor07 */
+#define TLOCK_CNT 7, 0
+
+/* Monitor12 */
+#define QPSK_OUT 6, 1 /* QPSK output monitoring */
+#define DC_FREEZE 0, 0 /* [1] Do not update DC_OFFSET */
+
+/* FEC Block */
+/* FEC01 */
+#define DERAND_BPAS 6, 6
+#define RS_BPAS 5, 5
+#define FEC_SRST_CNTL 4, 4
+#define FEC_SRESET 3, 3
+#define MPEG_CLK_INTL 2, 0
+ /* Tmp=(FMClk/FSR) x (1 / (2xCR)); FMClk: System Clock Frequency, FSR: Symbol Rate, CR: Code Rate
+ * 0: 1 < Tmp <= 2, 4: 13 < Tmp <= 17,
+ * 1: 2 < Tmp <= 5, 5: 17 < Tmp <= 25,
+ * 2: 5 < Tmp <= 9, 6: 25 < Tmp <= 33,
+ * 3: 9 < Tmp <= 13, 7: 33 < Tmp */
+
+/* Soft01 */
+#define ST_VAL_R12 2, 0
+#define STEP_R12 5, 3
+#define STEP_R23 5, 3
+#define STEP_R34 5, 3
+#define STEP_R56 5, 3
+#define STEP_R67 5, 3
+#define STEP_R78 5, 3
+/* Soft02 */
+#define ST_VAL_R23 7, 0
+/* Soft03 */
+#define ST_VAL_R34 7, 0
+/* Soft04 */
+#define ST_VAL_R56 7, 0
+/* Soft05 */
+#define ST_VAL_R67 7, 0
+/* Soft06 */
+#define ST_VAL_R78 7, 0
+
+/* Vit01 */
+#define RENORM_R12 7, 0
+/* Vit02 */
+#define RENORM_R23 7, 0
+/* Vit03 */
+#define RENORM_R34 7, 0
+/* Vit04 */
+#define RENORM_R56 7, 0
+/* Vit05 */
+#define RENORM_R67 7, 0
+/* Vit06 */
+#define RENORM_R78 7, 0
+/* Vit07 */
+#define RENORM_PRD 7, 0
+
+/* Vit08 */
+#define VIT_IN_SR78 7, 7
+#define VIT_IN_SR34 6, 6
+#define VIT_SR78 5, 5
+#define VIT_SR67 4, 4
+#define VIT_SR56 3, 3
+#define VIT_SR34 2, 2
+#define VIT_SR23 1, 1 /* .... */
+#define VIT_SR12 0, 0 /* Include CR 1/2 in search */
+
+/* Vit09 */
+#define PARM_FIX 4, 4 /* Parameter fix mode: [1] Known parameter [0] Unknown parameter */
+#define VIT_INV_SPECPARM_FIX 3, 3 /* Initial spectrum information */
+#define VIT_FR 2, 0 /* Start synchronization search at code rate as follows */
+ #define VIT_CR_12 0x00
+ #define VIT_CR_23 0x01
+ #define VIT_CR_34 0x02
+ #define VIT_CR_56 0x03
+ #define VIT_CR_67 0x04
+ #define VIT_CR_78 0x05
+
+/* Vit10 */
+#define INV_SPEC_STS 3, 3 /* Spectrum information monitoring [1] Inv spectrum [0] Not inv spectrum */
+#define VIT_CR 2, 0 /* Viterbi decoder current code rate [0] R=1/2 [1] R=2/3 [2] R=3/4 [3] R=5/6 [4] R=6/7 [5] R=7/8 */
+
+/* Vit11 */
+#define VIT_CER 7, 0
+
+/* Vit12 */
+#define RENORM_RAT 7, 0
+
+/* Sync01 */
+#define SYNC_MISS_TH 7, 4 /* Sync byte detector?s miss threshold */
+#define SYNC_HIT_TH 3, 0 /* Sync byte detector?s hit threshold This value should be greater than 2 */
+
+/* Sync02 */
+#define BYTE_SYNC 5, 5 /* [1] Acquire byte sync [0] Not acquire byte sync */
+#define SYNC_BYTE_STS 4, 2
+#define VIT_SRCH_STS 1, 1
+#define VIT_SYNC 0, 0 /* [1] Viterbi decoder is in sync [0] Viterbi decoder is out of sync */
+
+/* Rs01 */
+#define RS_ERR 3, 0
+#define PKT_ERR 4, 4
+
+/* Mpeg01 */
+#define ERR_POL 3, 3 /* Packet error polarity [1] Active low [0] Active high */
+#define SYNC_POL 2, 2 /* Sync polarity [1] Active low [0] Active high */
+#define VALID_POL 1, 1 /* Data valid polarity [1] Active low [0] Active high */
+#define CDCLK_POL 0, 0 /* CDCLK polarity [1] Falling edge event [0] Rising edge event */
+
+/* Mpeg02 */
+#define MPEG_OEN 6, 6
+#define DOUT_CONT 5, 5
+#define ERR_CONT 4, 4
+#define CLK_CONT 3, 3 /* Clock continuous mode [1] Continuous clock, [0] Clock is enable during payload data transfer */
+#define ENVELOPE 2, 2
+#define SER_PAR 1, 1 /* Serial / Parallel mode [1] Serial mode, [0] Parallel mode */
+#define DSS_SYNC 0, 0 /* DSS sync mode [1] Output sync, [0] No output sync */
+
+/* DiS01 */
+#define TONE_FREQ 7, 0 /* Tone frequency ratio ftone = fclk / (TONE_FREQ x 32) */
+
+/* DiS02 */
+#define RCV_EN 7, 7 /* DiSEqC receive enable mode [1] Receive enable [0] Receive disable */
+#define DIS_LENGTH 6, 4 /* Message length */
+#define DIS_RDY 3, 3 /* Data Transfer ready / finish [1] Ready [0] Finish */
+#define SWITCH_CON 2, 2 /* Satellite switch in tone burst mode [1] Satellite B [0] Satellite A */
+#define LNB_CON 1, 0 /* LNB control mode, [0] Continuous mode, [1] Tone burst mode, [2] DiSEqC mode, [3] Reserved */
+
+/* DiS03 */
+#define OLF_N 2, 2 /* [1] Disable [0] OLF (active low) */
+#define LNB_DN 1, 1 /* [1] LNB down [0] Disable (active high) */
+#define V18_13V 0, 0 /* 13V/18V select register (0=13V, 1=18V) */
+
+/* DiS04 .. DiS11*/
+#define LNB_MESGE0 7, 0
+#define LNB_MESGE1 7, 0
+#define LNB_MESGE2 7, 0
+#define LNB_MESGE3 7, 0
+#define LNB_MESGE4 7, 0
+#define LNB_MESGE5 7, 0
+#define LNB_MESGE6 7, 0
+#define LNB_MESGE7 7, 0
+
+/* Rf01 */
+#define SLAVE_ADDR 6, 0 /* RF tuner slave Address (SOC VERSION) */
+
+/* Err01 */
+#define ALARM_MODE 4, 4
+#define ERR_CNT_PRD 3, 2
+#define ERR_SRC 1, 0 /* Error monitoring source */
+ #define QPSK_BIT_ERRORS 0x0
+ #define VITERBI_BIT_ERRORS 0x1
+ #define VITERBI_BYTE_ERRORS 0x2
+ #define PACKET_ERRORS 0x3
+
+/* Err02 */
+#define ERR_CNT_L 7, 0 /* Error counter value register (LSB 8 bits) */
+
+/* Err03 */
+#define ERR_CNT_H 7, 0 /* Error counter value register (MSB 8 bits) */
+
+/* Err04 */
+#define PARITY_ERR 7, 0 /* Error flag for DiSEqC receive data */
+
+#endif
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c
index f5b3bfc00..aa78aa14a 100644
--- a/linux/drivers/media/dvb/frontends/sp8870.c
+++ b/linux/drivers/media/dvb/frontends/sp8870.c
@@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
int err;
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
return -EREMOTEIO;
}
@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2) {
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
return -1;
}
@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
int tx_len;
int err = 0;
- dprintk ("%s: ...\n", __FUNCTION__);
+ dprintk ("%s: ...\n", __func__);
if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
return -EINVAL;
@@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
msg.buf = tx_buf;
msg.len = tx_len + 2;
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- printk("%s: firmware upload failed!\n", __FUNCTION__);
- printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+ printk("%s: firmware upload failed!\n", __func__);
+ printk ("%s: i2c error (err == %i)\n", __func__, err);
return err;
}
fw_pos += tx_len;
}
- dprintk ("%s: done!\n", __FUNCTION__);
+ dprintk ("%s: done!\n", __func__);
return 0;
};
@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
if (state->initialised) return 0;
state->initialised = 1;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
/* request the firmware, this will block until someone uploads it */
@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
int trials = 0;
int check_count = 0;
- dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
+ dprintk("%s: frequency = %i\n", __func__, p->frequency);
for (trials = 1; trials <= MAXTRIALS; trials++) {
@@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
valid = sp8870_read_data_valid_signal(state);
if (valid) {
dprintk("%s: delay = %i usec\n",
- __FUNCTION__, check_count * 10);
+ __func__, check_count * 10);
break;
}
udelay(10);
@@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
}
if (!valid) {
- printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
+ printk("%s: firmware crash!!!!!!\n", __func__);
return -EIO;
}
if (debug) {
if (valid) {
if (trials > 1) {
- printk("%s: firmware lockup!!!\n", __FUNCTION__);
- printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
+ printk("%s: firmware lockup!!!\n", __func__);
+ printk("%s: recovered after %i trial(s))\n", __func__, trials - 1);
lockups++;
}
}
switches++;
- printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
+ printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
}
return 0;
diff --git a/linux/drivers/media/dvb/frontends/sp8870.h b/linux/drivers/media/dvb/frontends/sp8870.h
index 909cefe71..a764a793c 100644
--- a/linux/drivers/media/dvb/frontends/sp8870.h
+++ b/linux/drivers/media/dvb/frontends/sp8870.h
@@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_SP8870
diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c
index 1aa2539f5..49f55877f 100644
--- a/linux/drivers/media/dvb/frontends/sp887x.c
+++ b/linux/drivers/media/dvb/frontends/sp887x.c
@@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk ("%s: i2c write error (addr %02x, err == %i)\n",
- __FUNCTION__, state->config->demod_address, err);
+ __func__, state->config->demod_address, err);
return -EREMOTEIO;
}
@@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
{
printk("%s: writereg error "
"(reg %03x, data %03x, ret == %i)\n",
- __FUNCTION__, reg & 0xffff, data & 0xffff, ret);
+ __func__, reg & 0xffff, data & 0xffff, ret);
return ret;
}
}
@@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ printk("%s: readreg error (ret == %i)\n", __func__, ret);
return -1;
}
@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
static void sp887x_microcontroller_stop (struct sp887x_state* state)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
sp887x_writereg(state, 0xf08, 0x000);
sp887x_writereg(state, 0xf09, 0x000);
@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
static void sp887x_microcontroller_start (struct sp887x_state* state)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
sp887x_writereg(state, 0xf08, 0x000);
sp887x_writereg(state, 0xf09, 0x000);
@@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state)
static void sp887x_setup_agc (struct sp887x_state* state)
{
/* setup AGC parameters */
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
sp887x_writereg(state, 0x33c, 0x054);
sp887x_writereg(state, 0x33b, 0x04c);
sp887x_writereg(state, 0x328, 0x000);
@@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
int fw_size = fw->size;
unsigned char *mem = fw->data;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
if (fw_size < FW_SIZE+10)
@@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
sp887x_microcontroller_stop (state);
- printk ("%s: firmware upload... ", __FUNCTION__);
+ printk ("%s: firmware upload... ", __func__);
/* setup write pointer to -1 (end of memory) */
/* bit 0x8000 in address is set to enable 13bit mode */
@@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
printk ("failed.\n");
- printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+ printk ("%s: i2c error (err == %i)\n", __func__, err);
return err;
}
}
diff --git a/linux/drivers/media/dvb/frontends/sp887x.h b/linux/drivers/media/dvb/frontends/sp887x.h
index 7ee78d7d9..04eff6e0e 100644
--- a/linux/drivers/media/dvb/frontends/sp887x.h
+++ b/linux/drivers/media/dvb/frontends/sp887x.h
@@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_SP887X
diff --git a/linux/drivers/media/dvb/frontends/stv0297.c b/linux/drivers/media/dvb/frontends/stv0297.c
index cd8f74b57..1c5a0ae82 100644
--- a/linux/drivers/media/dvb/frontends/stv0297.c
+++ b/linux/drivers/media/dvb/frontends/stv0297.c
@@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
if (ret != 1)
dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
- "ret == %i)\n", __FUNCTION__, reg, data, ret);
+ "ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
@@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
// this device needs a STOP between the register and data
if (state->config->stop_during_read) {
if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
return -1;
}
if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
return -1;
}
} else {
if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
return -1;
}
}
@@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
// this device needs a STOP between the register and data
if (state->config->stop_during_read) {
if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
return -1;
}
if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
return -1;
}
} else {
if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
return -1;
}
}
diff --git a/linux/drivers/media/dvb/frontends/stv0297.h b/linux/drivers/media/dvb/frontends/stv0297.h
index 69f4515df..3f8f9468f 100644
--- a/linux/drivers/media/dvb/frontends/stv0297.h
+++ b/linux/drivers/media/dvb/frontends/stv0297.h
@@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_STV0297
diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c
index 035dd7ba6..17556183e 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.c
+++ b/linux/drivers/media/dvb/frontends/stv0299.c
@@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
if (ret != 1)
dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
- "ret == %i)\n", __FUNCTION__, reg, data, ret);
+ "ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
if (ret != 2)
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
- __FUNCTION__, reg, ret);
+ __func__, reg, ret);
return b1[0];
}
@@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2)
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
return ret == 2 ? 0 : ret;
}
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
switch (fec) {
case FEC_AUTO:
@@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
FEC_7_8, FEC_1_2 };
u8 index;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
index = stv0299_readreg (state, 0x1b);
index &= 0x7;
@@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
{
unsigned long start = jiffies;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
while (stv0299_readreg(state, 0x0a) & 1) {
if (jiffies - start > timeout) {
- dprintk ("%s: timeout!!\n", __FUNCTION__);
+ dprintk ("%s: timeout!!\n", __func__);
return -ETIMEDOUT;
}
msleep(10);
@@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
{
unsigned long start = jiffies;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
if (jiffies - start > timeout) {
- dprintk ("%s: timeout!!\n", __FUNCTION__);
+ dprintk ("%s: timeout!!\n", __func__);
return -ETIMEDOUT;
}
msleep(10);
@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
u8 sfr[3];
s8 rtf;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
stv0299_readregs (state, 0x1f, sfr, 3);
stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
@@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
offset = (s32) rtf * (srate / 4096L);
offset /= 128;
- dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
- dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
+ dprintk ("%s : srate = %i\n", __func__, srate);
+ dprintk ("%s : ofset = %i\n", __func__, offset);
srate += offset;
@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
u8 val;
int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (stv0299_wait_diseqc_idle (state, 100) < 0)
return -ETIMEDOUT;
@@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
struct stv0299_state* state = fe->demodulator_priv;
u8 val;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (stv0299_wait_diseqc_idle (state, 100) < 0)
return -ETIMEDOUT;
@@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
u8 reg0x08;
u8 reg0x0c;
- dprintk("%s: %s\n", __FUNCTION__,
+ dprintk("%s: %s\n", __func__,
voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
@@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
* H/V switching over OP0, OP1 and OP2 are LNB power enable bits
*/
reg0x0c &= 0x0f;
-
- if (voltage == SEC_VOLTAGE_OFF) {
- stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */
- return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */
- }
-
- stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
+ reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
switch (voltage) {
case SEC_VOLTAGE_13:
- if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10;
- else reg0x0c |= 0x40;
-
- return stv0299_writeregI(state, 0x0c, reg0x0c);
-
+ if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+ reg0x0c |= 0x10; /* OP1 off, OP0 on */
+ else
+ reg0x0c |= 0x40; /* OP1 on, OP0 off */
+ break;
case SEC_VOLTAGE_18:
- return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50);
+ reg0x0c |= 0x50; /* OP1 on, OP0 on */
+ break;
+ case SEC_VOLTAGE_OFF:
+ /* LNB power off! */
+ reg0x08 = 0x00;
+ reg0x0c = 0x00;
+ break;
default:
return -EINVAL;
};
+
+ if (state->config->op0_off)
+ reg0x0c &= ~0x10;
+
+ stv0299_writeregI(state, 0x08, reg0x08);
+ return stv0299_writeregI(state, 0x0c, reg0x0c);
}
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
cmd = cmd << 1;
if (debug_legacy_dish_switch)
- printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
+ printk ("%s switch command: 0x%04lx\n",__func__, cmd);
do_gettimeofday (&nexttime);
if (debug_legacy_dish_switch)
@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
}
if (debug_legacy_dish_switch) {
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
- __FUNCTION__, fe->dvb->num);
+ __func__, fe->dvb->num);
for (i = 1; i < 10; i++)
printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
}
@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
{
struct stv0299_state* state = fe->demodulator_priv;
int i;
+ u8 reg;
+ u8 val;
dprintk("stv0299: init chip\n");
- for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
- stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
+ for (i = 0; ; i += 2) {
+ reg = state->config->inittab[i];
+ val = state->config->inittab[i+1];
+ if (reg == 0xff && val == 0xff)
+ break;
+ if (reg == 0x0c && state->config->op0_off)
+ val &= ~0x10;
+ stv0299_writeregI(state, reg, val);
+ }
return 0;
}
@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
u8 signal = 0xff - stv0299_readreg (state, 0x18);
u8 sync = stv0299_readreg (state, 0x1b);
- dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
+ dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
*status = 0;
if (signal > 10)
@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
| stv0299_readreg (state, 0x19));
- dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
+ dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
stv0299_readreg (state, 0x18),
stv0299_readreg (state, 0x19), (int) signal);
@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
struct stv0299_state* state = fe->demodulator_priv;
int invval = 0;
- dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
+ dprintk ("%s : FE_SET_FRONTEND\n", __func__);
// set the inversion
if (p->inversion == INVERSION_OFF) invval = 0;
diff --git a/linux/drivers/media/dvb/frontends/stv0299.h b/linux/drivers/media/dvb/frontends/stv0299.h
index 33df94959..3282f4302 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.h
+++ b/linux/drivers/media/dvb/frontends/stv0299.h
@@ -48,10 +48,10 @@
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
-#define STV0229_LOCKOUTPUT_0 0
-#define STV0229_LOCKOUTPUT_1 1
-#define STV0229_LOCKOUTPUT_CF 2
-#define STV0229_LOCKOUTPUT_LK 3
+#define STV0299_LOCKOUTPUT_0 0
+#define STV0299_LOCKOUTPUT_1 1
+#define STV0299_LOCKOUTPUT_CF 2
+#define STV0299_LOCKOUTPUT_LK 3
#define STV0299_VOLT13_OP0 0
#define STV0299_VOLT13_OP1 1
@@ -82,6 +82,9 @@ struct stv0299_config
/* Is 13v controlled by OP0 or OP1? */
u8 volt13_op0_op1:1;
+ /* Turn-off OP0? */
+ u8 op0_off:1;
+
/* minimum delay before retuning */
int min_delay_ms;
@@ -96,7 +99,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_STV0299
diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c
index 68a1103c9..c6f90f33a 100644
--- a/linux/drivers/media/dvb/frontends/tda10021.c
+++ b/linux/drivers/media/dvb/frontends/tda10021.c
@@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
if (ret != 1)
printk("DVB: TDA10021(%d): %s, writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+ state->frontend.dvb->num, __func__, reg, data, ret);
msleep(10);
return (ret != 1) ? -EREMOTEIO : 0;
@@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
// Don't print an error message if the id is read.
if (ret != 2 && reg != 0x1a)
printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
- __FUNCTION__, ret);
+ __func__, ret);
return b1[0];
}
diff --git a/linux/drivers/media/dvb/frontends/tda10023.c b/linux/drivers/media/dvb/frontends/tda10023.c
index b565bc2d7..82d6cb5b8 100644
--- a/linux/drivers/media/dvb/frontends/tda10023.c
+++ b/linux/drivers/media/dvb/frontends/tda10023.c
@@ -38,17 +38,24 @@
#include "dvb_frontend.h"
#include "tda1002x.h"
+#define REG0_INIT_VAL 0x23
struct tda10023_state {
struct i2c_adapter* i2c;
/* configuration settings */
- const struct tda1002x_config* config;
+ const struct tda10023_config *config;
struct dvb_frontend frontend;
u8 pwm;
u8 reg0;
-};
+ /* clock settings */
+ u32 xtal;
+ u8 pll_m;
+ u8 pll_p;
+ u8 pll_n;
+ u32 sysclk;
+};
#if 0
#define dprintk(x...) printk(x)
@@ -58,59 +65,6 @@ struct tda10023_state {
static int verbose;
-#define XTAL 28920000UL
-#define PLL_M 8UL
-#define PLL_P 4UL
-#define PLL_N 1UL
-#define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P)) // -> 57840000
-
-static u8 tda10023_inittab[]={
- // reg mask val
- 0x2a,0xff,0x02, // PLL3, Bypass, Power Down
- 0xff,0x64,0x00, // Sleep 100ms
- 0x2a,0xff,0x03, // PLL3, Bypass, Power Down
- 0xff,0x64,0x00, // Sleep 100ms
- 0x28,0xff,PLL_M-1, // PLL1 M=8
- 0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1), // PLL2
- 0x00,0xff,0x23, // GPR FSAMPLING=1
- 0x2a,0xff,0x08, // PLL3 PSACLK=1
- 0xff,0x64,0x00, // Sleep 100ms
- 0x1f,0xff,0x00, // RESET
- 0xff,0x64,0x00, // Sleep 100ms
- 0xe6,0x0c,0x04, // RSCFG_IND
- 0x10,0xc0,0x80, // DECDVBCFG1 PBER=1
-
- 0x0e,0xff,0x82, // GAIN1
- 0x03,0x08,0x08, // CLKCONF DYN=1
- 0x2e,0xbf,0x30, // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0
- 0x01,0xff,0x30, // AGCREF
- 0x1e,0x84,0x84, // CONTROL SACLK_ON=1
- 0x1b,0xff,0xc8, // ADC TWOS=1
- 0x3b,0xff,0xff, // IFMAX
- 0x3c,0xff,0x00, // IFMIN
- 0x34,0xff,0x00, // PWMREF
- 0x35,0xff,0xff, // TUNMAX
- 0x36,0xff,0x00, // TUNMIN
- 0x06,0xff,0x7f, // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 // 0x77
- 0x1c,0x30,0x30, // EQCONF2 STEPALGO=SGNALGO=1
- 0x37,0xff,0xf6, // DELTAF_LSB
- 0x38,0xff,0xff, // DELTAF_MSB
- 0x02,0xff,0x93, // AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3
- 0x2d,0xff,0xf6, // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2
- 0x04,0x10,0x00, // SWRAMP=1
- 0x12,0xff,0xa1, // INTP1 POCLKP=1 FEL=1 MFS=0
- 0x2b,0x01,0xa1, // INTS1
- 0x20,0xff,0x04, // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=?
- 0x2c,0xff,0x0d, // INTP/S TRIP=0 TRIS=0
- 0xc4,0xff,0x00,
- 0xc3,0x30,0x00,
- 0xb5,0xff,0x19, // ERAGC_THD
- 0x00,0x03,0x01, // GPR, CLBS soft reset
- 0x00,0x03,0x03, // GPR, CLBS soft reset
- 0xff,0x64,0x00, // Sleep 100ms
- 0xff,0xff,0xff
-};
-
static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
{
u8 b0 [] = { reg };
@@ -122,7 +76,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
ret = i2c_transfer (state->i2c, msg, 2);
if (ret != 2)
printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
- __FUNCTION__, ret);
+ __func__, ret);
return b1[0];
}
@@ -136,7 +90,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
if (ret != 1)
printk("DVB: TDA10023(%d): %s, writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+ state->frontend.dvb->num, __func__, reg, data, ret);
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -219,30 +173,34 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
s16 SFIL=0;
u16 NDEC = 0;
- if (sr < (u32)(SYSCLK/98.40)) {
+ /* avoid floating point operations multiplying syscloc and divider
+ by 10 */
+ u32 sysclk_x_10 = state->sysclk * 10;
+
+ if (sr < (u32)(sysclk_x_10/984)) {
NDEC=3;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/64.0)) {
+ } else if (sr < (u32)(sysclk_x_10/640)) {
NDEC=3;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/49.2)) {
+ } else if (sr < (u32)(sysclk_x_10/492)) {
NDEC=2;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/32.0)) {
+ } else if (sr < (u32)(sysclk_x_10/320)) {
NDEC=2;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/24.6)) {
+ } else if (sr < (u32)(sysclk_x_10/246)) {
NDEC=1;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/16.0)) {
+ } else if (sr < (u32)(sysclk_x_10/160)) {
NDEC=1;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/12.3)) {
+ } else if (sr < (u32)(sysclk_x_10/123)) {
NDEC=0;
SFIL=1;
}
- BDRI=SYSCLK*16;
+ BDRI = (state->sysclk)*16;
BDRI>>=NDEC;
BDRI +=sr/2;
BDRI /=sr;
@@ -255,11 +213,12 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
BDRX=1<<(24+NDEC);
BDRX*=sr;
- do_div(BDRX,SYSCLK); // BDRX/=SYSCLK;
+ do_div(BDRX, state->sysclk); /* BDRX/=SYSCLK; */
BDR=(s32)BDRX;
}
-// printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC);
+ dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
+ sr, BDR, BDRI, NDEC);
tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
tda10023_writereg (state, 0x0a, BDR&255);
tda10023_writereg (state, 0x0b, (BDR>>8)&255);
@@ -272,8 +231,63 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
static int tda10023_init (struct dvb_frontend *fe)
{
struct tda10023_state* state = fe->demodulator_priv;
+ u8 tda10023_inittab[] = {
+/* reg mask val */
+/* 000 */ 0x2a, 0xff, 0x02, /* PLL3, Bypass, Power Down */
+/* 003 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 006 */ 0x2a, 0xff, 0x03, /* PLL3, Bypass, Power Down */
+/* 009 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+ /* PLL1 */
+/* 012 */ 0x28, 0xff, (state->pll_m-1),
+ /* PLL2 */
+/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
+ /* GPR FSAMPLING=1 */
+/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
+/* 021 */ 0x2a, 0xff, 0x08, /* PLL3 PSACLK=1 */
+/* 024 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 027 */ 0x1f, 0xff, 0x00, /* RESET */
+/* 030 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 033 */ 0xe6, 0x0c, 0x04, /* RSCFG_IND */
+/* 036 */ 0x10, 0xc0, 0x80, /* DECDVBCFG1 PBER=1 */
+
+/* 039 */ 0x0e, 0xff, 0x82, /* GAIN1 */
+/* 042 */ 0x03, 0x08, 0x08, /* CLKCONF DYN=1 */
+/* 045 */ 0x2e, 0xbf, 0x30, /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
+ PPWMTUN=0 PPWMIF=0 */
+/* 048 */ 0x01, 0xff, 0x30, /* AGCREF */
+/* 051 */ 0x1e, 0x84, 0x84, /* CONTROL SACLK_ON=1 */
+/* 054 */ 0x1b, 0xff, 0xc8, /* ADC TWOS=1 */
+/* 057 */ 0x3b, 0xff, 0xff, /* IFMAX */
+/* 060 */ 0x3c, 0xff, 0x00, /* IFMIN */
+/* 063 */ 0x34, 0xff, 0x00, /* PWMREF */
+/* 066 */ 0x35, 0xff, 0xff, /* TUNMAX */
+/* 069 */ 0x36, 0xff, 0x00, /* TUNMIN */
+/* 072 */ 0x06, 0xff, 0x7f, /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
+/* 075 */ 0x1c, 0x30, 0x30, /* EQCONF2 STEPALGO=SGNALGO=1 */
+/* 078 */ 0x37, 0xff, 0xf6, /* DELTAF_LSB */
+/* 081 */ 0x38, 0xff, 0xff, /* DELTAF_MSB */
+/* 084 */ 0x02, 0xff, 0x93, /* AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 */
+/* 087 */ 0x2d, 0xff, 0xf6, /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
+/* 090 */ 0x04, 0x10, 0x00, /* SWRAMP=1 */
+/* 093 */ 0x12, 0xff, 0xa1, /* INTP1 POCLKP=1 FEL=1 MFS=0 */
+/* 096 */ 0x2b, 0x01, 0xa1, /* INTS1 */
+/* 099 */ 0x20, 0xff, 0x04, /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
+/* 102 */ 0x2c, 0xff, 0x0d, /* INTP/S TRIP=0 TRIS=0 */
+/* 105 */ 0xc4, 0xff, 0x00,
+/* 108 */ 0xc3, 0x30, 0x00,
+/* 111 */ 0xb5, 0xff, 0x19, /* ERAGC_THD */
+/* 114 */ 0x00, 0x03, 0x01, /* GPR, CLBS soft reset */
+/* 117 */ 0x00, 0x03, 0x03, /* GPR, CLBS soft reset */
+/* 120 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 123 */ 0xff, 0xff, 0xff
+};
+ dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
- dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num);
+ /* override default values if set in config */
+ if (state->config->deltaf) {
+ tda10023_inittab[80] = (state->config->deltaf & 0xff);
+ tda10023_inittab[83] = (state->config->deltaf >> 8);
+ }
tda10023_writetab(state, tda10023_inittab);
@@ -460,12 +474,11 @@ static void tda10023_release(struct dvb_frontend* fe)
static struct dvb_frontend_ops tda10023_ops;
-struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c,
+struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
+ struct i2c_adapter *i2c,
u8 pwm)
{
struct tda10023_state* state = NULL;
- int i;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL);
@@ -474,22 +487,40 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
- state->pwm = pwm;
- for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) {
- if (tda10023_inittab[i] == 0x00) {
- state->reg0 = tda10023_inittab[i+2];
- break;
- }
- }
- // Wakeup if in standby
+ /* wakeup if in standby */
tda10023_writereg (state, 0x00, 0x33);
/* check if the demod is there */
if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
/* create dvb_frontend */
memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
+ state->pwm = pwm;
+ state->reg0 = REG0_INIT_VAL;
+ if (state->config->xtal) {
+ state->xtal = state->config->xtal;
+ state->pll_m = state->config->pll_m;
+ state->pll_p = state->config->pll_p;
+ state->pll_n = state->config->pll_n;
+ } else {
+ /* set default values if not defined in config */
+ state->xtal = 28920000;
+ state->pll_m = 8;
+ state->pll_p = 4;
+ state->pll_n = 1;
+ }
+
+ /* calc sysclk */
+ state->sysclk = (state->xtal * state->pll_m / \
+ (state->pll_n * state->pll_p));
+
+ state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
+ state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
+
+ dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
+ __func__, state->xtal, state->pll_m, state->pll_p,
+ state->pll_n);
+
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -504,10 +535,10 @@ static struct dvb_frontend_ops tda10023_ops = {
.name = "Philips TDA10023 DVB-C",
.type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 47000000,
+ .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 */
+ .symbol_rate_min = 0, /* set in tda10023_attach */
+ .symbol_rate_max = 0, /* set in tda10023_attach */
#if 0
.frequency_tolerance = ???,
.symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
diff --git a/linux/drivers/media/dvb/frontends/tda1002x.h b/linux/drivers/media/dvb/frontends/tda1002x.h
index e9094d812..4522b7ef5 100644
--- a/linux/drivers/media/dvb/frontends/tda1002x.h
+++ b/linux/drivers/media/dvb/frontends/tda1002x.h
@@ -26,11 +26,25 @@
#include <linux/dvb/frontend.h>
-struct tda1002x_config
-{
+struct tda1002x_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+ u8 invert;
+};
+
+struct tda10023_config {
/* the demodulator's i2c address */
u8 demod_address;
u8 invert;
+
+ /* clock settings */
+ u32 xtal; /* defaults: 28920000 */
+ u8 pll_m; /* defaults: 8 */
+ u8 pll_p; /* defaults: 4 */
+ u8 pll_n; /* defaults: 1 */
+
+ /* input freq offset + baseband conversion type */
+ u16 deltaf;
};
#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
@@ -40,19 +54,22 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config
static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
struct i2c_adapter* i2c, u8 pwm)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TDA10021
-#if defined(CONFIG_DVB_TDA10023) || (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c, u8 pwm);
+#if defined(CONFIG_DVB_TDA10023) || \
+ (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10023_attach(
+ const struct tda10023_config *config,
+ struct i2c_adapter *i2c, u8 pwm);
#else
-static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c, u8 pwm)
+static inline struct dvb_frontend *tda10023_attach(
+ const struct tda1002x_config *config,
+ struct i2c_adapter *i2c, u8 pwm)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TDA10023
diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c
new file mode 100644
index 000000000..f2d66234a
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/tda10048.c
@@ -0,0 +1,846 @@
+/*
+ NXP TDA10048HN DVB OFDM demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "tda10048.h"
+
+#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
+#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
+
+/* Register name definitions */
+#define TDA10048_IDENTITY 0x00
+#define TDA10048_VERSION 0x01
+#define TDA10048_DSP_CODE_CPT 0x0C
+#define TDA10048_DSP_CODE_IN 0x0E
+#define TDA10048_IN_CONF1 0x10
+#define TDA10048_IN_CONF2 0x11
+#define TDA10048_IN_CONF3 0x12
+#define TDA10048_OUT_CONF1 0x14
+#define TDA10048_OUT_CONF2 0x15
+#define TDA10048_OUT_CONF3 0x16
+#define TDA10048_AUTO 0x18
+#define TDA10048_SYNC_STATUS 0x1A
+#define TDA10048_CONF_C4_1 0x1E
+#define TDA10048_CONF_C4_2 0x1F
+#define TDA10048_CODE_IN_RAM 0x20
+#define TDA10048_CHANNEL_INFO_1_R 0x22
+#define TDA10048_CHANNEL_INFO_2_R 0x23
+#define TDA10048_CHANNEL_INFO1 0x24
+#define TDA10048_CHANNEL_INFO2 0x25
+#define TDA10048_TIME_ERROR_R 0x26
+#define TDA10048_TIME_ERROR 0x27
+#define TDA10048_FREQ_ERROR_LSB_R 0x28
+#define TDA10048_FREQ_ERROR_MSB_R 0x29
+#define TDA10048_FREQ_ERROR_LSB 0x2A
+#define TDA10048_FREQ_ERROR_MSB 0x2B
+#define TDA10048_IT_SEL 0x30
+#define TDA10048_IT_STAT 0x32
+#define TDA10048_DSP_AD_LSB 0x3C
+#define TDA10048_DSP_AD_MSB 0x3D
+#define TDA10048_DSP_REF_LSB 0x3E
+#define TDA10048_DSP_REF_MSB 0x3F
+#define TDA10048_CONF_TRISTATE1 0x44
+#define TDA10048_CONF_TRISTATE2 0x45
+#define TDA10048_CONF_POLARITY 0x46
+#define TDA10048_GPIO_SP_DS0 0x48
+#define TDA10048_GPIO_SP_DS1 0x49
+#define TDA10048_GPIO_SP_DS2 0x4A
+#define TDA10048_GPIO_SP_DS3 0x4B
+#define TDA10048_GPIO_OUT_SEL 0x4C
+#define TDA10048_GPIO_SELECT 0x4D
+#define TDA10048_IC_MODE 0x4E
+#define TDA10048_CONF_XO 0x50
+#define TDA10048_CONF_PLL1 0x51
+#define TDA10048_CONF_PLL2 0x52
+#define TDA10048_CONF_PLL3 0x53
+#define TDA10048_CONF_ADC 0x54
+#define TDA10048_CONF_ADC_2 0x55
+#define TDA10048_CONF_C1_1 0x60
+#define TDA10048_CONF_C1_3 0x62
+#define TDA10048_AGC_CONF 0x70
+#define TDA10048_AGC_THRESHOLD_LSB 0x72
+#define TDA10048_AGC_THRESHOLD_MSB 0x73
+#define TDA10048_AGC_RENORM 0x74
+#define TDA10048_AGC_GAINS 0x76
+#define TDA10048_AGC_TUN_MIN 0x78
+#define TDA10048_AGC_TUN_MAX 0x79
+#define TDA10048_AGC_IF_MIN 0x7A
+#define TDA10048_AGC_IF_MAX 0x7B
+#define TDA10048_AGC_TUN_LEVEL 0x7E
+#define TDA10048_AGC_IF_LEVEL 0x7F
+#define TDA10048_DIG_AGC_LEVEL 0x81
+#define TDA10048_FREQ_PHY2_LSB 0x86
+#define TDA10048_FREQ_PHY2_MSB 0x87
+#define TDA10048_TIME_INVWREF_LSB 0x88
+#define TDA10048_TIME_INVWREF_MSB 0x89
+#define TDA10048_TIME_WREF_LSB 0x8A
+#define TDA10048_TIME_WREF_MID1 0x8B
+#define TDA10048_TIME_WREF_MID2 0x8C
+#define TDA10048_TIME_WREF_MSB 0x8D
+#define TDA10048_NP_OUT 0xA2
+#define TDA10048_CELL_ID_LSB 0xA4
+#define TDA10048_CELL_ID_MSB 0xA5
+#define TDA10048_EXTTPS_ODD 0xAA
+#define TDA10048_EXTTPS_EVEN 0xAB
+#define TDA10048_TPS_LENGTH 0xAC
+#define TDA10048_FREE_REG_1 0xB2
+#define TDA10048_FREE_REG_2 0xB3
+#define TDA10048_CONF_C3_1 0xC0
+#define TDA10048_CYBER_CTRL 0xC2
+#define TDA10048_CBER_NMAX_LSB 0xC4
+#define TDA10048_CBER_NMAX_MSB 0xC5
+#define TDA10048_CBER_LSB 0xC6
+#define TDA10048_CBER_MSB 0xC7
+#define TDA10048_VBER_LSB 0xC8
+#define TDA10048_VBER_MID 0xC9
+#define TDA10048_VBER_MSB 0xCA
+#define TDA10048_CYBER_LUT 0xCC
+#define TDA10048_UNCOR_CTRL 0xCD
+#define TDA10048_UNCOR_CPT_LSB 0xCE
+#define TDA10048_UNCOR_CPT_MSB 0xCF
+#define TDA10048_SOFT_IT_C3 0xD6
+#define TDA10048_CONF_TS2 0xE0
+#define TDA10048_CONF_TS1 0xE1
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+ do { if (debug >= level)\
+ printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
+ } while (0)
+
+struct tda10048_state {
+
+ struct i2c_adapter *i2c;
+
+ /* configuration settings */
+ const struct tda10048_config *config;
+ struct dvb_frontend frontend;
+
+ int fwloaded;
+};
+
+static struct init_tab {
+ u8 reg;
+ u16 data;
+} init_tab[] = {
+ { TDA10048_CONF_PLL1, 0x08 },
+ { TDA10048_CONF_ADC_2, 0x00 },
+ { TDA10048_CONF_C4_1, 0x00 },
+ { TDA10048_CONF_PLL1, 0x0f },
+ { TDA10048_CONF_PLL2, 0x0a },
+ { TDA10048_CONF_PLL3, 0x43 },
+ { TDA10048_FREQ_PHY2_LSB, 0x02 },
+ { TDA10048_FREQ_PHY2_MSB, 0x0a },
+ { TDA10048_TIME_WREF_LSB, 0xbd },
+ { TDA10048_TIME_WREF_MID1, 0xe4 },
+ { TDA10048_TIME_WREF_MID2, 0xa8 },
+ { TDA10048_TIME_WREF_MSB, 0x02 },
+ { TDA10048_TIME_INVWREF_LSB, 0x04 },
+ { TDA10048_TIME_INVWREF_MSB, 0x06 },
+ { TDA10048_CONF_C4_1, 0x00 },
+ { TDA10048_CONF_C1_1, 0xa8 },
+ { TDA10048_AGC_CONF, 0x16 },
+ { TDA10048_CONF_C1_3, 0x0b },
+ { TDA10048_AGC_TUN_MIN, 0x00 },
+ { TDA10048_AGC_TUN_MAX, 0xff },
+ { TDA10048_AGC_IF_MIN, 0x00 },
+ { TDA10048_AGC_IF_MAX, 0xff },
+ { TDA10048_AGC_THRESHOLD_MSB, 0x00 },
+ { TDA10048_AGC_THRESHOLD_LSB, 0x70 },
+ { TDA10048_CYBER_CTRL, 0x38 },
+ { TDA10048_AGC_GAINS, 0x12 },
+ { TDA10048_CONF_XO, 0x00 },
+ { TDA10048_CONF_TS1, 0x07 },
+ { TDA10048_IC_MODE, 0x00 },
+ { TDA10048_CONF_TS2, 0xc0 },
+ { TDA10048_CONF_TRISTATE1, 0x21 },
+ { TDA10048_CONF_TRISTATE2, 0x00 },
+ { TDA10048_CONF_POLARITY, 0x00 },
+ { TDA10048_CONF_C4_2, 0x04 },
+ { TDA10048_CONF_ADC, 0x60 },
+ { TDA10048_CONF_ADC_2, 0x10 },
+ { TDA10048_CONF_ADC, 0x60 },
+ { TDA10048_CONF_ADC_2, 0x00 },
+ { TDA10048_CONF_C1_1, 0xa8 },
+ { TDA10048_UNCOR_CTRL, 0x00 },
+ { TDA10048_CONF_C4_2, 0x04 },
+};
+
+static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
+{
+ int ret;
+ u8 buf [] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0, .buf = buf, .len = 2 };
+
+ dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk("%s: writereg error (ret == %i)\n", __func__, ret);
+
+ return (ret != 1) ? -1 : 0;
+}
+
+static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
+{
+ int ret;
+ u8 b0 [] = { reg };
+ u8 b1 [] = { 0 };
+ struct i2c_msg msg [] = {
+ { .addr = state->config->demod_address,
+ .flags = 0, .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address,
+ .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+ dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
+
+ return b1[0];
+}
+
+static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
+ u8 *data, u16 len)
+{
+ int ret = -EREMOTEIO;
+ struct i2c_msg msg;
+ u8 *buf;
+
+ dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
+
+ buf = kmalloc(len + 1, GFP_KERNEL);
+ if (buf == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ *buf = reg;
+ memcpy(buf + 1, data, len);
+
+ msg.addr = state->config->demod_address;
+ msg.flags = 0;
+ msg.buf = buf;
+ msg.len = len + 1;
+
+ dprintk(2, "%s(): write len = %d\n",
+ __func__, msg.len);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1) {
+ printk(KERN_ERR "%s(): writereg error err %i\n",
+ __func__, ret);
+ ret = -EREMOTEIO;
+ }
+
+error:
+ kfree(buf);
+
+ return ret;
+}
+
+static int tda10048_firmware_upload(struct dvb_frontend *fe)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ const struct firmware *fw;
+ int ret;
+ int pos = 0;
+ int cnt;
+ u8 wlen = state->config->fwbulkwritelen;
+
+ if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
+ wlen = TDA10048_BULKWRITE_200;
+
+ /* request the firmware, this will block and timeout */
+ printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
+ __func__,
+ TDA10048_DEFAULT_FIRMWARE);
+
+ ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
+ &state->i2c->dev);
+ if (ret) {
+ printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
+ __func__);
+ return -EIO;
+ } else {
+ printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
+ __func__,
+ fw->size);
+ ret = 0;
+ }
+
+ if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
+ printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
+ return -EIO;
+ } else {
+ printk(KERN_INFO "%s: firmware uploading\n", __func__);
+
+ /* Soft reset */
+ tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+ tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+ & 0xfe);
+ tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+ tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+ | 0x01);
+
+ /* Put the demod into host download mode */
+ tda10048_writereg(state, TDA10048_CONF_C4_1,
+ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
+
+ /* Boot the DSP */
+ tda10048_writereg(state, TDA10048_CONF_C4_1,
+ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
+
+ /* Prepare for download */
+ tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
+
+ /* Download the firmware payload */
+ while (pos < fw->size) {
+
+ if ((fw->size - pos) > wlen)
+ cnt = wlen;
+ else
+ cnt = fw->size - pos;
+
+ tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
+ &fw->data[pos], cnt);
+
+ pos += cnt;
+ }
+
+ ret = -EIO;
+ /* Wait up to 250ms for the DSP to boot */
+ for (cnt = 0; cnt < 250 ; cnt += 10) {
+
+ msleep(10);
+
+ if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
+ & 0x40) {
+ ret = 0;
+ break;
+ }
+ }
+ }
+
+ release_firmware(fw);
+
+ if (ret == 0) {
+ printk(KERN_INFO "%s: firmware uploaded\n", __func__);
+ state->fwloaded = 1;
+ } else
+ printk(KERN_ERR "%s: firmware upload failed\n", __func__);
+
+ return ret;
+}
+
+static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+
+ dprintk(1, "%s(%d)\n", __func__, inversion);
+
+ if (inversion == TDA10048_INVERSION_ON)
+ tda10048_writereg(state, TDA10048_CONF_C1_1,
+ tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
+ else
+ tda10048_writereg(state, TDA10048_CONF_C1_1,
+ tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
+
+ return 0;
+}
+
+/* Retrieve the demod settings */
+static int tda10048_get_tps(struct tda10048_state *state,
+ struct dvb_ofdm_parameters *p)
+{
+ u8 val;
+
+ /* Make sure the TPS regs are valid */
+ if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
+ return -EAGAIN;
+
+ val = tda10048_readreg(state, TDA10048_OUT_CONF2);
+ switch ((val & 0x60) >> 5) {
+ case 0: p->constellation = QPSK; break;
+ case 1: p->constellation = QAM_16; break;
+ case 2: p->constellation = QAM_64; break;
+ }
+ switch ((val & 0x18) >> 3) {
+ case 0: p->hierarchy_information = HIERARCHY_NONE; break;
+ case 1: p->hierarchy_information = HIERARCHY_1; break;
+ case 2: p->hierarchy_information = HIERARCHY_2; break;
+ case 3: p->hierarchy_information = HIERARCHY_4; break;
+ }
+ switch (val & 0x07) {
+ case 0: p->code_rate_HP = FEC_1_2; break;
+ case 1: p->code_rate_HP = FEC_2_3; break;
+ case 2: p->code_rate_HP = FEC_3_4; break;
+ case 3: p->code_rate_HP = FEC_5_6; break;
+ case 4: p->code_rate_HP = FEC_7_8; break;
+ }
+
+ val = tda10048_readreg(state, TDA10048_OUT_CONF3);
+ switch (val & 0x07) {
+ case 0: p->code_rate_LP = FEC_1_2; break;
+ case 1: p->code_rate_LP = FEC_2_3; break;
+ case 2: p->code_rate_LP = FEC_3_4; break;
+ case 3: p->code_rate_LP = FEC_5_6; break;
+ case 4: p->code_rate_LP = FEC_7_8; break;
+ }
+
+ val = tda10048_readreg(state, TDA10048_OUT_CONF1);
+ switch ((val & 0x0c) >> 2) {
+ case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
+ }
+ switch (val & 0x02) {
+ case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+ }
+
+ return 0;
+}
+
+static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ dprintk(1, "%s(%d)\n", __func__, enable);
+
+ if (enable)
+ return tda10048_writereg(state, TDA10048_CONF_C4_1,
+ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
+ else
+ return tda10048_writereg(state, TDA10048_CONF_C4_1,
+ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
+}
+
+static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ dprintk(1, "%s(%d)\n", __func__, serial);
+
+ /* Ensure pins are out of tri-state */
+ tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
+ tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
+
+ if (serial) {
+ tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
+ tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
+ } else {
+ tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
+ tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
+ }
+
+ return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+/* TODO: Support manual tuning with specific params */
+static int tda10048_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+
+ dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+
+ if (fe->ops.tuner_ops.set_params) {
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ fe->ops.tuner_ops.set_params(fe, p);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ /* Enable demod TPS auto detection and begin acquisition */
+ tda10048_writereg(state, TDA10048_AUTO, 0x57);
+
+ return 0;
+}
+
+/* Establish sane defaults and load firmware. */
+static int tda10048_init(struct dvb_frontend *fe)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ int ret = 0, i;
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* Apply register defaults */
+ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+ tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+ if (state->fwloaded == 0)
+ ret = tda10048_firmware_upload(fe);
+
+ /* Set either serial or parallel */
+ tda10048_output_mode(fe, state->config->output_mode);
+
+ /* set inversion */
+ tda10048_set_inversion(fe, state->config->inversion);
+
+ /* Ensure we leave the gate closed */
+ tda10048_i2c_gate_ctrl(fe, 0);
+
+ return ret;
+}
+
+static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u8 reg;
+
+ *status = 0;
+
+ reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
+
+ dprintk(1, "%s() status =0x%02x\n", __func__, reg);
+
+ if (reg & 0x02)
+ *status |= FE_HAS_CARRIER;
+
+ if (reg & 0x04)
+ *status |= FE_HAS_SIGNAL;
+
+ if (reg & 0x08) {
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ }
+
+ return 0;
+}
+
+static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* TODO: A reset may be required here */
+ *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
+ tda10048_readreg(state, TDA10048_CBER_LSB);
+
+ return 0;
+}
+
+static int tda10048_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u8 v;
+
+ dprintk(1, "%s()\n", __func__);
+
+ *signal_strength = 65535;
+
+ v = tda10048_readreg(state, TDA10048_NP_OUT);
+ if (v > 0)
+ *signal_strength -= (v << 8) | v;
+
+ return 0;
+}
+
+/* SNR lookup table */
+static struct snr_tab {
+ u8 val;
+ u8 data;
+} snr_tab[] = {
+ { 0, 0 },
+ { 1, 246 },
+ { 2, 215 },
+ { 3, 198 },
+ { 4, 185 },
+ { 5, 176 },
+ { 6, 168 },
+ { 7, 161 },
+ { 8, 155 },
+ { 9, 150 },
+ { 10, 146 },
+ { 11, 141 },
+ { 12, 138 },
+ { 13, 134 },
+ { 14, 131 },
+ { 15, 128 },
+ { 16, 125 },
+ { 17, 122 },
+ { 18, 120 },
+ { 19, 118 },
+ { 20, 115 },
+ { 21, 113 },
+ { 22, 111 },
+ { 23, 109 },
+ { 24, 107 },
+ { 25, 106 },
+ { 26, 104 },
+ { 27, 102 },
+ { 28, 101 },
+ { 29, 99 },
+ { 30, 98 },
+ { 31, 96 },
+ { 32, 95 },
+ { 33, 94 },
+ { 34, 92 },
+ { 35, 91 },
+ { 36, 90 },
+ { 37, 89 },
+ { 38, 88 },
+ { 39, 86 },
+ { 40, 85 },
+ { 41, 84 },
+ { 42, 83 },
+ { 43, 82 },
+ { 44, 81 },
+ { 45, 80 },
+ { 46, 79 },
+ { 47, 78 },
+ { 48, 77 },
+ { 49, 76 },
+ { 50, 76 },
+ { 51, 75 },
+ { 52, 74 },
+ { 53, 73 },
+ { 54, 72 },
+ { 56, 71 },
+ { 57, 70 },
+ { 58, 69 },
+ { 60, 68 },
+ { 61, 67 },
+ { 63, 66 },
+ { 64, 65 },
+ { 66, 64 },
+ { 67, 63 },
+ { 68, 62 },
+ { 69, 62 },
+ { 70, 61 },
+ { 72, 60 },
+ { 74, 59 },
+ { 75, 58 },
+ { 77, 57 },
+ { 79, 56 },
+ { 81, 55 },
+ { 83, 54 },
+ { 85, 53 },
+ { 87, 52 },
+ { 89, 51 },
+ { 91, 50 },
+ { 93, 49 },
+ { 95, 48 },
+ { 97, 47 },
+ { 100, 46 },
+ { 102, 45 },
+ { 104, 44 },
+ { 107, 43 },
+ { 109, 42 },
+ { 112, 41 },
+ { 114, 40 },
+ { 117, 39 },
+ { 120, 38 },
+ { 123, 37 },
+ { 125, 36 },
+ { 128, 35 },
+ { 131, 34 },
+ { 134, 33 },
+ { 138, 32 },
+ { 141, 31 },
+ { 144, 30 },
+ { 147, 29 },
+ { 151, 28 },
+ { 154, 27 },
+ { 158, 26 },
+ { 162, 25 },
+ { 165, 24 },
+ { 169, 23 },
+ { 173, 22 },
+ { 177, 21 },
+ { 181, 20 },
+ { 186, 19 },
+ { 190, 18 },
+ { 194, 17 },
+ { 199, 16 },
+ { 204, 15 },
+ { 208, 14 },
+ { 213, 13 },
+ { 218, 12 },
+ { 223, 11 },
+ { 229, 10 },
+ { 234, 9 },
+ { 239, 8 },
+ { 245, 7 },
+ { 251, 6 },
+ { 255, 5 },
+};
+
+static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ u8 v;
+ int i, ret = -EINVAL;
+
+ dprintk(1, "%s()\n", __func__);
+
+ v = tda10048_readreg(state, TDA10048_NP_OUT);
+ for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
+ if (v <= snr_tab[i].val) {
+ *snr = snr_tab[i].data;
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+
+ dprintk(1, "%s()\n", __func__);
+#if 0
+ /* Reset and begin counting */
+ tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x01);
+ msleep(10);
+#endif
+
+ *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
+ tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
+
+ return 0;
+}
+
+static int tda10048_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+
+ dprintk(1, "%s()\n", __func__);
+
+ p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
+ & 0x20 ? INVERSION_ON : INVERSION_OFF;
+
+ return tda10048_get_tps(state, &p->u.ofdm);
+}
+
+static int tda10048_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void tda10048_release(struct dvb_frontend *fe)
+{
+ struct tda10048_state *state = fe->demodulator_priv;
+ dprintk(1, "%s()\n", __func__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops tda10048_ops;
+
+struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct tda10048_state *state = NULL;
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ state->fwloaded = 0;
+
+ /* check if the demod is present */
+ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &tda10048_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ /* Leave the gate closed */
+ tda10048_i2c_gate_ctrl(&state->frontend, 0);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(tda10048_attach);
+
+static struct dvb_frontend_ops tda10048_ops = {
+
+ .info = {
+ .name = "NXP TDA10048HN DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 177000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 166666,
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+ },
+
+ .release = tda10048_release,
+ .init = tda10048_init,
+ .i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
+ .set_frontend = tda10048_set_frontend,
+ .get_frontend = tda10048_get_frontend,
+ .get_tune_settings = tda10048_get_tune_settings,
+ .read_status = tda10048_read_status,
+ .read_ber = tda10048_read_ber,
+ .read_signal_strength = tda10048_read_signal_strength,
+ .read_snr = tda10048_read_snr,
+ .read_ucblocks = tda10048_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/tda10048.h b/linux/drivers/media/dvb/frontends/tda10048.h
new file mode 100644
index 000000000..2b5c78e62
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/tda10048.h
@@ -0,0 +1,63 @@
+/*
+ NXP TDA10048HN DVB OFDM demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef TDA10048_H
+#define TDA10048_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct tda10048_config {
+
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* serial/parallel output */
+#define TDA10048_PARALLEL_OUTPUT 0
+#define TDA10048_SERIAL_OUTPUT 1
+ u8 output_mode;
+
+#define TDA10048_BULKWRITE_200 200
+#define TDA10048_BULKWRITE_50 50
+ u8 fwbulkwritelen;
+
+ /* Spectral Inversion */
+#define TDA10048_INVERSION_OFF 0
+#define TDA10048_INVERSION_ON 1
+ u8 inversion;
+};
+
+#if defined(CONFIG_DVB_TDA10048) || \
+ (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10048_attach(
+ const struct tda10048_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10048_attach(
+ const struct tda10048_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_TDA10048 */
+
+#endif /* TDA10048_H */
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c
index 8415a8a52..499738463 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.c
+++ b/linux/drivers/media/dvb/frontends/tda1004x.c
@@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
u8 buf[] = { reg, data };
struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
- dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
+ dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
msg.addr = state->config->demod_address;
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
- __FUNCTION__, reg, data, ret);
+ __func__, reg, data, ret);
- dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+ dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
reg, data, ret);
return (ret != 1) ? -1 : 0;
}
@@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
- dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
+ dprintk("%s: reg=0x%x\n", __func__, reg);
msg[0].addr = state->config->demod_address;
msg[1].addr = state->config->demod_address;
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
- dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+ dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
ret);
return -1;
}
- dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+ dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
reg, b1[0], ret);
return b1[0];
}
@@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
{
int val;
- dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
+ dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
mask, data);
// read a byte and check
@@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
int i;
int result;
- dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
+ dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
result = 0;
for (i = 0; i < len; i++) {
@@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
{
int result;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
msleep(20);
@@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
}
@@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
}
pos += tx_size;
- dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
+ dprintk("%s: fw_pos=0x%x\n", __func__, pos);
}
// give the DSP a chance to settle 03/10/05 Hac
msleep(100);
@@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
}
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
- dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
+ dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
} else {
- dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
+ dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
}
if(tda10046_clk53m)
@@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
if (state->config->xtal_freq == TDA10046_XTAL_4M) {
tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
} else {
- dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__);
+ dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
}
tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
@@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (tda10045_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
@@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe)
static int tda10046_init(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
@@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
int tmp;
int inversion;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
// setup auto offset
@@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
{
struct tda1004x_state* state = fe->demodulator_priv;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// inversion status
fe_params->inversion = INVERSION_OFF;
@@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
int cber;
int vber;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// read status
status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
@@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
}
// success
- dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
+ dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
return 0;
}
@@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
int tmp;
int reg = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// determine the register to use
switch (state->demod_type) {
@@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
return -EIO;
*signal = (tmp << 8) | tmp;
- dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
+ dprintk("%s: signal=0x%x\n", __func__, *signal);
return 0;
}
@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
struct tda1004x_state* state = fe->demodulator_priv;
int tmp;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// read it
tmp = tda1004x_read_byte(state, TDA1004X_SNR);
@@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
tmp = 255 - tmp;
*snr = ((tmp << 8) | tmp);
- dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
+ dprintk("%s: snr=0x%x\n", __func__, *snr);
return 0;
}
@@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
int tmp2;
int counter;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// read the UCBLOCKS and reset
counter = 0;
@@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
else
*ucblocks = 0xffffffff;
- dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
+ dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
return 0;
}
@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
struct tda1004x_state* state = fe->demodulator_priv;
int tmp;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
// read it in
tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
@@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
// The address 0x20 should be read to cope with a TDA10046 bug
tda1004x_read_byte(state, TDA1004X_CBER_RESET);
- dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
+ dprintk("%s: ber=0x%x\n", __func__, *ber);
return 0;
}
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.h b/linux/drivers/media/dvb/frontends/tda1004x.h
index ebb2c5f5a..4e27ffb0f 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.h
+++ b/linux/drivers/media/dvb/frontends/tda1004x.h
@@ -127,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config
static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TDA1004X
diff --git a/linux/drivers/media/dvb/frontends/tda10086.c b/linux/drivers/media/dvb/frontends/tda10086.c
index a4b48bdf2..c749f96c2 100644
--- a/linux/drivers/media/dvb/frontends/tda10086.c
+++ b/linux/drivers/media/dvb/frontends/tda10086.c
@@ -61,7 +61,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
if (ret != 1)
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
- __FUNCTION__, reg, data, ret);
+ __func__, reg, data, ret);
return (ret != 1) ? ret : 0;
}
@@ -79,7 +79,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg)
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
- dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+ dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
ret);
return ret;
}
@@ -91,16 +91,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
{
int val;
- // read a byte and check
+ /* read a byte and check */
val = tda10086_read_byte(state, reg);
if (val < 0)
return val;
- // mask if off
+ /* mask if off */
val = val & ~mask;
val |= data & 0xff;
- // write it out again
+ /* write it out again */
return tda10086_write_byte(state, reg, val);
}
@@ -109,62 +109,67 @@ static int tda10086_init(struct dvb_frontend* fe)
struct tda10086_state* state = fe->demodulator_priv;
u8 t22k_off = 0x80;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (state->config->diseqc_tone)
t22k_off = 0;
- // reset
+ /* reset */
tda10086_write_byte(state, 0x00, 0x00);
msleep(10);
- // misc setup
+ /* misc setup */
tda10086_write_byte(state, 0x01, 0x94);
- tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
+ tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
tda10086_write_byte(state, 0x03, 0xe4);
tda10086_write_byte(state, 0x04, 0x43);
tda10086_write_byte(state, 0x0c, 0x0c);
- tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
- tda10086_write_byte(state, 0x20, 0x89); // misc
- tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
- tda10086_write_byte(state, 0x32, 0x00); // irq off
- tda10086_write_byte(state, 0x31, 0x56); // setup AFC
-
- // setup PLL (assumes 16Mhz XIN)
- tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
- tda10086_write_byte(state, 0x3a, 0x0b); // M=12
- tda10086_write_byte(state, 0x3b, 0x01); // P=2
- tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
-
- // setup TS interface
+ tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
+ tda10086_write_byte(state, 0x20, 0x89); /* misc */
+ tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
+ tda10086_write_byte(state, 0x32, 0x00); /* irq off */
+ tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
+
+ /* setup PLL (this assumes SACLK = 96MHz) */
+ tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
+ if (state->config->xtal_freq == TDA10086_XTAL_16M) {
+ tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
+ tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
+ } else {
+ tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
+ tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
+ }
+ tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
+
+ /* setup TS interface */
tda10086_write_byte(state, 0x11, 0x81);
tda10086_write_byte(state, 0x12, 0x81);
- tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
- tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
- tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
+ tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
+ tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
+ tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
tda10086_write_byte(state, 0x10, 0x2a);
- // setup ADC
- tda10086_write_byte(state, 0x58, 0x61); // ADC setup
- tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
+ /* setup ADC */
+ tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
+ tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
- // setup AGC
+ /* setup AGC */
tda10086_write_byte(state, 0x05, 0x0B);
tda10086_write_byte(state, 0x37, 0x63);
- tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
+ tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
tda10086_write_byte(state, 0x40, 0x64);
tda10086_write_byte(state, 0x41, 0x4f);
tda10086_write_byte(state, 0x42, 0x43);
- // setup viterbi
- tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
+ /* setup viterbi */
+ tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
- // setup carrier recovery
+ /* setup carrier recovery */
tda10086_write_byte(state, 0x3d, 0x80);
- // setup SEC
- tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
- tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency
- tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
+ /* setup SEC */
+ tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
+ tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
+ tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
return 0;
}
@@ -174,7 +179,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
unsigned long timeout = jiffies + msecs_to_jiffies(200);
while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
if(time_after(jiffies, timeout)) {
- printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+ printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
break;
}
msleep(10);
@@ -186,7 +191,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct tda10086_state* state = fe->demodulator_priv;
u8 t22k_off = 0x80;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (state->config->diseqc_tone)
t22k_off = 0;
@@ -212,7 +217,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
u8 oldval;
u8 t22k_off = 0x80;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (state->config->diseqc_tone)
t22k_off = 0;
@@ -240,7 +245,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
u8 oldval = tda10086_read_byte(state, 0x36);
u8 t22k_off = 0x80;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (state->config->diseqc_tone)
t22k_off = 0;
@@ -267,7 +272,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
{
u8 invval = 0x80;
- dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
+ dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
switch(fe_params->inversion) {
case INVERSION_OFF:
@@ -301,9 +306,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
u32 bdri;
u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
- dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
+ dprintk ("%s %i\n", __func__, symbol_rate);
- // setup the decimation and anti-aliasing filters..
+ /* setup the decimation and anti-aliasing filters.. */
if (symbol_rate < (u32) (SACLK * 0.0137)) {
dfn=4;
afs=1;
@@ -340,13 +345,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
byp=1;
}
- // calculate BDR
+ /* calculate BDR */
big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
big += ((SACLK/1000ULL)-1ULL);
do_div(big, (SACLK/1000ULL));
bdr = big & 0xfffff;
- // calculate BDRI
+ /* calculate BDRI */
tmp = (1<<dfn)*(symbol_rate/1000);
bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
@@ -367,7 +372,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
{
u8 fecval;
- dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
+ dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
switch(fe_params->u.qpsk.fec_inner) {
case FEC_1_2:
@@ -413,13 +418,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
u32 freq = 0;
int freqoff;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
- // modify parameters for tuning
+ /* modify parameters for tuning */
tda10086_write_byte(state, 0x02, 0x35);
state->has_lock = false;
- // set params
+ /* set params */
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fe_params);
if (fe->ops.i2c_gate_ctrl)
@@ -431,7 +436,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
fe->ops.i2c_gate_ctrl(fe, 0);
}
- // calcluate the frequency offset (in *Hz* not kHz)
+ /* calcluate the frequency offset (in *Hz* not kHz) */
freqoff = fe_params->frequency - freq;
freqoff = ((1<<16) * freqoff) / (SACLK/1000);
tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
@@ -444,7 +449,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
if ((ret = tda10086_set_fec(state, fe_params)) < 0)
return ret;
- // soft reset + disable TS output until lock
+ /* soft reset + disable TS output until lock */
tda10086_write_mask(state, 0x10, 0x40, 0x40);
tda10086_write_mask(state, 0x00, 0x01, 0x00);
@@ -460,13 +465,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
int tmp;
u64 tmp64;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
- // check for invalid symbol rate
+ /* check for invalid symbol rate */
if (fe_params->u.qpsk.symbol_rate < 500000)
return -EINVAL;
- // calculate the updated frequency (note: we convert from Hz->kHz)
+ /* calculate the updated frequency (note: we convert from Hz->kHz) */
tmp64 = tda10086_read_byte(state, 0x52);
tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
if (tmp64 & 0x8000)
@@ -475,7 +480,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
do_div(tmp64, (1ULL<<15) * (1ULL<<1));
fe_params->frequency = (int) state->frequency + (int) tmp64;
- // the inversion
+ /* the inversion */
val = tda10086_read_byte(state, 0x0c);
if (val & 0x80) {
switch(val & 0x40) {
@@ -506,7 +511,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
}
}
- // calculate the updated symbol rate
+ /* calculate the updated symbol rate */
tmp = tda10086_read_byte(state, 0x1d);
if (tmp & 0x80)
tmp |= 0xffffff00;
@@ -514,7 +519,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
- // the FEC
+ /* the FEC */
val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
switch(val) {
case 0x00:
@@ -551,7 +556,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
struct tda10086_state* state = fe->demodulator_priv;
u8 val;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
val = tda10086_read_byte(state, 0x0e);
*fe_status = 0;
@@ -567,7 +572,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
*fe_status |= FE_HAS_LOCK;
if (!state->has_lock) {
state->has_lock = true;
- // modify parameters for stable reception
+ /* modify parameters for stable reception */
tda10086_write_byte(state, 0x02, 0x00);
}
}
@@ -580,7 +585,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
struct tda10086_state* state = fe->demodulator_priv;
u8 _str;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
_str = 0xff - tda10086_read_byte(state, 0x43);
*signal = (_str << 8) | _str;
@@ -593,7 +598,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
struct tda10086_state* state = fe->demodulator_priv;
u8 _snr;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
_snr = 0xff - tda10086_read_byte(state, 0x1c);
*snr = (_snr << 8) | _snr;
@@ -605,12 +610,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct tda10086_state* state = fe->demodulator_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
- // read it
+ /* read it */
*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
- // reset counter
+ /* reset counter */
tda10086_write_byte(state, 0x18, 0x00);
tda10086_write_byte(state, 0x18, 0x80);
@@ -621,9 +626,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct tda10086_state* state = fe->demodulator_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
- // read it
+ /* read it */
*ber = 0;
*ber |= tda10086_read_byte(state, 0x15);
*ber |= tda10086_read_byte(state, 0x16) << 8;
@@ -636,7 +641,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
{
struct tda10086_state* state = fe->demodulator_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
tda10086_write_mask(state, 0x00, 0x08, 0x08);
@@ -647,7 +652,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct tda10086_state* state = fe->demodulator_priv;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
if (enable) {
tda10086_write_mask(state, 0x00, 0x10, 0x10);
@@ -738,7 +743,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
{
struct tda10086_state *state;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __func__);
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
diff --git a/linux/drivers/media/dvb/frontends/tda10086.h b/linux/drivers/media/dvb/frontends/tda10086.h
index eeceaeee7..61148c558 100644
--- a/linux/drivers/media/dvb/frontends/tda10086.h
+++ b/linux/drivers/media/dvb/frontends/tda10086.h
@@ -26,6 +26,11 @@
#include <linux/dvb/frontend.h>
#include <linux/firmware.h>
+enum tda10086_xtal {
+ TDA10086_XTAL_16M,
+ TDA10086_XTAL_4M
+};
+
struct tda10086_config
{
/* the demodulator's i2c address */
@@ -36,6 +41,9 @@ struct tda10086_config
/* do we need the diseqc signal with carrier? */
u8 diseqc_tone;
+
+ /* frequency of the reference xtal */
+ enum tda10086_xtal xtal_freq;
};
#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
@@ -45,9 +53,9 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config
static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_TDA10086
+#endif /* CONFIG_DVB_TDA10086 */
-#endif // TDA10086_H
+#endif /* TDA10086_H */
diff --git a/linux/drivers/media/dvb/frontends/tda8083.c b/linux/drivers/media/dvb/frontends/tda8083.c
index 011b74f79..5b843b2e6 100644
--- a/linux/drivers/media/dvb/frontends/tda8083.c
+++ b/linux/drivers/media/dvb/frontends/tda8083.c
@@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
if (ret != 1)
dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
- __FUNCTION__, reg, ret);
+ __func__, reg, ret);
return (ret != 1) ? -1 : 0;
}
@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
if (ret != 2)
dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
- __FUNCTION__, reg1, ret);
+ __func__, reg1, ret);
return ret == 2 ? 0 : -1;
}
diff --git a/linux/drivers/media/dvb/frontends/tda8083.h b/linux/drivers/media/dvb/frontends/tda8083.h
index 2d3307999..5a03c14a1 100644
--- a/linux/drivers/media/dvb/frontends/tda8083.h
+++ b/linux/drivers/media/dvb/frontends/tda8083.h
@@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TDA8083
diff --git a/linux/drivers/media/dvb/frontends/tda826x.c b/linux/drivers/media/dvb/frontends/tda826x.c
index 71c486b4e..596fc4275 100644
--- a/linux/drivers/media/dvb/frontends/tda826x.c
+++ b/linux/drivers/media/dvb/frontends/tda826x.c
@@ -55,7 +55,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
u8 buf [] = { 0x00, 0x8d };
struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
- dprintk("%s:\n", __FUNCTION__);
+ dprintk("%s:\n", __func__);
if (!priv->has_loopthrough)
buf[1] = 0xad;
@@ -63,7 +63,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
- dprintk("%s: i2c error\n", __FUNCTION__);
+ dprintk("%s: i2c error\n", __func__);
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -76,13 +76,24 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
struct tda826x_priv *priv = fe->tuner_priv;
int ret;
u32 div;
+ u32 ksyms;
+ u32 bandwidth;
u8 buf [11];
struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
- dprintk("%s:\n", __FUNCTION__);
+ dprintk("%s:\n", __func__);
div = (params->frequency + (1000-1)) / 1000;
+ /* BW = ((1 + RO) * SR/2 + 5) * 1.3 [SR in MSPS, BW in MHz] */
+ /* with R0 = 0.35 and some transformations: */
+ ksyms = params->u.qpsk.symbol_rate / 1000;
+ bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
+ if (bandwidth < 5)
+ bandwidth = 5;
+ else if (bandwidth > 36)
+ bandwidth = 36;
+
buf[0] = 0x00; // subaddress
buf[1] = 0x09; // powerdown RSSI + the magic value 1
if (!priv->has_loopthrough)
@@ -90,7 +101,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
buf[3] = div >> 7;
buf[4] = div << 1;
- buf[5] = 0x77; // baseband cut-off 19 MHz
+ buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
buf[7] = 0x83; // charge pumps at high, tests off
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
@@ -100,7 +111,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
- dprintk("%s: i2c error\n", __FUNCTION__);
+ dprintk("%s: i2c error\n", __func__);
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -139,7 +150,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
};
int ret;
- dprintk("%s:\n", __FUNCTION__);
+ dprintk("%s:\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
diff --git a/linux/drivers/media/dvb/frontends/tda826x.h b/linux/drivers/media/dvb/frontends/tda826x.h
index ad9981195..89e97926a 100644
--- a/linux/drivers/media/dvb/frontends/tda826x.h
+++ b/linux/drivers/media/dvb/frontends/tda826x.h
@@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
int has_loopthrough)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TDA826X
diff --git a/linux/drivers/media/dvb/frontends/tua6100.c b/linux/drivers/media/dvb/frontends/tua6100.c
index 34e7c93f3..dfa7fa150 100644
--- a/linux/drivers/media/dvb/frontends/tua6100.c
+++ b/linux/drivers/media/dvb/frontends/tua6100.c
@@ -59,7 +59,7 @@ static int tua6100_sleep(struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
- printk("%s: i2c error\n", __FUNCTION__);
+ printk("%s: i2c error\n", __func__);
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
diff --git a/linux/drivers/media/dvb/frontends/tua6100.h b/linux/drivers/media/dvb/frontends/tua6100.h
index 03a665e7d..f83dbd5e4 100644
--- a/linux/drivers/media/dvb/frontends/tua6100.h
+++ b/linux/drivers/media/dvb/frontends/tua6100.h
@@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st
#else
static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_TUA6100
diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c
index 8791701c8..a184597f1 100644
--- a/linux/drivers/media/dvb/frontends/ves1820.c
+++ b/linux/drivers/media/dvb/frontends/ves1820.c
@@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
if (ret != 1)
printk("ves1820: %s(): writereg error (reg == 0x%02x, "
- "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
+ "val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
if (ret != 2)
printk("ves1820: %s(): readreg error (reg == 0x%02x, "
- "ret == %i)\n", __FUNCTION__, reg, ret);
+ "ret == %i)\n", __func__, reg, ret);
return b1[0];
}
diff --git a/linux/drivers/media/dvb/frontends/ves1820.h b/linux/drivers/media/dvb/frontends/ves1820.h
index e4a2a3240..e902ed634 100644
--- a/linux/drivers/media/dvb/frontends/ves1820.h
+++ b/linux/drivers/media/dvb/frontends/ves1820.h
@@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
struct i2c_adapter* i2c, u8 pwm)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_VES1820
diff --git a/linux/drivers/media/dvb/frontends/ves1x93.c b/linux/drivers/media/dvb/frontends/ves1x93.c
index c041c81f9..bd558960b 100644
--- a/linux/drivers/media/dvb/frontends/ves1x93.c
+++ b/linux/drivers/media/dvb/frontends/ves1x93.c
@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
int err;
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
return -EREMOTEIO;
}
@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
u32 tmp;
u32 FIN;
- dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
+ dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
if (srate > state->config->xin/2)
srate = state->config->xin/2;
@@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
int i;
int val;
- dprintk("%s: init chip\n", __FUNCTION__);
+ dprintk("%s: init chip\n", __func__);
for (i = 0; i < state->tab_size; i++) {
if (state->init_1x93_wtab[i]) {
diff --git a/linux/drivers/media/dvb/frontends/ves1x93.h b/linux/drivers/media/dvb/frontends/ves1x93.h
index d507f8966..8a5a49e80 100644
--- a/linux/drivers/media/dvb/frontends/ves1x93.h
+++ b/linux/drivers/media/dvb/frontends/ves1x93.h
@@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
struct i2c_adapter* i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif // CONFIG_DVB_VES1X93
diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c
index 1ae9f0ef1..11160a3ee 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.c
+++ b/linux/drivers/media/dvb/frontends/zl10353.c
@@ -91,7 +91,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
if (ret != 2) {
printk("%s: readreg error (reg=%d, ret==%i)\n",
- __FUNCTION__, reg, ret);
+ __func__, reg, ret);
return ret;
}
@@ -157,7 +157,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
*nominal_rate = value;
dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
- __FUNCTION__, bw, adc_clock, *nominal_rate);
+ __func__, bw, adc_clock, *nominal_rate);
}
static void zl10353_calc_input_freq(struct dvb_frontend *fe,
@@ -186,7 +186,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
*input_freq = -value;
dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
- __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
+ __func__, if2, ife, adc_clock, -(int)value, *input_freq);
}
static int zl10353_sleep(struct dvb_frontend *fe)
diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h
index fc734c22b..fdbb88ff7 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.h
+++ b/linux/drivers/media/dvb/frontends/zl10353.h
@@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
struct i2c_adapter *i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_ZL10353 */
diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c
index b104e63eb..33a98f0f0 100644
--- a/linux/drivers/media/dvb/pluto2/pluto2.c
+++ b/linux/drivers/media/dvb/pluto2/pluto2.c
@@ -39,6 +39,8 @@
#include "dvbdev.h"
#include "tda1004x.h"
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define DRIVER_NAME "pluto2"
#define REG_PIDn(n) ((n) << 2) /* PID n pattern registers */
@@ -666,7 +668,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
goto err_pluto_hw_exit;
/* dvb */
- ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
+ ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
+ THIS_MODULE, &pdev->dev, adapter_nr);
if (ret < 0)
goto err_i2c_del_adapter;
diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig
index ae882432d..07643e010 100644
--- a/linux/drivers/media/dvb/ttpci/Kconfig
+++ b/linux/drivers/media/dvb/ttpci/Kconfig
@@ -5,6 +5,7 @@ config TTPCI_EEPROM
config DVB_AV7110
tristate "AV7110 cards"
depends on DVB_CORE && PCI && I2C
+ depends on HOTPLUG
select FW_LOADER if !DVB_AV7110_FIRMWARE
select TTPCI_EEPROM
select VIDEO_SAA7146_VV
@@ -100,6 +101,7 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
depends on DVB_BUDGET_CORE && I2C
+ depends on INPUT # due to IR
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@@ -123,6 +125,7 @@ config DVB_BUDGET_AV
depends on DVB_BUDGET_CORE && I2C
select VIDEO_SAA7146_VV
depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
+ depends on HOTPLUG # dependency of FW_LOADER
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c
index 35b0814e0..073ed350f 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.c
+++ b/linux/drivers/media/dvb/ttpci/av7110.c
@@ -51,6 +51,7 @@
#include <linux/crc32.h>
#include <linux/i2c.h>
#include <linux/kthread.h>
+#include <asm/unaligned.h>
#include <asm/system.h>
@@ -112,6 +113,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14:
module_param(tv_standard, int, 0444);
MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
static void restart_feeds(struct av7110 *av7110);
static int av7110_num;
@@ -359,7 +362,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
{
dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
- printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
return;
}
@@ -497,7 +500,7 @@ static void gpioirq(unsigned long data)
saa7146_read(av7110->dev, SSR));
if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
- printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
+ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
BUG(); /* maybe we should try resetting the debi? */
}
@@ -827,7 +830,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
if (ret != 0 || handle >= 32) {
printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
"ret %d handle %04x\n",
- __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
+ __func__, buf[0], buf[1], buf[2], buf[3],
ret, handle);
dvbdmxfilter->hw_handle = 0xffff;
if (!ret)
@@ -854,7 +857,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
handle = dvbdmxfilter->hw_handle;
if (handle >= 32) {
printk("%s tried to stop invalid filter %04x, filter type = %x\n",
- __FUNCTION__, handle, dvbdmxfilter->type);
+ __func__, handle, dvbdmxfilter->type);
return -EINVAL;
}
@@ -867,7 +870,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
if (ret != 0 || answ[1] != handle) {
printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
"resp %04x %04x pid %d\n",
- __FUNCTION__, buf[0], buf[1], buf[2], ret,
+ __func__, buf[0], buf[1], buf[2], ret,
answ[0], answ[1], dvbdmxfilter->feed->pid);
if (!ret)
ret = -1;
@@ -1122,7 +1125,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
if (ret) {
- printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
+ printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
return ret;
}
dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
@@ -1459,9 +1462,9 @@ static int check_firmware(struct av7110* av7110)
ptr += 4;
/* check dpram file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len >= 512) {
printk("dvb-ttpci: dpram file is way too big.\n");
@@ -1476,9 +1479,9 @@ static int check_firmware(struct av7110* av7110)
ptr += len;
/* check root file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len <= 200000 || len >= 300000 ||
@@ -2461,7 +2464,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
goto err_kfree_0;
ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
- THIS_MODULE, &dev->pci->dev);
+ THIS_MODULE, &dev->pci->dev, adapter_nr);
if (ret < 0)
goto err_put_firmware_1;
diff --git a/linux/drivers/media/dvb/ttpci/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h
index 5bb48ab1c..290ffc188 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.h
+++ b/linux/drivers/media/dvb/ttpci/av7110.h
@@ -44,7 +44,7 @@
extern int av7110_debug;
#define dprintk(level,args...) \
- do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
+ do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
#define MAXFILT 32
diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c
index 3e6b650fb..ec55a968f 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_av.c
+++ b/linux/drivers/media/dvb/ttpci/av7110_av.c
@@ -965,8 +965,9 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x
static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
{
- int i, n;
+ unsigned i, n;
int progressive = 0;
+ int match = 0;
dprintk(2, "av7110:%p, \n", av7110);
@@ -975,12 +976,31 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
return -EBUSY;
}
- for (i = 0; i < len - 5; i++) {
- /* get progressive flag from picture extension */
- if (buf[i] == 0x00 && buf[i+1] == 0x00 &&
- buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 &&
- (buf[i+4] & 0xf0) == 0x10)
- progressive = buf[i+5] & 0x08;
+ /* search in buf for instances of 00 00 01 b5 1? */
+ for (i = 0; i < len; i++) {
+ unsigned char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (match == 5) {
+ progressive = c & 0x08;
+ match = 0;
+ }
+ if (c == 0x00) {
+ match = (match == 1 || match == 2) ? 2 : 1;
+ continue;
+ }
+ switch (match++) {
+ case 2: if (c == 0x01)
+ continue;
+ break;
+ case 3: if (c == 0xb5)
+ continue;
+ break;
+ case 4: if ((c & 0xf0) == 0x10)
+ continue;
+ break;
+ }
+ match = 0;
}
/* setting n always > 1, fixes problems when playing stillframes
diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c
index a0d7acd9e..ec049bb6e 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c
@@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
struct saa7146_dev *dev = av7110->dev;
if (count <= 0 || count > 32764) {
- printk("%s: invalid count %d\n", __FUNCTION__, count);
+ printk("%s: invalid count %d\n", __func__, count);
return -1;
}
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
- printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
+ printk("%s: wait_for_debi_done failed\n", __func__);
return -1;
}
saa7146_write(dev, DEBI_CONFIG, config);
@@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
u32 result = 0;
if (count > 32764 || count <= 0) {
- printk("%s: invalid count %d\n", __FUNCTION__, count);
+ printk("%s: invalid count %d\n", __func__, count);
return 0;
}
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
- printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
+ printk("%s: wait_for_debi_done #1 failed\n", __func__);
return 0;
}
saa7146_write(dev, DEBI_AD, av7110->debi_bus);
@@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
if (count > 4)
return count;
if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
- printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
+ printk("%s: wait_for_debi_done #2 failed\n", __func__);
return 0;
}
@@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
break;
if (err) {
printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
- __FUNCTION__, stat & flags);
+ __func__, stat & flags);
return -ETIMEDOUT;
}
msleep(1);
@@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
break;
if (err) {
- printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
av7110->arm_errors++;
return -ETIMEDOUT;
}
@@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
break;
if (err) {
- printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
return -ETIMEDOUT;
}
msleep(1);
@@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & flags[0]) {
printk(KERN_ERR "%s: %s QUEUE overflow\n",
- __FUNCTION__, type);
+ __func__, type);
return -1;
}
if ((stat & flags[1]) == 0)
break;
if (err) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
- __FUNCTION__, type);
+ __func__, type);
return -ETIMEDOUT;
}
msleep(1);
@@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
- __FUNCTION__, (buf[0] >> 8) & 0xff);
+ __func__, (buf[0] >> 8) & 0xff);
return -ETIMEDOUT;
}
msleep(1);
@@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & GPMQOver) {
- printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
+ printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
return -ENOSPC;
}
else if (stat & OSDQOver) {
- printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
+ printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
return -ENOSPC;
}
#endif
@@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
mutex_unlock(&av7110->dcomlock);
if (ret && ret!=-ERESTARTSYS)
printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
- __FUNCTION__, ret);
+ __func__, ret);
return ret;
}
@@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
break;
if (err) {
- printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
+ printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
mutex_unlock(&av7110->dcomlock);
return -ETIMEDOUT;
}
@@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
break;
if (err) {
- printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+ printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
mutex_unlock(&av7110->dcomlock);
return -ETIMEDOUT;
}
@@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
#ifdef COM_DEBUG
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & GPMQOver) {
- printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
+ printk(KERN_ERR "%s: GPMQOver\n", __func__);
mutex_unlock(&av7110->dcomlock);
return -1;
}
else if (stat & OSDQOver) {
- printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
+ printk(KERN_ERR "%s: OSDQOver\n", __func__);
mutex_unlock(&av7110->dcomlock);
return -1;
}
@@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
- __FUNCTION__);
+ __func__);
mutex_unlock(&av7110->dcomlock);
return -ETIMEDOUT;
}
@@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
break;
if (ret) {
printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
- __FUNCTION__);
+ __func__);
mutex_unlock(&av7110->dcomlock);
return -ETIMEDOUT;
}
@@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
break;
if (ret) {
printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
- __FUNCTION__);
+ __func__);
mutex_unlock(&av7110->dcomlock);
return -ETIMEDOUT;
}
diff --git a/linux/drivers/media/dvb/ttpci/av7110_ir.c b/linux/drivers/media/dvb/ttpci/av7110_ir.c
index 9097646a3..18171c051 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/linux/drivers/media/dvb/ttpci/av7110_ir.c
@@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm)
break;
default:
- printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol);
+ printk("%s invalid protocol %x\n", __func__, ir->protocol);
return;
}
@@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm)
keycode = ir->key_map[data];
dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
- __FUNCTION__, ircom, addr, data, keycode);
+ __func__, ircom, addr, data, keycode);
/* check device address */
if (!(ir->device_mask & (1 << addr)))
@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
if (!keycode) {
printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
- __FUNCTION__, ircom, addr, data);
+ __func__, ircom, addr, data);
return;
}
diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c
index e2f066fb7..b4a0cc5dc 100644
--- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file)
struct saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
- dprintk(2, "%s\n", __FUNCTION__);
+ dprintk(2, "%s\n", __func__);
av7110->wssMode = 0;
av7110->wssData = 0;
if (FW_VERSION(av7110->arm_app) < 0x2623)
@@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
struct v4l2_sliced_vbi_data d;
int rc;
- dprintk(2, "%s\n", __FUNCTION__);
+ dprintk(2, "%s\n", __func__);
if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
return -EINVAL;
if (copy_from_user(&d, data, count))
diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c
index 2d64d557b..b7d1f2f18 100644
--- a/linux/drivers/media/dvb/ttpci/budget-av.c
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c
@@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
udelay(1);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
- if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+ if (result == -ETIMEDOUT) {
ciintf_slot_shutdown(ca, slot);
printk(KERN_INFO "budget-av: cam ejected 3\n");
return -ETIMEDOUT;
@@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = {
.mclk = 88000000UL,
.invert = 0,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = {
.mclk = 88000000UL,
.invert = 0,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_0,
+ .lock_output = STV0299_LOCKOUTPUT_0,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
@@ -667,6 +667,11 @@ static struct tda1002x_config philips_cu1216_config_altaddress = {
.invert = 0,
};
+static struct tda10023_config philips_cu1216_tda10023_config = {
+ .demod_address = 0x0c,
+ .invert = 1,
+};
+
static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
@@ -869,7 +874,7 @@ static struct stv0299_config philips_sd1878_config = {
.mclk = 88000000UL,
.invert = 0,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
@@ -941,6 +946,12 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
+ /*
+ * maybe that setting is needed for other dvb-s cards as well,
+ * but so far it has been only confirmed for this type
+ */
+ budget_av->reinitialise_demod = 1;
+ /* fall through */
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_EASYWATCH_1:
if (saa->pci->subsystem_vendor == 0x1894) {
@@ -1013,9 +1024,10 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_KNC1_PLUS_MK3:
budget_av->reinitialise_demod = 1;
budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
- fe = dvb_attach(tda10023_attach, &philips_cu1216_config,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
+ fe = dvb_attach(tda10023_attach,
+ &philips_cu1216_tda10023_config,
+ &budget_av->budget.i2c_adap,
+ read_pwm(budget_av));
if (fe) {
fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
}
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c
index c35ad070c..8c6ba2edc 100644
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c
@@ -738,7 +738,7 @@ static struct stv0299_config philips_su1278_tt_config = {
.mclk = 64000000UL,
.invert = 0,
.skip_reinit = 1,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 50,
.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
@@ -1131,7 +1131,7 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ printk("%s: No LNBP21 found!\n", __func__);
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
budget_ci->budget.dvb_frontend = NULL;
}
diff --git a/linux/drivers/media/dvb/ttpci/budget-core.c b/linux/drivers/media/dvb/ttpci/budget-core.c
index 0252081f0..18cac4b12 100644
--- a/linux/drivers/media/dvb/ttpci/budget-core.c
+++ b/linux/drivers/media/dvb/ttpci/budget-core.c
@@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/****************************************************************************
* TT budget / WinTV Nova
****************************************************************************/
@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
- budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+ budget->dev->name, __func__, budget->buffer_warnings, count);
budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
budget->buffer_warnings = 0;
}
@@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
budget->buffer_width, budget->buffer_height);
printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
- if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+ ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
+ owner, &budget->dev->pci->dev, adapter_nr);
+ if (ret < 0)
return ret;
- }
/* set dd1 stream a & b */
saa7146_write(dev, DD1_STREAM_B, 0x00000000);
diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c
index 14b00f57b..2293d80c6 100644
--- a/linux/drivers/media/dvb/ttpci/budget.c
+++ b/linux/drivers/media/dvb/ttpci/budget.c
@@ -45,6 +45,7 @@
#include "tda826x.h"
#include "lnbp21.h"
#include "bsru6.h"
+#include "bsbe1.h"
static int diseqc_method;
module_param(diseqc_method, int, 0444);
@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
- struct budget* budget = (struct budget*) fe->dvb->priv;
+ struct budget *budget = fe->dvb->priv;
+ u8 *tuner_addr = fe->tuner_priv;
u32 div;
u8 cfg, cpump, band_select;
u8 data[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+ struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
+
+ if (tuner_addr)
+ msg.addr = *tuner_addr;
+ else
+ msg.addr = 0x61;
div = (36125000 + params->frequency) / 166666;
@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
.demod_address = 0x55,
};
+static struct l64781_config grundig_29504_401_config_activy = {
+ .demod_address = 0x54,
+};
+
+static u8 tuner_address_grundig_29504_401_activy = 0x60;
+
static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -346,14 +359,48 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
static struct s5h1420_config s5h1420_config = {
.demod_address = 0x53,
.invert = 1,
+ .cdclk_polarity = 1,
};
static struct tda10086_config tda10086_config = {
.demod_address = 0x0e,
.invert = 0,
.diseqc_tone = 1,
+ .xtal_freq = TDA10086_XTAL_16M,
};
+static struct stv0299_config alps_bsru6_config_activy = {
+ .demod_address = 0x68,
+ .inittab = alps_bsru6_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .op0_off = 1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_bsru6_set_symbol_rate,
+};
+
+static struct stv0299_config alps_bsbe1_config_activy = {
+ .demod_address = 0x68,
+ .inittab = alps_bsbe1_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .op0_off = 1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_bsbe1_set_symbol_rate,
+};
+
+
+static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
+{
+ u8 val;
+ struct i2c_msg msg[] = {
+ { .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+ };
+
+ return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
+}
+
static u8 read_pwm(struct budget* budget)
{
u8 b = 0xff;
@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
static void frontend_init(struct budget *budget)
{
+ (void)alps_bsbe1_config; /* avoid warning */
+
switch(budget->dev->pci->subsystem_device) {
case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
case 0x1013:
@@ -414,15 +463,43 @@ static void frontend_init(struct budget *budget)
}
break;
- case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
+ {
+ int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
+
+ if (subtype < 0)
+ break;
+ /* fixme: find a better way to identify the card */
+ if (subtype < 0x36) {
+ /* assume ALPS BSRU6 */
+ budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ break;
+ }
+ } else {
+ /* assume ALPS BSBE1 */
+ /* reset tuner */
+ saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
+ msleep(50);
+ saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
+ msleep(250);
+ budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ break;
+ }
}
break;
+ }
case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
@@ -433,12 +510,20 @@ static void frontend_init(struct budget *budget)
}
break;
+ case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
+ budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
+ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+ }
+ break;
+
case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ printk("%s: No LNBP21 found!\n", __func__);
goto error_out;
}
break;
@@ -454,9 +539,9 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
- printk("%s: No tda826x found!\n", __FUNCTION__);
+ printk("%s: No tda826x found!\n", __func__);
if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ printk("%s: No LNBP21 found!\n", __func__);
goto error_out;
}
break;
@@ -537,6 +622,7 @@ MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
@@ -547,6 +633,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
+ MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
{
.vendor = 0,
}
diff --git a/linux/drivers/media/dvb/ttpci/budget.h b/linux/drivers/media/dvb/ttpci/budget.h
index 94922db7a..0e8e596d6 100644
--- a/linux/drivers/media/dvb/ttpci/budget.h
+++ b/linux/drivers/media/dvb/ttpci/budget.h
@@ -1,3 +1,4 @@
+
#ifndef __BUDGET_DVB__
#define __BUDGET_DVB__
@@ -25,10 +26,10 @@ extern int budget_debug;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
#define dprintk(level,args...) \
- do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+ do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __func__); printk(args); } } while (0)
#else
#define dprintk(level,args...) \
- do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
+ do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
#endif
struct budget_info {
diff --git a/linux/drivers/media/dvb/ttpci/ttpci-eeprom.c b/linux/drivers/media/dvb/ttpci/ttpci-eeprom.c
index d6f43269e..bb3ba8153 100644
--- a/linux/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/linux/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
{ .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
};
- /* dprintk("%s\n", __FUNCTION__); */
+ /* dprintk("%s\n", __func__); */
ret = i2c_transfer(adapter, msg, 2);
diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 2e1572fb9..df7add8a9 100644
--- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -59,10 +59,11 @@
*/
static int debug;
-
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
#define ISO_BUF_COUNT 4
@@ -161,12 +162,12 @@ static int ttusb_cmd(struct ttusb *ttusb,
(u8 *) data, len, &actual_len, 1000);
if (err != 0) {
dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
- __FUNCTION__, err);
+ __func__, err);
mutex_unlock(&ttusb->semusb);
return err;
}
if (actual_len != len) {
- dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
+ dprintk("%s: only wrote %d of %d bytes\n", __func__,
actual_len, len);
mutex_unlock(&ttusb->semusb);
return -1;
@@ -176,7 +177,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
ttusb->last_result, 32, &actual_len, 1000);
if (err != 0) {
- printk("%s: failed, receive error %d\n", __FUNCTION__,
+ printk("%s: failed, receive error %d\n", __func__,
err);
mutex_unlock(&ttusb->semusb);
return err;
@@ -237,7 +238,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
if (err || b[0] != 0x55 || b[1] != id) {
dprintk
("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
- __FUNCTION__, err, id);
+ __func__, err, id);
return -EREMOTEIO;
}
@@ -281,7 +282,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
snd_buf, snd_len, rcv_buf, rcv_len);
if (err < rcv_len) {
- dprintk("%s: i == %i\n", __FUNCTION__, i);
+ dprintk("%s: i == %i\n", __func__, i);
break;
}
@@ -335,7 +336,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
done:
if (err) {
dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
- __FUNCTION__, err);
+ __func__, err);
}
return err;
@@ -435,7 +436,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
return err;
- dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
+ dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
get_version[4], get_version[5], get_version[6],
get_version[7], get_version[8]);
@@ -445,7 +446,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
memcmp(get_version + 4, "V 2.2", 5)) {
printk
("%s: unknown STC version %c%c%c%c%c, please report!\n",
- __FUNCTION__, get_version[4], get_version[5],
+ __func__, get_version[4], get_version[5],
get_version[6], get_version[7], get_version[8]);
}
@@ -461,7 +462,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
if (err)
return err;
- printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
+ printk("%s: dsp-version: %c%c%c\n", __func__,
get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
return 0;
}
@@ -484,7 +485,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
/* Diseqc */
if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
- __FUNCTION__, err);
+ __func__, err);
}
return err;
@@ -502,7 +503,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb)
/* SetLNB */
if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
- __FUNCTION__, err);
+ __func__, err);
}
return err;
@@ -536,7 +537,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
err = ttusb_cmd(ttusb, b, sizeof(b), 0);
if (err) {
dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
- __FUNCTION__, err);
+ __func__, err);
}
}
#endif
@@ -559,10 +560,10 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
u16 csum = 0, cc;
int i;
for (i = 0; i < len; i += 2)
- csum ^= le16_to_cpup((u16 *) (muxpack + i));
+ csum ^= le16_to_cpup((__le16 *) (muxpack + i));
if (csum) {
printk("%s: muxpack with incorrect checksum, ignoring\n",
- __FUNCTION__);
+ __func__);
numinvalid++;
return;
}
@@ -571,7 +572,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
cc &= 0x7FFF;
if ((cc != ttusb->cc) && (ttusb->cc != -1))
printk("%s: cc discontinuity (%d frames missing)\n",
- __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
+ __func__, (cc - ttusb->cc) & 0x7FFF);
ttusb->cc = (cc + 1) & 0x7FFF;
if (muxpack[0] & 0x80) {
#ifdef TTUSB_HWSECTIONS
@@ -621,7 +622,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
int maxwork = 1024;
while (len) {
if (!(maxwork--)) {
- printk("%s: too much work\n", __FUNCTION__);
+ printk("%s: too much work\n", __func__);
break;
}
@@ -640,7 +641,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
#else
if (ttusb->insync) {
printk("%s: lost sync.\n",
- __FUNCTION__);
+ __func__);
ttusb->insync = 0;
}
#endif
@@ -699,7 +700,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
else {
dprintk
("%s: invalid state: first byte is %x\n",
- __FUNCTION__,
+ __func__,
ttusb->muxpack[0]);
ttusb->mux_state = 0;
}
@@ -752,7 +753,7 @@ static void ttusb_iso_irq(struct urb *urb)
#if 0 /* keep */
printk("%s: status %d, errcount == %d, length == %i\n",
- __FUNCTION__,
+ __func__,
urb->status, urb->error_count, urb->actual_length);
#endif
@@ -845,7 +846,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
int i, j, err, buffer_offset = 0;
if (ttusb->iso_streaming) {
- printk("%s: iso xfer already running!\n", __FUNCTION__);
+ printk("%s: iso xfer already running!\n", __func__);
return 0;
}
@@ -881,7 +882,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
ttusb_stop_iso_xfer(ttusb);
printk
("%s: failed urb submission (%i: err = %i)!\n",
- __FUNCTION__, i, err);
+ __func__, i, err);
return err;
}
}
@@ -1325,7 +1326,7 @@ static struct stv0299_config alps_stv0299_config = {
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_1,
+ .lock_output = STV0299_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_stv0299_set_symbol_rate,
@@ -1655,7 +1656,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
struct ttusb *ttusb;
int result;
- dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
+ dprintk("%s: TTUSB DVB connected\n", __func__);
udev = interface_to_usbdev(intf);
@@ -1681,7 +1682,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
mutex_unlock(&ttusb->semi2c);
- if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
+ result = dvb_register_adapter(&ttusb->adapter,
+ "Technotrend/Hauppauge Nova-USB",
+ THIS_MODULE, &udev->dev, adapter_nr);
+ if (result < 0) {
ttusb_free_iso_urbs(ttusb);
kfree(ttusb);
return result;
@@ -1785,7 +1789,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
kfree(ttusb);
- dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
+ dprintk("%s: TTUSB DVB disconnected\n", __func__);
}
static struct usb_device_id ttusb_table[] = {
diff --git a/linux/drivers/media/dvb/ttusb-dec/Kconfig b/linux/drivers/media/dvb/ttusb-dec/Kconfig
index 83611012e..a23cc0aa1 100644
--- a/linux/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/linux/drivers/media/dvb/ttusb-dec/Kconfig
@@ -1,6 +1,7 @@
config DVB_TTUSB_DEC
tristate "Technotrend/Hauppauge USB DEC devices"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && INPUT
+ depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
select CRC32
help
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index f6667cf3d..052979dc9 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -55,6 +55,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
module_param(enable_rc, int, 0644);
MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define dprintk if (debug) printk
#define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB"
@@ -232,11 +234,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
case -ETIME:
/* this urb is dead, cleanup */
dprintk("%s:urb shutting down with status: %d\n",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
return;
default:
dprintk("%s:nonzero status received: %d\n",
- __FUNCTION__,urb->status);
+ __func__,urb->status);
goto exit;
}
@@ -250,7 +252,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
* keyrepeat signal is recieved for lets say 200ms.
* this should/could be added later ...
* for now lets report each signal as a key down and up*/
- dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
+ dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
input_sync(dec->rc_input_dev);
input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
@@ -260,7 +262,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
if(retval)
printk("%s - usb_commit_urb failed with result: %d\n",
- __FUNCTION__, retval);
+ __func__, retval);
}
static u16 crc16(u16 crc, const u8 *buf, size_t len)
@@ -283,7 +285,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
int result, actual_len, i;
u8 *b;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
if (!b)
@@ -291,7 +293,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
kfree(b);
- printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
+ printk("%s: Failed to lock usb mutex.\n", __func__);
return result;
}
@@ -304,7 +306,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
memcpy(&b[4], params, param_length);
if (debug) {
- printk("%s: command: ", __FUNCTION__);
+ printk("%s: command: ", __func__);
for (i = 0; i < param_length + 4; i++)
printk("0x%02X ", b[i]);
printk("\n");
@@ -315,7 +317,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
if (result) {
printk("%s: command bulk message failed: error %d\n",
- __FUNCTION__, result);
+ __func__, result);
mutex_unlock(&dec->usb_mutex);
kfree(b);
return result;
@@ -326,13 +328,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
if (result) {
printk("%s: result bulk message failed: error %d\n",
- __FUNCTION__, result);
+ __func__, result);
mutex_unlock(&dec->usb_mutex);
kfree(b);
return result;
} else {
if (debug) {
- printk("%s: result: ", __FUNCTION__);
+ printk("%s: result: ", __func__);
for (i = 0; i < actual_len; i++)
printk("0x%02X ", b[i]);
printk("\n");
@@ -356,9 +358,9 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
- unsigned int tmp;
+ __be32 tmp;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
if (result)
@@ -411,11 +413,11 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
- u16 pcr = htons(dec->pid[DMX_PES_PCR]);
- u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
- u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+ __be16 pcr = htons(dec->pid[DMX_PES_PCR]);
+ __be16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+ __be16 video = htons(dec->pid[DMX_PES_VIDEO]);
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
memcpy(&b[0], &pcr, 2);
memcpy(&b[2], &audio, 2);
@@ -434,12 +436,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
{
if (length < 8) {
- printk("%s: packet too short - discarding\n", __FUNCTION__);
+ printk("%s: packet too short - discarding\n", __func__);
return;
}
if (length > 8 + MAX_PVA_LENGTH) {
- printk("%s: packet too long - discarding\n", __FUNCTION__);
+ printk("%s: packet too long - discarding\n", __func__);
return;
}
@@ -448,7 +450,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x01: { /* VideoStream */
int prebytes = pva[5] & 0x03;
int postbytes = (pva[5] & 0x0c) >> 2;
- u16 v_pes_payload_length;
+ __be16 v_pes_payload_length;
if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
@@ -522,7 +524,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
break;
default:
- printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
+ printk("%s: unknown PVA type: %02x.\n", __func__,
pva[2]);
break;
}
@@ -561,7 +563,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
u16 packet_id;
if (dec->packet_length % 2) {
- printk("%s: odd sized packet - discarding\n", __FUNCTION__);
+ printk("%s: odd sized packet - discarding\n", __func__);
return;
}
@@ -569,7 +571,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
if (csum) {
- printk("%s: checksum failed - discarding\n", __FUNCTION__);
+ printk("%s: checksum failed - discarding\n", __func__);
return;
}
@@ -578,7 +580,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
printk("%s: warning: lost packets between %u and %u\n",
- __FUNCTION__, dec->next_packet_id - 1, packet_id);
+ __func__, dec->next_packet_id - 1, packet_id);
}
if (packet_id == 0xffff)
@@ -667,7 +669,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
dec->packet_state = 7;
} else {
printk("%s: unknown packet type: "
- "%02x%02x\n", __FUNCTION__,
+ "%02x%02x\n", __func__,
dec->packet[0], dec->packet[1]);
dec->packet_state = 0;
}
@@ -739,7 +741,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
default:
printk("%s: illegal packet state encountered.\n",
- __FUNCTION__);
+ __func__);
dec->packet_state = 0;
}
}
@@ -811,7 +813,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
} else {
/* -ENOENT is expected when unlinking urbs */
if (urb->status != -ENOENT)
- dprintk("%s: urb error: %d\n", __FUNCTION__,
+ dprintk("%s: urb error: %d\n", __func__,
urb->status);
}
@@ -823,7 +825,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
{
int i, j, buffer_offset = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
for (i = 0; i < ISO_BUF_COUNT; i++) {
int frame_offset = 0;
@@ -853,7 +855,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
{
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (mutex_lock_interruptible(&dec->iso_mutex))
return;
@@ -908,7 +910,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
{
int i, result;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (mutex_lock_interruptible(&dec->iso_mutex))
return -EAGAIN;
@@ -924,7 +926,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
if ((result = usb_submit_urb(dec->iso_urb[i],
GFP_ATOMIC))) {
printk("%s: failed urb submission %d: "
- "error %d\n", __FUNCTION__, i, result);
+ "error %d\n", __func__, i, result);
while (i) {
usb_kill_urb(dec->iso_urb[i - 1]);
@@ -951,7 +953,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
u8 b0[] = { 0x05 };
int result = 0;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dprintk(" ts_type:");
@@ -1023,7 +1025,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00 };
- u16 pid;
+ __be16 pid;
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
@@ -1031,7 +1033,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
unsigned long flags;
u8 x = 1;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
pid = htons(dvbdmxfeed->pid);
memcpy(&b0[0], &pid, 2);
@@ -1071,7 +1073,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (!dvbdmx->dmx.frontend)
return -EINVAL;
@@ -1132,7 +1134,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
@@ -1151,7 +1153,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
{
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
for (i = 0; i < ISO_BUF_COUNT; i++)
usb_free_urb(dec->iso_urb[i]);
@@ -1166,7 +1168,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
{
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dec->iso_buffer = pci_alloc_consistent(NULL,
ISO_FRAME_SIZE *
@@ -1233,7 +1235,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
dec->rc_input_dev = input_dev;
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
- printk("%s: usb_submit_urb failed\n",__FUNCTION__);
+ printk("%s: usb_submit_urb failed\n",__func__);
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
@@ -1242,7 +1244,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dec->v_pes[0] = 0x00;
dec->v_pes[1] = 0x00;
@@ -1252,7 +1254,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
static int ttusb_dec_init_usb(struct ttusb_dec *dec)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
mutex_init(&dec->usb_mutex);
mutex_init(&dec->iso_mutex);
@@ -1295,16 +1297,17 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
u8 *firmware = NULL;
size_t firmware_size = 0;
u16 firmware_csum = 0;
- u16 firmware_csum_ns;
- u32 firmware_size_nl;
- u32 crc32_csum, crc32_check, tmp;
+ __be16 firmware_csum_ns;
+ __be32 firmware_size_nl;
+ u32 crc32_csum, crc32_check;
+ __be32 tmp;
const struct firmware *fw_entry = NULL;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
- __FUNCTION__, dec->firmware_name);
+ __func__, dec->firmware_name);
return 1;
}
@@ -1313,7 +1316,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
if (firmware_size < 60) {
printk("%s: firmware size too small for DSP code (%zu < 60).\n",
- __FUNCTION__, firmware_size);
+ __func__, firmware_size);
release_firmware(fw_entry);
return -1;
}
@@ -1323,11 +1326,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
valid. */
crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
memcpy(&tmp, &firmware[56], 4);
- crc32_check = htonl(tmp);
+ crc32_check = ntohl(tmp);
if (crc32_csum != crc32_check) {
printk("%s: crc32 check of DSP code failed (calculated "
"0x%08x != 0x%08x in file), file invalid.\n",
- __FUNCTION__, crc32_csum, crc32_check);
+ __func__, crc32_csum, crc32_check);
release_firmware(fw_entry);
return -1;
}
@@ -1395,7 +1398,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
int result;
unsigned int mode, model, version;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
@@ -1434,7 +1437,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
default:
printk(KERN_ERR "%s: unknown model returned "
"by firmware (%08x) - please report\n",
- __FUNCTION__, model);
+ __func__, model);
return -1;
break;
}
@@ -1453,12 +1456,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
{
int result;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if ((result = dvb_register_adapter(&dec->adapter,
- dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
+ dec->model_name, THIS_MODULE,
+ &dec->udev->dev,
+ adapter_nr)) < 0) {
printk("%s: dvb_register_adapter failed: error %d\n",
- __FUNCTION__, result);
+ __func__, result);
return result;
}
@@ -1473,7 +1478,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dec->demux.write_to_decoder = NULL;
if ((result = dvb_dmx_init(&dec->demux)) < 0) {
- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
result);
dvb_unregister_adapter(&dec->adapter);
@@ -1487,7 +1492,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
printk("%s: dvb_dmxdev_init failed: error %d\n",
- __FUNCTION__, result);
+ __func__, result);
dvb_dmx_release(&dec->demux);
dvb_unregister_adapter(&dec->adapter);
@@ -1499,7 +1504,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
&dec->frontend)) < 0) {
- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
result);
dvb_dmxdev_release(&dec->dmxdev);
@@ -1511,7 +1516,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
&dec->frontend)) < 0) {
- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
result);
dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
@@ -1529,7 +1534,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dvb_net_release(&dec->dvb_net);
dec->demux.dmx.close(&dec->demux.dmx);
@@ -1547,7 +1552,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
{
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
/* we have to check whether the irq URB is already submitted.
* As the irq is submitted after the interface is changed,
* this is the best method i figured out.
@@ -1571,7 +1576,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
{
int i;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
dec->iso_stream_count = 0;
@@ -1631,18 +1636,18 @@ static int ttusb_dec_probe(struct usb_interface *intf,
struct usb_device *udev;
struct ttusb_dec *dec;
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
udev = interface_to_usbdev(intf);
if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
- printk("%s: couldn't allocate memory.\n", __FUNCTION__);
+ printk("%s: couldn't allocate memory.\n", __func__);
return -ENOMEM;
}
usb_set_intfdata(intf, (void *)dec);
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
@@ -1667,7 +1672,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_dvb(dec);
dec->adapter.priv = dec;
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
break;
@@ -1711,7 +1716,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
- dprintk("%s\n", __FUNCTION__);
+ dprintk("%s\n", __func__);
if (dec->active) {
ttusb_dec_exit_tasklet(dec);
@@ -1768,7 +1773,7 @@ static int __init ttusb_dec_init(void)
int result;
if ((result = usb_register(&ttusb_dec_driver)) < 0) {
- printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
+ printk("%s: initialisation failed: error %d.\n", __func__,
result);
return result;
}
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index a6fb1d6a7..443af2409 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
return ret;
if(len != 4) {
- printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+ printk(KERN_ERR "%s: unexpected reply\n", __func__);
return -EIO;
}
@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
break;
default:
pr_info("%s: returned unknown value: %d\n",
- __FUNCTION__, result[3]);
+ __func__, result[3]);
return -EIO;
}
@@ -86,7 +86,7 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff };
- u32 freq = htonl(p->frequency / 1000);
+ __be32 freq = htonl(p->frequency / 1000);
memcpy(&b[4], &freq, sizeof (u32));
state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
@@ -117,10 +117,10 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
- u32 freq;
- u32 sym_rate;
- u32 band;
- u32 lnb_voltage;
+ __be32 freq;
+ __be32 sym_rate;
+ __be32 band;
+ __be32 lnb_voltage;
freq = htonl(p->frequency +
(state->hi_band ? LOF_HI : LOF_LO));
diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c
index 25e59032f..7b9afd7e6 100644
--- a/linux/drivers/media/radio/radio-aimslab.c
+++ b/linux/drivers/media/radio/radio-aimslab.c
@@ -37,7 +37,6 @@
#include "compat.h"
#include <linux/videodev2.h> /* kernel radio structs */
#include <media/v4l2-common.h>
-#include <asm/semaphore.h> /* Lock for the I/O */
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
#define RADIO_VERSION KERNEL_VERSION(0,0,2)
diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c
index 83333734e..b41eddd4f 100644
--- a/linux/drivers/media/radio/radio-si470x.c
+++ b/linux/drivers/media/radio/radio-si470x.c
@@ -24,6 +24,19 @@
/*
+ * User Notes:
+ * - USB Audio is provided by the alsa snd_usb_audio module.
+ * For listing you have to redirect the sound, for example using:
+ * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
+ * - regarding module parameters in /sys/module/radio_si470x/parameters:
+ * the contents of read-only files (0444) are not updated, even if
+ * space, band and de are changed using private video controls
+ * - increase tune_timeout, if you often get -EIO errors
+ * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached
+ */
+
+
+/*
* History:
* 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.0
@@ -85,10 +98,14 @@
* Oliver Neukum <oliver@neukum.org>
* Version 1.0.7
* - usb autosuspend support
- * - unplugging fixed
+ * - unplugging fixed
+ * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
+ * Version 1.0.8
+ * - hardware frequency seek support
+ * - afc indication
+ * - more safety checks, let si470x_get_freq return errno
*
* ToDo:
- * - add seeking support
* - add firmware download/update support
* - RDS support: interrupt mode, instead of polling
* - add LED status output (check if that's not already done in firmware)
@@ -98,10 +115,10 @@
/* driver definitions */
#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
#define DRIVER_NAME "radio-si470x"
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8)
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.7"
+#define DRIVER_VERSION "1.0.8"
/* kernel includes */
@@ -178,6 +195,11 @@ static unsigned int tune_timeout = 3000;
module_param(tune_timeout, uint, 0);
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
+/* Seek timeout */
+static unsigned int seek_timeout = 5000;
+module_param(seek_timeout, uint, 0);
+MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
+
/* RDS buffer blocks */
static unsigned int rds_buf = 100;
module_param(rds_buf, uint, 0);
@@ -428,7 +450,8 @@ struct si470x_device {
/* driver management */
unsigned int users;
- unsigned char disconnected;
+ unsigned char disconnected;
+ struct mutex disconnect_lock;
/* Silabs internal registers (0..15) */
unsigned short registers[RADIO_REGISTER_NUM];
@@ -453,12 +476,6 @@ struct si470x_device {
/*
- * Lock to prevent kfree of data before all users have releases the device.
- */
-static DEFINE_MUTEX(open_close_lock);
-
-
-/*
* The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
* 62.5 kHz otherwise.
* The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
@@ -487,11 +504,11 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
report[0], 2,
buf, size, usb_timeout);
+
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": si470x_get_report: usb_control_msg returned %d\n",
retval);
-
return retval;
}
@@ -510,11 +527,11 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
report[0], 2,
buf, size, usb_timeout);
+
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": si470x_set_report: usb_control_msg returned %d\n",
retval);
-
return retval;
}
@@ -532,8 +549,7 @@ static int si470x_get_register(struct si470x_device *radio, int regnr)
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
if (retval >= 0)
- radio->registers[regnr] = be16_to_cpu(get_unaligned(
- (unsigned short *) &buf[1]));
+ radio->registers[regnr] = get_unaligned_be16(&buf[1]);
return (retval < 0) ? -EINVAL : 0;
}
@@ -548,8 +564,7 @@ static int si470x_set_register(struct si470x_device *radio, int regnr)
int retval;
buf[0] = REGISTER_REPORT(regnr);
- put_unaligned(cpu_to_be16(radio->registers[regnr]),
- (unsigned short *) &buf[1]);
+ put_unaligned_be16(radio->registers[regnr], &buf[1]);
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
@@ -572,9 +587,8 @@ static int si470x_get_all_registers(struct si470x_device *radio)
if (retval >= 0)
for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
- radio->registers[regnr] = be16_to_cpu(get_unaligned(
- (unsigned short *)
- &buf[regnr * RADIO_REGISTER_SIZE + 1]));
+ radio->registers[regnr] = get_unaligned_be16(
+ &buf[regnr * RADIO_REGISTER_SIZE + 1]);
return (retval < 0) ? -EINVAL : 0;
}
@@ -596,7 +610,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
usb_rcvintpipe(radio->usbdev, 1),
(void *) &buf, sizeof(buf), &size, usb_timeout);
if (size != sizeof(buf))
- printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+ printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
"return size differs: %d != %zu\n", size, sizeof(buf));
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -605,8 +619,8 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
if (retval >= 0)
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
radio->registers[STATUSRSSI + regnr] =
- be16_to_cpu(get_unaligned((unsigned short *)
- &buf[regnr * RADIO_REGISTER_SIZE + 1]));
+ get_unaligned_be16(
+ &buf[regnr * RADIO_REGISTER_SIZE + 1]);
return (retval < 0) ? -EINVAL : 0;
}
@@ -626,33 +640,39 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
retval = si470x_set_register(radio, CHANNEL);
if (retval < 0)
- return retval;
+ goto done;
- /* wait till seek operation has completed */
+ /* wait till tune operation has completed */
timeout = jiffies + msecs_to_jiffies(tune_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
- return retval;
+ goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
(!timed_out));
+ if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
+ printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n");
if (timed_out)
printk(KERN_WARNING DRIVER_NAME
- ": seek does not finish after %u ms\n", tune_timeout);
+ ": tune timed out after %u ms\n", tune_timeout);
+stop:
/* stop tuning */
radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
- return si470x_set_register(radio, CHANNEL);
+ retval = si470x_set_register(radio, CHANNEL);
+
+done:
+ return retval;
}
/*
* si470x_get_freq - get the frequency
*/
-static unsigned int si470x_get_freq(struct si470x_device *radio)
+static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
{
- unsigned int spacing, band_bottom, freq;
+ unsigned int spacing, band_bottom;
unsigned short chan;
int retval;
@@ -678,14 +698,12 @@ static unsigned int si470x_get_freq(struct si470x_device *radio)
/* read channel */
retval = si470x_get_register(radio, READCHAN);
- if (retval < 0)
- return retval;
chan = radio->registers[READCHAN] & READCHAN_READCHAN;
/* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
- freq = chan * spacing + band_bottom;
+ *freq = chan * spacing + band_bottom;
- return freq;
+ return retval;
}
@@ -725,6 +743,62 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
/*
+ * si470x_set_seek - set seek
+ */
+static int si470x_set_seek(struct si470x_device *radio,
+ unsigned int wrap_around, unsigned int seek_upward)
+{
+ int retval = 0;
+ unsigned long timeout;
+ bool timed_out = 0;
+
+ /* start seeking */
+ radio->registers[POWERCFG] |= POWERCFG_SEEK;
+ if (wrap_around == 1)
+ radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
+ else
+ radio->registers[POWERCFG] |= POWERCFG_SKMODE;
+ if (seek_upward == 1)
+ radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
+ else
+ radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
+ retval = si470x_set_register(radio, POWERCFG);
+ if (retval < 0)
+ goto done;
+
+ /* wait till seek operation has completed */
+ timeout = jiffies + msecs_to_jiffies(seek_timeout);
+ do {
+ retval = si470x_get_register(radio, STATUSRSSI);
+ if (retval < 0)
+ goto stop;
+ timed_out = time_after(jiffies, timeout);
+ } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
+ (!timed_out));
+ if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
+ printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n");
+ if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
+ printk(KERN_WARNING DRIVER_NAME
+ ": seek failed / band limit reached\n");
+ if (timed_out)
+ printk(KERN_WARNING DRIVER_NAME
+ ": seek timed out after %u ms\n", seek_timeout);
+
+stop:
+ /* stop seeking */
+ radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
+ retval = si470x_set_register(radio, POWERCFG);
+
+done:
+ /* try again, if timed out */
+ if ((retval == 0) && timed_out)
+ retval = -EAGAIN;
+
+ return retval;
+}
+
+
+/*
* si470x_start - switch on radio
*/
static int si470x_start(struct si470x_device *radio)
@@ -736,27 +810,30 @@ static int si470x_start(struct si470x_device *radio)
POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
retval = si470x_set_register(radio, POWERCFG);
if (retval < 0)
- return retval;
+ goto done;
/* sysconfig 1 */
radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
- return retval;
+ goto done;
/* sysconfig 2 */
radio->registers[SYSCONFIG2] =
- (0x3f << 8) | /* SEEKTH */
- (band << 6) | /* BAND */
- (space << 4) | /* SPACE */
- 15; /* VOLUME (max) */
+ (0x3f << 8) | /* SEEKTH */
+ ((band << 6) & SYSCONFIG2_BAND) | /* BAND */
+ ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */
+ 15; /* VOLUME (max) */
retval = si470x_set_register(radio, SYSCONFIG2);
if (retval < 0)
- return retval;
+ goto done;
/* reset last channel */
- return si470x_set_chan(radio,
+ retval = si470x_set_chan(radio,
radio->registers[CHANNEL] & CHANNEL_CHAN);
+
+done:
+ return retval;
}
@@ -771,13 +848,16 @@ static int si470x_stop(struct si470x_device *radio)
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
- return retval;
+ goto done;
/* powercfg */
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
/* POWERCFG_ENABLE has to automatically go low */
radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
- return si470x_set_register(radio, POWERCFG);
+ retval = si470x_set_register(radio, POWERCFG);
+
+done:
+ return retval;
}
@@ -854,7 +934,7 @@ static void si470x_rds(struct si470x_device *radio)
};
/* Fill the V4L2 RDS buffer */
- put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf);
+ put_unaligned_le16(rds, &tmpbuf);
tmpbuf[2] = blocknum; /* offset name */
tmpbuf[2] |= blocknum << 3; /* received offset */
if (bler > max_rds_errors)
@@ -894,8 +974,9 @@ static void si470x_work(struct work_struct *work)
struct si470x_device *radio = container_of(work, struct si470x_device,
work.work);
- if (radio->disconnected)
- return;
+ /* safety checks */
+ if (radio->disconnected)
+ return;
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
return;
@@ -928,11 +1009,15 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
/* block if no new data available */
while (radio->wr_index == radio->rd_index) {
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EWOULDBLOCK;
+ goto done;
+ }
if (wait_event_interruptible(radio->read_queue,
- radio->wr_index != radio->rd_index) < 0)
- return -EINTR;
+ radio->wr_index != radio->rd_index) < 0) {
+ retval = -EINTR;
+ goto done;
+ }
}
/* calculate block count from byte count */
@@ -961,6 +1046,7 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
}
mutex_unlock(&radio->lock);
+done:
return retval;
}
@@ -972,6 +1058,7 @@ static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
@@ -983,9 +1070,9 @@ static unsigned int si470x_fops_poll(struct file *file,
poll_wait(file, &radio->read_queue, pts);
if (radio->rd_index != radio->wr_index)
- return POLLIN | POLLRDNORM;
+ retval = POLLIN | POLLRDNORM;
- return 0;
+ return retval;
}
@@ -1002,17 +1089,18 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
retval = usb_autopm_get_interface(radio->intf);
if (retval < 0) {
radio->users--;
- return -EIO;
+ retval = -EIO;
+ goto done;
}
if (radio->users == 1) {
retval = si470x_start(radio);
if (retval < 0)
usb_autopm_put_interface(radio->intf);
- return retval;
}
- return 0;
+done:
+ return retval;
}
@@ -1022,20 +1110,23 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
static int si470x_fops_release(struct inode *inode, struct file *file)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval = 0;
+ int retval = 0;
- if (!radio)
- return -ENODEV;
+ /* safety check */
+ if (!radio) {
+ retval = -ENODEV;
+ goto done;
+ }
- mutex_lock(&open_close_lock);
+ mutex_lock(&radio->disconnect_lock);
radio->users--;
if (radio->users == 0) {
- if (radio->disconnected) {
- video_unregister_device(radio->videodev);
- kfree(radio->buffer);
- kfree(radio);
- goto done;
- }
+ if (radio->disconnected) {
+ video_unregister_device(radio->videodev);
+ kfree(radio->buffer);
+ kfree(radio);
+ goto unlock;
+ }
/* stop rds reception */
cancel_delayed_work_sync(&radio->work);
@@ -1047,9 +1138,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
usb_autopm_put_interface(radio->intf);
}
+unlock:
+ mutex_unlock(&radio->disconnect_lock);
+
done:
- mutex_unlock(&open_close_lock);
- return retval;
+ return retval;
}
@@ -1127,7 +1220,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
sprintf(capability->bus_info, "USB");
capability->version = DRIVER_KERNEL_VERSION;
- capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
+ V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0;
}
@@ -1136,7 +1230,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
/*
* si470x_vidioc_g_input - get input
*/
-static int si470x_vidioc_g_input(struct file *filp, void *priv,
+static int si470x_vidioc_g_input(struct file *file, void *priv,
unsigned int *i)
{
*i = 0;
@@ -1148,12 +1242,18 @@ static int si470x_vidioc_g_input(struct file *filp, void *priv,
/*
* si470x_vidioc_s_input - set input
*/
-static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
+ int retval = 0;
+
+ /* safety checks */
if (i != 0)
- return -EINVAL;
+ retval = -EINVAL;
- return 0;
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": set input failed with %d\n", retval);
+ return retval;
}
@@ -1166,17 +1266,22 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv,
unsigned char i;
int retval = -EINVAL;
+ /* safety checks */
+ if (!qc->id)
+ goto done;
+
for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
- if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) {
+ if (qc->id == si470x_v4l2_queryctrl[i].id) {
memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
retval = 0;
break;
}
}
+
+done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
- ": query control failed with %d\n", retval);
-
+ ": query controls failed with %d\n", retval);
return retval;
}
@@ -1188,9 +1293,13 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -1201,9 +1310,15 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
ctrl->value = ((radio->registers[POWERCFG] &
POWERCFG_DMUTE) == 0) ? 1 : 0;
break;
+ default:
+ retval = -EINVAL;
}
- return 0;
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": get control failed with %d\n", retval);
+ return retval;
}
@@ -1214,10 +1329,13 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval;
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -1235,10 +1353,11 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
default:
retval = -EINVAL;
}
+
+done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set control failed with %d\n", retval);
-
return retval;
}
@@ -1249,13 +1368,22 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
static int si470x_vidioc_g_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
- if (audio->index > 1)
- return -EINVAL;
+ int retval = 0;
+
+ /* safety checks */
+ if (audio->index != 0) {
+ retval = -EINVAL;
+ goto done;
+ }
strcpy(audio->name, "Radio");
audio->capability = V4L2_AUDCAP_STEREO;
- return 0;
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": get audio failed with %d\n", retval);
+ return retval;
}
@@ -1265,10 +1393,19 @@ static int si470x_vidioc_g_audio(struct file *file, void *priv,
static int si470x_vidioc_s_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
- if (audio->index != 0)
- return -EINVAL;
+ int retval = 0;
- return 0;
+ /* safety checks */
+ if (audio->index != 0) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": set audio failed with %d\n", retval);
+ return retval;
}
@@ -1279,20 +1416,23 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval;
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
- if (tuner->index > 0)
- return -EINVAL;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
+ if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
+ retval = -EINVAL;
+ goto done;
+ }
- /* read status rssi */
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
- return retval;
+ goto done;
strcpy(tuner->name, "FM");
- tuner->type = V4L2_TUNER_RADIO;
switch (band) {
/* 0: 87.5 - 108 MHz (USA, Europe, default) */
default:
@@ -1324,9 +1464,14 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
* 0x0101;
/* automatic frequency control: -1: freq to low, 1 freq to high */
- tuner->afc = 0;
+ /* AFCRL does only indicate that freq. differs, not if too low/high */
+ tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
- return 0;
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": get tuner failed with %d\n", retval);
+ return retval;
}
@@ -1337,12 +1482,17 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval;
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
- if (tuner->index > 0)
- return -EINVAL;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
+ if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
+ retval = -EINVAL;
+ goto done;
+ }
if (tuner->audmode == V4L2_TUNER_MODE_MONO)
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
@@ -1350,10 +1500,11 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
retval = si470x_set_register(radio, POWERCFG);
+
+done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set tuner failed with %d\n", retval);
-
return retval;
}
@@ -1365,14 +1516,25 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
+ if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ retval = -EINVAL;
+ goto done;
+ }
- freq->type = V4L2_TUNER_RADIO;
- freq->frequency = si470x_get_freq(radio);
+ retval = si470x_get_freq(radio, &freq->frequency);
- return 0;
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": get frequency failed with %d\n", retval);
+ return retval;
}
@@ -1383,19 +1545,55 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval;
+ int retval = 0;
- if (radio->disconnected)
- return -EIO;
- if (freq->type != V4L2_TUNER_RADIO)
- return -EINVAL;
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
+ if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ retval = -EINVAL;
+ goto done;
+ }
retval = si470x_set_freq(radio, freq->frequency);
+
+done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
": set frequency failed with %d\n", retval);
+ return retval;
+}
- return 0;
+
+/*
+ * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
+ */
+static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
+ struct v4l2_hw_freq_seek *seek)
+{
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval = 0;
+
+ /* safety checks */
+ if (radio->disconnected) {
+ retval = -EIO;
+ goto done;
+ }
+ if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
+
+done:
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME
+ ": set hardware frequency seek failed with %d\n",
+ retval);
+ return retval;
}
@@ -1419,6 +1617,7 @@ static struct video_device si470x_viddev_template = {
.vidioc_s_tuner = si470x_vidioc_s_tuner,
.vidioc_g_frequency = si470x_vidioc_g_frequency,
.vidioc_s_frequency = si470x_vidioc_s_frequency,
+ .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
.owner = THIS_MODULE,
};
@@ -1435,31 +1634,36 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct si470x_device *radio;
- int retval = -ENOMEM;
+ int retval = 0;
- /* private data allocation */
+ /* private data allocation and initialization */
radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
- if (!radio)
+ if (!radio) {
+ retval = -ENOMEM;
goto err_initial;
+ }
+ radio->users = 0;
+ radio->disconnected = 0;
+ radio->usbdev = interface_to_usbdev(intf);
+ radio->intf = intf;
+ mutex_init(&radio->disconnect_lock);
+ mutex_init(&radio->lock);
- /* video device allocation */
+ /* video device allocation and initialization */
radio->videodev = video_device_alloc();
- if (!radio->videodev)
+ if (!radio->videodev) {
+ retval = -ENOMEM;
goto err_radio;
-
- /* initial configuration */
+ }
memcpy(radio->videodev, &si470x_viddev_template,
sizeof(si470x_viddev_template));
- radio->users = 0;
- radio->usbdev = interface_to_usbdev(intf);
- radio->intf = intf;
- mutex_init(&radio->lock);
video_set_drvdata(radio->videodev, radio);
/* show some infos about the specific device */
- retval = -EIO;
- if (si470x_get_all_registers(radio) < 0)
+ if (si470x_get_all_registers(radio) < 0) {
+ retval = -EIO;
goto err_all;
+ }
printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
radio->registers[DEVICEID], radio->registers[CHIPID]);
@@ -1485,8 +1689,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
/* rds buffer allocation */
radio->buf_size = rds_buf * 3;
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
- if (!radio->buffer)
+ if (!radio->buffer) {
+ retval = -EIO;
goto err_all;
+ }
/* rds buffer configuration */
radio->wr_index = 0;
@@ -1498,6 +1704,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
/* register video device */
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+ retval = -EIO;
printk(KERN_WARNING DRIVER_NAME
": Could not register video device\n");
goto err_all;
@@ -1557,16 +1764,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
{
struct si470x_device *radio = usb_get_intfdata(intf);
- mutex_lock(&open_close_lock);
- radio->disconnected = 1;
+ mutex_lock(&radio->disconnect_lock);
+ radio->disconnected = 1;
cancel_delayed_work_sync(&radio->work);
usb_set_intfdata(intf, NULL);
- if (radio->users == 0) {
- video_unregister_device(radio->videodev);
- kfree(radio->buffer);
- kfree(radio);
- }
- mutex_unlock(&open_close_lock);
+ if (radio->users == 0) {
+ video_unregister_device(radio->videodev);
+ kfree(radio->buffer);
+ kfree(radio);
+ }
+ mutex_unlock(&radio->disconnect_lock);
}
diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c
index 22c999461..5db38526e 100644
--- a/linux/drivers/media/radio/radio-typhoon.c
+++ b/linux/drivers/media/radio/radio-typhoon.c
@@ -35,6 +35,7 @@
#include <linux/init.h> /* Initdata */
#include <linux/ioport.h> /* request_region */
#include <linux/proc_fs.h> /* radio card status report */
+#include <linux/seq_file.h>
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
#include "compat.h"
@@ -98,9 +99,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
static void typhoon_mute(struct typhoon_device *dev);
static void typhoon_unmute(struct typhoon_device *dev);
static int typhoon_setvol(struct typhoon_device *dev, int vol);
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
-#endif
static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
{
@@ -373,30 +371,39 @@ static struct video_device typhoon_radio =
#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
+static int typhoon_proc_show(struct seq_file *m, void *v)
{
- char *out = buf;
-
#ifdef MODULE
#define MODULEPROCSTRING "Driver loaded as a module"
#else
#define MODULEPROCSTRING "Driver compiled into kernel"
#endif
- /* output must be kept under PAGE_SIZE */
- out += sprintf(out, BANNER);
- out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
- out += sprintf(out, "frequency = %lu kHz\n",
+ seq_puts(m, BANNER);
+ seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
+ seq_printf(m, "frequency = %lu kHz\n",
typhoon_unit.curfreq >> 4);
- out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
- out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
+ seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
+ seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
"on" : "off");
- out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
- out += sprintf(out, "mute frequency = %lu kHz\n",
+ seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
+ seq_printf(m, "mute frequency = %lu kHz\n",
typhoon_unit.mutefreq >> 4);
- return out - buf;
+ return 0;
}
+static int typhoon_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, typhoon_proc_show, NULL);
+}
+
+static const struct file_operations typhoon_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = typhoon_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
MODULE_AUTHOR("Dr. Henrik Seidel");
@@ -457,8 +464,7 @@ static int __init typhoon_init(void)
typhoon_mute(&typhoon_unit);
#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
- if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
- typhoon_get_info))
+ if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
#endif
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index 31823b8f2..edd5a652d 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -1,4 +1,54 @@
#
+# Generic video config states
+#
+
+config VIDEO_V4L2
+ tristate
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ default VIDEO_DEV && VIDEO_V4L2_COMMON
+
+config VIDEO_V4L1
+ tristate
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+ default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
+config VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_DMA_SG
+ depends on HAS_DMA
+ select VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_VMALLOC
+ select VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_DVB
+ tristate
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_SG
+
+config VIDEO_BTCX
+ tristate
+
+config VIDEO_IR_I2C
+ tristate
+
+config VIDEO_IR
+ tristate
+ depends on INPUT
+ select VIDEO_IR_I2C if I2C
+
+config VIDEO_TVEEPROM
+ tristate
+ depends on I2C
+
+config VIDEO_TUNER
+ tristate
+ depends on MEDIA_TUNER
+
+#
# Multimedia Video device configuration
#
@@ -270,6 +320,15 @@ config VIDEO_SAA711X
To compile this driver as a module, choose M here: the
module will be called saa7115.
+config VIDEO_SAA717X
+ tristate "Philips SAA7171/3/4 audio/video decoders"
+ depends on VIDEO_V4L2 && I2C
+ ---help---
+ Support for the Philips SAA7171/3/4 audio/video decoders.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa717x.
+
config VIDEO_SAA7191
tristate "Philips SAA7191 video decoder"
depends on VIDEO_V4L1 && I2C
@@ -689,8 +748,12 @@ source "drivers/media/video/cx88/Kconfig"
source "drivers/media/video/cx23885/Kconfig"
+source "drivers/media/video/au0828/Kconfig"
+
source "drivers/media/video/ivtv/Kconfig"
+source "drivers/media/video/cx18/Kconfig"
+
config VIDEO_M32R_AR
tristate "AR devices"
depends on M32R && VIDEO_V4L1
@@ -840,7 +903,7 @@ endif # V4L_USB_DRIVERS
config SOC_CAMERA
tristate "SoC camera support"
- depends on VIDEO_V4L2
+ depends on VIDEO_V4L2 && HAS_DMA
select VIDEOBUF_DMA_SG
help
SoC Camera is a common API to several cameras, not connecting
@@ -849,7 +912,7 @@ config SOC_CAMERA
config SOC_CAMERA_MT9M001
tristate "mt9m001 support"
- depends on SOC_CAMERA
+ depends on SOC_CAMERA && I2C
select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
help
This driver supports MT9M001 cameras from Micron, monochrome
@@ -864,7 +927,7 @@ config MT9M001_PCA9536_SWITCH
config SOC_CAMERA_MT9V022
tristate "mt9v022 support"
- depends on SOC_CAMERA
+ depends on SOC_CAMERA && I2C
select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
help
This driver supports MT9V022 cameras from Micron
diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile
index 53d4dbf50..29139b53d 100644
--- a/linux/drivers/media/video/Makefile
+++ b/linux/drivers/media/video/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
@@ -86,16 +87,6 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
-# tuner-types will be merged into tuner-simple, in the future
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
-obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
-obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
-obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
-obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
-obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
-
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
@@ -134,6 +125,7 @@ obj-$(CONFIG_USB_VICAM) += usbvideo/
obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+obj-$(CONFIG_VIDEO_CX18) += cx18/
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
@@ -143,5 +135,8 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
+obj-$(CONFIG_VIDEO_AU0828) += au0828/
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c
index 0d15ce53d..54ef7aa63 100644
--- a/linux/drivers/media/video/adv7170.c
+++ b/linux/drivers/media/video/adv7170.c
@@ -409,7 +409,7 @@ adv7170_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c
index 86345ba5c..b8618c021 100644
--- a/linux/drivers/media/video/adv7175.c
+++ b/linux/drivers/media/video/adv7175.c
@@ -427,7 +427,7 @@ adv7175_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig
new file mode 100644
index 000000000..52b249158
--- /dev/null
+++ b/linux/drivers/media/video/au0828/Kconfig
@@ -0,0 +1,13 @@
+
+config VIDEO_AU0828
+ tristate "Auvitek AU0828 support"
+ depends on I2C && INPUT && DVB_CORE && USB
+ select I2C_ALGOBIT
+ select VIDEO_TVEEPROM
+ select DVB_AU8522 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+ ---help---
+ This is a video4linux driver for Auvitek's USB device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called au0828
diff --git a/linux/drivers/media/video/au0828/Makefile b/linux/drivers/media/video/au0828/Makefile
new file mode 100644
index 000000000..cd2c58281
--- /dev/null
+++ b/linux/drivers/media/video/au0828/Makefile
@@ -0,0 +1,9 @@
+au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828.o
+
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c
new file mode 100644
index 000000000..a2a698344
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-cards.c
@@ -0,0 +1,181 @@
+/*
+ * Driver for the Auvitek USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "au0828.h"
+#include "au0828-cards.h"
+
+struct au0828_board au0828_boards[] = {
+ [AU0828_BOARD_UNKNOWN] = {
+ .name = "Unknown board",
+ },
+ [AU0828_BOARD_HAUPPAUGE_HVR850] = {
+ .name = "Hauppauge HVR850",
+ },
+ [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
+ .name = "Hauppauge HVR950Q",
+ },
+ [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
+ .name = "DViCO FusionHDTV USB",
+ },
+};
+
+/* Tuner callback function for au0828 boards. Currently only needed
+ * for HVR1500Q, which has an xc5000 tuner.
+ */
+int au0828_tuner_callback(void *priv, int command, int arg)
+{
+ struct au0828_dev *dev = priv;
+
+ dprintk(1, "%s()\n", __func__);
+
+ switch (dev->board) {
+ case AU0828_BOARD_HAUPPAUGE_HVR850:
+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+ case AU0828_BOARD_DVICO_FUSIONHDTV7:
+ if (command == 0) {
+ /* Tuner Reset Command from xc5000 */
+ /* Drive the tuner into reset and out */
+ au0828_clear(dev, REG_001, 2);
+ mdelay(200);
+ au0828_set(dev, REG_001, 2);
+ mdelay(50);
+ return 0;
+ } else {
+ printk(KERN_ERR
+ "%s(): Unknown command.\n", __func__);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ return 0; /* Should never be here */
+}
+
+static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
+{
+ struct tveeprom tv;
+
+ tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+
+ /* Make sure we support the board model */
+ switch (tv.model) {
+ case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
+ case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
+ break;
+ default:
+ printk(KERN_WARNING "%s: warning: "
+ "unknown hauppauge model #%d\n", __func__, tv.model);
+ break;
+ }
+
+ printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+ __func__, tv.model);
+}
+
+void au0828_card_setup(struct au0828_dev *dev)
+{
+ static u8 eeprom[256];
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (dev->i2c_rc == 0) {
+ dev->i2c_client.addr = 0xa0 >> 1;
+ tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
+ }
+
+ switch (dev->board) {
+ case AU0828_BOARD_HAUPPAUGE_HVR850:
+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+ if (dev->i2c_rc == 0)
+ hauppauge_eeprom(dev, eeprom+0xa0);
+ break;
+ }
+}
+
+/*
+ * The bridge has between 8 and 12 gpios.
+ * Regs 1 and 0 deal with output enables.
+ * Regs 3 and 2 deal with direction.
+ */
+void au0828_gpio_setup(struct au0828_dev *dev)
+{
+ dprintk(1, "%s()\n", __func__);
+
+ switch (dev->board) {
+ case AU0828_BOARD_HAUPPAUGE_HVR850:
+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+ /* GPIO's
+ * 4 - CS5340
+ * 5 - AU8522 Demodulator
+ * 6 - eeprom W/P
+ * 9 - XC5000 Tuner
+ */
+
+ /* Into reset */
+ au0828_write(dev, REG_003, 0x02);
+ au0828_write(dev, REG_002, 0x88 | 0x20);
+ au0828_write(dev, REG_001, 0x0);
+ au0828_write(dev, REG_000, 0x0);
+ msleep(100);
+
+ /* Out of reset */
+ au0828_write(dev, REG_003, 0x02);
+ au0828_write(dev, REG_001, 0x02);
+ au0828_write(dev, REG_002, 0x88 | 0x20);
+ au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
+ msleep(250);
+ break;
+ case AU0828_BOARD_DVICO_FUSIONHDTV7:
+ /* GPIO's
+ * 6 - ?
+ * 8 - AU8522 Demodulator
+ * 9 - XC5000 Tuner
+ */
+
+ /* Into reset */
+ au0828_write(dev, REG_003, 0x02);
+ au0828_write(dev, REG_002, 0xa0);
+ au0828_write(dev, REG_001, 0x0);
+ au0828_write(dev, REG_000, 0x0);
+ msleep(100);
+
+ /* Out of reset */
+ au0828_write(dev, REG_003, 0x02);
+ au0828_write(dev, REG_002, 0xa0);
+ au0828_write(dev, REG_001, 0x02);
+ au0828_write(dev, REG_000, 0xa0);
+ msleep(250);
+ break;
+ }
+}
+
+/* table of devices that work with this driver */
+struct usb_device_id au0828_usb_id_table [] = {
+ { USB_DEVICE(0x2040, 0x7200),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+ { USB_DEVICE(0x2040, 0x7240),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
+ { USB_DEVICE(0x0fe9, 0xd620),
+ .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
diff --git a/linux/drivers/media/video/au0828/au0828-cards.h b/linux/drivers/media/video/au0828/au0828-cards.h
new file mode 100644
index 000000000..e26f54a96
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-cards.h
@@ -0,0 +1,25 @@
+/*
+ * Driver for the Auvitek USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define AU0828_BOARD_UNKNOWN 0
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
+#define AU0828_BOARD_HAUPPAUGE_HVR850 2
+#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c
new file mode 100644
index 000000000..5642058ae
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-core.c
@@ -0,0 +1,262 @@
+/*
+ * Driver for the Auvitek USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include "compat.h"
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+#include <linux/mutex.h>
+#endif
+
+#include "au0828.h"
+
+/*
+ * 1 = General debug messages
+ * 2 = USB handling
+ * 4 = I2C related
+ * 8 = Bridge related
+ */
+int au0828_debug;
+module_param_named(debug, au0828_debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+#define _AU0828_BULKPIPE 0x03
+#define _BULKPIPESIZE 0xffff
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+ u16 index, unsigned char *cp, u16 size);
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+ u16 index, unsigned char *cp, u16 size);
+
+/* USB Direction */
+#define CMD_REQUEST_IN 0x00
+#define CMD_REQUEST_OUT 0x01
+
+u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
+{
+ recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
+ dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
+ return dev->ctrlmsg[0];
+}
+
+u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
+{
+ dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
+ return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
+ dev->ctrlmsg, 0);
+}
+
+static void cmd_msg_dump(struct au0828_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
+ dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ __func__,
+ dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
+ dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
+ dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
+ dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
+ dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
+ dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
+ dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
+ dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
+}
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+ u16 index, unsigned char *cp, u16 size)
+{
+ int status = -ENODEV;
+ mutex_lock(&dev->mutex);
+ if (dev->usbdev) {
+
+ /* cp must be memory that has been allocated by kmalloc */
+ status = usb_control_msg(dev->usbdev,
+ usb_sndctrlpipe(dev->usbdev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index,
+ cp, size, 1000);
+
+ status = min(status, 0);
+
+ if (status < 0) {
+ printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
+ __func__, status);
+ }
+
+ }
+ mutex_unlock(&dev->mutex);
+ return status;
+}
+
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+ u16 index, unsigned char *cp, u16 size)
+{
+ int status = -ENODEV;
+ mutex_lock(&dev->mutex);
+ if (dev->usbdev) {
+
+ memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
+
+ /* cp must be memory that has been allocated by kmalloc */
+ status = usb_control_msg(dev->usbdev,
+ usb_rcvctrlpipe(dev->usbdev, 0),
+ request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index,
+ cp, size, 1000);
+
+ status = min(status, 0);
+
+ if (status < 0) {
+ printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
+ __func__, status);
+ } else
+ cmd_msg_dump(dev);
+ }
+ mutex_unlock(&dev->mutex);
+ return status;
+}
+
+static void au0828_usb_disconnect(struct usb_interface *interface)
+{
+ struct au0828_dev *dev = usb_get_intfdata(interface);
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* Digital TV */
+ au0828_dvb_unregister(dev);
+
+ /* I2C */
+ au0828_i2c_unregister(dev);
+
+ usb_set_intfdata(interface, NULL);
+
+ mutex_lock(&dev->mutex);
+ dev->usbdev = NULL;
+ mutex_unlock(&dev->mutex);
+
+ kfree(dev);
+
+}
+
+static int au0828_usb_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int ifnum;
+ struct au0828_dev *dev;
+ struct usb_device *usbdev = interface_to_usbdev(interface);
+
+ ifnum = interface->altsetting->desc.bInterfaceNumber;
+
+ if (ifnum != 0)
+ return -ENODEV;
+
+ dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct),
+ ifnum);
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_init(&dev->mutex);
+ mutex_init(&dev->dvb.lock);
+ dev->usbdev = usbdev;
+ dev->board = id->driver_info;
+
+ usb_set_intfdata(interface, dev);
+
+ /* Power Up the bridge */
+ au0828_write(dev, REG_600, 1 << 4);
+
+ /* Bring up the GPIO's and supporting devices */
+ au0828_gpio_setup(dev);
+
+ /* I2C */
+ au0828_i2c_register(dev);
+
+ /* Setup */
+ au0828_card_setup(dev);
+
+ /* Digital TV */
+ au0828_dvb_register(dev);
+
+ printk(KERN_INFO "Registered device AU0828 [%s]\n",
+ au0828_boards[dev->board].name == NULL ? "Unset" :
+ au0828_boards[dev->board].name);
+
+ return 0;
+}
+
+static struct usb_driver au0828_usb_driver = {
+ .name = DRIVER_NAME,
+ .probe = au0828_usb_probe,
+ .disconnect = au0828_usb_disconnect,
+ .id_table = au0828_usb_id_table,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
+ .owner = THIS_MODULE,
+#endif
+};
+
+static int __init au0828_init(void)
+{
+ int ret;
+
+ if (au0828_debug & 1)
+ printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
+
+ if (au0828_debug & 2)
+ printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
+
+ if (au0828_debug & 4)
+ printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
+
+ if (au0828_debug & 8)
+ printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
+ __func__);
+
+ printk(KERN_INFO "au0828 driver loaded\n");
+
+ ret = usb_register(&au0828_usb_driver);
+ if (ret)
+ printk(KERN_ERR "usb_register failed, error = %d\n", ret);
+
+ return ret;
+}
+
+static void __exit au0828_exit(void)
+{
+ usb_deregister(&au0828_usb_driver);
+}
+
+module_init(au0828_init);
+module_exit(au0828_exit);
+
+MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
+MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/au0828/au0828-dvb.c b/linux/drivers/media/video/au0828/au0828-dvb.c
new file mode 100644
index 000000000..709a703fe
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-dvb.c
@@ -0,0 +1,393 @@
+/*
+ * Driver for the Auvitek USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <media/v4l2-common.h>
+#include "compat.h"
+
+#include "au0828.h"
+#include "au8522.h"
+#include "xc5000.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define _AU0828_BULKPIPE 0x83
+#define _BULKPIPESIZE 0xe522
+
+static struct au8522_config hauppauge_hvr950q_config = {
+ .demod_address = 0x8e >> 1,
+ .status_mode = AU8522_DEMODLOCKING,
+};
+
+static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
+ .i2c_address = 0x61,
+ .if_khz = 6000,
+ .tuner_callback = au0828_tuner_callback
+};
+
+/*-------------------------------------------------------------------*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void urb_completion(struct urb *purb, struct pt_regs *regs)
+#else
+static void urb_completion(struct urb *purb)
+#endif
+{
+ u8 *ptr;
+ struct au0828_dev *dev = purb->context;
+ int ptype = usb_pipetype(purb->pipe);
+
+ dprintk(2, "%s()\n", __func__);
+
+ if (!dev)
+ return;
+
+ if (dev->urb_streaming == 0)
+ return;
+
+ if (ptype != PIPE_BULK) {
+ printk(KERN_ERR "%s() Unsupported URB type %d\n",
+ __func__, ptype);
+ return;
+ }
+
+ ptr = (u8 *)purb->transfer_buffer;
+
+ /* Feed the transport payload into the kernel demux */
+ dvb_dmx_swfilter_packets(&dev->dvb.demux,
+ purb->transfer_buffer, purb->actual_length / 188);
+
+ /* Clean the buffer before we requeue */
+ memset(purb->transfer_buffer, 0, URB_BUFSIZE);
+
+ /* Requeue URB */
+ usb_submit_urb(purb, GFP_ATOMIC);
+}
+
+static int stop_urb_transfer(struct au0828_dev *dev)
+{
+ int i;
+
+ dprintk(2, "%s()\n", __func__);
+
+ for (i = 0; i < URB_COUNT; i++) {
+ usb_kill_urb(dev->urbs[i]);
+ kfree(dev->urbs[i]->transfer_buffer);
+ usb_free_urb(dev->urbs[i]);
+ }
+
+ dev->urb_streaming = 0;
+
+ return 0;
+}
+
+static int start_urb_transfer(struct au0828_dev *dev)
+{
+ struct urb *purb;
+ int i, ret = -ENOMEM;
+
+ dprintk(2, "%s()\n", __func__);
+
+ if (dev->urb_streaming) {
+ dprintk(2, "%s: iso xfer already running!\n", __func__);
+ return 0;
+ }
+
+ for (i = 0; i < URB_COUNT; i++) {
+
+ dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->urbs[i])
+ goto err;
+
+ purb = dev->urbs[i];
+
+ purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
+ if (!purb->transfer_buffer) {
+ usb_free_urb(purb);
+ dev->urbs[i] = NULL;
+ goto err;
+ }
+
+ purb->status = -EINPROGRESS;
+ usb_fill_bulk_urb(purb,
+ dev->usbdev,
+ usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+ purb->transfer_buffer,
+ URB_BUFSIZE,
+ urb_completion,
+ dev);
+
+ }
+
+ for (i = 0; i < URB_COUNT; i++) {
+ ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
+ if (ret != 0) {
+ stop_urb_transfer(dev);
+ printk(KERN_ERR "%s: failed urb submission, "
+ "err = %d\n", __func__, ret);
+ return ret;
+ }
+ }
+
+ dev->urb_streaming = 1;
+ ret = 0;
+
+err:
+ return ret;
+}
+
+static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+ struct au0828_dvb *dvb = &dev->dvb;
+ int ret = 0;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (!demux->dmx.frontend)
+ return -EINVAL;
+
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (dvb->feeding++ == 0) {
+ /* Start transport */
+ au0828_write(dev, 0x608, 0x90);
+ au0828_write(dev, 0x609, 0x72);
+ au0828_write(dev, 0x60a, 0x71);
+ au0828_write(dev, 0x60b, 0x01);
+ ret = start_urb_transfer(dev);
+ }
+ mutex_unlock(&dvb->lock);
+ }
+
+ return ret;
+}
+
+static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+ struct au0828_dvb *dvb = &dev->dvb;
+ int ret = 0;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (--dvb->feeding == 0) {
+ /* Stop transport */
+ au0828_write(dev, 0x608, 0x00);
+ au0828_write(dev, 0x609, 0x00);
+ au0828_write(dev, 0x60a, 0x00);
+ au0828_write(dev, 0x60b, 0x00);
+ ret = stop_urb_transfer(dev);
+ }
+ mutex_unlock(&dvb->lock);
+ }
+
+ return ret;
+}
+
+static int dvb_register(struct au0828_dev *dev)
+{
+ struct au0828_dvb *dvb = &dev->dvb;
+ int result;
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* register adapter */
+ result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
+ &dev->usbdev->dev, adapter_nr);
+ if (result < 0) {
+ printk(KERN_ERR "%s: dvb_register_adapter failed "
+ "(errno = %d)\n", DRIVER_NAME, result);
+ goto fail_adapter;
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb->adapter.priv = dev;
+
+ /* register frontend */
+ result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+#else
+ dvb->adapter->priv = dev;
+
+ /* register frontend */
+ result = dvb_register_frontend(dvb->adapter, dvb->frontend);
+#endif
+ if (result < 0) {
+ printk(KERN_ERR "%s: dvb_register_frontend failed "
+ "(errno = %d)\n", DRIVER_NAME, result);
+ goto fail_frontend;
+ }
+
+ /* register demux stuff */
+ dvb->demux.dmx.capabilities =
+ DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING;
+ dvb->demux.priv = dev;
+ dvb->demux.filternum = 256;
+ dvb->demux.feednum = 256;
+ dvb->demux.start_feed = au0828_dvb_start_feed;
+ dvb->demux.stop_feed = au0828_dvb_stop_feed;
+ result = dvb_dmx_init(&dvb->demux);
+ if (result < 0) {
+ printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
+ DRIVER_NAME, result);
+ goto fail_dmx;
+ }
+
+ dvb->dmxdev.filternum = 256;
+ dvb->dmxdev.demux = &dvb->demux.dmx;
+ dvb->dmxdev.capabilities = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+#else
+ result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter);
+#endif
+ if (result < 0) {
+ printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
+ DRIVER_NAME, result);
+ goto fail_dmxdev;
+ }
+
+ dvb->fe_hw.source = DMX_FRONTEND_0;
+ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ if (result < 0) {
+ printk(KERN_ERR "%s: add_frontend failed "
+ "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
+ goto fail_fe_hw;
+ }
+
+ dvb->fe_mem.source = DMX_MEMORY_FE;
+ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+ if (result < 0) {
+ printk(KERN_ERR "%s: add_frontend failed "
+ "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
+ goto fail_fe_mem;
+ }
+
+ result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ if (result < 0) {
+ printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
+ DRIVER_NAME, result);
+ goto fail_fe_conn;
+ }
+
+ /* register network adapter */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+#else
+ dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx);
+#endif
+ return 0;
+
+fail_fe_conn:
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+ dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+ dvb_dmx_release(&dvb->demux);
+fail_dmx:
+ dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+ dvb_frontend_detach(dvb->frontend);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_unregister_adapter(&dvb->adapter);
+#else
+ dvb_unregister_adapter(dvb->adapter);
+#endif
+fail_adapter:
+ return result;
+}
+
+void au0828_dvb_unregister(struct au0828_dev *dev)
+{
+ struct au0828_dvb *dvb = &dev->dvb;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (dvb->frontend == NULL)
+ return;
+
+ dvb_net_release(&dvb->net);
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ dvb_dmxdev_release(&dvb->dmxdev);
+ dvb_dmx_release(&dvb->demux);
+ dvb_unregister_frontend(dvb->frontend);
+ dvb_frontend_detach(dvb->frontend);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_unregister_adapter(&dvb->adapter);
+#else
+ dvb_unregister_adapter(dvb->adapter);
+#endif
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+int au0828_dvb_register(struct au0828_dev *dev)
+{
+ struct au0828_dvb *dvb = &dev->dvb;
+ int ret;
+
+ dprintk(1, "%s()\n", __func__);
+
+ /* init frontend */
+ switch (dev->board) {
+ case AU0828_BOARD_HAUPPAUGE_HVR850:
+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+ case AU0828_BOARD_DVICO_FUSIONHDTV7:
+ dvb->frontend = dvb_attach(au8522_attach,
+ &hauppauge_hvr950q_config,
+ &dev->i2c_adap);
+ if (dvb->frontend != NULL)
+ dvb_attach(xc5000_attach, dvb->frontend,
+ &dev->i2c_adap,
+ &hauppauge_hvr950q_tunerconfig, dev);
+ break;
+ default:
+ printk(KERN_WARNING "The frontend of your DVB/ATSC card "
+ "isn't supported yet\n");
+ break;
+ }
+ if (NULL == dvb->frontend) {
+ printk(KERN_ERR "%s() Frontend initialization failed\n",
+ __func__);
+ return -1;
+ }
+
+ /* register everything */
+ ret = dvb_register(dev);
+ if (ret < 0) {
+ if (dvb->frontend->ops.release)
+ dvb->frontend->ops.release(dvb->frontend);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c
new file mode 100644
index 000000000..b40a086e4
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-i2c.c
@@ -0,0 +1,384 @@
+/*
+ * Driver for the Auvitek AU0828 USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "compat.h"
+#include "au0828.h"
+
+#include <media/v4l2-common.h>
+
+static int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define I2C_WAIT_DELAY 512
+#define I2C_WAIT_RETRY 64
+
+static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
+}
+
+static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
+}
+
+static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
+{
+ int count;
+
+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
+ if (!i2c_slave_did_read_ack(i2c_adap))
+ break;
+ udelay(I2C_WAIT_DELAY);
+ }
+
+ if (I2C_WAIT_RETRY == count)
+ return 0;
+
+ return 1;
+}
+
+static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
+}
+
+static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
+{
+ int count;
+
+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
+ if (!i2c_is_read_busy(i2c_adap))
+ break;
+ udelay(I2C_WAIT_DELAY);
+ }
+
+ if (I2C_WAIT_RETRY == count)
+ return 0;
+
+ return 1;
+}
+
+static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
+}
+
+static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
+{
+ int count;
+
+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
+ if (i2c_is_write_done(i2c_adap))
+ break;
+ udelay(I2C_WAIT_DELAY);
+ }
+
+ if (I2C_WAIT_RETRY == count)
+ return 0;
+
+ return 1;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+ int count;
+
+ for (count = 0; count < I2C_WAIT_RETRY; count++) {
+ if (!i2c_is_busy(i2c_adap))
+ break;
+ udelay(I2C_WAIT_DELAY);
+ }
+
+ if (I2C_WAIT_RETRY == count)
+ return 0;
+
+ return 1;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ const struct i2c_msg *msg, int joined_rlen)
+{
+ int i, strobe = 0;
+ struct au0828_dev *dev = i2c_adap->algo_data;
+
+ dprintk(4, "%s()\n", __func__);
+
+ au0828_write(dev, REG_2FF, 0x01);
+ au0828_write(dev, REG_202, 0x07);
+
+ /* Hardware needs 8 bit addresses */
+ au0828_write(dev, REG_203, msg->addr << 1);
+
+ dprintk(4, "SEND: %02x\n", msg->addr);
+
+ for (i = 0; i < msg->len;) {
+
+ dprintk(4, " %02x\n", msg->buf[i]);
+
+ au0828_write(dev, REG_205, msg->buf[i]);
+
+ strobe++;
+ i++;
+
+ if ((strobe >= 4) || (i >= msg->len)) {
+
+ /* Strobe the byte into the bus */
+ if (i < msg->len)
+ au0828_write(dev, REG_200, 0x41);
+ else
+ au0828_write(dev, REG_200, 0x01);
+
+ /* Reset strobe trigger */
+ strobe = 0;
+
+ if (!i2c_wait_write_done(i2c_adap))
+ return -EIO;
+
+ }
+
+ }
+ if (!i2c_wait_done(i2c_adap))
+ return -EIO;
+
+ dprintk(4, "\n");
+
+ return msg->len;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ const struct i2c_msg *msg, int joined)
+{
+ struct au0828_dev *dev = i2c_adap->algo_data;
+ int i;
+
+ dprintk(4, "%s()\n", __func__);
+
+ au0828_write(dev, REG_2FF, 0x01);
+ au0828_write(dev, REG_202, 0x07);
+
+ /* Hardware needs 8 bit addresses */
+ au0828_write(dev, REG_203, msg->addr << 1);
+
+ dprintk(4, " RECV:\n");
+
+ /* Deal with i2c_scan */
+ if (msg->len == 0) {
+ au0828_write(dev, REG_200, 0x20);
+ if (i2c_wait_read_ack(i2c_adap))
+ return -EIO;
+ return 0;
+ }
+
+ for (i = 0; i < msg->len;) {
+
+ i++;
+
+ if (i < msg->len)
+ au0828_write(dev, REG_200, 0x60);
+ else
+ au0828_write(dev, REG_200, 0x20);
+
+ if (!i2c_wait_read_done(i2c_adap))
+ return -EIO;
+
+ msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
+
+ dprintk(4, " %02x\n", msg->buf[i-1]);
+ }
+ if (!i2c_wait_done(i2c_adap))
+ return -EIO;
+
+ dprintk(4, "\n");
+
+ return msg->len;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msgs, int num)
+{
+ int i, retval = 0;
+
+ dprintk(4, "%s(num = %d)\n", __func__, num);
+
+ for (i = 0; i < num; i++) {
+ dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
+ __func__, num, msgs[i].addr, msgs[i].len);
+ if (msgs[i].flags & I2C_M_RD) {
+ /* read */
+ retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+ } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+ msgs[i].addr == msgs[i + 1].addr) {
+ /* write then read from same address */
+ retval = i2c_sendbytes(i2c_adap, &msgs[i],
+ msgs[i + 1].len);
+ if (retval < 0)
+ goto err;
+ i++;
+ retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+ } else {
+ /* write */
+ retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+ }
+ if (retval < 0)
+ goto err;
+ }
+ return num;
+
+err:
+ return retval;
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+ dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
+ client->driver->driver.name, client->addr, client->name);
+
+ if (!client->driver->command)
+ return 0;
+
+ return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+ dprintk(1, "i2c detach [client=%s]\n", client->name);
+
+ return 0;
+}
+
+void au0828_call_i2c_clients(struct au0828_dev *dev,
+ unsigned int cmd, void *arg)
+{
+ if (dev->i2c_rc != 0)
+ return;
+
+ i2c_clients_command(&dev->i2c_adap, cmd, arg);
+}
+
+static u32 au0828_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au0828_i2c_algo_template = {
+ .master_xfer = i2c_xfer,
+ .functionality = au0828_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter au0828_i2c_adap_template = {
+ .name = DRIVER_NAME,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ .owner = THIS_MODULE,
+#endif
+ .id = I2C_HW_B_AU0828,
+ .algo = &au0828_i2c_algo_template,
+ .class = I2C_CLASS_TV_ANALOG,
+ .client_register = attach_inform,
+ .client_unregister = detach_inform,
+};
+
+static struct i2c_client au0828_i2c_client_template = {
+ .name = "au0828 internal",
+};
+
+static char *i2c_devs[128] = {
+ [0x8e >> 1] = "au8522",
+ [0xa0 >> 1] = "eeprom",
+ [0xc2 >> 1] = "tuner/xc5000",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+ unsigned char buf;
+ int i, rc;
+
+ for (i = 0; i < 128; i++) {
+ c->addr = i;
+ rc = i2c_master_recv(c, &buf, 0);
+ if (rc < 0)
+ continue;
+ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
+ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ }
+}
+
+/* init + register i2c algo-bit adapter */
+int au0828_i2c_register(struct au0828_dev *dev)
+{
+ dprintk(1, "%s()\n", __func__);
+
+ memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
+ sizeof(dev->i2c_adap));
+ memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
+ sizeof(dev->i2c_algo));
+ memcpy(&dev->i2c_client, &au0828_i2c_client_template,
+ sizeof(dev->i2c_client));
+
+ dev->i2c_adap.dev.parent = &dev->usbdev->dev;
+
+ strlcpy(dev->i2c_adap.name, DRIVER_NAME,
+ sizeof(dev->i2c_adap.name));
+
+ dev->i2c_algo.data = dev;
+ dev->i2c_adap.algo_data = dev;
+ i2c_set_adapdata(&dev->i2c_adap, dev);
+ i2c_add_adapter(&dev->i2c_adap);
+
+ dev->i2c_client.adapter = &dev->i2c_adap;
+
+ if (0 == dev->i2c_rc) {
+ printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
+ if (i2c_scan)
+ do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
+ } else
+ printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
+
+ return dev->i2c_rc;
+}
+
+int au0828_i2c_unregister(struct au0828_dev *dev)
+{
+ i2c_del_adapter(&dev->i2c_adap);
+ return 0;
+}
+
diff --git a/linux/drivers/media/video/au0828/au0828-reg.h b/linux/drivers/media/video/au0828/au0828-reg.h
new file mode 100644
index 000000000..398275508
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828-reg.h
@@ -0,0 +1,38 @@
+/*
+ * Driver for the Auvitek USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* We'll start to rename these registers once we have a better
+ * understanding of their meaning.
+ */
+#define REG_000 0x000
+#define REG_001 0x001
+#define REG_002 0x002
+#define REG_003 0x003
+
+#define REG_200 0x200
+#define REG_201 0x201
+#define REG_202 0x202
+#define REG_203 0x203
+#define REG_205 0x205
+#define REG_209 0x209
+#define REG_2FF 0x2ff
+
+#define REG_600 0x600
diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h
new file mode 100644
index 000000000..b00d8cda5
--- /dev/null
+++ b/linux/drivers/media/video/au0828/au0828.h
@@ -0,0 +1,132 @@
+/*
+ * Driver for the Auvitek AU0828 USB bridge
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <media/tveeprom.h>
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#include "au0828-reg.h"
+#include "au0828-cards.h"
+
+#define DRIVER_NAME "au0828"
+#define URB_COUNT 16
+#define URB_BUFSIZE (0xe522)
+
+struct au0828_board {
+ char *name;
+};
+
+struct au0828_dvb {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex lock;
+#else
+ struct semaphore lock;
+#endif
+ struct dvb_adapter adapter;
+ struct dvb_frontend *frontend;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dmx_frontend fe_hw;
+ struct dmx_frontend fe_mem;
+ struct dvb_net net;
+ int feeding;
+};
+
+struct au0828_dev {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex mutex;
+#else
+ struct semaphore mutex;
+#endif
+ struct usb_device *usbdev;
+ int board;
+ u8 ctrlmsg[64];
+
+ /* I2C */
+ struct i2c_adapter i2c_adap;
+ struct i2c_algo_bit_data i2c_algo;
+ struct i2c_client i2c_client;
+ u32 i2c_rc;
+
+ /* Digital */
+ struct au0828_dvb dvb;
+
+ /* USB / URB Related */
+ int urb_streaming;
+ struct urb *urbs[URB_COUNT];
+
+};
+
+struct au0828_buff {
+ struct au0828_dev *dev;
+ struct urb *purb;
+ struct list_head buff_list;
+};
+
+/* ----------------------------------------------------------- */
+#define au0828_read(dev, reg) au0828_readreg(dev, reg)
+#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
+#define au0828_andor(dev, reg, mask, value) \
+ au0828_writereg(dev, reg, \
+ (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
+
+#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
+#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* au0828-core.c */
+extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
+extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
+extern int au0828_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-cards.c */
+extern struct au0828_board au0828_boards[];
+extern struct usb_device_id au0828_usb_id_table[];
+extern void au0828_gpio_setup(struct au0828_dev *dev);
+extern int au0828_tuner_callback(void *priv, int command, int arg);
+extern void au0828_card_setup(struct au0828_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* au0828-i2c.c */
+extern int au0828_i2c_register(struct au0828_dev *dev);
+extern int au0828_i2c_unregister(struct au0828_dev *dev);
+extern void au0828_call_i2c_clients(struct au0828_dev *dev,
+ unsigned int cmd, void *arg);
+
+/* ----------------------------------------------------------- */
+/* au0828-dvb.c */
+extern int au0828_dvb_register(struct au0828_dev *dev);
+extern void au0828_dvb_unregister(struct au0828_dev *dev);
+
+#define dprintk(level, fmt, arg...)\
+ do { if (au0828_debug & level)\
+ printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
+ } while (0)
diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c
index 9264e2cff..402bccaf7 100644
--- a/linux/drivers/media/video/bt819.c
+++ b/linux/drivers/media/video/bt819.c
@@ -525,7 +525,7 @@ bt819_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c
index 7abfad9a4..50ca987ad 100644
--- a/linux/drivers/media/video/bt856.c
+++ b/linux/drivers/media/video/bt856.c
@@ -312,7 +312,7 @@ bt856_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig
index cfc822bb5..24a34fc1f 100644
--- a/linux/drivers/media/video/bt8xx/Kconfig
+++ b/linux/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,7 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
+ depends on HOTPLUG # due to FW_LOADER
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/linux/drivers/media/video/bt8xx/Makefile b/linux/drivers/media/video/bt8xx/Makefile
index 924d216d9..e415f6fc4 100644
--- a/linux/drivers/media/video/bt8xx/Makefile
+++ b/linux/drivers/media/video/bt8xx/Makefile
@@ -9,4 +9,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c
index 177b75ebc..0e6771643 100644
--- a/linux/drivers/media/video/bt8xx/bttv-cards.c
+++ b/linux/drivers/media/video/bt8xx/bttv-cards.c
@@ -35,6 +35,7 @@
#include <net/checksum.h>
#include "compat.h"
+#include <asm/unaligned.h>
#include <asm/io.h>
#include "bttvp.h"
@@ -3922,7 +3923,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
ee += i;
/* found a valid descriptor */
- type = be16_to_cpup((u16*)(ee+4));
+ type = get_unaligned_be16((__be16 *)(ee+4));
switch(type) {
/* 848 based */
@@ -3982,7 +3983,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
btv->c.nr, type);
break;
}
- serial = be32_to_cpup((u32*)(ee+6));
+ serial = get_unaligned_be32((__be32 *)(ee+6));
}
printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n",
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index c1173a94a..bb9ad09f8 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -2489,7 +2489,7 @@ pix_format_set_size (struct v4l2_pix_format * f,
}
}
-static int bttv_g_fmt_cap(struct file *file, void *priv,
+static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
@@ -2502,7 +2502,7 @@ static int bttv_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int bttv_g_fmt_overlay(struct file *file, void *priv,
+static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
@@ -2513,7 +2513,7 @@ static int bttv_g_fmt_overlay(struct file *file, void *priv,
return 0;
}
-static int bttv_try_fmt_cap(struct file *file, void *priv,
+static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
const struct bttv_format *fmt;
@@ -2573,7 +2573,7 @@ static int bttv_try_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int bttv_try_fmt_overlay(struct file *file, void *priv,
+static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
@@ -2583,7 +2583,7 @@ static int bttv_try_fmt_overlay(struct file *file, void *priv,
/* adjust_crop */ 0);
}
-static int bttv_s_fmt_cap(struct file *file, void *priv,
+static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
int retval;
@@ -2597,7 +2597,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
if (0 != retval)
return retval;
- retval = bttv_try_fmt_cap(file, priv, f);
+ retval = bttv_try_fmt_vid_cap(file, priv, f);
if (0 != retval)
return retval;
@@ -2632,7 +2632,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int bttv_s_fmt_overlay(struct file *file, void *priv,
+static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct bttv_fh *fh = priv;
@@ -2654,7 +2654,7 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
struct bttv_fh *fh = priv;
mutex_lock(&fh->cap.vb_lock);
- retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
+ retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
V4L2_MEMORY_MMAP);
if (retval < 0) {
mutex_unlock(&fh->cap.vb_lock);
@@ -2702,7 +2702,7 @@ static int bttv_querycap(struct file *file, void *priv,
return 0;
}
-static int bttv_enum_fmt_vbi(struct file *file, void *priv,
+static int bttv_enum_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (0 != f->index)
@@ -2733,7 +2733,7 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
return i;
}
-static int bttv_enum_fmt_cap(struct file *file, void *priv,
+static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
int rc = bttv_enum_fmt_cap_ovr(f);
@@ -2744,7 +2744,7 @@ static int bttv_enum_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int bttv_enum_fmt_overlay(struct file *file, void *priv,
+static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
int rc;
@@ -3405,18 +3405,18 @@ static struct video_device bttv_video_template =
.fops = &bttv_fops,
.minor = -1,
.vidioc_querycap = bttv_querycap,
- .vidioc_enum_fmt_cap = bttv_enum_fmt_cap,
- .vidioc_g_fmt_cap = bttv_g_fmt_cap,
- .vidioc_try_fmt_cap = bttv_try_fmt_cap,
- .vidioc_s_fmt_cap = bttv_s_fmt_cap,
- .vidioc_enum_fmt_overlay = bttv_enum_fmt_overlay,
- .vidioc_g_fmt_overlay = bttv_g_fmt_overlay,
- .vidioc_try_fmt_overlay = bttv_try_fmt_overlay,
- .vidioc_s_fmt_overlay = bttv_s_fmt_overlay,
- .vidioc_enum_fmt_vbi = bttv_enum_fmt_vbi,
- .vidioc_g_fmt_vbi = bttv_g_fmt_vbi,
- .vidioc_try_fmt_vbi = bttv_try_fmt_vbi,
- .vidioc_s_fmt_vbi = bttv_s_fmt_vbi,
+ .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
+ .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
+ .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
+ .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
+ .vidioc_enum_fmt_vbi_cap = bttv_enum_fmt_vbi_cap,
+ .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
+ .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
+ .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
.vidioc_g_audio = bttv_g_audio,
.vidioc_s_audio = bttv_s_audio,
.vidioc_cropcap = bttv_cropcap,
@@ -3506,6 +3506,9 @@ static int radio_release(struct inode *inode, struct file *file)
struct bttv *btv = fh->btv;
struct rds_command cmd;
+ file->private_data = NULL;
+ kfree(fh);
+
btv->radio_user--;
bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
diff --git a/linux/drivers/media/video/bt8xx/bttv-risc.c b/linux/drivers/media/video/bt8xx/bttv-risc.c
index a064f4ee9..a8c98e52c 100644
--- a/linux/drivers/media/video/bt8xx/bttv-risc.c
+++ b/linux/drivers/media/video/bt8xx/bttv-risc.c
@@ -48,7 +48,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
{
u32 instructions,line,todo;
struct scatterlist *sg;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -128,7 +128,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
unsigned int cpadding)
{
unsigned int instructions,line,todo,ylen,chroma;
- u32 *rp,ri;
+ __le32 *rp;
+ u32 ri;
struct scatterlist *ysg;
struct scatterlist *usg;
struct scatterlist *vsg;
@@ -244,7 +245,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
{
int dwords,rc,line,maxy,start,end,skip,nskips;
struct btcx_skiplist *skips;
- u32 *rp,ri,ra;
+ __le32 *rp;
+ u32 ri,ra;
u32 addr;
/* skip list for window clipping */
diff --git a/linux/drivers/media/video/bt8xx/bttv-vbi.c b/linux/drivers/media/video/bt8xx/bttv-vbi.c
index bfdbc469e..68f28e5fa 100644
--- a/linux/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/linux/drivers/media/video/bt8xx/bttv-vbi.c
@@ -303,7 +303,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
return 0;
}
-int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
@@ -321,7 +321,7 @@ int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
}
-int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
@@ -369,7 +369,7 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
}
-int bttv_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
+int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
const struct bttv_tvnorm *tvnorm;
diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h
index e9219458e..9fd8eeddf 100644
--- a/linux/drivers/media/video/bt8xx/bttvp.h
+++ b/linux/drivers/media/video/bt8xx/bttvp.h
@@ -90,8 +90,6 @@
/* Limits scaled width, which must be a multiple of 4. */
#define MAX_HACTIVE (0x3FF & -4)
-#define clamp(x, low, high) min (max (low, x), high)
-
#define BTTV_NORMS (\
V4L2_STD_PAL | V4L2_STD_PAL_N | \
V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
@@ -265,9 +263,9 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
/* ---------------------------------------------------------- */
/* bttv-vbi.c */
-int bttv_try_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_g_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
-int bttv_s_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
extern struct videobuf_queue_ops bttv_vbi_qops;
diff --git a/linux/drivers/media/video/btcx-risc.c b/linux/drivers/media/video/btcx-risc.c
index 2d2ad58b4..e0e1158ce 100644
--- a/linux/drivers/media/video/btcx-risc.c
+++ b/linux/drivers/media/video/btcx-risc.c
@@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
struct btcx_riscmem *risc,
unsigned int size)
{
- u32 *cpu;
+ __le32 *cpu;
dma_addr_t dma;
if (NULL != risc->cpu && risc->size < size)
diff --git a/linux/drivers/media/video/btcx-risc.h b/linux/drivers/media/video/btcx-risc.h
index 503e6c6d7..861bc8112 100644
--- a/linux/drivers/media/video/btcx-risc.h
+++ b/linux/drivers/media/video/btcx-risc.h
@@ -2,8 +2,8 @@
*/
struct btcx_riscmem {
unsigned int size;
- u32 *cpu;
- u32 *jmp;
+ __le32 *cpu;
+ __le32 *jmp;
dma_addr_t dma;
};
diff --git a/linux/drivers/media/video/c-qcam.c b/linux/drivers/media/video/c-qcam.c
index 479ef617b..a5f5b8a4a 100644
--- a/linux/drivers/media/video/c-qcam.c
+++ b/linux/drivers/media/video/c-qcam.c
@@ -39,6 +39,7 @@
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
#include <linux/mutex.h>
#endif
+#include <linux/jiffies.h>
#include <asm/uaccess.h>
@@ -102,7 +103,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
unsigned long oldjiffies = jiffies;
unsigned int i;
- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+ for (oldjiffies = jiffies;
+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
if (qcam_ready1(qcam) == value)
return 0;
@@ -127,7 +129,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
unsigned long oldjiffies = jiffies;
unsigned int i;
- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
+ for (oldjiffies = jiffies;
+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
if (qcam_ready2(qcam) == value)
return 0;
diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c
index 56409d585..b75c151cc 100644
--- a/linux/drivers/media/video/cafe_ccic.c
+++ b/linux/drivers/media/video/cafe_ccic.c
@@ -1600,7 +1600,7 @@ static struct v4l2_pix_format cafe_def_pix_format = {
.sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
};
-static int cafe_vidioc_enum_fmt_cap(struct file *filp,
+static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_fmtdesc *fmt)
{
struct cafe_camera *cam = priv;
@@ -1615,7 +1615,7 @@ static int cafe_vidioc_enum_fmt_cap(struct file *filp,
}
-static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv,
+static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *fmt)
{
struct cafe_camera *cam = priv;
@@ -1627,7 +1627,7 @@ static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv,
return ret;
}
-static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
+static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *fmt)
{
struct cafe_camera *cam = priv;
@@ -1642,7 +1642,7 @@ static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
/*
* See if the formatting works in principle.
*/
- ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt);
+ ret = cafe_vidioc_try_fmt_vid_cap(filp, priv, fmt);
if (ret)
return ret;
/*
@@ -1677,7 +1677,7 @@ static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
* The V4l2 spec wants us to be smarter, and actually get this from
* the camera (and not mess with it at open time). Someday.
*/
-static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv,
+static int cafe_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *f)
{
struct cafe_camera *cam = priv;
@@ -1787,10 +1787,10 @@ static struct video_device cafe_v4l_template = {
.release = cafe_v4l_dev_release,
.vidioc_querycap = cafe_vidioc_querycap,
- .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap,
- .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap,
- .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap,
- .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap,
+ .vidioc_enum_fmt_vid_cap = cafe_vidioc_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = cafe_vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = cafe_vidioc_s_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = cafe_vidioc_g_fmt_vid_cap,
.vidioc_enum_input = cafe_vidioc_enum_input,
.vidioc_g_input = cafe_vidioc_g_input,
.vidioc_s_input = cafe_vidioc_s_input,
diff --git a/linux/drivers/media/video/compat_ioctl32.c b/linux/drivers/media/video/compat_ioctl32.c
index c1ca880d0..6b405e75c 100644
--- a/linux/drivers/media/video/compat_ioctl32.c
+++ b/linux/drivers/media/video/compat_ioctl32.c
@@ -950,6 +950,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_G_INPUT32:
case VIDIOC_S_INPUT32:
case VIDIOC_TRY_FMT32:
+ case VIDIOC_S_HW_FREQ_SEEK:
ret = do_video_ioctl(file, cmd, arg);
break;
diff --git a/linux/drivers/media/video/cpia.h b/linux/drivers/media/video/cpia.h
index 107234853..d579b5edb 100644
--- a/linux/drivers/media/video/cpia.h
+++ b/linux/drivers/media/video/cpia.h
@@ -423,11 +423,11 @@ void cpia_unregister_camera(struct cam_data *cam);
/* ErrorCode */
#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */
#define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
+#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
#ifdef _CPIA_DEBUG_
#define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
+#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
#else
#define DBG(fmn,args...) do {} while(0)
#endif
diff --git a/linux/drivers/media/video/cpia2/cpia2_core.c b/linux/drivers/media/video/cpia2/cpia2_core.c
index a439a56c3..c8b9fdb70 100644
--- a/linux/drivers/media/video/cpia2/cpia2_core.c
+++ b/linux/drivers/media/video/cpia2/cpia2_core.c
@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
block_name[block_index]);
break;
default:
- LOG("%s: invalid request mode\n",__FUNCTION__);
+ LOG("%s: invalid request mode\n",__func__);
return -EINVAL;
}
@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
frame_rate = CPIA2_VP_FRAMERATE_30;
break;
default:
- LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
+ LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
cam->params.version.sensor_flags);
return -EINVAL;
}
@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
}
if (!buf) {
- ERR("%s: buffer NULL\n",__FUNCTION__);
+ ERR("%s: buffer NULL\n",__func__);
return -EINVAL;
}
if (!cam) {
- ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
+ ERR("%s: Internal error, camera_data NULL!\n",__func__);
return -EINVAL;
}
@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
return -ERESTARTSYS;
if (!cam->present) {
- LOG("%s: camera removed\n",__FUNCTION__);
+ LOG("%s: camera removed\n",__func__);
mutex_unlock(&cam->busy_lock);
return 0; /* EOF */
}
@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
unsigned int status=0;
if(!cam) {
- ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
+ ERR("%s: Internal error, camera_data not found!\n",__func__);
return POLLERR;
}
diff --git a/linux/drivers/media/video/cpia_usb.c b/linux/drivers/media/video/cpia_usb.c
index 0d974be34..781999632 100644
--- a/linux/drivers/media/video/cpia_usb.c
+++ b/linux/drivers/media/video/cpia_usb.c
@@ -174,7 +174,7 @@ static void cpia_usb_complete(struct urb *urb)
/* resubmit */
urb->dev = ucpia->dev;
if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
- printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__, i);
+ printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i);
}
static int cpia_usb_open(void *privdata)
diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c
index 0377a24c6..d0bdc009d 100644
--- a/linux/drivers/media/video/cs5345.c
+++ b/linux/drivers/media/video/cs5345.c
@@ -156,7 +156,8 @@ static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
/* ----------------------------------------------------------------------- */
-static int cs5345_probe(struct i2c_client *client)
+static int cs5345_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -173,11 +174,22 @@ static int cs5345_probe(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id cs5345_id[] = {
+ { "cs5345", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cs5345_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "cs5345",
.driverid = I2C_DRIVERID_CS5345,
.command = cs5345_command,
.probe = cs5345_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = cs5345_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c
index fe92723f1..7c0761e21 100644
--- a/linux/drivers/media/video/cs53l32a.c
+++ b/linux/drivers/media/video/cs53l32a.c
@@ -147,7 +147,8 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int cs53l32a_probe(struct i2c_client *client)
+static int cs53l32a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i;
@@ -155,7 +156,12 @@ static int cs53l32a_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
+#else
+ if (!id)
+ strlcpy(client->name, "cs53l32a", sizeof(client->name));
+#endif
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
@@ -186,11 +192,22 @@ static int cs53l32a_probe(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id cs53l32a_id[] = {
+ { "cs53l32a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "cs53l32a",
.driverid = I2C_DRIVERID_CS53L32A,
.command = cs53l32a_command,
.probe = cs53l32a_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = cs53l32a_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig
new file mode 100644
index 000000000..5f9426905
--- /dev/null
+++ b/linux/drivers/media/video/cx18/Kconfig
@@ -0,0 +1,23 @@
+config VIDEO_CX18
+ tristate "Conexant cx23418 MPEG encoder support"
+ depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
+ depends on INPUT # due to VIDEO_IR
+ depends on HOTPLUG # due to FW_LOADER
+ select I2C_ALGOBIT
+ select FW_LOADER
+ select VIDEO_IR
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_CX2341X
+ select VIDEO_CS5345
+ select DVB_S5H1409
+ select MEDIA_TUNER_MXL5005S
+ ---help---
+ This is a video4linux driver for Conexant cx23418 based
+ PCI combo video recorder devices.
+
+ This is used in devices such as the Hauppauge HVR-1600
+ cards.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx18.
diff --git a/linux/drivers/media/video/cx18/Makefile b/linux/drivers/media/video/cx18/Makefile
new file mode 100644
index 000000000..b23d2e261
--- /dev/null
+++ b/linux/drivers/media/video/cx18/Makefile
@@ -0,0 +1,11 @@
+cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
+ cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
+ cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
+ cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
+ cx18-dvb.o
+
+obj-$(CONFIG_VIDEO_CX18) += cx18.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c
new file mode 100644
index 000000000..1adc404d9
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-audio.c
@@ -0,0 +1,73 @@
+/*
+ * cx18 audio-related functions
+ *
+ * Derived from ivtv-audio.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-i2c.h"
+#include "cx18-cards.h"
+#include "cx18-audio.h"
+
+/* Selects the audio input and output according to the current
+ settings. */
+int cx18_audio_set_io(struct cx18 *cx)
+{
+ struct v4l2_routing route;
+ u32 audio_input;
+ int mux_input;
+
+ /* Determine which input to use */
+ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+ audio_input = cx->card->radio_input.audio_input;
+ mux_input = cx->card->radio_input.muxer_input;
+ } else {
+ audio_input =
+ cx->card->audio_inputs[cx->audio_input].audio_input;
+ mux_input =
+ cx->card->audio_inputs[cx->audio_input].muxer_input;
+ }
+
+ /* handle muxer chips */
+ route.input = mux_input;
+ route.output = 0;
+ cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+
+ route.input = audio_input;
+ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
+ VIDIOC_INT_S_AUDIO_ROUTING, &route);
+}
+
+void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route)
+{
+ cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
+ VIDIOC_INT_S_AUDIO_ROUTING, route);
+}
+
+void cx18_audio_set_audio_clock_freq(struct cx18 *cx, 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;
+ cx18_call_i2c_clients(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]);
+}
diff --git a/linux/drivers/media/video/cx18/cx18-audio.h b/linux/drivers/media/video/cx18/cx18-audio.h
new file mode 100644
index 000000000..cb569a693
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-audio.h
@@ -0,0 +1,26 @@
+/*
+ * cx18 audio-related functions
+ *
+ * Derived from ivtv-audio.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+int cx18_audio_set_io(struct cx18 *cx);
+void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route);
+void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq);
diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c
new file mode 100644
index 000000000..2dc3a5dd1
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-av-audio.c
@@ -0,0 +1,361 @@
+/*
+ * cx18 ADEC audio functions
+ *
+ * Derived from cx25840-audio.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+
+static int set_audclk_freq(struct cx18 *cx, u32 freq)
+{
+ struct cx18_av_state *state = &cx->av_state;
+
+ if (freq != 32000 && freq != 44100 && freq != 48000)
+ return -EINVAL;
+
+ /* common for all inputs and rates */
+ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
+ cx18_av_write(cx, 0x127, 0x50);
+
+ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+ switch (freq) {
+ case 32000:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x1006040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x01bb39ee);
+
+ /* src3/4/6_ctl = 0x0801f77f */
+ cx18_av_write4(cx, 0x900, 0x0801f77f);
+ cx18_av_write4(cx, 0x904, 0x0801f77f);
+ cx18_av_write4(cx, 0x90c, 0x0801f77f);
+ break;
+
+ case 44100:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x1009040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
+ /* src3/4/6_ctl = 0x08016d59 */
+ cx18_av_write4(cx, 0x900, 0x08016d59);
+ cx18_av_write4(cx, 0x904, 0x08016d59);
+ cx18_av_write4(cx, 0x90c, 0x08016d59);
+ break;
+
+ case 48000:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x100a040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x0098d6e5);
+
+ /* src3/4/6_ctl = 0x08014faa */
+ cx18_av_write4(cx, 0x900, 0x08014faa);
+ cx18_av_write4(cx, 0x904, 0x08014faa);
+ cx18_av_write4(cx, 0x90c, 0x08014faa);
+ break;
+ }
+ } else {
+ switch (freq) {
+ case 32000:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x1e08040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x012a0869);
+
+ /* src1_ctl = 0x08010000 */
+ cx18_av_write4(cx, 0x8f8, 0x08010000);
+
+ /* src3/4/6_ctl = 0x08020000 */
+ cx18_av_write4(cx, 0x900, 0x08020000);
+ cx18_av_write4(cx, 0x904, 0x08020000);
+ cx18_av_write4(cx, 0x90c, 0x08020000);
+
+ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
+ cx18_av_write(cx, 0x127, 0x54);
+ break;
+
+ case 44100:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x1809040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
+ /* src1_ctl = 0x08010000 */
+ cx18_av_write4(cx, 0x8f8, 0x080160cd);
+
+ /* src3/4/6_ctl = 0x08020000 */
+ cx18_av_write4(cx, 0x900, 0x08017385);
+ cx18_av_write4(cx, 0x904, 0x08017385);
+ cx18_av_write4(cx, 0x90c, 0x08017385);
+ break;
+
+ case 48000:
+ /* VID_PLL and AUX_PLL */
+ cx18_av_write4(cx, 0x108, 0x180a040f);
+
+ /* AUX_PLL_FRAC */
+ cx18_av_write4(cx, 0x110, 0x0098d6e5);
+
+ /* src1_ctl = 0x08010000 */
+ cx18_av_write4(cx, 0x8f8, 0x08018000);
+
+ /* src3/4/6_ctl = 0x08020000 */
+ cx18_av_write4(cx, 0x900, 0x08015555);
+ cx18_av_write4(cx, 0x904, 0x08015555);
+ cx18_av_write4(cx, 0x90c, 0x08015555);
+ break;
+ }
+ }
+
+ state->audclk_freq = freq;
+
+ return 0;
+}
+
+void cx18_av_audio_set_path(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+
+ /* stop microcontroller */
+ cx18_av_and_or(cx, 0x803, ~0x10, 0);
+
+ /* assert soft reset */
+ cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
+
+ /* Mute everything to prevent the PFFT! */
+ cx18_av_write(cx, 0x8d3, 0x1f);
+
+ if (state->aud_input == CX18_AV_AUDIO_SERIAL) {
+ /* Set Path1 to Serial Audio Input */
+ cx18_av_write4(cx, 0x8d0, 0x01011012);
+
+ /* The microcontroller should not be started for the
+ * non-tuner inputs: autodetection is specific for
+ * TV audio. */
+ } else {
+ /* Set Path1 to Analog Demod Main Channel */
+ cx18_av_write4(cx, 0x8d0, 0x1f063870);
+ }
+
+ set_audclk_freq(cx, state->audclk_freq);
+
+ /* deassert soft reset */
+ cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
+
+ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+ /* When the microcontroller detects the
+ * audio format, it will unmute the lines */
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ }
+}
+
+static int get_volume(struct cx18 *cx)
+{
+ /* Volume runs +18dB to -96dB in 1/2dB steps
+ * change to fit the msp3400 -114dB to +12dB range */
+
+ /* check PATH1_VOLUME */
+ int vol = 228 - cx18_av_read(cx, 0x8d4);
+ vol = (vol / 2) + 23;
+ return vol << 9;
+}
+
+static void set_volume(struct cx18 *cx, int volume)
+{
+ /* First convert the volume to msp3400 values (0-127) */
+ int vol = volume >> 9;
+ /* now scale it up to cx18_av values
+ * -114dB to -96dB maps to 0
+ * this should be 19, but in my testing that was 4dB too loud */
+ if (vol <= 23)
+ vol = 0;
+ else
+ vol -= 23;
+
+ /* PATH1_VOLUME */
+ cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
+}
+
+static int get_bass(struct cx18 *cx)
+{
+ /* bass is 49 steps +12dB to -12dB */
+
+ /* check PATH1_EQ_BASS_VOL */
+ int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
+ bass = (((48 - bass) * 0xffff) + 47) / 48;
+ return bass;
+}
+
+static void set_bass(struct cx18 *cx, int bass)
+{
+ /* PATH1_EQ_BASS_VOL */
+ cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
+}
+
+static int get_treble(struct cx18 *cx)
+{
+ /* treble is 49 steps +12dB to -12dB */
+
+ /* check PATH1_EQ_TREBLE_VOL */
+ int treble = cx18_av_read(cx, 0x8db) & 0x3f;
+ treble = (((48 - treble) * 0xffff) + 47) / 48;
+ return treble;
+}
+
+static void set_treble(struct cx18 *cx, int treble)
+{
+ /* PATH1_EQ_TREBLE_VOL */
+ cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
+}
+
+static int get_balance(struct cx18 *cx)
+{
+ /* balance is 7 bit, 0 to -96dB */
+
+ /* check PATH1_BAL_LEVEL */
+ int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
+ /* check PATH1_BAL_LEFT */
+ if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
+ balance = 0x80 - balance;
+ else
+ balance = 0x80 + balance;
+ return balance << 8;
+}
+
+static void set_balance(struct cx18 *cx, int balance)
+{
+ int bal = balance >> 8;
+ if (bal > 0x80) {
+ /* PATH1_BAL_LEFT */
+ cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
+ /* PATH1_BAL_LEVEL */
+ cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
+ } else {
+ /* PATH1_BAL_LEFT */
+ cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
+ /* PATH1_BAL_LEVEL */
+ cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
+ }
+}
+
+static int get_mute(struct cx18 *cx)
+{
+ /* check SRC1_MUTE_EN */
+ return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
+}
+
+static void set_mute(struct cx18 *cx, int mute)
+{
+ struct cx18_av_state *state = &cx->av_state;
+
+ if (state->aud_input != CX18_AV_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 */
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+ cx18_av_write(cx, 0x8d3, 0x1f);
+ } else {
+ /* enable microcontroller */
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ }
+ } else {
+ /* SRC1_MUTE_EN */
+ cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+ }
+}
+
+int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ struct v4l2_control *ctrl = arg;
+ int retval;
+
+ switch (cmd) {
+ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+ cx18_av_and_or(cx, 0x803, ~0x10, 0);
+ cx18_av_write(cx, 0x8d3, 0x1f);
+ }
+ cx18_av_and_or(cx, 0x810, ~0x1, 1);
+ retval = set_audclk_freq(cx, *(u32 *)arg);
+ cx18_av_and_or(cx, 0x810, ~0x1, 0);
+ if (state->aud_input != CX18_AV_AUDIO_SERIAL)
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ return retval;
+
+ case VIDIOC_G_CTRL:
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = get_volume(cx);
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ ctrl->value = get_bass(cx);
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ ctrl->value = get_treble(cx);
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ ctrl->value = get_balance(cx);
+ break;
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = get_mute(cx);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case VIDIOC_S_CTRL:
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ set_volume(cx, ctrl->value);
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ set_bass(cx, ctrl->value);
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ set_treble(cx, ctrl->value);
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ set_balance(cx, ctrl->value);
+ break;
+ case V4L2_CID_AUDIO_MUTE:
+ set_mute(cx, ctrl->value);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c
new file mode 100644
index 000000000..8f2959ae7
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-av-core.c
@@ -0,0 +1,888 @@
+/*
+ * cx18 ADEC audio functions
+ *
+ * Derived from cx25840-core.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
+{
+ u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+ u32 mask = 0xff;
+ int shift = (addr & 3) * 8;
+
+ x = (x & ~(mask << shift)) | ((u32)value << shift);
+ writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
+ return 0;
+}
+
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
+{
+ writel(value, cx->reg_mem + 0xc40000 + addr);
+ return 0;
+}
+
+u8 cx18_av_read(struct cx18 *cx, u16 addr)
+{
+ u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+ int shift = (addr & 3) * 8;
+
+ return (x >> shift) & 0xff;
+}
+
+u32 cx18_av_read4(struct cx18 *cx, u16 addr)
+{
+ return readl(cx->reg_mem + 0xc40000 + addr);
+}
+
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
+ u8 or_value)
+{
+ return cx18_av_write(cx, addr,
+ (cx18_av_read(cx, addr) & and_mask) |
+ or_value);
+}
+
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
+ u32 or_value)
+{
+ return cx18_av_write4(cx, addr,
+ (cx18_av_read4(cx, addr) & and_mask) |
+ or_value);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
+ enum cx18_av_audio_input aud_input);
+static void log_audio_status(struct cx18 *cx);
+static void log_video_status(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+
+static void cx18_av_initialize(struct cx18 *cx)
+{
+ u32 v;
+
+ cx18_av_loadfw(cx);
+ /* Stop 8051 code execution */
+ cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
+
+ /* initallize the PLL by toggling sleep bit */
+ v = cx18_av_read4(cx, CXADEC_HOST_REG1);
+ /* enable sleep mode */
+ cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
+ /* disable sleep mode */
+ cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
+
+ /* initialize DLLs */
+ v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
+ /* disable FLD */
+ cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
+ /* enable FLD */
+ cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
+
+ v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
+ /* disable FLD */
+ cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
+ /* enable FLD */
+ cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
+
+ /* set analog bias currents. Set Vreg to 1.20V. */
+ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
+
+ v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
+ /* enable TUNE_FIL_RST */
+ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
+ /* disable TUNE_FIL_RST */
+ cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
+
+ /* enable 656 output */
+ cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
+
+ /* video output drive strength */
+ cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
+
+ /* reset video */
+ cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
+ cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
+
+ /* set video to auto-detect */
+ /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */
+ /* set the comb notch = 1 */
+ cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
+
+ /* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
+ /* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
+ cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
+
+ /* Set VGA_TRACK_RANGE to 0x20 */
+ cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
+
+ /* Enable VBI capture */
+ cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F);
+ /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */
+
+ /* Set the video input.
+ The setting in MODE_CTRL gets lost when we do the above setup */
+ /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
+ /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
+
+ v = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+ v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */
+ v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */
+ v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */
+ /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */
+ cx18_av_write4(cx, CXADEC_AFE_CTRL, v);
+
+/* if(dwEnable && dw3DCombAvailable) { */
+/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
+/* } else { */
+/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
+/* } */
+ cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void input_change(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ v4l2_std_id std = state->std;
+
+ /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
+ if (std & V4L2_STD_SECAM)
+ cx18_av_write(cx, 0x402, 0);
+ else {
+ cx18_av_write(cx, 0x402, 0x04);
+ cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+ }
+ cx18_av_and_or(cx, 0x401, ~0x60, 0);
+ cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+
+ if (std & V4L2_STD_525_60) {
+ if (std == V4L2_STD_NTSC_M_JP) {
+ /* Japan uses EIAJ audio standard */
+ cx18_av_write(cx, 0x808, 0xf7);
+ cx18_av_write(cx, 0x80b, 0x02);
+ } else if (std == V4L2_STD_NTSC_M_KR) {
+ /* South Korea uses A2 audio standard */
+ cx18_av_write(cx, 0x808, 0xf8);
+ cx18_av_write(cx, 0x80b, 0x03);
+ } else {
+ /* Others use the BTSC audio standard */
+ cx18_av_write(cx, 0x808, 0xf6);
+ cx18_av_write(cx, 0x80b, 0x01);
+ }
+ } else if (std & V4L2_STD_PAL) {
+ /* Follow tuner change procedure for PAL */
+ cx18_av_write(cx, 0x808, 0xff);
+ cx18_av_write(cx, 0x80b, 0x03);
+ } else if (std & V4L2_STD_SECAM) {
+ /* Select autodetect for SECAM */
+ cx18_av_write(cx, 0x808, 0xff);
+ cx18_av_write(cx, 0x80b, 0x03);
+ }
+
+ if (cx18_av_read(cx, 0x803) & 0x10) {
+ /* restart audio decoder microcontroller */
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+ cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ }
+}
+
+static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
+ enum cx18_av_audio_input aud_input)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
+ vid_input <= CX18_AV_COMPOSITE8);
+ u8 reg;
+
+ CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
+ vid_input, aud_input);
+
+ if (is_composite) {
+ reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+ } else {
+ int luma = vid_input & 0xf0;
+ int chroma = vid_input & 0xf00;
+
+ if ((vid_input & ~0xff0) ||
+ luma < CX18_AV_SVIDEO_LUMA1 ||
+ luma > CX18_AV_SVIDEO_LUMA8 ||
+ chroma < CX18_AV_SVIDEO_CHROMA4 ||
+ chroma > CX18_AV_SVIDEO_CHROMA8) {
+ CX18_ERR("0x%04x is not a valid video input!\n",
+ vid_input);
+ return -EINVAL;
+ }
+ reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+ if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
+ reg &= 0x3f;
+ reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+ } else {
+ reg &= 0xcf;
+ reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+ }
+ }
+
+ switch (aud_input) {
+ case CX18_AV_AUDIO_SERIAL:
+ /* do nothing, use serial audio input */
+ break;
+ case CX18_AV_AUDIO4: reg &= ~0x30; break;
+ case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+ case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+ case CX18_AV_AUDIO7: reg &= ~0xc0; break;
+ case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+
+ default:
+ CX18_ERR("0x%04x is not a valid audio input!\n", aud_input);
+ return -EINVAL;
+ }
+
+ cx18_av_write(cx, 0x103, reg);
+ /* Set INPUT_MODE to Composite (0) or S-Video (1) */
+ cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+ /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+ cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+ /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+ if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+ cx18_av_and_or(cx, 0x102, ~0x4, 4);
+ else
+ cx18_av_and_or(cx, 0x102, ~0x4, 0);
+ /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
+
+ state->vid_input = vid_input;
+ state->aud_input = aud_input;
+ cx18_av_audio_set_path(cx);
+ input_change(cx);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_v4lstd(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ u8 fmt = 0; /* zero is autodetect */
+ u8 pal_m = 0;
+
+ /* First tests should be against specific std */
+ if (state->std == V4L2_STD_NTSC_M_JP) {
+ fmt = 0x2;
+ } else if (state->std == V4L2_STD_NTSC_443) {
+ fmt = 0x3;
+ } else if (state->std == V4L2_STD_PAL_M) {
+ pal_m = 1;
+ fmt = 0x5;
+ } else if (state->std == V4L2_STD_PAL_N) {
+ fmt = 0x6;
+ } else if (state->std == V4L2_STD_PAL_Nc) {
+ fmt = 0x7;
+ } else if (state->std == V4L2_STD_PAL_60) {
+ fmt = 0x8;
+ } else {
+ /* Then, test against generic ones */
+ if (state->std & V4L2_STD_NTSC)
+ fmt = 0x1;
+ else if (state->std & V4L2_STD_PAL)
+ fmt = 0x4;
+ else if (state->std & V4L2_STD_SECAM)
+ fmt = 0xc;
+ }
+
+ CX18_DEBUG_INFO("changing video std to fmt %i\n", fmt);
+
+ /* Follow step 9 of section 3.16 in the cx18_av datasheet.
+ Without this PAL may display a vertical ghosting effect.
+ This happens for example with the Yuan MPC622. */
+ if (fmt >= 4 && fmt < 8) {
+ /* Set format to NTSC-M */
+ cx18_av_and_or(cx, 0x400, ~0xf, 1);
+ /* Turn off LCOMB */
+ cx18_av_and_or(cx, 0x47b, ~6, 0);
+ }
+ cx18_av_and_or(cx, 0x400, ~0xf, fmt);
+ cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
+ cx18_av_vbi_setup(cx);
+ input_change(cx);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value < 0 || ctrl->value > 255) {
+ CX18_ERR("invalid brightness setting %d\n",
+ ctrl->value);
+ return -ERANGE;
+ }
+
+ cx18_av_write(cx, 0x414, ctrl->value - 128);
+ break;
+
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value < 0 || ctrl->value > 127) {
+ CX18_ERR("invalid contrast setting %d\n",
+ ctrl->value);
+ return -ERANGE;
+ }
+
+ cx18_av_write(cx, 0x415, ctrl->value << 1);
+ break;
+
+ case V4L2_CID_SATURATION:
+ if (ctrl->value < 0 || ctrl->value > 127) {
+ CX18_ERR("invalid saturation setting %d\n",
+ ctrl->value);
+ return -ERANGE;
+ }
+
+ cx18_av_write(cx, 0x420, ctrl->value << 1);
+ cx18_av_write(cx, 0x421, ctrl->value << 1);
+ break;
+
+ case V4L2_CID_HUE:
+ if (ctrl->value < -127 || ctrl->value > 127) {
+ CX18_ERR("invalid hue setting %d\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ cx18_av_write(cx, 0x422, ctrl->value);
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_MUTE:
+ return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl);
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = cx18_av_read(cx, 0x415) >> 1;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->value = cx18_av_read(cx, 0x420) >> 1;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->value = (s8)cx18_av_read(cx, 0x422);
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_MUTE:
+ return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int get_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ struct v4l2_pix_format *pix;
+ int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+ int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pix = &(fmt->fmt.pix);
+
+ Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+ Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+
+ Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+ Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+
+ Vlines = pix->height + (is_50Hz ? 4 : 7);
+
+ if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
+ (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+ CX18_ERR("%dx%d is not a valid size!\n",
+ pix->width, pix->height);
+ return -ERANGE;
+ }
+
+ HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
+ VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+ VSC &= 0x1fff;
+
+ if (pix->width >= 385)
+ filter = 0;
+ else if (pix->width > 192)
+ filter = 1;
+ else if (pix->width > 96)
+ filter = 2;
+ else
+ filter = 3;
+
+ CX18_DEBUG_INFO("decoder set size %dx%d -> scale %ux%u\n",
+ pix->width, pix->height, HSC, VSC);
+
+ /* HSCALE=HSC */
+ cx18_av_write(cx, 0x418, HSC & 0xff);
+ cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+ cx18_av_write(cx, 0x41a, HSC >> 16);
+ /* VSCALE=VSC */
+ cx18_av_write(cx, 0x41c, VSC & 0xff);
+ cx18_av_write(cx, 0x41d, VSC >> 8);
+ /* VS_INTRLACE=1 VFILT=filter */
+ cx18_av_write(cx, 0x41e, 0x8 | filter);
+ break;
+
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ 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) {
+ CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd);
+ /* initialize on first use */
+ state->is_initialized = 1;
+ cx18_av_initialize(cx);
+ }
+
+ switch (cmd) {
+ case VIDIOC_INT_DECODE_VBI_LINE:
+ return cx18_av_vbi(cx, cmd, arg);
+
+ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ return cx18_av_audio(cx, cmd, arg);
+
+ case VIDIOC_STREAMON:
+ CX18_DEBUG_INFO("enable output\n");
+ cx18_av_write(cx, 0x115, 0x8c);
+ cx18_av_write(cx, 0x116, 0x07);
+ break;
+
+ case VIDIOC_STREAMOFF:
+ CX18_DEBUG_INFO("disable output\n");
+ cx18_av_write(cx, 0x115, 0x00);
+ cx18_av_write(cx, 0x116, 0x00);
+ break;
+
+ case VIDIOC_LOG_STATUS:
+ log_video_status(cx);
+ log_audio_status(cx);
+ break;
+
+ case VIDIOC_G_CTRL:
+ return get_v4lctrl(cx, (struct v4l2_control *)arg);
+
+ case VIDIOC_S_CTRL:
+ return set_v4lctrl(cx, (struct v4l2_control *)arg);
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+
+ switch (qc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_CONTRAST:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_HUE:
+ return v4l2_ctrl_query_fill_std(qc);
+ default:
+ break;
+ }
+
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ return v4l2_ctrl_query_fill_std(qc);
+ default:
+ return -EINVAL;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_G_STD:
+ *(v4l2_std_id *)arg = state->std;
+ break;
+
+ case VIDIOC_S_STD:
+ if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
+ return 0;
+ state->radio = 0;
+ state->std = *(v4l2_std_id *)arg;
+ return set_v4lstd(cx);
+
+ case AUDC_SET_RADIO:
+ state->radio = 1;
+ break;
+
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = state->vid_input;
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ return set_input(cx, route->input, state->aud_input);
+
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ route->input = state->aud_input;
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_AUDIO_ROUTING:
+ return set_input(cx, state->vid_input, route->input);
+
+ case VIDIOC_S_FREQUENCY:
+ input_change(cx);
+ break;
+
+ case VIDIOC_G_TUNER:
+ {
+ u8 vpres = cx18_av_read(cx, 0x40e) & 0x20;
+ u8 mode;
+ int val = 0;
+
+ if (state->radio)
+ break;
+
+ vt->signal = vpres ? 0xffff : 0x0;
+
+ vt->capability |=
+ V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+ V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+ mode = cx18_av_read(cx, 0x804);
+
+ /* get rxsubchans and audmode */
+ if ((mode & 0xf) == 1)
+ val |= V4L2_TUNER_SUB_STEREO;
+ else
+ val |= V4L2_TUNER_SUB_MONO;
+
+ if (mode == 2 || mode == 4)
+ val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+ if (mode & 0x10)
+ val |= V4L2_TUNER_SUB_SAP;
+
+ vt->rxsubchans = val;
+ vt->audmode = state->audmode;
+ break;
+ }
+
+ case VIDIOC_S_TUNER:
+ if (state->radio)
+ break;
+
+ switch (vt->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ /* mono -> mono
+ stereo -> mono
+ bilingual -> lang1 */
+ cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1:
+ /* mono -> mono
+ stereo -> stereo
+ bilingual -> lang1 */
+ cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
+ break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ /* mono -> mono
+ stereo -> stereo
+ bilingual -> lang1/lang2 */
+ cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ /* mono -> mono
+ stereo -> stereo
+ bilingual -> lang2 */
+ cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
+ break;
+ default:
+ return -EINVAL;
+ }
+ state->audmode = vt->audmode;
+ break;
+
+ case VIDIOC_G_FMT:
+ return get_v4lfmt(cx, (struct v4l2_format *)arg);
+
+ case VIDIOC_S_FMT:
+ return set_v4lfmt(cx, (struct v4l2_format *)arg);
+
+ case VIDIOC_INT_RESET:
+ cx18_av_initialize(cx);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+
+static void log_video_status(struct cx18 *cx)
+{
+ static const char *const fmt_strs[] = {
+ "0x0",
+ "NTSC-M", "NTSC-J", "NTSC-4.43",
+ "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+ "0x9", "0xA", "0xB",
+ "SECAM",
+ "0xD", "0xE", "0xF"
+ };
+
+ struct cx18_av_state *state = &cx->av_state;
+ u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
+ u8 gen_stat1 = cx18_av_read(cx, 0x40d);
+ u8 gen_stat2 = cx18_av_read(cx, 0x40e);
+ int vid_input = state->vid_input;
+
+ CX18_INFO("Video signal: %spresent\n",
+ (gen_stat2 & 0x20) ? "" : "not ");
+ CX18_INFO("Detected format: %s\n",
+ fmt_strs[gen_stat1 & 0xf]);
+
+ CX18_INFO("Specified standard: %s\n",
+ vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+ if (vid_input >= CX18_AV_COMPOSITE1 &&
+ vid_input <= CX18_AV_COMPOSITE8) {
+ CX18_INFO("Specified video input: Composite %d\n",
+ vid_input - CX18_AV_COMPOSITE1 + 1);
+ } else {
+ CX18_INFO("Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
+ (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+ }
+
+ CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ u8 download_ctl = cx18_av_read(cx, 0x803);
+ u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
+ u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
+ u8 audio_config = cx18_av_read(cx, 0x808);
+ u8 pref_mode = cx18_av_read(cx, 0x809);
+ u8 afc0 = cx18_av_read(cx, 0x80b);
+ u8 mute_ctl = cx18_av_read(cx, 0x8d3);
+ int aud_input = state->aud_input;
+ char *p;
+
+ switch (mod_det_stat0) {
+ case 0x00: p = "mono"; break;
+ case 0x01: p = "stereo"; break;
+ case 0x02: p = "dual"; break;
+ case 0x04: p = "tri"; break;
+ case 0x10: p = "mono with SAP"; break;
+ case 0x11: p = "stereo with SAP"; break;
+ case 0x12: p = "dual with SAP"; break;
+ case 0x14: p = "tri with SAP"; break;
+ case 0xfe: p = "forced mode"; break;
+ default: p = "not defined"; break;
+ }
+ CX18_INFO("Detected audio mode: %s\n", p);
+
+ switch (mod_det_stat1) {
+ case 0x00: p = "not defined"; break;
+ case 0x01: p = "EIAJ"; break;
+ case 0x02: p = "A2-M"; break;
+ case 0x03: p = "A2-BG"; break;
+ case 0x04: p = "A2-DK1"; break;
+ case 0x05: p = "A2-DK2"; break;
+ case 0x06: p = "A2-DK3"; break;
+ case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+ case 0x08: p = "AM-L"; break;
+ case 0x09: p = "NICAM-BG"; break;
+ case 0x0a: p = "NICAM-DK"; break;
+ case 0x0b: p = "NICAM-I"; break;
+ case 0x0c: p = "NICAM-L"; break;
+ case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+ case 0x0e: p = "IF FM Radio"; break;
+ case 0x0f: p = "BTSC"; break;
+ case 0x10: p = "detected chrominance"; break;
+ case 0xfd: p = "unknown audio standard"; break;
+ case 0xfe: p = "forced audio standard"; break;
+ case 0xff: p = "no detected audio standard"; break;
+ default: p = "not defined"; break;
+ }
+ CX18_INFO("Detected audio standard: %s\n", p);
+ CX18_INFO("Audio muted: %s\n",
+ (mute_ctl & 0x2) ? "yes" : "no");
+ CX18_INFO("Audio microcontroller: %s\n",
+ (download_ctl & 0x10) ? "running" : "stopped");
+
+ switch (audio_config >> 4) {
+ case 0x00: p = "undefined"; break;
+ case 0x01: p = "BTSC"; break;
+ case 0x02: p = "EIAJ"; break;
+ case 0x03: p = "A2-M"; break;
+ case 0x04: p = "A2-BG"; break;
+ case 0x05: p = "A2-DK1"; break;
+ case 0x06: p = "A2-DK2"; break;
+ case 0x07: p = "A2-DK3"; break;
+ case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+ case 0x09: p = "AM-L"; break;
+ case 0x0a: p = "NICAM-BG"; break;
+ case 0x0b: p = "NICAM-DK"; break;
+ case 0x0c: p = "NICAM-I"; break;
+ case 0x0d: p = "NICAM-L"; break;
+ case 0x0e: p = "FM radio"; break;
+ case 0x0f: p = "automatic detection"; break;
+ default: p = "undefined"; break;
+ }
+ CX18_INFO("Configured audio standard: %s\n", p);
+
+ if ((audio_config >> 4) < 0xF) {
+ switch (audio_config & 0xF) {
+ case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+ case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+ case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+ case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+ case 0x04: p = "STEREO"; break;
+ case 0x05: p = "DUAL1 (AC)"; break;
+ case 0x06: p = "DUAL2 (BC)"; break;
+ case 0x07: p = "DUAL3 (AB)"; break;
+ default: p = "undefined";
+ }
+ CX18_INFO("Configured audio mode: %s\n", p);
+ } else {
+ switch (audio_config & 0xF) {
+ case 0x00: p = "BG"; break;
+ case 0x01: p = "DK1"; break;
+ case 0x02: p = "DK2"; break;
+ case 0x03: p = "DK3"; break;
+ case 0x04: p = "I"; break;
+ case 0x05: p = "L"; break;
+ case 0x06: p = "BTSC"; break;
+ case 0x07: p = "EIAJ"; break;
+ case 0x08: p = "A2-M"; break;
+ case 0x09: p = "FM Radio (4.5 MHz)"; break;
+ case 0x0a: p = "FM Radio (5.5 MHz)"; break;
+ case 0x0b: p = "S-Video"; break;
+ case 0x0f: p = "automatic standard and mode detection"; break;
+ default: p = "undefined"; break;
+ }
+ CX18_INFO("Configured audio system: %s\n", p);
+ }
+
+ if (aud_input)
+ CX18_INFO("Specified audio input: Tuner (In%d)\n",
+ aud_input);
+ else
+ CX18_INFO("Specified audio input: External\n");
+
+ switch (pref_mode & 0xf) {
+ case 0: p = "mono/language A"; break;
+ case 1: p = "language B"; break;
+ case 2: p = "language C"; break;
+ case 3: p = "analog fallback"; break;
+ case 4: p = "stereo"; break;
+ case 5: p = "language AC"; break;
+ case 6: p = "language BC"; break;
+ case 7: p = "language AB"; break;
+ default: p = "undefined"; break;
+ }
+ CX18_INFO("Preferred audio mode: %s\n", p);
+
+ if ((audio_config & 0xf) == 0xf) {
+ switch ((afc0 >> 3) & 0x1) {
+ case 0: p = "system DK"; break;
+ case 1: p = "system L"; break;
+ }
+ CX18_INFO("Selected 65 MHz format: %s\n", p);
+
+ switch (afc0 & 0x7) {
+ case 0: p = "Chroma"; break;
+ case 1: p = "BTSC"; break;
+ case 2: p = "EIAJ"; break;
+ case 3: p = "A2-M"; break;
+ case 4: p = "autodetect"; break;
+ default: p = "undefined"; break;
+ }
+ CX18_INFO("Selected 45 MHz format: %s\n", p);
+ }
+}
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h
new file mode 100644
index 000000000..39f3c9397
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-av-core.h
@@ -0,0 +1,322 @@
+/*
+ * cx18 ADEC header
+ *
+ * Derived from cx25840-core.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _CX18_AV_CORE_H_
+#define _CX18_AV_CORE_H_
+
+struct cx18;
+
+enum cx18_av_video_input {
+ /* Composite video inputs In1-In8 */
+ CX18_AV_COMPOSITE1 = 1,
+ CX18_AV_COMPOSITE2,
+ CX18_AV_COMPOSITE3,
+ CX18_AV_COMPOSITE4,
+ CX18_AV_COMPOSITE5,
+ CX18_AV_COMPOSITE6,
+ CX18_AV_COMPOSITE7,
+ CX18_AV_COMPOSITE8,
+
+ /* S-Video inputs consist of one luma input (In1-In8) ORed with one
+ chroma input (In5-In8) */
+ CX18_AV_SVIDEO_LUMA1 = 0x10,
+ CX18_AV_SVIDEO_LUMA2 = 0x20,
+ CX18_AV_SVIDEO_LUMA3 = 0x30,
+ CX18_AV_SVIDEO_LUMA4 = 0x40,
+ CX18_AV_SVIDEO_LUMA5 = 0x50,
+ CX18_AV_SVIDEO_LUMA6 = 0x60,
+ CX18_AV_SVIDEO_LUMA7 = 0x70,
+ CX18_AV_SVIDEO_LUMA8 = 0x80,
+ CX18_AV_SVIDEO_CHROMA4 = 0x400,
+ CX18_AV_SVIDEO_CHROMA5 = 0x500,
+ CX18_AV_SVIDEO_CHROMA6 = 0x600,
+ CX18_AV_SVIDEO_CHROMA7 = 0x700,
+ CX18_AV_SVIDEO_CHROMA8 = 0x800,
+
+ /* S-Video aliases for common luma/chroma combinations */
+ CX18_AV_SVIDEO1 = 0x510,
+ CX18_AV_SVIDEO2 = 0x620,
+ CX18_AV_SVIDEO3 = 0x730,
+ CX18_AV_SVIDEO4 = 0x840,
+};
+
+enum cx18_av_audio_input {
+ /* Audio inputs: serial or In4-In8 */
+ CX18_AV_AUDIO_SERIAL,
+ CX18_AV_AUDIO4 = 4,
+ CX18_AV_AUDIO5,
+ CX18_AV_AUDIO6,
+ CX18_AV_AUDIO7,
+ CX18_AV_AUDIO8,
+};
+
+struct cx18_av_state {
+ int radio;
+ v4l2_std_id std;
+ enum cx18_av_video_input vid_input;
+ enum cx18_av_audio_input aud_input;
+ u32 audclk_freq;
+ int audmode;
+ int vbi_line_offset;
+ u32 id;
+ u32 rev;
+ int is_initialized;
+};
+
+
+/* Registers */
+#define CXADEC_CHIP_TYPE_TIGER 0x837
+#define CXADEC_CHIP_TYPE_MAKO 0x843
+
+#define CXADEC_HOST_REG1 0x000
+#define CXADEC_HOST_REG2 0x001
+
+#define CXADEC_CHIP_CTRL 0x100
+#define CXADEC_AFE_CTRL 0x104
+#define CXADEC_PLL_CTRL1 0x108
+#define CXADEC_VID_PLL_FRAC 0x10C
+#define CXADEC_AUX_PLL_FRAC 0x110
+#define CXADEC_PIN_CTRL1 0x114
+#define CXADEC_PIN_CTRL2 0x118
+#define CXADEC_PIN_CFG1 0x11C
+#define CXADEC_PIN_CFG2 0x120
+
+#define CXADEC_PIN_CFG3 0x124
+#define CXADEC_I2S_MCLK 0x127
+
+#define CXADEC_AUD_LOCK1 0x128
+#define CXADEC_AUD_LOCK2 0x12C
+#define CXADEC_POWER_CTRL 0x130
+#define CXADEC_AFE_DIAG_CTRL1 0x134
+#define CXADEC_AFE_DIAG_CTRL2 0x138
+#define CXADEC_AFE_DIAG_CTRL3 0x13C
+#define CXADEC_PLL_DIAG_CTRL 0x140
+#define CXADEC_TEST_CTRL1 0x144
+#define CXADEC_TEST_CTRL2 0x148
+#define CXADEC_BIST_STAT 0x14C
+#define CXADEC_DLL1_DIAG_CTRL 0x158
+#define CXADEC_DLL2_DIAG_CTRL 0x15C
+
+/* IR registers */
+#define CXADEC_IR_CTRL_REG 0x200
+#define CXADEC_IR_TXCLK_REG 0x204
+#define CXADEC_IR_RXCLK_REG 0x208
+#define CXADEC_IR_CDUTY_REG 0x20C
+#define CXADEC_IR_STAT_REG 0x210
+#define CXADEC_IR_IRQEN_REG 0x214
+#define CXADEC_IR_FILTER_REG 0x218
+#define CXADEC_IR_FIFO_REG 0x21C
+
+/* Video Registers */
+#define CXADEC_MODE_CTRL 0x400
+#define CXADEC_OUT_CTRL1 0x404
+#define CXADEC_OUT_CTRL2 0x408
+#define CXADEC_GEN_STAT 0x40C
+#define CXADEC_INT_STAT_MASK 0x410
+#define CXADEC_LUMA_CTRL 0x414
+
+#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
+#define CXADEC_CONTRAST_CTRL_BYTE 0x415
+#define CXADEC_LUMA_CTRL_BYTE_3 0x416
+
+#define CXADEC_HSCALE_CTRL 0x418
+#define CXADEC_VSCALE_CTRL 0x41C
+
+#define CXADEC_CHROMA_CTRL 0x420
+
+#define CXADEC_USAT_CTRL_BYTE 0x420
+#define CXADEC_VSAT_CTRL_BYTE 0x421
+#define CXADEC_HUE_CTRL_BYTE 0x422
+
+#define CXADEC_VBI_LINE_CTRL1 0x424
+#define CXADEC_VBI_LINE_CTRL2 0x428
+#define CXADEC_VBI_LINE_CTRL3 0x42C
+#define CXADEC_VBI_LINE_CTRL4 0x430
+#define CXADEC_VBI_LINE_CTRL5 0x434
+#define CXADEC_VBI_FC_CFG 0x438
+#define CXADEC_VBI_MISC_CFG1 0x43C
+#define CXADEC_VBI_MISC_CFG2 0x440
+#define CXADEC_VBI_PAY1 0x444
+#define CXADEC_VBI_PAY2 0x448
+#define CXADEC_VBI_CUST1_CFG1 0x44C
+#define CXADEC_VBI_CUST1_CFG2 0x450
+#define CXADEC_VBI_CUST1_CFG3 0x454
+#define CXADEC_VBI_CUST2_CFG1 0x458
+#define CXADEC_VBI_CUST2_CFG2 0x45C
+#define CXADEC_VBI_CUST2_CFG3 0x460
+#define CXADEC_VBI_CUST3_CFG1 0x464
+#define CXADEC_VBI_CUST3_CFG2 0x468
+#define CXADEC_VBI_CUST3_CFG3 0x46C
+#define CXADEC_HORIZ_TIM_CTRL 0x470
+#define CXADEC_VERT_TIM_CTRL 0x474
+#define CXADEC_SRC_COMB_CFG 0x478
+#define CXADEC_CHROMA_VBIOFF_CFG 0x47C
+#define CXADEC_FIELD_COUNT 0x480
+#define CXADEC_MISC_TIM_CTRL 0x484
+#define CXADEC_DFE_CTRL1 0x488
+#define CXADEC_DFE_CTRL2 0x48C
+#define CXADEC_DFE_CTRL3 0x490
+#define CXADEC_PLL_CTRL2 0x494
+#define CXADEC_HTL_CTRL 0x498
+#define CXADEC_COMB_CTRL 0x49C
+#define CXADEC_CRUSH_CTRL 0x4A0
+#define CXADEC_SOFT_RST_CTRL 0x4A4
+#define CXADEC_MV_DT_CTRL2 0x4A8
+#define CXADEC_MV_DT_CTRL3 0x4AC
+#define CXADEC_MISC_DIAG_CTRL 0x4B8
+
+#define CXADEC_DL_CTL 0x800
+#define CXADEC_DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */
+#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */
+#define CXADEC_DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */
+#define CXADEC_DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */
+
+#define CXADEC_STD_DET_STATUS 0x804
+
+#define CXADEC_STD_DET_CTL 0x808
+#define CXADEC_STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */
+#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
+
+#define CXADEC_DW8051_INT 0x80C
+#define CXADEC_GENERAL_CTL 0x810
+#define CXADEC_AAGC_CTL 0x814
+#define CXADEC_IF_SRC_CTL 0x818
+#define CXADEC_ANLOG_DEMOD_CTL 0x81C
+#define CXADEC_ROT_FREQ_CTL 0x820
+#define CXADEC_FM1_CTL 0x824
+#define CXADEC_PDF_CTL 0x828
+#define CXADEC_DFT1_CTL1 0x82C
+#define CXADEC_DFT1_CTL2 0x830
+#define CXADEC_DFT_STATUS 0x834
+#define CXADEC_DFT2_CTL1 0x838
+#define CXADEC_DFT2_CTL2 0x83C
+#define CXADEC_DFT2_STATUS 0x840
+#define CXADEC_DFT3_CTL1 0x844
+#define CXADEC_DFT3_CTL2 0x848
+#define CXADEC_DFT3_STATUS 0x84C
+#define CXADEC_DFT4_CTL1 0x850
+#define CXADEC_DFT4_CTL2 0x854
+#define CXADEC_DFT4_STATUS 0x858
+#define CXADEC_AM_MTS_DET 0x85C
+#define CXADEC_ANALOG_MUX_CTL 0x860
+#define CXADEC_DIG_PLL_CTL1 0x864
+#define CXADEC_DIG_PLL_CTL2 0x868
+#define CXADEC_DIG_PLL_CTL3 0x86C
+#define CXADEC_DIG_PLL_CTL4 0x870
+#define CXADEC_DIG_PLL_CTL5 0x874
+#define CXADEC_DEEMPH_GAIN_CTL 0x878
+#define CXADEC_DEEMPH_COEF1 0x87C
+#define CXADEC_DEEMPH_COEF2 0x880
+#define CXADEC_DBX1_CTL1 0x884
+#define CXADEC_DBX1_CTL2 0x888
+#define CXADEC_DBX1_STATUS 0x88C
+#define CXADEC_DBX2_CTL1 0x890
+#define CXADEC_DBX2_CTL2 0x894
+#define CXADEC_DBX2_STATUS 0x898
+#define CXADEC_AM_FM_DIFF 0x89C
+
+/* NICAM registers go here */
+#define CXADEC_NICAM_STATUS 0x8C8
+#define CXADEC_DEMATRIX_CTL 0x8CC
+
+#define CXADEC_PATH1_CTL1 0x8D0
+#define CXADEC_PATH1_VOL_CTL 0x8D4
+#define CXADEC_PATH1_EQ_CTL 0x8D8
+#define CXADEC_PATH1_SC_CTL 0x8DC
+
+#define CXADEC_PATH2_CTL1 0x8E0
+#define CXADEC_PATH2_VOL_CTL 0x8E4
+#define CXADEC_PATH2_EQ_CTL 0x8E8
+#define CXADEC_PATH2_SC_CTL 0x8EC
+
+#define CXADEC_SRC_CTL 0x8F0
+#define CXADEC_SRC_LF_COEF 0x8F4
+#define CXADEC_SRC1_CTL 0x8F8
+#define CXADEC_SRC2_CTL 0x8FC
+#define CXADEC_SRC3_CTL 0x900
+#define CXADEC_SRC4_CTL 0x904
+#define CXADEC_SRC5_CTL 0x908
+#define CXADEC_SRC6_CTL 0x90C
+
+#define CXADEC_BASEBAND_OUT_SEL 0x910
+#define CXADEC_I2S_IN_CTL 0x914
+#define CXADEC_I2S_OUT_CTL 0x918
+#define CXADEC_AC97_CTL 0x91C
+#define CXADEC_QAM_PDF 0x920
+#define CXADEC_QAM_CONST_DEC 0x924
+#define CXADEC_QAM_ROTATOR_FREQ 0x948
+
+/* Bit defintions / settings used in Mako Audio */
+#define CXADEC_PREF_MODE_MONO_LANGA 0
+#define CXADEC_PREF_MODE_MONO_LANGB 1
+#define CXADEC_PREF_MODE_MONO_LANGC 2
+#define CXADEC_PREF_MODE_FALLBACK 3
+#define CXADEC_PREF_MODE_STEREO 4
+#define CXADEC_PREF_MODE_DUAL_LANG_AC 5
+#define CXADEC_PREF_MODE_DUAL_LANG_BC 6
+#define CXADEC_PREF_MODE_DUAL_LANG_AB 7
+
+
+#define CXADEC_DETECT_STEREO 1
+#define CXADEC_DETECT_DUAL 2
+#define CXADEC_DETECT_TRI 4
+#define CXADEC_DETECT_SAP 0x10
+#define CXADEC_DETECT_NO_SIGNAL 0xFF
+
+#define CXADEC_SELECT_AUDIO_STANDARD_BG 0xF0 /* NICAM BG and A2 BG */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK1 0xF1 /* NICAM DK and A2 DK */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK2 0xF2
+#define CXADEC_SELECT_AUDIO_STANDARD_DK3 0xF3
+#define CXADEC_SELECT_AUDIO_STANDARD_I 0xF4 /* NICAM I and A1 */
+#define CXADEC_SELECT_AUDIO_STANDARD_L 0xF5 /* NICAM L and System L AM */
+#define CXADEC_SELECT_AUDIO_STANDARD_BTSC 0xF6
+#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ 0xF7
+#define CXADEC_SELECT_AUDIO_STANDARD_A2_M 0xF8 /* A2 M */
+#define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */
+#define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-core.c */
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+u8 cx18_av_read(struct cx18 *cx, u16 addr);
+u32 cx18_av_read4(struct cx18 *cx, u16 addr);
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
+int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-firmware.c */
+int cx18_av_loadfw(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-audio.c */
+int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg);
+void cx18_av_audio_set_path(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-vbi.c */
+void cx18_av_vbi_setup(struct cx18 *cx);
+int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
+
+#endif
diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c
new file mode 100644
index 000000000..526e14215
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c
@@ -0,0 +1,120 @@
+/*
+ * cx18 ADEC firmware functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+#include <linux/firmware.h>
+
+#define FWFILE "v4l-cx23418-dig.fw"
+
+int cx18_av_loadfw(struct cx18 *cx)
+{
+ const struct firmware *fw = NULL;
+ u32 size;
+ u32 v;
+ u8 *ptr;
+ int i;
+
+ if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
+ CX18_ERR("unable to open firmware %s\n", FWFILE);
+ return -EINVAL;
+ }
+
+ cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
+ cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */
+
+ /* Reset the Mako core (Register is undocumented.) */
+ cx18_av_write4(cx, 0x8100, 0x00010000);
+
+ /* Put the 8051 in reset and enable firmware upload */
+ cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+
+ ptr = fw->data;
+ size = fw->size;
+
+ for (i = 0; i < size; i++) {
+ u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16);
+ u32 value = 0;
+ int retries;
+
+ for (retries = 0; retries < 5; retries++) {
+ cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
+ value = cx18_av_read4(cx, CXADEC_DL_CTL);
+ if ((value & 0x3F00) == (dl_control & 0x3F00))
+ break;
+ }
+ if (retries >= 5) {
+ CX18_ERR("unable to load firmware %s\n", FWFILE);
+ release_firmware(fw);
+ return -EIO;
+ }
+ }
+
+ cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
+
+ /* Output to the 416 */
+ cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
+
+ /* Audio input control 1 set to Sony mode */
+ /* Audio output input 2 is 0 for slave operation input */
+ /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+ /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+ after WS transition for first bit of audio word. */
+ cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
+
+ /* Audio output control 1 is set to Sony mode */
+ /* Audio output control 2 is set to 1 for master mode */
+ /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+ /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+ after WS transition for first bit of audio word. */
+ /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
+ are generated) */
+ cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
+
+ /* set alt I2s master clock to /16 and enable alt divider i2s
+ passthrough */
+ cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
+
+ cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
+ /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
+
+ /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
+ /* Register 0x09CC is defined by the Merlin firmware, and doesn't
+ have a name in the spec. */
+ cx18_av_write4(cx, 0x09CC, 1);
+
+#define CX18_AUDIO_ENABLE 0xc72014
+ v = read_reg(CX18_AUDIO_ENABLE);
+ /* If bit 11 is 1 */
+ if (v & 0x800)
+ write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
+
+ /* Enable WW auto audio standard detection */
+ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
+ v |= 0xFF; /* Auto by default */
+ v |= 0x400; /* Stereo by default */
+ v |= 0x14000000;
+ cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
+
+ release_firmware(fw);
+
+ CX18_INFO("loaded %s firmware (%d bytes)\n", FWFILE, size);
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c
new file mode 100644
index 000000000..d09f1daf4
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c
@@ -0,0 +1,413 @@
+/*
+ * cx18 ADEC VBI functions
+ *
+ * Derived from cx25840-vbi.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#include "cx18-driver.h"
+
+static int odd_parity(u8 c)
+{
+ c ^= (c >> 4);
+ c ^= (c >> 2);
+ c ^= (c >> 1);
+
+ return c & 1;
+}
+
+static int decode_vps(u8 *dst, u8 *p)
+{
+ static const u8 biphase_tbl[] = {
+ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+ 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+ 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+ 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+ 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+ 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+ 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+ 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+ 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+ 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+ 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+ 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+ 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+ 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+ 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+ 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+ 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+ 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+ 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+ 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+ 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+ 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+ 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+ 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+ 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+ 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+ 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+ };
+
+ u8 c, err = 0;
+ int i;
+
+ for (i = 0; i < 2 * 13; i += 2) {
+ err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+ c = (biphase_tbl[p[i + 1]] & 0xf) |
+ ((biphase_tbl[p[i]] & 0xf) << 4);
+ dst[i / 2] = c;
+ }
+
+ return err & 0xf0;
+}
+
+void cx18_av_vbi_setup(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ v4l2_std_id std = state->std;
+ int hblank, hactive, burst, vblank, vactive, sc;
+ int vblank656, src_decimation;
+ int luma_lpf, uv_lpf, comb;
+ u32 pll_int, pll_frac, pll_post;
+
+ /* datasheet startup, step 8d */
+ if (std & ~V4L2_STD_NTSC)
+ cx18_av_write(cx, 0x49f, 0x11);
+ else
+ cx18_av_write(cx, 0x49f, 0x14);
+
+ if (std & V4L2_STD_625_50) {
+ hblank = 0x084;
+ hactive = 0x2d0;
+ burst = 0x5d;
+ vblank = 0x024;
+ vactive = 0x244;
+ vblank656 = 0x28;
+ src_decimation = 0x21f;
+
+ luma_lpf = 2;
+ if (std & V4L2_STD_SECAM) {
+ uv_lpf = 0;
+ comb = 0;
+ sc = 0x0a425f;
+ } else if (std == V4L2_STD_PAL_Nc) {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 556453;
+ } else {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 0x0a8263;
+ }
+ } else {
+ hactive = 720;
+ hblank = 122;
+ vactive = 487;
+ luma_lpf = 1;
+ uv_lpf = 1;
+
+ src_decimation = 0x21f;
+ if (std == V4L2_STD_PAL_60) {
+ vblank = 26;
+ vblank656 = 26;
+ burst = 0x5b;
+ luma_lpf = 2;
+ comb = 0x20;
+ sc = 0x0a8263;
+ } else if (std == V4L2_STD_PAL_M) {
+ vblank = 20;
+ vblank656 = 24;
+ burst = 0x61;
+ comb = 0x20;
+
+ sc = 555452;
+ } else {
+ vblank = 26;
+ vblank656 = 26;
+ burst = 0x5b;
+ comb = 0x66;
+ sc = 556063;
+ }
+ }
+
+ /* DEBUG: Displays configured PLL frequency */
+ pll_int = cx18_av_read(cx, 0x108);
+ pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
+ pll_post = cx18_av_read(cx, 0x109);
+ CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
+ pll_int, pll_frac, pll_post);
+
+ if (pll_post) {
+ int fin, fsc;
+ int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
+
+ pll >>= 25;
+ pll /= pll_post;
+ CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
+ pll / 1000000, pll % 1000000);
+ CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
+ pll / 8000000, (pll / 8) % 1000000);
+
+ fin = ((u64)src_decimation * pll) >> 12;
+ CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
+ fin / 1000000, fin % 1000000);
+
+ fsc = (((u64)sc) * pll) >> 24L;
+ CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
+ fsc / 1000000, fsc % 1000000);
+
+ CX18_DEBUG_INFO("hblank %i, hactive %i, "
+ "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
+ "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
+ " sc 0x%06x\n",
+ hblank, hactive, vblank, vactive, vblank656,
+ src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+ }
+
+ /* Sets horizontal blanking delay and active lines */
+ cx18_av_write(cx, 0x470, hblank);
+ cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+ (hactive << 4)));
+ cx18_av_write(cx, 0x472, hactive >> 4);
+
+ /* Sets burst gate delay */
+ cx18_av_write(cx, 0x473, burst);
+
+ /* Sets vertical blanking delay and active duration */
+ cx18_av_write(cx, 0x474, vblank);
+ cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+ (vactive << 4)));
+ cx18_av_write(cx, 0x476, vactive >> 4);
+ cx18_av_write(cx, 0x477, vblank656);
+
+ /* Sets src decimation rate */
+ cx18_av_write(cx, 0x478, 0xff & src_decimation);
+ cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
+
+ /* Sets Luma and UV Low pass filters */
+ cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+ /* Enables comb filters */
+ cx18_av_write(cx, 0x47b, comb);
+
+ /* Sets SC Step*/
+ cx18_av_write(cx, 0x47c, sc);
+ cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+ cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
+
+ /* Sets VBI parameters */
+ if (std & V4L2_STD_625_50) {
+ cx18_av_write(cx, 0x47f, 0x01);
+ state->vbi_line_offset = 5;
+ } else {
+ cx18_av_write(cx, 0x47f, 0x00);
+ state->vbi_line_offset = 8;
+ }
+}
+
+int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ struct v4l2_format *fmt;
+ struct v4l2_sliced_vbi_format *svbi;
+
+ switch (cmd) {
+ case VIDIOC_G_FMT:
+ {
+ static u16 lcr2vbi[] = {
+ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
+ 0, V4L2_SLICED_WSS_625, 0, /* 4 */
+ V4L2_SLICED_CAPTION_525, /* 6 */
+ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
+ 0, 0, 0, 0
+ };
+ int is_pal = !(state->std & V4L2_STD_525_60);
+ int i;
+
+ fmt = arg;
+ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+ return -EINVAL;
+ svbi = &fmt->fmt.sliced;
+ memset(svbi, 0, sizeof(*svbi));
+ /* we're done if raw VBI is active */
+ if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
+ break;
+
+ if (is_pal) {
+ for (i = 7; i <= 23; i++) {
+ u8 v = cx18_av_read(cx, 0x424 + i - 7);
+
+ svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+ svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+ svbi->service_set |= svbi->service_lines[0][i] |
+ svbi->service_lines[1][i];
+ }
+ } else {
+ for (i = 10; i <= 21; i++) {
+ u8 v = cx18_av_read(cx, 0x424 + i - 10);
+
+ svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+ svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+ svbi->service_set |= svbi->service_lines[0][i] |
+ svbi->service_lines[1][i];
+ }
+ }
+ break;
+ }
+
+ case VIDIOC_S_FMT:
+ {
+ int is_pal = !(state->std & V4L2_STD_525_60);
+ int vbi_offset = is_pal ? 1 : 0;
+ int i, x;
+ u8 lcr[24];
+
+ fmt = arg;
+ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+ return -EINVAL;
+ svbi = &fmt->fmt.sliced;
+ if (svbi->service_set == 0) {
+ /* raw VBI */
+ memset(svbi, 0, sizeof(*svbi));
+
+ /* Setup VBI */
+ cx18_av_vbi_setup(cx);
+
+ /* VBI Offset */
+ cx18_av_write(cx, 0x47f, vbi_offset);
+ cx18_av_write(cx, 0x404, 0x2e);
+ break;
+ }
+
+ for (x = 0; x <= 23; x++)
+ lcr[x] = 0x00;
+
+ /* Setup VBI */
+ cx18_av_vbi_setup(cx);
+
+ /* Sliced VBI */
+ cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
+ cx18_av_write(cx, 0x406, 0x13);
+ cx18_av_write(cx, 0x47f, vbi_offset);
+
+ if (is_pal) {
+ for (i = 0; i <= 6; i++)
+ svbi->service_lines[0][i] =
+ svbi->service_lines[1][i] = 0;
+ } else {
+ for (i = 0; i <= 9; i++)
+ svbi->service_lines[0][i] =
+ svbi->service_lines[1][i] = 0;
+
+ for (i = 22; i <= 23; i++)
+ svbi->service_lines[0][i] =
+ svbi->service_lines[1][i] = 0;
+ }
+
+ for (i = 7; i <= 23; i++) {
+ for (x = 0; x <= 1; x++) {
+ switch (svbi->service_lines[1-x][i]) {
+ case V4L2_SLICED_TELETEXT_B:
+ lcr[i] |= 1 << (4 * x);
+ break;
+ case V4L2_SLICED_WSS_625:
+ lcr[i] |= 4 << (4 * x);
+ break;
+ case V4L2_SLICED_CAPTION_525:
+ lcr[i] |= 6 << (4 * x);
+ break;
+ case V4L2_SLICED_VPS:
+ lcr[i] |= 9 << (4 * x);
+ break;
+ }
+ }
+ }
+
+ if (is_pal) {
+ for (x = 1, i = 0x424; i <= 0x434; i++, x++)
+ cx18_av_write(cx, i, lcr[6 + x]);
+ } else {
+ for (x = 1, i = 0x424; i <= 0x430; i++, x++)
+ cx18_av_write(cx, i, lcr[9 + x]);
+ for (i = 0x431; i <= 0x434; i++)
+ cx18_av_write(cx, i, 0);
+ }
+
+ cx18_av_write(cx, 0x43c, 0x16);
+ cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22);
+ break;
+ }
+
+ case VIDIOC_INT_DECODE_VBI_LINE:
+ {
+ struct v4l2_decode_vbi_line *vbi = arg;
+ u8 *p = vbi->p;
+ int id1, id2, l, err = 0;
+
+ if (p[0] || p[1] != 0xff || p[2] != 0xff ||
+ (p[3] != 0x55 && p[3] != 0x91)) {
+ vbi->line = vbi->type = 0;
+ break;
+ }
+
+ p += 4;
+ id1 = p[-1];
+ id2 = p[0] & 0xf;
+ l = p[2] & 0x3f;
+ l += state->vbi_line_offset;
+ p += 4;
+
+ switch (id2) {
+ case 1:
+ id2 = V4L2_SLICED_TELETEXT_B;
+ break;
+ case 4:
+ id2 = V4L2_SLICED_WSS_625;
+ break;
+ case 6:
+ id2 = V4L2_SLICED_CAPTION_525;
+ err = !odd_parity(p[0]) || !odd_parity(p[1]);
+ break;
+ case 9:
+ id2 = V4L2_SLICED_VPS;
+ if (decode_vps(p, p) != 0)
+ err = 1;
+ break;
+ default:
+ id2 = 0;
+ err = 1;
+ break;
+ }
+
+ vbi->type = err ? 0 : id2;
+ vbi->line = err ? 0 : l;
+ vbi->is_second_field = err ? 0 : (id1 == 0x55);
+ vbi->p = p;
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c
new file mode 100644
index 000000000..c35eb53a3
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-cards.c
@@ -0,0 +1,281 @@
+/*
+ * cx18 functions to query card hardware
+ *
+ * Derived from ivtv-cards.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include "cx18-i2c.h"
+#include <media/cs5345.h>
+
+/********************** card configuration *******************************/
+
+/* usual i2c tuner addresses to probe */
+static struct cx18_card_tuner_i2c cx18_i2c_std = {
+ .radio = { I2C_CLIENT_END },
+ .demod = { 0x43, I2C_CLIENT_END },
+ .tv = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/iii
+ This keeps the PCI ID database up to date. Note that the entries
+ must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+ New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge HVR-1600 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead
+ of PCI IDs */
+static const struct cx18_card cx18_card_hvr1600_esmt = {
+ .type = CX18_CARD_HVR_1600_ESMT,
+ .name = "Hauppauge HVR-1600",
+ .comment = "VBI is not yet supported\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_muxer = CX18_HW_CS5345,
+ .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
+ CX18_HW_CS5345 | CX18_HW_DVB,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
+ { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+ { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 },
+ { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+ { CX18_CARD_INPUT_LINE_IN1,
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ { CX18_CARD_INPUT_LINE_IN2,
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ .ddr = {
+ /* ESMT M13S128324A-5B memory */
+ .chip_config = 0x003,
+ .refresh = 0x30c,
+ .timing1 = 0x44220e82,
+ .timing2 = 0x08,
+ .tune_lane = 0,
+ .initial_emrs = 0,
+ },
+ .gpio_init.initial_value = 0x3001,
+ .gpio_init.direction = 0x3001,
+ .i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card cx18_card_hvr1600_samsung = {
+ .type = CX18_CARD_HVR_1600_SAMSUNG,
+ .name = "Hauppauge HVR-1600 (Preproduction)",
+ .comment = "VBI is not yet supported\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_muxer = CX18_HW_CS5345,
+ .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
+ CX18_HW_CS5345 | CX18_HW_DVB,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
+ { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+ { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 },
+ { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+ { CX18_CARD_INPUT_LINE_IN1,
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ { CX18_CARD_INPUT_LINE_IN2,
+ CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ .ddr = {
+ /* Samsung K4D263238G-VC33 memory */
+ .chip_config = 0x003,
+ .refresh = 0x30c,
+ .timing1 = 0x23230b73,
+ .timing2 = 0x08,
+ .tune_lane = 0,
+ .initial_emrs = 2,
+ },
+ .gpio_init.initial_value = 0x3001,
+ .gpio_init.direction = 0x3001,
+ .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Compro VideoMate H900: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_h900[] = {
+ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
+ { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_h900 = {
+ .type = CX18_CARD_COMPRO_H900,
+ .name = "Compro VideoMate H900",
+ .comment = "VBI is not yet supported\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_all = CX18_HW_TUNER,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },
+ { CX18_CARD_INPUT_SVIDEO1, 1,
+ CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO8, 0 },
+ { CX18_CARD_INPUT_LINE_IN1,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .ddr = {
+ /* EtronTech EM6A9160TS-5G memory */
+ .chip_config = 0x50003,
+ .refresh = 0x753,
+ .timing1 = 0x24330e84,
+ .timing2 = 0x1f,
+ .tune_lane = 0,
+ .initial_emrs = 0,
+ },
+ .xceive_pin = 15,
+ .pci_list = cx18_pci_h900,
+ .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC718: not working at the moment! */
+
+static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
+ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
+ { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_mpc718 = {
+ .type = CX18_CARD_YUAN_MPC718,
+ .name = "Yuan MPC718",
+ .comment = "Not yet supported!\n",
+ .v4l2_capabilities = 0,
+ .hw_audio_ctrl = CX18_HW_CX23418,
+ .hw_all = CX18_HW_TUNER,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
+ { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO8, 0 },
+ { CX18_CARD_INPUT_LINE_IN1,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+ CX18_AV_AUDIO_SERIAL, 0 },
+ .tuners = {
+ /* XC3028 tuner */
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .ddr = {
+ /* Probably Samsung K4D263238G-VC33 memory */
+ .chip_config = 0x003,
+ .refresh = 0x30c,
+ .timing1 = 0x23230b73,
+ .timing2 = 0x08,
+ .tune_lane = 0,
+ .initial_emrs = 2,
+ },
+ .xceive_pin = 15,
+ .pci_list = cx18_pci_mpc718,
+ .i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card *cx18_card_list[] = {
+ &cx18_card_hvr1600_esmt,
+ &cx18_card_hvr1600_samsung,
+ &cx18_card_h900,
+ &cx18_card_mpc718,
+};
+
+const struct cx18_card *cx18_get_card(u16 index)
+{
+ if (index >= ARRAY_SIZE(cx18_card_list))
+ return NULL;
+ return cx18_card_list[index];
+}
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
+{
+ const struct cx18_card_video_input *card_input =
+ cx->card->video_inputs + index;
+ static const char * const input_strs[] = {
+ "Tuner 1",
+ "S-Video 1",
+ "S-Video 2",
+ "Composite 1",
+ "Composite 2",
+ "Composite 3"
+ };
+
+ memset(input, 0, sizeof(*input));
+ if (index >= cx->nof_inputs)
+ return -EINVAL;
+ input->index = index;
+ strlcpy(input->name, input_strs[card_input->video_type - 1],
+ sizeof(input->name));
+ input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
+ V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+ input->audioset = (1 << cx->nof_audio_inputs) - 1;
+ input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+ cx->tuner_std : V4L2_STD_ALL;
+ return 0;
+}
+
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
+{
+ const struct cx18_card_audio_input *aud_input =
+ cx->card->audio_inputs + index;
+ static const char * const input_strs[] = {
+ "Tuner 1",
+ "Line In 1",
+ "Line In 2"
+ };
+
+ memset(audio, 0, sizeof(*audio));
+ if (index >= cx->nof_audio_inputs)
+ return -EINVAL;
+ strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+ sizeof(audio->name));
+ audio->index = index;
+ audio->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-cards.h b/linux/drivers/media/video/cx18/cx18-cards.h
new file mode 100644
index 000000000..3c2c0b929
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-cards.h
@@ -0,0 +1,131 @@
+/*
+ * cx18 functions to query card hardware
+ *
+ * Derived from ivtv-cards.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* hardware flags */
+#define CX18_HW_TUNER (1 << 0)
+#define CX18_HW_TVEEPROM (1 << 1)
+#define CX18_HW_CS5345 (1 << 2)
+#define CX18_HW_GPIO (1 << 3)
+#define CX18_HW_CX23418 (1 << 4)
+#define CX18_HW_DVB (1 << 5)
+
+/* video inputs */
+#define CX18_CARD_INPUT_VID_TUNER 1
+#define CX18_CARD_INPUT_SVIDEO1 2
+#define CX18_CARD_INPUT_SVIDEO2 3
+#define CX18_CARD_INPUT_COMPOSITE1 4
+#define CX18_CARD_INPUT_COMPOSITE2 5
+#define CX18_CARD_INPUT_COMPOSITE3 6
+
+/* audio inputs */
+#define CX18_CARD_INPUT_AUD_TUNER 1
+#define CX18_CARD_INPUT_LINE_IN1 2
+#define CX18_CARD_INPUT_LINE_IN2 3
+
+#define CX18_CARD_MAX_VIDEO_INPUTS 6
+#define CX18_CARD_MAX_AUDIO_INPUTS 3
+#define CX18_CARD_MAX_TUNERS 2
+
+/* V4L2 capability aliases */
+#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
+ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE)
+/* | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */
+
+struct cx18_card_video_input {
+ u8 video_type; /* video input type */
+ u8 audio_index; /* index in cx18_card_audio_input array */
+ u16 video_input; /* hardware video input */
+};
+
+struct cx18_card_audio_input {
+ u8 audio_type; /* audio input type */
+ u32 audio_input; /* hardware audio input */
+ u16 muxer_input; /* hardware muxer input for boards with a
+ multiplexer chip */
+};
+
+struct cx18_card_pci_info {
+ u16 device;
+ u16 subsystem_vendor;
+ u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
+ u32 direction; /* DIR setting. Leave to 0 if no init is needed */
+ u32 initial_value;
+};
+
+struct cx18_card_tuner {
+ v4l2_std_id std; /* standard for which the tuner is suitable */
+ int tuner; /* tuner ID (from tuner.h) */
+};
+
+struct cx18_card_tuner_i2c {
+ unsigned short radio[2];/* radio tuner i2c address to probe */
+ unsigned short demod[2];/* demodulator i2c address to probe */
+ unsigned short tv[4]; /* tv tuner i2c addresses to probe */
+};
+
+struct cx18_ddr { /* DDR config data */
+ u32 chip_config;
+ u32 refresh;
+ u32 timing1;
+ u32 timing2;
+ u32 tune_lane;
+ u32 initial_emrs;
+};
+
+/* for card information/parameters */
+struct cx18_card {
+ int type;
+ char *name;
+ char *comment;
+ u32 v4l2_capabilities;
+ u32 hw_audio_ctrl; /* hardware used for the V4L2 controls (only
+ 1 dev allowed) */
+ u32 hw_muxer; /* hardware used to multiplex audio input */
+ u32 hw_all; /* all hardware used by the board */
+ struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
+ struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
+ struct cx18_card_audio_input radio_input;
+
+ /* GPIO card-specific settings */
+ u8 xceive_pin; /* XCeive tuner GPIO reset pin */
+ struct cx18_gpio_init gpio_init;
+
+ struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
+ struct cx18_card_tuner_i2c *i2c;
+
+ struct cx18_ddr ddr;
+
+ /* list of device and subsystem vendor/devices that
+ correspond to this card type. */
+ const struct cx18_card_pci_info *pci_list;
+};
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
+const struct cx18_card *cx18_get_card(u16 index);
diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c
new file mode 100644
index 000000000..87cf41021
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-controls.c
@@ -0,0 +1,306 @@
+/*
+ * cx18 ioctl control functions
+ *
+ * Derived from ivtv-controls.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-av-core.h"
+#include "cx18-cards.h"
+#include "cx18-ioctl.h"
+#include "cx18-audio.h"
+#include "cx18-i2c.h"
+#include "cx18-mailbox.h"
+#include "cx18-controls.h"
+
+static const u32 user_ctrls[] = {
+ V4L2_CID_USER_CLASS,
+ V4L2_CID_BRIGHTNESS,
+ V4L2_CID_CONTRAST,
+ V4L2_CID_SATURATION,
+ V4L2_CID_HUE,
+ V4L2_CID_AUDIO_VOLUME,
+ V4L2_CID_AUDIO_BALANCE,
+ V4L2_CID_AUDIO_BASS,
+ V4L2_CID_AUDIO_TREBLE,
+ V4L2_CID_AUDIO_MUTE,
+ V4L2_CID_AUDIO_LOUDNESS,
+ 0
+};
+
+static const u32 *ctrl_classes[] = {
+ user_ctrls,
+ cx2341x_mpeg_ctrls,
+ NULL
+};
+
+static int cx18_queryctrl(struct cx18 *cx, struct v4l2_queryctrl *qctrl)
+{
+ const char *name;
+
+ CX18_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id);
+
+ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ if (qctrl->id == 0)
+ return -EINVAL;
+
+ switch (qctrl->id) {
+ /* Standard V4L2 controls */
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_HUE:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_CONTRAST:
+ if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl))
+ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+ return 0;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_LOUDNESS:
+ if (cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl))
+ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+ return 0;
+
+ default:
+ if (cx2341x_ctrl_query(&cx->params, qctrl))
+ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+ return 0;
+ }
+ strncpy(qctrl->name, name, sizeof(qctrl->name) - 1);
+ qctrl->name[sizeof(qctrl->name) - 1] = 0;
+ return 0;
+}
+
+static int cx18_querymenu(struct cx18 *cx, struct v4l2_querymenu *qmenu)
+{
+ struct v4l2_queryctrl qctrl;
+
+ qctrl.id = qmenu->id;
+ cx18_queryctrl(cx, &qctrl);
+ return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
+}
+
+static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
+ s32 v = vctrl->value;
+
+ CX18_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v);
+
+ switch (vctrl->id) {
+ /* Standard V4L2 controls */
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_HUE:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_CONTRAST:
+ return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl);
+
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_LOUDNESS:
+ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
+
+ default:
+ CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
+ CX18_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id);
+
+ switch (vctrl->id) {
+ /* Standard V4L2 controls */
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_HUE:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_CONTRAST:
+ return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl);
+
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_BALANCE:
+ case V4L2_CID_AUDIO_BASS:
+ case V4L2_CID_AUDIO_TREBLE:
+ case V4L2_CID_AUDIO_LOUDNESS:
+ return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
+ default:
+ CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt)
+{
+ if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
+ return -EINVAL;
+ if (atomic_read(&cx->ana_capturing) > 0)
+ return -EBUSY;
+
+ /* First try to allocate sliced VBI buffers if needed. */
+ if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) {
+ int i;
+
+ for (i = 0; i < CX18_VBI_FRAMES; i++) {
+ /* Yuck, hardcoded. Needs to be a define */
+ cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
+ if (cx->vbi.sliced_mpeg_data[i] == NULL) {
+ while (--i >= 0) {
+ kfree(cx->vbi.sliced_mpeg_data[i]);
+ cx->vbi.sliced_mpeg_data[i] = NULL;
+ }
+ return -ENOMEM;
+ }
+ }
+ }
+
+ cx->vbi.insert_mpeg = fmt;
+
+ if (cx->vbi.insert_mpeg == 0)
+ return 0;
+ /* Need sliced data for mpeg insertion */
+ if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
+ if (cx->is_60hz)
+ cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
+ else
+ cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+ cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
+ }
+ return 0;
+}
+
+int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct v4l2_control ctrl;
+
+ switch (cmd) {
+ case VIDIOC_QUERYMENU:
+ CX18_DEBUG_IOCTL("VIDIOC_QUERYMENU\n");
+ return cx18_querymenu(cx, arg);
+
+ case VIDIOC_QUERYCTRL:
+ return cx18_queryctrl(cx, arg);
+
+ case VIDIOC_S_CTRL:
+ return cx18_s_ctrl(cx, arg);
+
+ case VIDIOC_G_CTRL:
+ return cx18_g_ctrl(cx, arg);
+
+ case VIDIOC_S_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *c = arg;
+
+ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+ int i;
+ int err = 0;
+
+ for (i = 0; i < c->count; i++) {
+ ctrl.id = c->controls[i].id;
+ ctrl.value = c->controls[i].value;
+ err = cx18_s_ctrl(cx, &ctrl);
+ c->controls[i].value = ctrl.value;
+ if (err) {
+ c->error_idx = i;
+ break;
+ }
+ }
+ return err;
+ }
+ CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
+ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+ struct cx2341x_mpeg_params p = cx->params;
+ int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd);
+
+ if (err)
+ return err;
+
+ if (p.video_encoding != cx->params.video_encoding) {
+ int is_mpeg1 = p.video_encoding ==
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+ struct v4l2_format fmt;
+
+ /* fix videodecoder resolution */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = cx->params.width / (is_mpeg1 ? 2 : 1);
+ fmt.fmt.pix.height = cx->params.height;
+ cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
+ }
+ err = cx2341x_update(cx, cx18_api_func, &cx->params, &p);
+ if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
+ err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
+ cx->params = p;
+ cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
+ cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
+ return err;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_G_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *c = arg;
+
+ if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+ int i;
+ int err = 0;
+
+ for (i = 0; i < c->count; i++) {
+ ctrl.id = c->controls[i].id;
+ ctrl.value = c->controls[i].value;
+ err = cx18_g_ctrl(cx, &ctrl);
+ c->controls[i].value = ctrl.value;
+ if (err) {
+ c->error_idx = i;
+ break;
+ }
+ }
+ return err;
+ }
+ CX18_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n");
+ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
+ return cx2341x_ext_ctrls(&cx->params, 0, arg, cmd);
+ return -EINVAL;
+ }
+
+ case VIDIOC_TRY_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *c = arg;
+
+ CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
+ if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
+ return cx2341x_ext_ctrls(&cx->params,
+ atomic_read(&cx->ana_capturing), arg, cmd);
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-controls.h b/linux/drivers/media/video/cx18/cx18-controls.h
new file mode 100644
index 000000000..6e985cf42
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-controls.h
@@ -0,0 +1,24 @@
+/*
+ * cx18 ioctl control functions
+ *
+ * Derived from ivtv-controls.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg);
diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c
new file mode 100644
index 000000000..d9178843e
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-driver.c
@@ -0,0 +1,962 @@
+/*
+ * cx18 driver initialization and card probing
+ *
+ * Derived from ivtv-driver.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-cards.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+#include "cx18-gpio.h"
+#include "cx18-firmware.h"
+#include "cx18-streams.h"
+#include "cx18-av-core.h"
+#include "cx18-scb.h"
+#include "cx18-mailbox.h"
+#include "cx18-ioctl.h"
+#include "tuner-xc2028.h"
+
+#include <media/tveeprom.h>
+
+
+/* var to keep track of the number of array elements in use */
+int cx18_cards_active;
+
+/* If you have already X v4l cards, then set this to X. This way
+ the device numbers stay matched. Example: you have a WinTV card
+ without radio and a Compro H900 with. Normally this would give a
+ video1 device together with a radio0 device for the Compro. By
+ setting this to 1 you ensure that radio0 is now also radio1. */
+int cx18_first_minor;
+
+/* Master variable for all cx18 info */
+struct cx18 *cx18_cards[CX18_MAX_CARDS];
+
+/* Protects cx18_cards_active */
+DEFINE_SPINLOCK(cx18_cards_lock);
+
+/* add your revision and whatnot here */
+static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
+ {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
+
+/* Parameter declarations */
+static int cardtype[CX18_MAX_CARDS];
+static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1 };
+
+static int cardtype_c = 1;
+static int tuner_c = 1;
+static int radio_c = 1;
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
+static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
+
+static int cx18_pci_latency = 1;
+
+int cx18_debug;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, bool, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug, cx18_debug, int, 0644);
+module_param(cx18_pci_latency, int, 0644);
+module_param(cx18_first_minor, int, 0644);
+
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_ts_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+ "\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+ "Enable or disable the radio. Use only if autodetection\n"
+ "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+ "Only use this option if your card is not detected properly.\n"
+ "\t\tSpecify card type:\n"
+ "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
+ "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
+ "\t\t\t 3 = Compro VideoMate H900\n"
+ "\t\t\t 4 = Yuan MPC718\n"
+ "\t\t\t 0 = Autodetect (default)\n"
+ "\t\t\t-1 = Ignore this card\n\t\t");
+MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
+MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
+MODULE_PARM_DESC(debug,
+ "Debug level (bitmask). Default: 0\n"
+ "\t\t\t 1/0x0001: warning\n"
+ "\t\t\t 2/0x0002: info\n"
+ "\t\t\t 4/0x0004: mailbox\n"
+ "\t\t\t 8/0x0008: dma\n"
+ "\t\t\t 16/0x0010: ioctl\n"
+ "\t\t\t 32/0x0020: file\n"
+ "\t\t\t 64/0x0040: i2c\n"
+ "\t\t\t128/0x0080: irq\n"
+ "\t\t\t256/0x0100: high volume\n");
+MODULE_PARM_DESC(cx18_pci_latency,
+ "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+ "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(enc_mpg_buffers,
+ "Encoder MPG Buffers (in MB)\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_ts_buffers,
+ "Encoder TS Buffers (in MB)\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_buffers,
+ "Encoder YUV Buffers (in MB)\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_buffers,
+ "Encoder VBI Buffers (in MB)\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_buffers,
+ "Encoder PCM buffers (in MB)\n"
+ "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
+
+MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card");
+
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_DESCRIPTION("CX23418 driver");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+/* Generic utility functions */
+int cx18_msleep_timeout(unsigned int msecs, int intr)
+{
+ int timeout = msecs_to_jiffies(msecs);
+ int sig;
+
+ do {
+ set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+ timeout = schedule_timeout(timeout);
+ sig = intr ? signal_pending(current) : 0;
+ } while (!sig && timeout);
+ return sig;
+}
+
+/* Release ioremapped memory */
+static void cx18_iounmap(struct cx18 *cx)
+{
+ if (cx == NULL)
+ return;
+
+ /* Release io memory */
+ if (cx->enc_mem != NULL) {
+ CX18_DEBUG_INFO("releasing enc_mem\n");
+ iounmap(cx->enc_mem);
+ cx->enc_mem = NULL;
+ }
+}
+
+/* Hauppauge card? get values from tveeprom */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
+{
+ u8 eedata[256];
+
+ cx->i2c_client[0].addr = 0xA0 >> 1;
+ tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata));
+ tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata);
+}
+
+static void cx18_process_eeprom(struct cx18 *cx)
+{
+ struct tveeprom tv;
+
+ cx18_read_eeprom(cx, &tv);
+
+ /* Many thanks to Steven Toth from Hauppauge for providing the
+ model numbers */
+ /* Note: the Samsung memory models cannot be reliably determined
+ from the model number. Use the cardtype module option if you
+ have one of these preproduction models. */
+ switch (tv.model) {
+ case 74000 ... 74999:
+ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+ break;
+ case 0:
+ CX18_ERR("Invalid EEPROM\n");
+ return;
+ default:
+ CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model);
+ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+ break;
+ }
+
+ cx->v4l2_cap = cx->card->v4l2_capabilities;
+ cx->card_name = cx->card->name;
+ cx->card_i2c = cx->card->i2c;
+
+ CX18_INFO("Autodetected %s\n", cx->card_name);
+
+ if (tv.tuner_type == TUNER_ABSENT)
+ CX18_ERR("tveeprom cannot autodetect tuner!");
+
+ if (cx->options.tuner == -1)
+ cx->options.tuner = tv.tuner_type;
+ if (cx->options.radio == -1)
+ cx->options.radio = (tv.has_radio != 0);
+
+ if (cx->std != 0)
+ /* user specified tuner standard */
+ return;
+
+ /* autodetect tuner standard */
+ if (tv.tuner_formats & V4L2_STD_PAL) {
+ CX18_DEBUG_INFO("PAL tuner detected\n");
+ cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+ } else if (tv.tuner_formats & V4L2_STD_NTSC) {
+ CX18_DEBUG_INFO("NTSC tuner detected\n");
+ cx->std |= V4L2_STD_NTSC_M;
+ } else if (tv.tuner_formats & V4L2_STD_SECAM) {
+ CX18_DEBUG_INFO("SECAM tuner detected\n");
+ cx->std |= V4L2_STD_SECAM_L;
+ } else {
+ CX18_INFO("No tuner detected, default to NTSC-M\n");
+ cx->std |= V4L2_STD_NTSC_M;
+ }
+}
+
+static v4l2_std_id cx18_parse_std(struct cx18 *cx)
+{
+ switch (pal[0]) {
+ case '6':
+ return V4L2_STD_PAL_60;
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ return V4L2_STD_PAL_BG;
+ case 'h':
+ case 'H':
+ return V4L2_STD_PAL_H;
+ case 'n':
+ case 'N':
+ if (pal[1] == 'c' || pal[1] == 'C')
+ return V4L2_STD_PAL_Nc;
+ return V4L2_STD_PAL_N;
+ case 'i':
+ case 'I':
+ return V4L2_STD_PAL_I;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ return V4L2_STD_PAL_DK;
+ case 'M':
+ case 'm':
+ return V4L2_STD_PAL_M;
+ case '-':
+ break;
+ default:
+ CX18_WARN("pal= argument not recognised\n");
+ return 0;
+ }
+
+ switch (secam[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ return V4L2_STD_SECAM_DK;
+ case 'l':
+ case 'L':
+ if (secam[1] == 'C' || secam[1] == 'c')
+ return V4L2_STD_SECAM_LC;
+ return V4L2_STD_SECAM_L;
+ case '-':
+ break;
+ default:
+ CX18_WARN("secam= argument not recognised\n");
+ return 0;
+ }
+
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
+ return V4L2_STD_NTSC_M;
+ case 'j':
+ case 'J':
+ return V4L2_STD_NTSC_M_JP;
+ case 'k':
+ case 'K':
+ return V4L2_STD_NTSC_M_KR;
+ case '-':
+ break;
+ default:
+ CX18_WARN("ntsc= argument not recognised\n");
+ return 0;
+ }
+
+ /* no match found */
+ return 0;
+}
+
+static void cx18_process_options(struct cx18 *cx)
+{
+ int i, j;
+
+ cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
+ cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
+ cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
+ cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
+ cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+ cx->options.cardtype = cardtype[cx->num];
+ cx->options.tuner = tuner[cx->num];
+ cx->options.radio = radio[cx->num];
+
+ cx->std = cx18_parse_std(cx);
+ if (cx->options.cardtype == -1) {
+ CX18_INFO("Ignore card\n");
+ return;
+ }
+ cx->card = cx18_get_card(cx->options.cardtype - 1);
+ if (cx->card)
+ CX18_INFO("User specified %s card\n", cx->card->name);
+ else if (cx->options.cardtype != 0)
+ CX18_ERR("Unknown user specified type, trying to autodetect card\n");
+ if (cx->card == NULL) {
+ if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
+ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+ CX18_INFO("Autodetected Hauppauge card\n");
+ }
+ }
+ if (cx->card == NULL) {
+ for (i = 0; (cx->card = cx18_get_card(i)); i++) {
+ if (cx->card->pci_list == NULL)
+ continue;
+ for (j = 0; cx->card->pci_list[j].device; j++) {
+ if (cx->dev->device !=
+ cx->card->pci_list[j].device)
+ continue;
+ if (cx->dev->subsystem_vendor !=
+ cx->card->pci_list[j].subsystem_vendor)
+ continue;
+ if (cx->dev->subsystem_device !=
+ cx->card->pci_list[j].subsystem_device)
+ continue;
+ CX18_INFO("Autodetected %s card\n", cx->card->name);
+ goto done;
+ }
+ }
+ }
+done:
+
+ if (cx->card == NULL) {
+ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+ CX18_ERR("Unknown card: vendor/device: %04x/%04x\n",
+ cx->dev->vendor, cx->dev->device);
+ CX18_ERR(" subsystem vendor/device: %04x/%04x\n",
+ cx->dev->subsystem_vendor, cx->dev->subsystem_device);
+ CX18_ERR("Defaulting to %s card\n", cx->card->name);
+ CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
+ CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
+ CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
+ }
+ cx->v4l2_cap = cx->card->v4l2_capabilities;
+ cx->card_name = cx->card->name;
+ cx->card_i2c = cx->card->i2c;
+}
+
+/* Precondition: the cx18 structure has been memset to 0. Only
+ the dev and num fields have been filled in.
+ No assumptions on the card type may be made here (see cx18_init_struct2
+ for that).
+ */
+static int __devinit cx18_init_struct1(struct cx18 *cx)
+{
+ cx->base_addr = pci_resource_start(cx->dev, 0);
+
+ mutex_init(&cx->serialize_lock);
+ mutex_init(&cx->i2c_bus_lock[0]);
+ mutex_init(&cx->i2c_bus_lock[1]);
+
+ spin_lock_init(&cx->lock);
+ spin_lock_init(&cx->dma_reg_lock);
+
+ /* start counting open_id at 1 */
+ cx->open_id = 1;
+
+ /* Initial settings */
+ cx2341x_fill_defaults(&cx->params);
+ cx->temporal_strength = cx->params.video_temporal_filter;
+ cx->spatial_strength = cx->params.video_spatial_filter;
+ cx->filter_mode = cx->params.video_spatial_filter_mode |
+ (cx->params.video_temporal_filter_mode << 1) |
+ (cx->params.video_median_filter_type << 2);
+ cx->params.port = CX2341X_PORT_MEMORY;
+ cx->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
+ init_waitqueue_head(&cx->cap_w);
+ init_waitqueue_head(&cx->mb_apu_waitq);
+ init_waitqueue_head(&cx->mb_cpu_waitq);
+ init_waitqueue_head(&cx->mb_epu_waitq);
+ init_waitqueue_head(&cx->mb_hpu_waitq);
+ init_waitqueue_head(&cx->dma_waitq);
+
+ /* VBI */
+ cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
+ cx->vbi.raw_size = 1456;
+ cx->vbi.raw_decoder_line_size = 1456;
+ cx->vbi.raw_decoder_sav_odd_field = 0x20;
+ cx->vbi.raw_decoder_sav_even_field = 0x60;
+ cx->vbi.sliced_decoder_line_size = 272;
+ cx->vbi.sliced_decoder_sav_odd_field = 0xB0;
+ cx->vbi.sliced_decoder_sav_even_field = 0xF0;
+ return 0;
+}
+
+/* Second initialization part. Here the card type has been
+ autodetected. */
+static void __devinit cx18_init_struct2(struct cx18 *cx)
+{
+ int i;
+
+ for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+ if (cx->card->video_inputs[i].video_type == 0)
+ break;
+ cx->nof_inputs = i;
+ for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+ if (cx->card->audio_inputs[i].audio_type == 0)
+ break;
+ cx->nof_audio_inputs = i;
+
+ /* Find tuner input */
+ for (i = 0; i < cx->nof_inputs; i++) {
+ if (cx->card->video_inputs[i].video_type ==
+ CX18_CARD_INPUT_VID_TUNER)
+ break;
+ }
+ if (i == cx->nof_inputs)
+ i = 0;
+ cx->active_input = i;
+ cx->audio_input = cx->card->video_inputs[i].audio_index;
+ cx->av_state.vid_input = CX18_AV_COMPOSITE7;
+ cx->av_state.aud_input = CX18_AV_AUDIO8;
+ cx->av_state.audclk_freq = 48000;
+ cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
+ cx->av_state.vbi_line_offset = 8;
+}
+
+static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
+ const struct pci_device_id *pci_id)
+{
+ u16 cmd;
+ unsigned char pci_latency;
+
+ CX18_DEBUG_INFO("Enabling pci device\n");
+
+ if (pci_enable_device(dev)) {
+ CX18_ERR("Can't enable device %d!\n", cx->num);
+ return -EIO;
+ }
+ if (pci_set_dma_mask(dev, 0xffffffff)) {
+ CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
+ return -EIO;
+ }
+ if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
+ CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
+ return -EIO;
+ }
+
+ /* Check for bus mastering */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+
+ if (pci_latency < 64 && cx18_pci_latency) {
+ CX18_INFO("Unreasonably low latency timer, "
+ "setting to 64 (was %d)\n", pci_latency);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+ }
+ /* This config space value relates to DMA latencies. The
+ default value 0x8080 is too low however and will lead
+ to DMA errors. 0xffff is the max value which solves
+ these problems. */
+ pci_write_config_dword(dev, 0x40, 0xffff);
+
+ CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
+ "irq: %d, latency: %d, memory: 0x%lx\n",
+ cx->dev->device, cx->card_rev, dev->bus->number,
+ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+ cx->dev->irq, pci_latency, (unsigned long)cx->base_addr);
+
+ return 0;
+}
+
+#ifdef MODULE
+static u32 cx18_request_module(struct cx18 *cx, u32 hw,
+ const char *name, u32 id)
+{
+ if ((hw & id) == 0)
+ return hw;
+ if (request_module(name) != 0) {
+ CX18_ERR("Failed to load module %s\n", name);
+ return hw & ~id;
+ }
+ CX18_DEBUG_INFO("Loaded module %s\n", name);
+ return hw;
+}
+#endif
+
+static void cx18_load_and_init_modules(struct cx18 *cx)
+{
+ u32 hw = cx->card->hw_all;
+ int i;
+
+#ifdef MODULE
+ /* load modules */
+#ifndef CONFIG_MEDIA_TUNER
+ hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
+#endif
+#ifndef CONFIG_VIDEO_CS5345
+ hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
+#endif
+#endif
+
+ /* check which i2c devices are actually found */
+ for (i = 0; i < 32; i++) {
+ u32 device = 1 << i;
+
+ if (!(device & hw))
+ continue;
+ if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM ||
+ device == CX18_HW_CX23418 || device == CX18_HW_DVB) {
+ /* These 'devices' do not use i2c probing */
+ cx->hw_flags |= device;
+ continue;
+ }
+ cx18_i2c_register(cx, i);
+ if (cx18_i2c_hw_addr(cx, device) > 0)
+ cx->hw_flags |= device;
+ }
+
+ hw = cx->hw_flags;
+}
+
+static int __devinit cx18_probe(struct pci_dev *dev,
+ const struct pci_device_id *pci_id)
+{
+ int retval = 0;
+ int vbi_buf_size;
+ u32 devtype;
+ struct cx18 *cx;
+
+ spin_lock(&cx18_cards_lock);
+
+ /* Make sure we've got a place for this card */
+ if (cx18_cards_active == CX18_MAX_CARDS) {
+ printk(KERN_ERR "cx18: Maximum number of cards detected (%d).\n",
+ cx18_cards_active);
+ spin_unlock(&cx18_cards_lock);
+ return -ENOMEM;
+ }
+
+ cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
+ if (!cx) {
+ spin_unlock(&cx18_cards_lock);
+ return -ENOMEM;
+ }
+ cx18_cards[cx18_cards_active] = cx;
+ cx->dev = dev;
+ cx->num = cx18_cards_active++;
+ snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
+ CX18_INFO("Initializing card #%d\n", cx->num);
+
+ spin_unlock(&cx18_cards_lock);
+
+ cx18_process_options(cx);
+ if (cx->options.cardtype == -1) {
+ retval = -ENODEV;
+ goto err;
+ }
+ if (cx18_init_struct1(cx)) {
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
+
+ /* PCI Device Setup */
+ retval = cx18_setup_pci(cx, dev, pci_id);
+ if (retval != 0) {
+ if (retval == -EIO)
+ goto free_workqueue;
+ else if (retval == -ENXIO)
+ goto free_mem;
+ }
+ /* save cx in the pci struct for later use */
+ pci_set_drvdata(dev, cx);
+
+ /* map io memory */
+ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
+ cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
+ cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
+ CX18_MEM_SIZE);
+ if (!cx->enc_mem) {
+ CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
+ CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+ retval = -ENOMEM;
+ goto free_mem;
+ }
+ cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
+ devtype = read_reg(0xC72028);
+ switch (devtype & 0xff000000) {
+ case 0xff000000:
+ CX18_INFO("cx23418 revision %08x (A)\n", devtype);
+ break;
+ case 0x01000000:
+ CX18_INFO("cx23418 revision %08x (B)\n", devtype);
+ break;
+ default:
+ CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
+ break;
+ }
+
+ cx18_init_power(cx, 1);
+ cx18_init_memory(cx);
+
+ cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
+ cx18_init_scb(cx);
+
+ cx18_gpio_init(cx);
+
+ /* active i2c */
+ CX18_DEBUG_INFO("activating i2c...\n");
+ if (init_cx18_i2c(cx)) {
+ CX18_ERR("Could not initialize i2c\n");
+ goto free_map;
+ }
+
+ CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
+
+ if (cx->card->hw_all & CX18_HW_TVEEPROM) {
+ /* Based on the model number the cardtype may be changed.
+ The PCI IDs are not always reliable. */
+ cx18_process_eeprom(cx);
+ }
+ if (cx->card->comment)
+ CX18_INFO("%s", cx->card->comment);
+ if (cx->card->v4l2_capabilities == 0) {
+ retval = -ENODEV;
+ goto free_i2c;
+ }
+ cx18_init_memory(cx);
+
+ /* Register IRQ */
+ retval = request_irq(cx->dev->irq, cx18_irq_handler,
+ IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
+ if (retval) {
+ CX18_ERR("Failed to register irq %d\n", retval);
+ goto free_i2c;
+ }
+
+ if (cx->std == 0)
+ cx->std = V4L2_STD_NTSC_M;
+
+ if (cx->options.tuner == -1) {
+ int i;
+
+ for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
+ if ((cx->std & cx->card->tuners[i].std) == 0)
+ continue;
+ cx->options.tuner = cx->card->tuners[i].tuner;
+ break;
+ }
+ }
+ /* if no tuner was found, then pick the first tuner in the card list */
+ if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
+ cx->std = cx->card->tuners[0].std;
+ cx->options.tuner = cx->card->tuners[0].tuner;
+ }
+ if (cx->options.radio == -1)
+ cx->options.radio = (cx->card->radio_input.audio_type != 0);
+
+ /* The card is now fully identified, continue with card-specific
+ initialization. */
+ cx18_init_struct2(cx);
+
+ cx18_load_and_init_modules(cx);
+
+ if (cx->std & V4L2_STD_525_60) {
+ cx->is_60hz = 1;
+ cx->is_out_60hz = 1;
+ } else {
+ cx->is_50hz = 1;
+ cx->is_out_50hz = 1;
+ }
+ cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
+
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000;
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000;
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200;
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000;
+ vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
+ cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
+
+ if (cx->options.radio > 0)
+ cx->v4l2_cap |= V4L2_CAP_RADIO;
+
+ if (cx->options.tuner > -1) {
+ struct tuner_setup setup;
+
+ setup.addr = ADDR_UNSET;
+ setup.type = cx->options.tuner;
+ setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
+ setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+ cx18_reset_tuner_gpio : NULL;
+ cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup);
+ if (setup.type == TUNER_XC2028) {
+ static struct xc2028_ctrl ctrl = {
+ .fname = XC2028_DEFAULT_FIRMWARE,
+ .max_len = 64,
+ };
+ struct v4l2_priv_tun_config cfg = {
+ .tuner = cx->options.tuner,
+ .priv = &ctrl,
+ };
+ cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg);
+ }
+ }
+
+ /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+ are not. */
+ cx->tuner_std = cx->std;
+
+ retval = cx18_streams_setup(cx);
+ if (retval) {
+ CX18_ERR("Error %d setting up streams\n", retval);
+ goto free_irq;
+ }
+ retval = cx18_streams_register(cx);
+ if (retval) {
+ CX18_ERR("Error %d registering devices\n", retval);
+ goto free_streams;
+ }
+
+ CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
+
+ return 0;
+
+free_streams:
+ cx18_streams_cleanup(cx, 1);
+free_irq:
+ free_irq(cx->dev->irq, (void *)cx);
+free_i2c:
+ exit_cx18_i2c(cx);
+free_map:
+ cx18_iounmap(cx);
+free_mem:
+ release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+free_workqueue:
+err:
+ if (retval == 0)
+ retval = -ENODEV;
+ CX18_ERR("Error %d on initialization\n", retval);
+
+ kfree(cx18_cards[cx18_cards_active]);
+ cx18_cards[cx18_cards_active] = NULL;
+ return retval;
+}
+
+int cx18_init_on_first_open(struct cx18 *cx)
+{
+ int video_input;
+ int fw_retry_count = 3;
+ struct v4l2_frequency vf;
+
+ if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
+ return -ENXIO;
+
+ if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
+ return 0;
+
+ while (--fw_retry_count > 0) {
+ /* load firmware */
+ if (cx18_firmware_init(cx) == 0)
+ break;
+ if (fw_retry_count > 1)
+ CX18_WARN("Retry loading firmware\n");
+ }
+
+ if (fw_retry_count == 0) {
+ set_bit(CX18_F_I_FAILED, &cx->i_flags);
+ return -ENXIO;
+ }
+ set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
+
+ /* Init the firmware twice to work around a silicon bug
+ * transport related. */
+
+ fw_retry_count = 3;
+ while (--fw_retry_count > 0) {
+ /* load firmware */
+ if (cx18_firmware_init(cx) == 0)
+ break;
+ if (fw_retry_count > 1)
+ CX18_WARN("Retry loading firmware\n");
+ }
+
+ if (fw_retry_count == 0) {
+ set_bit(CX18_F_I_FAILED, &cx->i_flags);
+ return -ENXIO;
+ }
+
+ vf.tuner = 0;
+ vf.type = V4L2_TUNER_ANALOG_TV;
+ vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+ /* Set initial frequency. For PAL/SECAM broadcasts no
+ 'default' channel exists AFAIK. */
+ if (cx->std == V4L2_STD_NTSC_M_JP)
+ vf.frequency = 1460; /* ch. 1 91250*16/1000 */
+ else if (cx->std & V4L2_STD_NTSC_M)
+ vf.frequency = 1076; /* ch. 4 67250*16/1000 */
+
+ video_input = cx->active_input;
+ cx->active_input++; /* Force update of input */
+ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_INPUT, &video_input);
+
+ /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+ in one place. */
+ cx->std++; /* Force full standard initialization */
+ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_STD, &cx->tuner_std);
+ cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_FREQUENCY, &vf);
+ return 0;
+}
+
+static void cx18_remove(struct pci_dev *pci_dev)
+{
+ struct cx18 *cx = pci_get_drvdata(pci_dev);
+
+ CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+
+ /* Stop all captures */
+ CX18_DEBUG_INFO("Stopping all streams\n");
+ if (atomic_read(&cx->tot_capturing) > 0)
+ cx18_stop_all_captures(cx);
+
+ /* Interrupts */
+ sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+ sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+ cx18_halt_firmware(cx);
+
+ cx18_streams_cleanup(cx, 1);
+
+ exit_cx18_i2c(cx);
+
+ free_irq(cx->dev->irq, (void *)cx);
+
+ cx18_iounmap(cx);
+
+ release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+
+ pci_disable_device(cx->dev);
+
+ CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+}
+
+/* define a pci_driver for card detection */
+static struct pci_driver cx18_pci_driver = {
+ .name = "cx18",
+ .id_table = cx18_pci_tbl,
+ .probe = cx18_probe,
+ .remove = cx18_remove,
+};
+
+static int module_start(void)
+{
+ printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION);
+
+ memset(cx18_cards, 0, sizeof(cx18_cards));
+
+ /* Validate parameters */
+ if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
+ printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n",
+ CX18_MAX_CARDS - 1);
+ return -1;
+ }
+
+ if (cx18_debug < 0 || cx18_debug > 511) {
+ cx18_debug = 0;
+ printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n");
+ }
+
+ if (pci_register_driver(&cx18_pci_driver)) {
+ printk(KERN_ERR "cx18: Error detecting PCI card\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "cx18: End initialization\n");
+ return 0;
+}
+
+static void module_cleanup(void)
+{
+ int i;
+
+ pci_unregister_driver(&cx18_pci_driver);
+
+ for (i = 0; i < cx18_cards_active; i++) {
+ if (cx18_cards[i] == NULL)
+ continue;
+ kfree(cx18_cards[i]);
+ }
+}
+
+module_init(module_start);
+module_exit(module_cleanup);
diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h
new file mode 100644
index 000000000..576358873
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-driver.h
@@ -0,0 +1,516 @@
+/*
+ * cx18 driver internal defines and structures
+ *
+ * Derived from ivtv-driver.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef CX18_DRIVER_H
+#define CX18_DRIVER_H
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/byteorder/swab.h>
+#include <linux/pagemap.h>
+#include <linux/workqueue.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+#include <linux/mutex.h>
+#endif
+
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "cx18-mailbox.h"
+#include "cx18-av-core.h"
+#include "cx23418.h"
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#ifndef CONFIG_PCI
+# error "This driver requires kernel PCI support."
+#endif
+
+#define CX18_MEM_OFFSET 0x00000000
+#define CX18_MEM_SIZE 0x04000000
+#define CX18_REG_OFFSET 0x02000000
+
+/* Maximum cx18 driver instances. */
+#define CX18_MAX_CARDS 32
+
+/* Supported cards */
+#define CX18_CARD_HVR_1600_ESMT 0 /* Hauppauge HVR 1600 (ESMT memory) */
+#define CX18_CARD_HVR_1600_SAMSUNG 1 /* Hauppauge HVR 1600 (Samsung memory) */
+#define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */
+#define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */
+#define CX18_CARD_LAST 3
+
+#define CX18_ENC_STREAM_TYPE_MPG 0
+#define CX18_ENC_STREAM_TYPE_TS 1
+#define CX18_ENC_STREAM_TYPE_YUV 2
+#define CX18_ENC_STREAM_TYPE_VBI 3
+#define CX18_ENC_STREAM_TYPE_PCM 4
+#define CX18_ENC_STREAM_TYPE_IDX 5
+#define CX18_ENC_STREAM_TYPE_RAD 6
+#define CX18_MAX_STREAMS 7
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_CX 0x14f1
+#define PCI_DEVICE_ID_CX23418 0x5b7a
+
+/* subsystem vendor ID */
+#define CX18_PCI_ID_HAUPPAUGE 0x0070
+#define CX18_PCI_ID_COMPRO 0x185b
+#define CX18_PCI_ID_YUAN 0x12ab
+
+/* ======================================================================== */
+/* ========================== START USER SETTABLE DMA VARIABLES =========== */
+/* ======================================================================== */
+
+/* DMA Buffers, Default size in MB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFFERS 1
+#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
+#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
+#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
+#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
+#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
+
+/* i2c stuff */
+#define I2C_CLIENTS_MAX 16
+
+/* debugging */
+
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_WARN (1 << 0)
+#define CX18_DBGFLG_INFO (1 << 1)
+#define CX18_DBGFLG_API (1 << 2)
+#define CX18_DBGFLG_DMA (1 << 3)
+#define CX18_DBGFLG_IOCTL (1 << 4)
+#define CX18_DBGFLG_FILE (1 << 5)
+#define CX18_DBGFLG_I2C (1 << 6)
+#define CX18_DBGFLG_IRQ (1 << 7)
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_HIGHVOL (1 << 8)
+
+/* NOTE: extra space before comma in 'cx->num , ## args' is required for
+ gcc-2.95, otherwise it won't compile. */
+#define CX18_DEBUG(x, type, fmt, args...) \
+ do { \
+ if ((x) & cx18_debug) \
+ printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
+ } while (0)
+#define CX18_DEBUG_WARN(fmt, args...) CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_INFO(fmt, args...) CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_API(fmt, args...) CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_DMA(fmt, args...) CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE(fmt, args...) CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_I2C(fmt, args...) CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+ do { \
+ if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+ printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
+ } while (0)
+#define CX18_DEBUG_HI_WARN(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_HI_INFO(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_HI_API(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_HI_IRQ(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+/* Standard kernel messages */
+#define CX18_ERR(fmt, args...) printk(KERN_ERR "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_WARN(fmt, args...) printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_INFO(fmt, args...) printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
+
+/* Values for CX18_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
+
+#define CX18_MAX_PGM_INDEX (400)
+
+extern int cx18_debug;
+
+
+struct cx18_options {
+ int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
+ int cardtype; /* force card type on load */
+ int tuner; /* set tuner on load */
+ int radio; /* enable/disable radio */
+};
+
+/* per-buffer bit flags */
+#define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */
+
+/* per-stream, s_flags */
+#define CX18_F_S_CLAIMED 3 /* this stream is claimed */
+#define CX18_F_S_STREAMING 4 /* the fw is decoding/encoding this stream */
+#define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */
+#define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */
+#define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */
+
+/* per-cx18, i_flags */
+#define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */
+#define CX18_F_I_EOS 4 /* End of encoder stream reached */
+#define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */
+#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */
+#define CX18_F_I_INITED 21 /* set after first open */
+#define CX18_F_I_FAILED 22 /* set if first open failed */
+
+/* These are the VBI types as they appear in the embedded VBI private packets. */
+#define CX18_SLICED_TYPE_TELETEXT_B (1)
+#define CX18_SLICED_TYPE_CAPTION_525 (4)
+#define CX18_SLICED_TYPE_WSS_625 (5)
+#define CX18_SLICED_TYPE_VPS (7)
+
+struct cx18_buffer {
+ struct list_head list;
+ dma_addr_t dma_handle;
+ u32 id;
+ unsigned long b_flags;
+ char *buf;
+
+ u32 bytesused;
+ u32 readpos;
+};
+
+struct cx18_queue {
+ struct list_head list;
+ u32 buffers;
+ u32 length;
+ u32 bytesused;
+};
+
+struct cx18_dvb {
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+ struct dmxdev dmxdev;
+ struct dvb_adapter dvb_adapter;
+ struct dvb_demux demux;
+ struct dvb_frontend *fe;
+ struct dvb_net dvbnet;
+ int enabled;
+ int feeding;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex feedlock;
+#else
+ struct semaphore feedlock;
+#endif
+
+};
+
+struct cx18; /* forward reference */
+struct cx18_scb; /* forward reference */
+
+struct cx18_stream {
+ /* These first four fields are always set, even if the stream
+ is not actually created. */
+ struct video_device *v4l2dev; /* NULL when stream not created */
+ struct cx18 *cx; /* for ease of use */
+ const char *name; /* name of the stream */
+ int type; /* stream type */
+ u32 handle; /* task handle */
+ unsigned mdl_offset;
+
+ 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 */
+ u64 dma_pts;
+ wait_queue_head_t waitq;
+
+ /* Buffer Stats */
+ u32 buffers;
+ u32 buf_size;
+ u32 buffers_stolen;
+
+ /* Buffer Queues */
+ struct cx18_queue q_free; /* free buffers */
+ struct cx18_queue q_full; /* full buffers */
+ struct cx18_queue q_io; /* waiting for I/O */
+
+ /* DVB / Digital Transport */
+ struct cx18_dvb dvb;
+};
+
+struct cx18_open_id {
+ u32 open_id;
+ int type;
+ enum v4l2_priority prio;
+ struct cx18 *cx;
+};
+
+/* forward declaration of struct defined in cx18-cards.h */
+struct cx18_card;
+
+
+#define CX18_VBI_FRAMES 32
+
+/* VBI data */
+struct vbi_info {
+ u32 enc_size;
+ u32 frame;
+ 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;
+ 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];
+
+ /* Buffer for VBI data inserted into MPEG stream.
+ The first byte is a dummy byte that's never used.
+ The next 16 bytes contain the MPEG header for the VBI data,
+ the remainder is the actual VBI data.
+ The max size accepted by the MPEG VBI reinsertion turns out
+ to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
+ where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
+ a single line header byte and 2 * 18 is the number of VBI lines per frame.
+
+ However, it seems that the data must be 1K aligned, so we have to
+ pad the data until the 1 or 2 K boundary.
+
+ This pointer array will allocate 2049 bytes to store each VBI frame. */
+ u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
+ u32 sliced_mpeg_size[CX18_VBI_FRAMES];
+ struct cx18_buffer sliced_mpeg_buf;
+ u32 inserted_frame;
+
+ u32 start[2], count;
+ u32 raw_size;
+ u32 sliced_size;
+};
+
+/* Per cx23418, per I2C bus private algo callback data */
+struct cx18_i2c_algo_callback_data {
+ struct cx18 *cx;
+ int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
+};
+
+/* Struct to hold info about cx18 cards */
+struct cx18 {
+ int num; /* board number, -1 during init! */
+ char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */
+ struct pci_dev *dev; /* PCI device */
+ const struct cx18_card *card; /* card information */
+ const char *card_name; /* full name of the card */
+ const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
+ u8 is_50hz;
+ u8 is_60hz;
+ u8 is_out_50hz;
+ u8 is_out_60hz;
+ u8 nof_inputs; /* number of video inputs */
+ u8 nof_audio_inputs; /* number of audio inputs */
+ u16 buffer_id; /* buffer ID counter */
+ u32 v4l2_cap; /* V4L2 capabilities of card */
+ u32 hw_flags; /* Hardware description of the board */
+ unsigned mdl_offset;
+ struct cx18_scb __iomem *scb; /* pointer to SCB */
+
+ struct cx18_av_state av_state;
+
+ /* codec settings */
+ struct cx2341x_mpeg_params params;
+ u32 filter_mode;
+ u32 temporal_strength;
+ u32 spatial_strength;
+
+ /* dualwatch */
+ unsigned long dualwatch_jiffies;
+ u16 dualwatch_stereo_mode;
+
+ /* Digitizer type */
+ int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */
+#else
+ struct semaphore serialize_lock;/* mutex used to serialize open/close/start/stop/ioctl operations */
+#endif
+ struct cx18_options options; /* User options */
+ int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
+ struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */
+ unsigned long i_flags; /* global cx18 flags */
+ atomic_t ana_capturing; /* count number of active analog capture streams */
+ atomic_t tot_capturing; /* total count number of active capture streams */
+ spinlock_t lock; /* lock access to this struct */
+ int search_pack_header;
+
+ spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
+
+ 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;
+ struct v4l2_prio_state prio;
+
+ u8 card_rev;
+ void __iomem *enc_mem, *reg_mem;
+
+ struct vbi_info vbi;
+
+ 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[CX18_MAX_PGM_INDEX];
+
+ u64 mpg_data_received;
+ u64 vbi_data_inserted;
+
+ wait_queue_head_t mb_apu_waitq;
+ wait_queue_head_t mb_cpu_waitq;
+ wait_queue_head_t mb_epu_waitq;
+ wait_queue_head_t mb_hpu_waitq;
+ wait_queue_head_t cap_w;
+ /* when the current DMA is finished this queue is woken up */
+ wait_queue_head_t dma_waitq;
+
+ /* i2c */
+ struct i2c_adapter i2c_adap[2];
+ struct i2c_algo_bit_data i2c_algo[2];
+ struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
+ struct i2c_client i2c_client[2];
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex i2c_bus_lock[2];
+#else
+ struct semaphore i2c_bus_lock[2];
+#endif
+ struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
+
+ /* gpio */
+ u32 gpio_dir;
+ u32 gpio_val;
+
+ /* v4l2 and User settings */
+
+ /* codec settings */
+ u32 audio_input;
+ u32 active_input;
+ u32 active_output;
+ v4l2_std_id std;
+ v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
+};
+
+/* Globals */
+extern struct cx18 *cx18_cards[];
+extern int cx18_cards_active;
+extern int cx18_first_minor;
+extern spinlock_t cx18_cards_lock;
+
+/*==============Prototypes==================*/
+
+/* Return non-zero if a signal is pending */
+int cx18_msleep_timeout(unsigned int msecs, int intr);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, etc. */
+int cx18_init_on_first_open(struct cx18 *cx);
+
+/* This is a PCI post thing, where if the pci register is not read, then
+ the write doesn't always take effect right away. By reading back the
+ register any pending PCI writes will be performed (in order), and so
+ you can be sure that the writes are guaranteed to be done.
+
+ Rarely needed, only in some timing sensitive cases.
+ Apparently if this is not done some motherboards seem
+ to kill the firmware and get into the broken state until computer is
+ rebooted. */
+#define write_sync(val, reg) \
+ do { writel(val, reg); readl(reg); } while (0)
+
+#define read_reg(reg) readl(cx->reg_mem + (reg))
+#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
+#define write_reg_sync(val, reg) \
+ do { write_reg(val, reg); read_reg(reg); } while (0)
+
+#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
+#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
+#define write_enc_sync(val, addr) \
+ do { write_enc(val, addr); read_enc(addr); } while (0)
+
+#define sw1_irq_enable(val) do { \
+ write_reg(val, SW1_INT_STATUS); \
+ write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
+} while (0)
+
+#define sw1_irq_disable(val) \
+ write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
+
+#define sw2_irq_enable(val) do { \
+ write_reg(val, SW2_INT_STATUS); \
+ write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
+} while (0)
+
+#define sw2_irq_disable(val) \
+ write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
+
+#define setup_page(addr) do { \
+ u32 val = read_reg(0xD000F8) & ~0x1f00; \
+ write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
+} while (0)
+
+#endif /* CX18_DRIVER_H */
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c
new file mode 100644
index 000000000..c9744173f
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-dvb.c
@@ -0,0 +1,286 @@
+/*
+ * cx18 functions for DVB support
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx18-version.h"
+#include "cx18-dvb.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "s5h1409.h"
+#include "mxl5005s.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+
+static struct mxl5005s_config hauppauge_hvr1600_tuner = {
+ .i2c_address = 0xC6 >> 1,
+ .if_freq = IF_FREQ_5380000HZ,
+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,
+ .agc_mode = MXL_SINGLE_AGC,
+ .tracking_filter = MXL_TF_C_H,
+ .rssi_enable = MXL_RSSI_ENABLE,
+ .cap_select = MXL_CAP_SEL_ENABLE,
+ .div_out = MXL_DIV_OUT_4,
+ .clock_out = MXL_CLOCK_OUT_DISABLE,
+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+ .top = MXL5005S_TOP_25P2,
+ .mod_mode = MXL_DIGITAL_MODE,
+ .if_mode = MXL_ZERO_IF,
+ .AgcMasterByte = 0x00,
+};
+
+static struct s5h1409_config hauppauge_hvr1600_config = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_SERIAL_OUTPUT,
+ .gpio = S5H1409_GPIO_ON,
+ .qam_if = 44000,
+ .inversion = S5H1409_INVERSION_OFF,
+ .status_mode = S5H1409_DEMODLOCKING,
+ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+
+};
+
+static int dvb_register(struct cx18_stream *stream);
+
+/* Kernel DVB framework calls this when the feed needs to start.
+ * The CX18 framework should enable the transport DMA handling
+ * and queue processing.
+ */
+static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
+ struct cx18 *cx = stream->cx;
+ int ret = -EINVAL;
+ u32 v;
+
+ CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
+ feed->pid, feed->index);
+ switch (cx->card->type) {
+ case CX18_CARD_HVR_1600_ESMT:
+ case CX18_CARD_HVR_1600_SAMSUNG:
+ v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+ v |= 0x00400000; /* Serial Mode */
+ v |= 0x00002000; /* Data Length - Byte */
+ v |= 0x00010000; /* Error - Polarity */
+ v |= 0x00020000; /* Error - Passthru */
+ v |= 0x000c0000; /* Error - Ignore */
+ write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+ break;
+
+ default:
+ /* Assumption - Parallel transport - Signalling
+ * undefined or default.
+ */
+ break;
+ }
+
+ if (!demux->dmx.frontend)
+ return -EINVAL;
+
+ if (stream) {
+ mutex_lock(&stream->dvb.feedlock);
+ if (stream->dvb.feeding++ == 0) {
+ CX18_DEBUG_INFO("Starting Transport DMA\n");
+ ret = cx18_start_v4l2_encode_stream(stream);
+ } else
+ ret = 0;
+ mutex_unlock(&stream->dvb.feedlock);
+ }
+
+ return ret;
+}
+
+/* Kernel DVB framework calls this when the feed needs to stop. */
+static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
+ struct cx18 *cx = stream->cx;
+ int ret = -EINVAL;
+
+ CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
+ feed->pid, feed->index);
+
+ if (stream) {
+ mutex_lock(&stream->dvb.feedlock);
+ if (--stream->dvb.feeding == 0) {
+ CX18_DEBUG_INFO("Stopping Transport DMA\n");
+ ret = cx18_stop_v4l2_encode_stream(stream, 0);
+ } else
+ ret = 0;
+ mutex_unlock(&stream->dvb.feedlock);
+ }
+
+ return ret;
+}
+
+int cx18_dvb_register(struct cx18_stream *stream)
+{
+ struct cx18 *cx = stream->cx;
+ struct cx18_dvb *dvb = &stream->dvb;
+ struct dvb_adapter *dvb_adapter;
+ struct dvb_demux *dvbdemux;
+ struct dmx_demux *dmx;
+ int ret;
+
+ if (!dvb)
+ return -EINVAL;
+
+ ret = dvb_register_adapter(&dvb->dvb_adapter,
+ CX18_DRIVER_NAME,
+ THIS_MODULE, &cx->dev->dev, adapter_nr);
+ if (ret < 0)
+ goto err_out;
+
+ dvb_adapter = &dvb->dvb_adapter;
+
+ dvbdemux = &dvb->demux;
+
+ dvbdemux->priv = (void *)stream;
+
+ dvbdemux->filternum = 256;
+ dvbdemux->feednum = 256;
+ dvbdemux->start_feed = cx18_dvb_start_feed;
+ dvbdemux->stop_feed = cx18_dvb_stop_feed;
+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+ DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+ ret = dvb_dmx_init(dvbdemux);
+ if (ret < 0)
+ goto err_dvb_unregister_adapter;
+
+ dmx = &dvbdemux->dmx;
+
+ dvb->hw_frontend.source = DMX_FRONTEND_0;
+ dvb->mem_frontend.source = DMX_MEMORY_FE;
+ dvb->dmxdev.filternum = 256;
+ dvb->dmxdev.demux = dmx;
+
+ ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
+ if (ret < 0)
+ goto err_dvb_dmx_release;
+
+ ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
+ if (ret < 0)
+ goto err_dvb_dmxdev_release;
+
+ ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
+ if (ret < 0)
+ goto err_remove_hw_frontend;
+
+ ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
+ if (ret < 0)
+ goto err_remove_mem_frontend;
+
+ ret = dvb_register(stream);
+ if (ret < 0)
+ goto err_disconnect_frontend;
+
+ dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
+
+ CX18_INFO("DVB Frontend registered\n");
+ mutex_init(&dvb->feedlock);
+ dvb->enabled = 1;
+ return ret;
+
+err_disconnect_frontend:
+ dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+ dmx->remove_frontend(dmx, &dvb->mem_frontend);
+err_remove_hw_frontend:
+ dmx->remove_frontend(dmx, &dvb->hw_frontend);
+err_dvb_dmxdev_release:
+ dvb_dmxdev_release(&dvb->dmxdev);
+err_dvb_dmx_release:
+ dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+ dvb_unregister_adapter(dvb_adapter);
+err_out:
+ return ret;
+}
+
+void cx18_dvb_unregister(struct cx18_stream *stream)
+{
+ struct cx18 *cx = stream->cx;
+ struct cx18_dvb *dvb = &stream->dvb;
+ struct dvb_adapter *dvb_adapter;
+ struct dvb_demux *dvbdemux;
+ struct dmx_demux *dmx;
+
+ CX18_INFO("unregister DVB\n");
+
+ dvb_adapter = &dvb->dvb_adapter;
+ dvbdemux = &dvb->demux;
+ dmx = &dvbdemux->dmx;
+
+ dmx->close(dmx);
+ dvb_net_release(&dvb->dvbnet);
+ dmx->remove_frontend(dmx, &dvb->mem_frontend);
+ dmx->remove_frontend(dmx, &dvb->hw_frontend);
+ dvb_dmxdev_release(&dvb->dmxdev);
+ dvb_dmx_release(dvbdemux);
+ dvb_unregister_frontend(dvb->fe);
+ dvb_frontend_detach(dvb->fe);
+ dvb_unregister_adapter(dvb_adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+static int dvb_register(struct cx18_stream *stream)
+{
+ struct cx18_dvb *dvb = &stream->dvb;
+ struct cx18 *cx = stream->cx;
+ int ret = 0;
+
+ switch (cx->card->type) {
+ case CX18_CARD_HVR_1600_ESMT:
+ case CX18_CARD_HVR_1600_SAMSUNG:
+ dvb->fe = dvb_attach(s5h1409_attach,
+ &hauppauge_hvr1600_config,
+ &cx->i2c_adap[0]);
+ if (dvb->fe != NULL) {
+ dvb_attach(mxl5005s_attach, dvb->fe,
+ &cx->i2c_adap[0],
+ &hauppauge_hvr1600_tuner);
+ ret = 0;
+ }
+ break;
+ default:
+ /* No Digital Tv Support */
+ break;
+ }
+
+ if (dvb->fe == NULL) {
+ CX18_ERR("frontend initialization failed\n");
+ return -1;
+ }
+
+ ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
+ if (ret < 0) {
+ if (dvb->fe->ops.release)
+ dvb->fe->ops.release(dvb->fe);
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.h b/linux/drivers/media/video/cx18/cx18-dvb.h
new file mode 100644
index 000000000..d6a6ccda7
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-dvb.h
@@ -0,0 +1,25 @@
+/*
+ * cx18 functions for DVB support
+ *
+ * Copyright (c) 2008 Steven Toth <stoth@hauppauge.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx18-driver.h"
+
+int cx18_dvb_register(struct cx18_stream *stream);
+void cx18_dvb_unregister(struct cx18_stream *stream);
diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c
new file mode 100644
index 000000000..12f9de74d
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-fileops.c
@@ -0,0 +1,749 @@
+/*
+ * cx18 file operation functions
+ *
+ * Derived from ivtv-fileops.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+#include "cx18-streams.h"
+#include "cx18-controls.h"
+#include "cx18-ioctl.h"
+#include "cx18-cards.h"
+
+/* This function tries to claim the stream for a specific file descriptor.
+ If no one else is using this stream then the stream is claimed and
+ associated VBI streams are also automatically claimed.
+ Possible error returns: -EBUSY if someone else has claimed
+ the stream or 0 on success. */
+static int cx18_claim_stream(struct cx18_open_id *id, int type)
+{
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[type];
+ struct cx18_stream *s_vbi;
+ int vbi_type;
+
+ if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+ /* someone already claimed this stream */
+ if (s->id == id->open_id) {
+ /* yes, this file descriptor did. So that's OK. */
+ return 0;
+ }
+ if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
+ /* VBI is handled already internally, now also assign
+ the file descriptor to this stream for external
+ reading of the stream. */
+ s->id = id->open_id;
+ CX18_DEBUG_INFO("Start Read VBI\n");
+ return 0;
+ }
+ /* someone else is using this stream already */
+ CX18_DEBUG_INFO("Stream %d is busy\n", type);
+ return -EBUSY;
+ }
+ s->id = id->open_id;
+
+ /* CX18_DEC_STREAM_TYPE_MPG needs to claim CX18_DEC_STREAM_TYPE_VBI,
+ CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI
+ (provided VBI insertion is on and sliced VBI is selected), for all
+ other streams we're done */
+ if (type == CX18_ENC_STREAM_TYPE_MPG &&
+ cx->vbi.insert_mpeg && cx->vbi.sliced_in->service_set) {
+ vbi_type = CX18_ENC_STREAM_TYPE_VBI;
+ } else {
+ return 0;
+ }
+ s_vbi = &cx->streams[vbi_type];
+
+ set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+
+ /* mark that it is used internally */
+ set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags);
+ return 0;
+}
+
+/* This function releases a previously claimed stream. It will take into
+ account associated VBI streams. */
+static void cx18_release_stream(struct cx18_stream *s)
+{
+ struct cx18 *cx = s->cx;
+ struct cx18_stream *s_vbi;
+
+ s->id = -1;
+ if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+ test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
+ /* this stream is still in use internally */
+ return;
+ }
+ if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+ CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+ return;
+ }
+
+ cx18_flush_queues(s);
+
+ /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI,
+ for all other streams we're done */
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+ s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+ else
+ return;
+
+ /* clear internal use flag */
+ if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
+ /* was already cleared */
+ return;
+ }
+ if (s_vbi->id != -1) {
+ /* VBI stream still claimed by a file descriptor */
+ return;
+ }
+ clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+ cx18_flush_queues(s_vbi);
+}
+
+static void cx18_dualwatch(struct cx18 *cx)
+{
+ struct v4l2_tuner vt;
+ u16 new_bitmap;
+ u16 new_stereo_mode;
+ const u16 stereo_mask = 0x0300;
+ const u16 dual = 0x0200;
+
+ new_stereo_mode = cx->params.audio_properties & stereo_mask;
+ memset(&vt, 0, sizeof(vt));
+ cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, &vt);
+ if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
+ (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
+ new_stereo_mode = dual;
+
+ if (new_stereo_mode == cx->dualwatch_stereo_mode)
+ return;
+
+ new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+
+ CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
+ cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+
+ if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+ cx18_find_handle(cx), new_bitmap) == 0) {
+ cx->dualwatch_stereo_mode = new_stereo_mode;
+ return;
+ }
+ CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+#if 0
+static void cx18_update_pgm_info(struct cx18 *cx)
+{
+ u32 wr_idx = (read_enc(cx->pgm_info_offset) - cx->pgm_info_offset - 4) / 24;
+ int cnt;
+ int i = 0;
+
+ if (wr_idx >= cx->pgm_info_num) {
+ CX18_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, cx->pgm_info_num);
+ return;
+ }
+ cnt = (wr_idx + cx->pgm_info_num - cx->pgm_info_write_idx) % cx->pgm_info_num;
+ while (i < cnt) {
+ int idx = (cx->pgm_info_write_idx + i) % cx->pgm_info_num;
+ struct v4l2_enc_idx_entry *e = cx->pgm_info + idx;
+ u32 addr = cx->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 };
+
+ e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
+ if (e->offset > cx->mpg_data_received)
+ break;
+ e->offset += cx->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];
+ i++;
+ }
+ cx->pgm_info_write_idx = (cx->pgm_info_write_idx + i) % cx->pgm_info_num;
+}
+#endif
+
+static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err)
+{
+ struct cx18 *cx = s->cx;
+ struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+ struct cx18_buffer *buf;
+ DEFINE_WAIT(wait);
+
+ *err = 0;
+ while (1) {
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+#if 0
+ /* Process pending program info updates and pending
+ VBI data */
+ cx18_update_pgm_info(cx);
+#endif
+
+ if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
+ cx->dualwatch_jiffies = jiffies;
+ cx18_dualwatch(cx);
+ }
+ if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+ !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+ while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) {
+ /* byteswap and process VBI data */
+/* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */
+ cx18_enqueue(s_vbi, buf, &s_vbi->q_free);
+ }
+ }
+ buf = &cx->vbi.sliced_mpeg_buf;
+ if (buf->readpos != buf->bytesused)
+ return buf;
+ }
+
+ /* do we have leftover data? */
+ buf = cx18_dequeue(s, &s->q_io);
+ if (buf)
+ return buf;
+
+ /* do we have new data? */
+ buf = cx18_dequeue(s, &s->q_full);
+ if (buf) {
+ if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP,
+ &buf->b_flags))
+ return buf;
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+ /* byteswap MPG data */
+ cx18_buf_swap(buf);
+ else {
+ /* byteswap and process VBI data */
+ cx18_process_vbi_data(cx, buf,
+ s->dma_pts, s->type);
+ }
+ return buf;
+ }
+
+ /* return if end of stream */
+ if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+ CX18_DEBUG_INFO("EOS %s\n", s->name);
+ return NULL;
+ }
+
+ /* return if file was opened with O_NONBLOCK */
+ if (non_block) {
+ *err = -EAGAIN;
+ return NULL;
+ }
+
+ /* wait for more data to arrive */
+ prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+ /* New buffers might have become available before we were added
+ to the waitqueue */
+ if (!s->q_full.buffers)
+ schedule();
+ finish_wait(&s->waitq, &wait);
+ if (signal_pending(current)) {
+ /* return if a signal was received */
+ CX18_DEBUG_INFO("User stopped %s\n", s->name);
+ *err = -EINTR;
+ return NULL;
+ }
+ }
+}
+
+static void cx18_setup_sliced_vbi_buf(struct cx18 *cx)
+{
+ int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+ cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx];
+ cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx];
+ cx->vbi.sliced_mpeg_buf.readpos = 0;
+}
+
+static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
+ struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
+{
+ struct cx18 *cx = s->cx;
+ size_t len = buf->bytesused - buf->readpos;
+
+ if (len > ucount)
+ len = ucount;
+ if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
+ cx->vbi.sliced_in->service_set && buf != &cx->vbi.sliced_mpeg_buf) {
+ const char *start = buf->buf + buf->readpos;
+ const char *p = start + 1;
+ const u8 *q;
+ u8 ch = cx->search_pack_header ? 0xba : 0xe0;
+ int stuffing, i;
+
+ while (start + len > p) {
+ q = memchr(p, 0, start + len - p);
+ if (q == NULL)
+ break;
+ p = q + 1;
+ if ((char *)q + 15 >= buf->buf + buf->bytesused ||
+ q[1] != 0 || q[2] != 1 || q[3] != ch)
+ continue;
+ if (!cx->search_pack_header) {
+ if ((q[6] & 0xc0) != 0x80)
+ continue;
+ if (((q[7] & 0xc0) == 0x80 &&
+ (q[9] & 0xf0) == 0x20) ||
+ ((q[7] & 0xc0) == 0xc0 &&
+ (q[9] & 0xf0) == 0x30)) {
+ ch = 0xba;
+ cx->search_pack_header = 1;
+ p = q + 9;
+ }
+ continue;
+ }
+ stuffing = q[13] & 7;
+ /* all stuffing bytes must be 0xff */
+ for (i = 0; i < stuffing; i++)
+ if (q[14 + i] != 0xff)
+ break;
+ if (i == stuffing &&
+ (q[4] & 0xc4) == 0x44 &&
+ (q[12] & 3) == 3 &&
+ q[14 + stuffing] == 0 &&
+ q[15 + stuffing] == 0 &&
+ q[16 + stuffing] == 1) {
+ cx->search_pack_header = 0;
+ len = (char *)q - start;
+ cx18_setup_sliced_vbi_buf(cx);
+ break;
+ }
+ }
+ }
+ if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+ CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
+ len, s->name);
+ return -EFAULT;
+ }
+ buf->readpos += len;
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+ buf != &cx->vbi.sliced_mpeg_buf)
+ cx->mpg_data_received += len;
+ return len;
+}
+
+static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
+ size_t tot_count, int non_block)
+{
+ struct cx18 *cx = s->cx;
+ size_t tot_written = 0;
+ int single_frame = 0;
+
+ if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
+ /* shouldn't happen */
+ CX18_DEBUG_WARN("Stream %s not initialized before read\n",
+ s->name);
+ return -EIO;
+ }
+
+ /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
+ frames should arrive one-by-one, so make sure we never output more
+ than one VBI frame at a time */
+ if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+ cx->vbi.sliced_in->service_set)
+ single_frame = 1;
+
+ for (;;) {
+ struct cx18_buffer *buf;
+ int rc;
+
+ buf = cx18_get_buffer(s, non_block, &rc);
+ /* if there is no data available... */
+ if (buf == NULL) {
+ /* if we got data, then return that regardless */
+ if (tot_written)
+ break;
+ /* EOS condition */
+ if (rc == 0) {
+ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+ clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+ cx18_release_stream(s);
+ }
+ /* set errno */
+ return rc;
+ }
+
+ rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written,
+ tot_count - tot_written);
+
+ if (buf != &cx->vbi.sliced_mpeg_buf) {
+ if (buf->readpos == buf->bytesused) {
+ cx18_buf_sync_for_device(s, buf);
+ cx18_enqueue(s, buf, &s->q_free);
+ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5,
+ s->handle,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] -
+ cx->enc_mem,
+ 1, buf->id, s->buf_size);
+ } else
+ cx18_enqueue(s, buf, &s->q_io);
+ } else if (buf->readpos == buf->bytesused) {
+ int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+ cx->vbi.sliced_mpeg_size[idx] = 0;
+ cx->vbi.inserted_frame++;
+ cx->vbi_data_inserted += buf->bytesused;
+ }
+ if (rc < 0)
+ return rc;
+ tot_written += rc;
+
+ if (tot_written == tot_count || single_frame)
+ break;
+ }
+ return tot_written;
+}
+
+static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
+ size_t count, loff_t *pos, int non_block)
+{
+ ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
+ struct cx18 *cx = s->cx;
+
+ CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+ if (rc > 0)
+ pos += rc;
+ return rc;
+}
+
+int cx18_start_capture(struct cx18_open_id *id)
+{
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[id->type];
+ struct cx18_stream *s_vbi;
+
+ if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
+ /* you cannot read from these stream types. */
+ return -EPERM;
+ }
+
+ /* Try to claim this stream. */
+ if (cx18_claim_stream(id, s->type))
+ return -EBUSY;
+
+ /* If capture is already in progress, then we also have to
+ do nothing extra. */
+ if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+ test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+ set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+ return 0;
+ }
+
+ /* Start VBI capture if required */
+ s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+ test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+ !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+ /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
+ automatically when the MPG stream is claimed.
+ We only need to start the VBI capturing. */
+ if (cx18_start_v4l2_encode_stream(s_vbi)) {
+ CX18_DEBUG_WARN("VBI capture start failed\n");
+
+ /* Failure, clean up and return an error */
+ clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+ /* also releases the associated VBI stream */
+ cx18_release_stream(s);
+ return -EIO;
+ }
+ CX18_DEBUG_INFO("VBI insertion started\n");
+ }
+
+ /* Tell the card to start capturing */
+ if (!cx18_start_v4l2_encode_stream(s)) {
+ /* We're done */
+ set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+ /* Resume a possibly paused encoder */
+ if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
+ return 0;
+ }
+
+ /* failure, clean up */
+ CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+ /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
+ automatically when the MPG stream is released.
+ We only need to stop the VBI capturing. */
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+ test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+ cx18_stop_v4l2_encode_stream(s_vbi, 0);
+ clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+ }
+ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+ cx18_release_stream(s);
+ return -EIO;
+}
+
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *pos)
+{
+ struct cx18_open_id *id = filp->private_data;
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[id->type];
+ int rc;
+
+ CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+ mutex_lock(&cx->serialize_lock);
+ rc = cx18_start_capture(id);
+ mutex_unlock(&cx->serialize_lock);
+ if (rc)
+ return rc;
+ return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+}
+
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+ struct cx18_open_id *id = filp->private_data;
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[id->type];
+ int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+ /* Start a capture if there is none */
+ if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+ int rc;
+
+ mutex_lock(&cx->serialize_lock);
+ rc = cx18_start_capture(id);
+ mutex_unlock(&cx->serialize_lock);
+ if (rc) {
+ CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
+ s->name, rc);
+ return POLLERR;
+ }
+ CX18_DEBUG_FILE("Encoder poll started capture\n");
+ }
+
+ /* add stream's waitq to the poll list */
+ CX18_DEBUG_HI_FILE("Encoder poll\n");
+ poll_wait(filp, &s->waitq, wait);
+
+ if (s->q_full.length || s->q_io.length)
+ return POLLIN | POLLRDNORM;
+ if (eof)
+ return POLLHUP;
+ return 0;
+}
+
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
+{
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[id->type];
+
+ CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+ /* 'Unclaim' this stream */
+
+ /* Stop capturing */
+ if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+ struct cx18_stream *s_vbi =
+ &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+
+ CX18_DEBUG_INFO("close stopping capture\n");
+ /* Special case: a running VBI capture for VBI insertion
+ in the mpeg stream. Need to stop that too. */
+ if (id->type == CX18_ENC_STREAM_TYPE_MPG &&
+ test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+ !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+ CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
+ cx18_stop_v4l2_encode_stream(s_vbi, 0);
+ }
+ if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
+ test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
+ /* Also used internally, don't stop capturing */
+ s->id = -1;
+ else
+ cx18_stop_v4l2_encode_stream(s, gop_end);
+ }
+ if (!gop_end) {
+ clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+ cx18_release_stream(s);
+ }
+}
+
+int cx18_v4l2_close(struct inode *inode, struct file *filp)
+{
+ struct cx18_open_id *id = filp->private_data;
+ struct cx18 *cx = id->cx;
+ struct cx18_stream *s = &cx->streams[id->type];
+
+ CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+ v4l2_prio_close(&cx->prio, &id->prio);
+
+ /* Easy case first: this stream was never claimed by us */
+ if (s->id != id->open_id) {
+ kfree(id);
+ return 0;
+ }
+
+ /* 'Unclaim' this stream */
+
+ /* Stop radio */
+ mutex_lock(&cx->serialize_lock);
+ if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
+ /* Closing radio device, return to TV mode */
+ cx18_mute(cx);
+ /* Mark that the radio is no longer in use */
+ clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+ /* Switch tuner to TV */
+ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+ /* Select correct audio input (i.e. TV tuner or Line in) */
+ cx18_audio_set_io(cx);
+ if (atomic_read(&cx->ana_capturing) > 0) {
+ /* Undo video mute */
+ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+ cx->params.video_mute |
+ (cx->params.video_mute_yuv << 8));
+ }
+ /* Done! Unmute and continue. */
+ cx18_unmute(cx);
+ cx18_release_stream(s);
+ } else {
+ cx18_stop_capture(id, 0);
+ }
+ kfree(id);
+ mutex_unlock(&cx->serialize_lock);
+ return 0;
+}
+
+static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
+{
+ struct cx18 *cx = s->cx;
+ struct cx18_open_id *item;
+
+ CX18_DEBUG_FILE("open %s\n", s->name);
+
+ /* Allocate memory */
+ item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
+ if (NULL == item) {
+ CX18_DEBUG_WARN("nomem on v4l2 open\n");
+ return -ENOMEM;
+ }
+ item->cx = cx;
+ item->type = s->type;
+ v4l2_prio_open(&cx->prio, &item->prio);
+
+ item->open_id = cx->open_id++;
+ filp->private_data = item;
+
+ if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
+ /* Try to claim this stream */
+ if (cx18_claim_stream(item, item->type)) {
+ /* No, it's already in use */
+ kfree(item);
+ return -EBUSY;
+ }
+
+ if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+ if (atomic_read(&cx->ana_capturing) > 0) {
+ /* switching to radio while capture is
+ in progress is not polite */
+ cx18_release_stream(s);
+ kfree(item);
+ return -EBUSY;
+ }
+ }
+
+ /* Mark that the radio is being used. */
+ set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+ /* We have the radio */
+ cx18_mute(cx);
+ /* Switch tuner to radio */
+ cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL);
+ /* Select the correct audio input (i.e. radio tuner) */
+ cx18_audio_set_io(cx);
+ /* Done! Unmute and continue. */
+ cx18_unmute(cx);
+ }
+ return 0;
+}
+
+int cx18_v4l2_open(struct inode *inode, struct file *filp)
+{
+ int res, x, y = 0;
+ struct cx18 *cx = NULL;
+ struct cx18_stream *s = NULL;
+ int minor = iminor(inode);
+
+ /* Find which card this open was on */
+ spin_lock(&cx18_cards_lock);
+ for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
+ /* find out which stream this open was on */
+ for (y = 0; y < CX18_MAX_STREAMS; y++) {
+ if (cx18_cards[x] == NULL)
+ continue;
+ s = &cx18_cards[x]->streams[y];
+ if (s->v4l2dev && s->v4l2dev->minor == minor) {
+ cx = cx18_cards[x];
+ break;
+ }
+ }
+ }
+ spin_unlock(&cx18_cards_lock);
+
+ if (cx == NULL) {
+ /* Couldn't find a device registered
+ on that minor, shouldn't happen! */
+ printk(KERN_WARNING "No cx18 device found on minor %d\n",
+ minor);
+ return -ENXIO;
+ }
+
+ mutex_lock(&cx->serialize_lock);
+ if (cx18_init_on_first_open(cx)) {
+ CX18_ERR("Failed to initialize on minor %d\n", minor);
+ mutex_unlock(&cx->serialize_lock);
+ return -ENXIO;
+ }
+ res = cx18_serialized_open(s, filp);
+ mutex_unlock(&cx->serialize_lock);
+ return res;
+}
+
+void cx18_mute(struct cx18 *cx)
+{
+ if (atomic_read(&cx->ana_capturing))
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+ cx18_find_handle(cx), 1);
+ CX18_DEBUG_INFO("Mute\n");
+}
+
+void cx18_unmute(struct cx18 *cx)
+{
+ if (atomic_read(&cx->ana_capturing)) {
+ cx18_msleep_timeout(100, 0);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
+ cx18_find_handle(cx), 12);
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+ cx18_find_handle(cx), 0);
+ }
+ CX18_DEBUG_INFO("Unmute\n");
+}
diff --git a/linux/drivers/media/video/cx18/cx18-fileops.h b/linux/drivers/media/video/cx18/cx18-fileops.h
new file mode 100644
index 000000000..46da0282f
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-fileops.h
@@ -0,0 +1,36 @@
+/*
+ * cx18 file operation functions
+ *
+ * Derived from ivtv-fileops.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+/* Testing/Debugging */
+int cx18_v4l2_open(struct inode *inode, struct file *filp);
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *pos);
+ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+ loff_t *pos);
+int cx18_v4l2_close(struct inode *inode, struct file *filp);
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
+int cx18_start_capture(struct cx18_open_id *id);
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
+void cx18_mute(struct cx18 *cx);
+void cx18_unmute(struct cx18 *cx);
+
diff --git a/linux/drivers/media/video/cx18/cx18-firmware.c b/linux/drivers/media/video/cx18/cx18-firmware.c
new file mode 100644
index 000000000..5e37427ec
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-firmware.c
@@ -0,0 +1,380 @@
+/*
+ * cx18 firmware functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-firmware.h"
+#include "cx18-cards.h"
+#include <linux/firmware.h>
+
+#define CX18_PROC_SOFT_RESET 0xc70010
+#define CX18_DDR_SOFT_RESET 0xc70014
+#define CX18_CLOCK_SELECT1 0xc71000
+#define CX18_CLOCK_SELECT2 0xc71004
+#define CX18_HALF_CLOCK_SELECT1 0xc71008
+#define CX18_HALF_CLOCK_SELECT2 0xc7100C
+#define CX18_CLOCK_POLARITY1 0xc71010
+#define CX18_CLOCK_POLARITY2 0xc71014
+#define CX18_ADD_DELAY_ENABLE1 0xc71018
+#define CX18_ADD_DELAY_ENABLE2 0xc7101C
+#define CX18_CLOCK_ENABLE1 0xc71020
+#define CX18_CLOCK_ENABLE2 0xc71024
+
+#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
+
+#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
+
+#define CX18_FAST_CLOCK_PLL_INT 0xc78000
+#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
+#define CX18_FAST_CLOCK_PLL_POST 0xc78008
+#define CX18_FAST_CLOCK_PLL_PRESCALE 0xc7800C
+#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
+
+#define CX18_SLOW_CLOCK_PLL_INT 0xc78014
+#define CX18_SLOW_CLOCK_PLL_FRAC 0xc78018
+#define CX18_SLOW_CLOCK_PLL_POST 0xc7801C
+#define CX18_MPEG_CLOCK_PLL_INT 0xc78040
+#define CX18_MPEG_CLOCK_PLL_FRAC 0xc78044
+#define CX18_MPEG_CLOCK_PLL_POST 0xc78048
+#define CX18_PLL_POWER_DOWN 0xc78088
+#define CX18_SW1_INT_STATUS 0xc73104
+#define CX18_SW1_INT_ENABLE_PCI 0xc7311C
+#define CX18_SW2_INT_SET 0xc73140
+#define CX18_SW2_INT_STATUS 0xc73144
+#define CX18_ADEC_CONTROL 0xc78120
+
+#define CX18_DDR_REQUEST_ENABLE 0xc80000
+#define CX18_DDR_CHIP_CONFIG 0xc80004
+#define CX18_DDR_REFRESH 0xc80008
+#define CX18_DDR_TIMING1 0xc8000C
+#define CX18_DDR_TIMING2 0xc80010
+#define CX18_DDR_POWER_REG 0xc8001C
+
+#define CX18_DDR_TUNE_LANE 0xc80048
+#define CX18_DDR_INITIAL_EMRS 0xc80054
+#define CX18_DDR_MB_PER_ROW_7 0xc8009C
+#define CX18_DDR_BASE_63_ADDR 0xc804FC
+
+#define CX18_WMB_CLIENT02 0xc90108
+#define CX18_WMB_CLIENT05 0xc90114
+#define CX18_WMB_CLIENT06 0xc90118
+#define CX18_WMB_CLIENT07 0xc9011C
+#define CX18_WMB_CLIENT08 0xc90120
+#define CX18_WMB_CLIENT09 0xc90124
+#define CX18_WMB_CLIENT10 0xc90128
+#define CX18_WMB_CLIENT11 0xc9012C
+#define CX18_WMB_CLIENT12 0xc90130
+#define CX18_WMB_CLIENT13 0xc90134
+#define CX18_WMB_CLIENT14 0xc90138
+
+#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
+
+/* Encoder/decoder firmware sizes */
+#define CX18_FW_CPU_SIZE (174716)
+#define CX18_FW_APU_SIZE (141200)
+
+#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
+#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
+
+struct cx18_apu_rom_seghdr {
+ u32 sync1;
+ u32 sync2;
+ u32 addr;
+ u32 size;
+};
+
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size)
+{
+ const struct firmware *fw = NULL;
+ int retries = 3;
+ int i, j;
+ u32 __iomem *dst = (u32 __iomem *)mem;
+ const u32 *src;
+
+retry:
+ if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
+ CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
+ fn, size);
+ CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+ return -ENOMEM;
+ }
+
+ src = (const u32 *)fw->data;
+
+ if (fw->size != size) {
+ /* Due to race conditions in firmware loading (esp. with
+ udev <0.95) the wrong file was sometimes loaded. So we check
+ filesizes to see if at least the right-sized file was
+ loaded. If not, then we retry. */
+ CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
+ fn, size, fw->size);
+ release_firmware(fw);
+ retries--;
+ goto retry;
+ }
+ for (i = 0; i < fw->size; i += 4096) {
+ setup_page(i);
+ for (j = i; j < fw->size && j < i + 4096; j += 4) {
+ /* no need for endianness conversion on the ppc */
+ __raw_writel(*src, dst);
+ if (__raw_readl(dst) != *src) {
+ CX18_ERR("Mismatch at offset %x\n", i);
+ release_firmware(fw);
+ return -EIO;
+ }
+ dst++;
+ src++;
+ }
+ }
+ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+ CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+ release_firmware(fw);
+ return size;
+}
+
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size)
+{
+ const struct firmware *fw = NULL;
+ int retries = 3;
+ int i, j;
+ const u32 *src;
+ struct cx18_apu_rom_seghdr seghdr;
+ const u8 *vers;
+ u32 offset = 0;
+ u32 apu_version = 0;
+ int sz;
+
+retry:
+ if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
+ CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
+ fn, size);
+ CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
+ return -ENOMEM;
+ }
+
+ src = (const u32 *)fw->data;
+ vers = fw->data + sizeof(seghdr);
+ sz = fw->size;
+
+ 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. */
+ CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
+ fn, size, fw->size);
+ release_firmware(fw);
+ retries--;
+ goto retry;
+ }
+ apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
+ while (offset + sizeof(seghdr) < size) {
+ /* TODO: byteswapping */
+ memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
+ offset += sizeof(seghdr);
+ if (seghdr.sync1 != APU_ROM_SYNC1 ||
+ seghdr.sync2 != APU_ROM_SYNC2) {
+ offset += seghdr.size;
+ continue;
+ }
+ CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
+ seghdr.addr + seghdr.size - 1);
+ if (offset + seghdr.size > sz)
+ break;
+ for (i = 0; i < seghdr.size; i += 4096) {
+ setup_page(offset + i);
+ for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
+ /* no need for endianness conversion on the ppc */
+ __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
+ if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
+ CX18_ERR("Mismatch at offset %x\n", offset + j);
+ release_firmware(fw);
+ return -EIO;
+ }
+ }
+ }
+ offset += seghdr.size;
+ }
+ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+ CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
+ fn, apu_version, fw->size);
+ release_firmware(fw);
+ /* Clear bit0 for APU to start from 0 */
+ write_reg(read_reg(0xc72030) & ~1, 0xc72030);
+ return size;
+}
+
+void cx18_halt_firmware(struct cx18 *cx)
+{
+ CX18_DEBUG_INFO("Preparing for firmware halt.\n");
+ write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+ write_reg(0x00020002, CX18_ADEC_CONTROL);
+}
+
+void cx18_init_power(struct cx18 *cx, int lowpwr)
+{
+ /* power-down Spare and AOM PLLs */
+ /* power-up fast, slow and mpeg PLLs */
+ write_reg(0x00000008, CX18_PLL_POWER_DOWN);
+
+ /* ADEC out of sleep */
+ write_reg(0x00020000, CX18_ADEC_CONTROL);
+
+ /* The fast clock is at 200/245 MHz */
+ write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+ write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
+
+ write_reg(2, CX18_FAST_CLOCK_PLL_POST);
+ write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
+ write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+
+ /* set slow clock to 125/120 MHz */
+ write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
+ write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
+ write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
+
+ /* mpeg clock pll 54MHz */
+ write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
+ write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
+ write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
+
+ /* Defaults */
+ /* APU = SC or SC/2 = 125/62.5 */
+ /* EPU = SC = 125 */
+ /* DDR = FC = 180 */
+ /* ENC = SC = 125 */
+ /* AI1 = SC = 125 */
+ /* VIM2 = disabled */
+ /* PCI = FC/2 = 90 */
+ /* AI2 = disabled */
+ /* DEMUX = disabled */
+ /* AO = SC/2 = 62.5 */
+ /* SER = 54MHz */
+ /* VFC = disabled */
+ /* USB = disabled */
+
+ write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
+ write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
+
+ write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
+ write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
+
+ write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
+ write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
+}
+
+void cx18_init_memory(struct cx18 *cx)
+{
+ cx18_msleep_timeout(10, 0);
+ write_reg(0x10000, CX18_DDR_SOFT_RESET);
+ cx18_msleep_timeout(10, 0);
+
+ write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+
+ cx18_msleep_timeout(10, 0);
+
+ write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
+ write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
+ write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
+
+ cx18_msleep_timeout(10, 0);
+
+ /* Initialize DQS pad time */
+ write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+ write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+
+ cx18_msleep_timeout(10, 0);
+
+ write_reg(0x20000, CX18_DDR_SOFT_RESET);
+ cx18_msleep_timeout(10, 0);
+
+ /* use power-down mode when idle */
+ write_reg(0x00000010, CX18_DDR_POWER_REG);
+
+ write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
+
+ write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
+ write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
+
+ write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */
+ write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */
+ write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */
+ write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */
+ write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */
+ write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */
+ write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */
+ write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */
+ write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */
+ write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */
+}
+
+int cx18_firmware_init(struct cx18 *cx)
+{
+ /* Allow chip to control CLKRUN */
+ write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
+
+ write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+
+ cx18_msleep_timeout(1, 0);
+
+ sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+ sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+ /* Only if the processor is not running */
+ if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
+ int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
+ cx->enc_mem, cx, CX18_FW_APU_SIZE);
+#if 0
+ /* this might be needed after all, check later */
+ write_enc(0xE51FF004, 0);
+ write_enc(0xa00000, 4); /* todo: not hardcoded */
+ write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */
+ cx18_msleep_timeout(500, 0);
+#endif
+
+ sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
+ cx->enc_mem, cx, CX18_FW_CPU_SIZE);
+
+ if (sz > 0) {
+ int retries = 0;
+
+ /* start the CPU */
+ write_reg(0x00080000, CX18_PROC_SOFT_RESET);
+ while (retries++ < 50) { /* Loop for max 500mS */
+ if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
+ break;
+ cx18_msleep_timeout(10, 0);
+ }
+ cx18_msleep_timeout(200, 0);
+ if (retries == 51) {
+ CX18_ERR("Could not start the CPU\n");
+ return -EIO;
+ }
+ }
+ if (sz <= 0)
+ return -EIO;
+ }
+ /* initialize GPIO */
+ write_reg(0x14001400, 0xC78110);
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-firmware.h b/linux/drivers/media/video/cx18/cx18-firmware.h
new file mode 100644
index 000000000..38d4c05e8
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-firmware.h
@@ -0,0 +1,25 @@
+/*
+ * cx18 firmware functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+int cx18_firmware_init(struct cx18 *cx);
+void cx18_halt_firmware(struct cx18 *cx);
+void cx18_init_memory(struct cx18 *cx);
+void cx18_init_power(struct cx18 *cx, int lowpwr);
diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c
new file mode 100644
index 000000000..ceb63653c
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-gpio.c
@@ -0,0 +1,100 @@
+/*
+ * cx18 gpio functions
+ *
+ * Derived from ivtv-gpio.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "tuner-xc2028.h"
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define CX18_REG_GPIO_IN 0xc72010
+#define CX18_REG_GPIO_OUT1 0xc78100
+#define CX18_REG_GPIO_DIR1 0xc78108
+#define CX18_REG_GPIO_OUT2 0xc78104
+#define CX18_REG_GPIO_DIR2 0xc7810c
+
+/*
+ * HVR-1600 GPIO pins, courtesy of Hauppauge:
+ *
+ * gpio0: zilog ir process reset pin
+ * gpio1: zilog programming pin (you should never use this)
+ * gpio12: cx24227 reset pin
+ * gpio13: cs5345 reset pin
+*/
+
+static void gpio_write(struct cx18 *cx)
+{
+ u32 dir = cx->gpio_dir;
+ u32 val = cx->gpio_val;
+
+ write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
+ write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
+ CX18_REG_GPIO_OUT1);
+ write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
+ write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
+ CX18_REG_GPIO_OUT2);
+}
+
+void cx18_gpio_init(struct cx18 *cx)
+{
+ cx->gpio_dir = cx->card->gpio_init.direction;
+ cx->gpio_val = cx->card->gpio_init.initial_value;
+
+ if (cx->card->tuners[0].tuner == TUNER_XC2028) {
+ cx->gpio_dir |= 1 << cx->card->xceive_pin;
+ cx->gpio_val |= 1 << cx->card->xceive_pin;
+ }
+
+ if (cx->gpio_dir == 0)
+ return;
+
+ CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
+ read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
+ read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
+
+ gpio_write(cx);
+}
+
+/* Xceive tuner reset function */
+int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
+{
+ struct i2c_algo_bit_data *algo = dev;
+ struct cx18_i2c_algo_callback_data *cb_data = algo->data;
+ struct cx18 *cx = cb_data->cx;
+
+ if (cmd != XC2028_TUNER_RESET)
+ return 0;
+ CX18_DEBUG_INFO("Resetting tuner\n");
+
+ cx->gpio_val &= ~(1 << cx->card->xceive_pin);
+
+ gpio_write(cx);
+ schedule_timeout_interruptible(msecs_to_jiffies(1));
+
+ cx->gpio_val |= 1 << cx->card->xceive_pin;
+ gpio_write(cx);
+ schedule_timeout_interruptible(msecs_to_jiffies(1));
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-gpio.h b/linux/drivers/media/video/cx18/cx18-gpio.h
new file mode 100644
index 000000000..41bac8856
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-gpio.h
@@ -0,0 +1,24 @@
+/*
+ * cx18 gpio functions
+ *
+ * Derived from ivtv-gpio.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+void cx18_gpio_init(struct cx18 *cx);
+int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c
new file mode 100644
index 000000000..30ec26a61
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-i2c.c
@@ -0,0 +1,465 @@
+/*
+ * cx18 I2C functions
+ *
+ * Derived from ivtv-i2c.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "cx18-av-core.h"
+#include "cx18-i2c.h"
+
+#include <media/ir-kbd-i2c.h>
+
+#define CX18_REG_I2C_1_WR 0xf15000
+#define CX18_REG_I2C_1_RD 0xf15008
+#define CX18_REG_I2C_2_WR 0xf25100
+#define CX18_REG_I2C_2_RD 0xf25108
+
+#define SETSCL_BIT 0x0001
+#define SETSDL_BIT 0x0002
+#define GETSCL_BIT 0x0004
+#define GETSDL_BIT 0x0008
+
+#ifndef I2C_ADAP_CLASS_TV_ANALOG
+#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
+#endif
+
+#define CX18_CS5345_I2C_ADDR 0x4c
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_driverids[] = {
+ I2C_DRIVERID_TUNER,
+ I2C_DRIVERID_TVEEPROM,
+ I2C_DRIVERID_CS5345,
+ 0, /* CX18_HW_GPIO dummy driver ID */
+ 0 /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_addrs[] = {
+ 0,
+ 0,
+ CX18_CS5345_I2C_ADDR,
+ 0, /* CX18_HW_GPIO dummy driver ID */
+ 0, /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+/* This might well become a card-specific array */
+static const u8 hw_bus[] = {
+ 0,
+ 0,
+ 0,
+ 0, /* CX18_HW_GPIO dummy driver ID */
+ 0, /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const char * const hw_devicenames[] = {
+ "tuner",
+ "tveeprom",
+ "cs5345",
+ "gpio",
+ "cx23418",
+};
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+ struct i2c_board_info info;
+ struct i2c_client *c;
+ u8 id, bus;
+ int i;
+
+ CX18_DEBUG_I2C("i2c client register\n");
+ if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0)
+ return -1;
+ id = hw_driverids[idx];
+ bus = hw_bus[idx];
+ memset(&info, 0, sizeof(info));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+ strlcpy(info.driver_name, hw_devicenames[idx],
+ sizeof(info.driver_name));
+#else
+ strlcpy(info.type, hw_devicenames[idx], sizeof(info.type));
+#endif
+ info.addr = hw_addrs[idx];
+ for (i = 0; i < I2C_CLIENTS_MAX; i++)
+ if (cx->i2c_clients[i] == NULL)
+ break;
+
+ if (i == I2C_CLIENTS_MAX) {
+ CX18_ERR("insufficient room for new I2C client!\n");
+ return -ENOMEM;
+ }
+
+ if (id != I2C_DRIVERID_TUNER) {
+ c = i2c_new_device(&cx->i2c_adap[bus], &info);
+ if (c->driver == NULL)
+ i2c_unregister_device(c);
+ else
+ cx->i2c_clients[i] = c;
+ return cx->i2c_clients[i] ? 0 : -ENODEV;
+ }
+
+ /* special tuner handling */
+ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio);
+ if (c && c->driver == NULL)
+ i2c_unregister_device(c);
+ else if (c)
+ cx->i2c_clients[i++] = c;
+ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod);
+ if (c && c->driver == NULL)
+ i2c_unregister_device(c);
+ else if (c)
+ cx->i2c_clients[i++] = c;
+ c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv);
+ if (c && c->driver == NULL)
+ i2c_unregister_device(c);
+ else if (c)
+ cx->i2c_clients[i++] = c;
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+ struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
+ int i;
+
+ CX18_DEBUG_I2C("i2c client attach\n");
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (cx->i2c_clients[i] == NULL) {
+ cx->i2c_clients[i] = client;
+ break;
+ }
+ }
+ if (i == I2C_CLIENTS_MAX)
+ CX18_ERR("Insufficient room for new I2C client\n");
+#endif
+ return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+ int i;
+ struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
+
+ CX18_DEBUG_I2C("i2c client detach\n");
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (cx->i2c_clients[i] == client) {
+ cx->i2c_clients[i] = NULL;
+ break;
+ }
+ }
+ CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n",
+ client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
+
+ return 0;
+}
+
+static void cx18_setscl(void *data, int state)
+{
+ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+ u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+ u32 r = read_reg(addr);
+
+ if (state)
+ write_reg_sync(r | SETSCL_BIT, addr);
+ else
+ write_reg_sync(r & ~SETSCL_BIT, addr);
+}
+
+static void cx18_setsda(void *data, int state)
+{
+ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+ u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+ u32 r = read_reg(addr);
+
+ if (state)
+ write_reg_sync(r | SETSDL_BIT, addr);
+ else
+ write_reg_sync(r & ~SETSDL_BIT, addr);
+}
+
+static int cx18_getscl(void *data)
+{
+ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+ u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+ return read_reg(addr) & GETSCL_BIT;
+}
+
+static int cx18_getsda(void *data)
+{
+ struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+ int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+ u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+ return read_reg(addr) & GETSDL_BIT;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter cx18_i2c_adap_template = {
+ .name = "cx18 i2c driver",
+ .id = I2C_HW_B_CX2341X,
+ .algo = NULL, /* set by i2c-algo-bit */
+ .algo_data = NULL, /* filled from template */
+ .client_register = attach_inform,
+ .client_unregister = detach_inform,
+ .owner = THIS_MODULE,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+#ifdef I2C_ADAP_CLASS_TV_ANALOG
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
+#endif
+#endif
+};
+
+#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
+#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
+
+static struct i2c_algo_bit_data cx18_i2c_algo_template = {
+ .setsda = cx18_setsda,
+ .setscl = cx18_setscl,
+ .getsda = cx18_getsda,
+ .getscl = cx18_getscl,
+ .udelay = CX18_SCL_PERIOD/2, /* 1/2 clock period in usec*/
+ .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
+};
+
+static struct i2c_client cx18_i2c_client_template = {
+ .name = "cx18 internal",
+};
+
+int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
+{
+ struct i2c_client *client;
+ int retval;
+ int i;
+
+ CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ client = cx->i2c_clients[i];
+ if (client == NULL || client->driver == NULL ||
+ client->driver->command == NULL)
+ continue;
+ if (addr == client->addr) {
+ retval = client->driver->command(client, cmd, arg);
+ return retval;
+ }
+ }
+ if (cmd != VIDIOC_G_CHIP_IDENT)
+ CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
+ addr, cmd);
+ return -ENODEV;
+}
+
+/* Find the i2c device based on the driver ID and return
+ its i2c address or -ENODEV if no matching device was found. */
+static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
+{
+ struct i2c_client *client;
+ int retval = -ENODEV;
+ int i;
+
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ client = cx->i2c_clients[i];
+ if (client == NULL || client->driver == NULL)
+ continue;
+ if (id == client->driver->id) {
+ retval = client->addr;
+ break;
+ }
+ }
+ return retval;
+}
+
+/* Find the i2c device name matching the DRIVERID */
+static const char *cx18_i2c_id_name(u32 id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+ if (hw_driverids[i] == id)
+ return hw_devicenames[i];
+ return "unknown device";
+}
+
+/* Find the i2c device name matching the CX18_HW_ flag */
+static const char *cx18_i2c_hw_name(u32 hw)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+ if (1 << i == hw)
+ return hw_devicenames[i];
+ return "unknown device";
+}
+
+/* Find the i2c device matching the CX18_HW_ flag and return
+ its i2c address or -ENODEV if no matching device was found. */
+int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+ if (1 << i == hw)
+ return cx18_i2c_id_addr(cx, hw_driverids[i]);
+ return -ENODEV;
+}
+
+/* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing.
+ If hw == CX18_HW_GPIO then call the gpio handler. */
+int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
+{
+ int addr;
+
+ if (hw == CX18_HW_GPIO || hw == 0)
+ return 0;
+ if (hw == CX18_HW_CX23418)
+ return cx18_av_cmd(cx, cmd, arg);
+
+ addr = cx18_i2c_hw_addr(cx, hw);
+ if (addr < 0) {
+ CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n",
+ hw, cx18_i2c_hw_name(hw), cmd);
+ return addr;
+ }
+ return cx18_call_i2c_client(cx, addr, cmd, arg);
+}
+
+/* Calls i2c device based on I2C driver ID. */
+int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
+{
+ int addr;
+
+ addr = cx18_i2c_id_addr(cx, id);
+ if (addr < 0) {
+ if (cmd != VIDIOC_G_CHIP_IDENT)
+ CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
+ id, cx18_i2c_id_name(id), cmd);
+ return addr;
+ }
+ return cx18_call_i2c_client(cx, addr, cmd, arg);
+}
+
+/* broadcast cmd for all I2C clients and for the gpio subsystem */
+void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) {
+ CX18_ERR("adapter is not set\n");
+ return;
+ }
+ cx18_av_cmd(cx, cmd, arg);
+ i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
+ i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
+}
+
+/* init + register i2c algo-bit adapter */
+int init_cx18_i2c(struct cx18 *cx)
+{
+ int i;
+ CX18_DEBUG_I2C("i2c init\n");
+
+ for (i = 0; i < 2; i++) {
+ memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
+ sizeof(struct i2c_adapter));
+ memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
+ sizeof(struct i2c_algo_bit_data));
+ cx->i2c_algo_cb_data[i].cx = cx;
+ cx->i2c_algo_cb_data[i].bus_index = i;
+ cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
+ cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
+
+ sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
+ " #%d-%d", cx->num, i);
+ i2c_set_adapdata(&cx->i2c_adap[i], cx);
+
+ memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
+ sizeof(struct i2c_client));
+ sprintf(cx->i2c_client[i].name +
+ strlen(cx->i2c_client[i].name), "%d", i);
+ cx->i2c_client[i].adapter = &cx->i2c_adap[i];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ cx->i2c_adap[i].dev.parent = &cx->dev->dev;
+#endif
+ }
+
+ if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
+ /* Reset/Unreset I2C hardware block */
+ write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
+ write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
+ }
+ /* courtesy of Steven Toth <stoth@hauppauge.com> */
+ write_reg_sync(0x00c00000, 0xc7001c);
+ mdelay(10);
+ write_reg_sync(0x00c000c0, 0xc7001c);
+ mdelay(10);
+ write_reg_sync(0x00c00000, 0xc7001c);
+
+ write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
+ write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
+
+ /* Hw I2C1 Clock Freq ~100kHz */
+ write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+ cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
+ cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
+
+ /* Hw I2C2 Clock Freq ~100kHz */
+ write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+ cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
+ cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
+
+ return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
+ i2c_bit_add_bus(&cx->i2c_adap[1]);
+}
+
+void exit_cx18_i2c(struct cx18 *cx)
+{
+ int i;
+ CX18_DEBUG_I2C("i2c exit\n");
+ write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
+ write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
+
+ for (i = 0; i < 2; i++) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ i2c_del_adapter(&cx->i2c_adap[i]);
+#else
+ i2c_bit_del_bus(&cx->i2c_adap[i]);
+#endif
+ }
+}
+
+/*
+ Hauppauge HVR1600 should have:
+ 32 cx24227
+ 98 unknown
+ a0 eeprom
+ c2 tuner
+ e? zilog ir
+ */
diff --git a/linux/drivers/media/video/cx18/cx18-i2c.h b/linux/drivers/media/video/cx18/cx18-i2c.h
new file mode 100644
index 000000000..113c3f9a2
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-i2c.h
@@ -0,0 +1,33 @@
+/*
+ * cx18 I2C functions
+ *
+ * Derived from ivtv-i2c.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
+int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
+int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg);
+int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
+void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
+int cx18_i2c_register(struct cx18 *cx, unsigned idx);
+
+/* init + register i2c algo-bit adapter */
+int init_cx18_i2c(struct cx18 *cx);
+void exit_cx18_i2c(struct cx18 *cx);
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c
new file mode 100644
index 000000000..f008604f9
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-ioctl.c
@@ -0,0 +1,878 @@
+/*
+ * cx18 ioctl system call
+ *
+ * Derived from ivtv-ioctl.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-fileops.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-video.h"
+#include "cx18-streams.h"
+#include "cx18-ioctl.h"
+#include "cx18-gpio.h"
+#include "cx18-controls.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/i2c-id.h>
+
+u16 cx18_service2vbi(int type)
+{
+ switch (type) {
+ case V4L2_SLICED_TELETEXT_B:
+ return CX18_SLICED_TYPE_TELETEXT_B;
+ case V4L2_SLICED_CAPTION_525:
+ return CX18_SLICED_TYPE_CAPTION_525;
+ case V4L2_SLICED_WSS_625:
+ return CX18_SLICED_TYPE_WSS_625;
+ case V4L2_SLICED_VPS:
+ return CX18_SLICED_TYPE_VPS;
+ default:
+ return 0;
+ }
+}
+
+static int valid_service_line(int field, int line, int is_pal)
+{
+ return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
+ (!is_pal && line >= 10 && line < 22);
+}
+
+static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
+{
+ u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
+ int i;
+
+ set = set & valid_set;
+ if (set == 0 || !valid_service_line(field, line, is_pal))
+ return 0;
+ if (!is_pal) {
+ if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+ return V4L2_SLICED_CAPTION_525;
+ } else {
+ if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+ return V4L2_SLICED_VPS;
+ if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+ return V4L2_SLICED_WSS_625;
+ if (line == 23)
+ return 0;
+ }
+ for (i = 0; i < 32; i++) {
+ if ((1 << i) & set)
+ return 1 << i;
+ }
+ return 0;
+}
+
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+ u16 set = fmt->service_set;
+ int f, l;
+
+ fmt->service_set = 0;
+ for (f = 0; f < 2; f++) {
+ for (l = 0; l < 24; l++)
+ fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
+ }
+}
+
+static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+ int f, l;
+ u16 set = 0;
+
+ for (f = 0; f < 2; f++) {
+ for (l = 0; l < 24; l++) {
+ fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
+ set |= fmt->service_lines[f][l];
+ }
+ }
+ return set != 0;
+}
+
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
+ int f, l;
+ u16 set = 0;
+
+ for (f = 0; f < 2; f++) {
+ for (l = 0; l < 24; l++)
+ set |= fmt->service_lines[f][l];
+ }
+ return set;
+}
+
+static const struct {
+ v4l2_std_id std;
+ char *name;
+} enum_stds[] = {
+ { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" },
+ { V4L2_STD_PAL_DK, "PAL-DK" },
+ { V4L2_STD_PAL_I, "PAL-I" },
+ { V4L2_STD_PAL_M, "PAL-M" },
+ { V4L2_STD_PAL_N, "PAL-N" },
+ { V4L2_STD_PAL_Nc, "PAL-Nc" },
+ { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" },
+ { V4L2_STD_SECAM_DK, "SECAM-DK" },
+ { V4L2_STD_SECAM_L, "SECAM-L" },
+ { V4L2_STD_SECAM_LC, "SECAM-L'" },
+ { V4L2_STD_NTSC_M, "NTSC-M" },
+ { V4L2_STD_NTSC_M_JP, "NTSC-J" },
+ { V4L2_STD_NTSC_M_KR, "NTSC-K" },
+};
+
+static const struct v4l2_standard cx18_std_60hz = {
+ .frameperiod = {.numerator = 1001, .denominator = 30000},
+ .framelines = 525,
+};
+
+static const struct v4l2_standard cx18_std_50hz = {
+ .frameperiod = { .numerator = 1, .denominator = 25 },
+ .framelines = 625,
+};
+
+static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+ struct v4l2_register *regs = arg;
+ unsigned long flags;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+ return -EINVAL;
+
+ spin_lock_irqsave(&cx18_cards_lock, flags);
+ if (cmd == VIDIOC_DBG_G_REGISTER)
+ regs->val = read_enc(regs->reg);
+ else
+ write_enc(regs->val, regs->reg);
+ spin_unlock_irqrestore(&cx18_cards_lock, flags);
+ return 0;
+}
+
+static int cx18_get_fmt(struct cx18 *cx, int streamtype, struct v4l2_format *fmt)
+{
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ fmt->fmt.pix.width = cx->params.width;
+ fmt->fmt.pix.height = cx->params.height;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ if (streamtype == CX18_ENC_STREAM_TYPE_YUV) {
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
+ /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
+ fmt->fmt.pix.sizeimage =
+ fmt->fmt.pix.height * fmt->fmt.pix.width +
+ fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
+ } else {
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ fmt->fmt.pix.sizeimage = 128 * 1024;
+ }
+ break;
+
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ fmt->fmt.vbi.sampling_rate = 27000000;
+ fmt->fmt.vbi.offset = 248;
+ fmt->fmt.vbi.samples_per_line = cx->vbi.raw_decoder_line_size - 4;
+ fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ fmt->fmt.vbi.start[0] = cx->vbi.start[0];
+ fmt->fmt.vbi.start[1] = cx->vbi.start[1];
+ fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = cx->vbi.count;
+ break;
+
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ {
+ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+ vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+ memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
+ memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
+
+ cx18_av_cmd(cx, VIDIOC_G_FMT, fmt);
+ vbifmt->service_set = cx18_get_service_set(vbifmt);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
+ struct v4l2_format *fmt, int set_fmt)
+{
+ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+ u16 set;
+
+ /* set window size */
+ if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ int w = fmt->fmt.pix.width;
+ int h = fmt->fmt.pix.height;
+
+ if (w > 720)
+ w = 720;
+ else if (w < 1)
+ w = 1;
+ if (h > (cx->is_50hz ? 576 : 480))
+ h = (cx->is_50hz ? 576 : 480);
+ else if (h < 2)
+ h = 2;
+ cx18_get_fmt(cx, streamtype, fmt);
+ fmt->fmt.pix.width = w;
+ fmt->fmt.pix.height = h;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
+ if (cx->params.width != 720 || cx->params.height != (cx->is_50hz ? 576 : 480))
+ cx->params.video_temporal_filter = 0;
+ else
+ cx->params.video_temporal_filter = 8;
+#endif
+
+ if (!set_fmt || (cx->params.width == w && cx->params.height == h))
+ return 0;
+ if (atomic_read(&cx->ana_capturing) > 0)
+ return -EBUSY;
+
+ cx->params.width = w;
+ cx->params.height = h;
+ if (w != 720 || h != (cx->is_50hz ? 576 : 480))
+ cx->params.video_temporal_filter = 0;
+ else
+ cx->params.video_temporal_filter = 8;
+ cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+ return cx18_get_fmt(cx, streamtype, fmt);
+ }
+
+ /* set raw VBI format */
+ if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI &&
+ cx->vbi.sliced_in->service_set &&
+ atomic_read(&cx->ana_capturing) > 0)
+ return -EBUSY;
+ if (set_fmt) {
+ cx->vbi.sliced_in->service_set = 0;
+ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
+ }
+ return cx18_get_fmt(cx, streamtype, fmt);
+ }
+
+ /* any else but sliced VBI capture is an error */
+ if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+ return -EINVAL;
+
+ /* TODO: implement sliced VBI, for now silently return 0 */
+ return 0;
+
+ /* set sliced VBI capture format */
+ vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+ memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
+
+ if (vbifmt->service_set)
+ cx18_expand_service_set(vbifmt, cx->is_50hz);
+ set = check_service_set(vbifmt, cx->is_50hz);
+ vbifmt->service_set = cx18_get_service_set(vbifmt);
+
+ if (!set_fmt)
+ return 0;
+ if (set == 0)
+ return -EINVAL;
+ if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
+ return -EBUSY;
+ cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+ memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
+ return 0;
+}
+
+static int cx18_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
+{
+ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+ struct cx18 *cx = id->cx;
+ struct v4l2_register *reg = arg;
+
+ switch (cmd) {
+ /* ioctls to allow direct access to the encoder registers for testing */
+ case VIDIOC_DBG_G_REGISTER:
+ if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return cx18_cxc(cx, cmd, arg);
+ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+
+ case VIDIOC_DBG_S_REGISTER:
+ if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ return cx18_cxc(cx, cmd, arg);
+ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+
+ case VIDIOC_G_CHIP_IDENT: {
+ struct v4l2_chip_ident *chip = arg;
+
+ chip->ident = V4L2_IDENT_NONE;
+ chip->revision = 0;
+ if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
+ if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
+ struct v4l2_chip_ident *chip = arg;
+
+ chip->ident = V4L2_IDENT_CX23418;
+ }
+ return 0;
+ }
+ if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+ return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+ if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
+ return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+ return -EINVAL;
+ }
+
+ case VIDIOC_INT_S_AUDIO_ROUTING: {
+ struct v4l2_routing *route = arg;
+
+ cx18_audio_set_route(cx, route);
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg)
+{
+ struct cx18_open_id *id = NULL;
+
+ if (filp)
+ id = (struct cx18_open_id *)filp->private_data;
+
+ switch (cmd) {
+ case VIDIOC_G_PRIORITY:
+ {
+ enum v4l2_priority *p = arg;
+
+ *p = v4l2_prio_max(&cx->prio);
+ break;
+ }
+
+ case VIDIOC_S_PRIORITY:
+ {
+ enum v4l2_priority *prio = arg;
+
+ return v4l2_prio_change(&cx->prio, &id->prio, *prio);
+ }
+
+ case VIDIOC_QUERYCAP:{
+ struct v4l2_capability *vcap = arg;
+
+ memset(vcap, 0, sizeof(*vcap));
+ strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
+ strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
+ strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
+ vcap->version = CX18_DRIVER_VERSION; /* version */
+ vcap->capabilities = cx->v4l2_cap; /* capabilities */
+
+ /* reserved.. must set to 0! */
+ vcap->reserved[0] = vcap->reserved[1] =
+ vcap->reserved[2] = vcap->reserved[3] = 0;
+ break;
+ }
+
+ case VIDIOC_ENUMAUDIO:{
+ struct v4l2_audio *vin = arg;
+
+ return cx18_get_audio_input(cx, vin->index, vin);
+ }
+
+ case VIDIOC_G_AUDIO:{
+ struct v4l2_audio *vin = arg;
+
+ vin->index = cx->audio_input;
+ return cx18_get_audio_input(cx, vin->index, vin);
+ }
+
+ case VIDIOC_S_AUDIO:{
+ struct v4l2_audio *vout = arg;
+
+ if (vout->index >= cx->nof_audio_inputs)
+ return -EINVAL;
+ cx->audio_input = vout->index;
+ cx18_audio_set_io(cx);
+ break;
+ }
+
+ case VIDIOC_ENUMINPUT:{
+ struct v4l2_input *vin = arg;
+
+ /* set it to defaults from our table */
+ return cx18_get_input(cx, vin->index, vin);
+ }
+
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *fmt = arg;
+
+ return cx18_try_or_set_fmt(cx, id->type, fmt, cmd == VIDIOC_S_FMT);
+ }
+
+ case VIDIOC_G_FMT: {
+ struct v4l2_format *fmt = arg;
+ int type = fmt->type;
+
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->type = type;
+ return cx18_get_fmt(cx, id->type, fmt);
+ }
+
+ case VIDIOC_CROPCAP: {
+ struct v4l2_cropcap *cropcap = arg;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = cx->is_50hz ? 576 : 480;
+ cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
+ cropcap->defrect = cropcap->bounds;
+ return 0;
+ }
+
+ case VIDIOC_S_CROP: {
+ struct v4l2_crop *crop = arg;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ return cx18_av_cmd(cx, VIDIOC_S_CROP, arg);
+ }
+
+ case VIDIOC_G_CROP: {
+ struct v4l2_crop *crop = arg;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ return cx18_av_cmd(cx, VIDIOC_G_CROP, arg);
+ }
+
+ case VIDIOC_ENUM_FMT: {
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
+ { 0, 0, 0, 0 }
+ },
+ { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+ "MPEG", V4L2_PIX_FMT_MPEG,
+ { 0, 0, 0, 0 }
+ }
+ };
+ struct v4l2_fmtdesc *fmt = arg;
+ enum v4l2_buf_type type = fmt->type;
+
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (fmt->index > 1)
+ return -EINVAL;
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
+ }
+
+ case VIDIOC_G_INPUT:{
+ *(int *)arg = cx->active_input;
+ break;
+ }
+
+ case VIDIOC_S_INPUT:{
+ int inp = *(int *)arg;
+
+ if (inp < 0 || inp >= cx->nof_inputs)
+ return -EINVAL;
+
+ if (inp == cx->active_input) {
+ CX18_DEBUG_INFO("Input unchanged\n");
+ break;
+ }
+ CX18_DEBUG_INFO("Changing input from %d to %d\n",
+ cx->active_input, inp);
+
+ cx->active_input = inp;
+ /* Set the audio input to whatever is appropriate for the
+ input type. */
+ cx->audio_input = cx->card->video_inputs[inp].audio_index;
+
+ /* prevent others from messing with the streams until
+ we're finished changing inputs. */
+ cx18_mute(cx);
+ cx18_video_set_io(cx);
+ cx18_audio_set_io(cx);
+ cx18_unmute(cx);
+ break;
+ }
+
+ case VIDIOC_G_FREQUENCY:{
+ struct v4l2_frequency *vf = arg;
+
+ if (vf->tuner != 0)
+ return -EINVAL;
+ cx18_call_i2c_clients(cx, cmd, arg);
+ break;
+ }
+
+ case VIDIOC_S_FREQUENCY:{
+ struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
+
+ if (vf.tuner != 0)
+ return -EINVAL;
+
+ cx18_mute(cx);
+ CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
+ cx18_call_i2c_clients(cx, cmd, &vf);
+ cx18_unmute(cx);
+ break;
+ }
+
+ case VIDIOC_ENUMSTD:{
+ struct v4l2_standard *vs = arg;
+ int idx = vs->index;
+
+ if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
+ return -EINVAL;
+
+ *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
+ cx18_std_60hz : cx18_std_50hz;
+ vs->index = idx;
+ vs->id = enum_stds[idx].std;
+ strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
+ break;
+ }
+
+ case VIDIOC_G_STD:{
+ *(v4l2_std_id *) arg = cx->std;
+ break;
+ }
+
+ case VIDIOC_S_STD: {
+ v4l2_std_id std = *(v4l2_std_id *) arg;
+
+ if ((std & V4L2_STD_ALL) == 0)
+ return -EINVAL;
+
+ if (std == cx->std)
+ break;
+
+ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
+ atomic_read(&cx->ana_capturing) > 0) {
+ /* Switching standard would turn off the radio or mess
+ with already running streams, prevent that by
+ returning EBUSY. */
+ return -EBUSY;
+ }
+
+ cx->std = std;
+ cx->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
+ cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
+ cx->params.width = 720;
+ cx->params.height = cx->is_50hz ? 576 : 480;
+ cx->vbi.count = cx->is_50hz ? 18 : 12;
+ cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
+ cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
+ cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
+ CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)cx->std);
+
+ /* Tuner */
+ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+ break;
+ }
+
+ case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
+ struct v4l2_tuner *vt = arg;
+
+ if (vt->index != 0)
+ return -EINVAL;
+
+ cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);
+ break;
+ }
+
+ case VIDIOC_G_TUNER: {
+ struct v4l2_tuner *vt = arg;
+
+ if (vt->index != 0)
+ return -EINVAL;
+
+ memset(vt, 0, sizeof(*vt));
+ cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
+
+ if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+ strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
+ vt->type = V4L2_TUNER_RADIO;
+ } else {
+ strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
+ vt->type = V4L2_TUNER_ANALOG_TV;
+ }
+ break;
+ }
+
+ case VIDIOC_G_SLICED_VBI_CAP: {
+ struct v4l2_sliced_vbi_cap *cap = arg;
+ int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+ int f, l;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+ enum v4l2_buf_type type = cap->type;
+#else
+ enum v4l2_buf_type type = VIDIOC_G_SLICED_VBI_CAP;
+#endif
+
+ memset(cap, 0, sizeof(*cap));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+ cap->type = type;
+#endif
+ if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+ for (f = 0; f < 2; f++) {
+ for (l = 0; l < 24; l++) {
+ if (valid_service_line(f, l, cx->is_50hz))
+ cap->service_lines[f][l] = set;
+ }
+ }
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+#if 0
+ case VIDIOC_G_ENC_INDEX: {
+ struct v4l2_enc_idx *idx = arg;
+ int i;
+
+ idx->entries = (cx->pgm_info_write_idx + CX18_MAX_PGM_INDEX - cx->pgm_info_read_idx) %
+ CX18_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] = cx->pgm_info[(cx->pgm_info_read_idx + i) % CX18_MAX_PGM_INDEX];
+ cx->pgm_info_read_idx = (cx->pgm_info_read_idx + idx->entries) % CX18_MAX_PGM_INDEX;
+ break;
+ }
+#endif
+ case VIDIOC_ENCODER_CMD:
+ case VIDIOC_TRY_ENCODER_CMD: {
+ struct v4l2_encoder_cmd *enc = arg;
+ int try = cmd == VIDIOC_TRY_ENCODER_CMD;
+
+ memset(&enc->raw, 0, sizeof(enc->raw));
+ switch (enc->cmd) {
+ case V4L2_ENC_CMD_START:
+ enc->flags = 0;
+ if (try)
+ return 0;
+ return cx18_start_capture(id);
+
+ case V4L2_ENC_CMD_STOP:
+ enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+ if (try)
+ return 0;
+ cx18_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+ return 0;
+
+ case V4L2_ENC_CMD_PAUSE:
+ enc->flags = 0;
+ if (try)
+ return 0;
+ if (!atomic_read(&cx->ana_capturing))
+ return -EPERM;
+ if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+ return 0;
+ cx18_mute(cx);
+ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
+ break;
+
+ case V4L2_ENC_CMD_RESUME:
+ enc->flags = 0;
+ if (try)
+ return 0;
+ if (!atomic_read(&cx->ana_capturing))
+ return -EPERM;
+ if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+ return 0;
+ cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
+ cx18_unmute(cx);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ {
+ struct v4l2_input vidin;
+ struct v4l2_audio audin;
+ int i;
+
+ CX18_INFO("================= START STATUS CARD #%d =================\n", cx->num);
+ if (cx->hw_flags & CX18_HW_TVEEPROM) {
+ struct tveeprom tv;
+
+ cx18_read_eeprom(cx, &tv);
+ }
+ cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
+ cx18_get_input(cx, cx->active_input, &vidin);
+ cx18_get_audio_input(cx, cx->audio_input, &audin);
+ CX18_INFO("Video Input: %s\n", vidin.name);
+ CX18_INFO("Audio Input: %s\n", audin.name);
+ CX18_INFO("Tuner: %s\n",
+ test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?
+ "Radio" : "TV");
+ cx2341x_log_status(&cx->params, cx->name);
+ CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
+ for (i = 0; i < CX18_MAX_STREAMS; i++) {
+ struct cx18_stream *s = &cx->streams[i];
+
+ if (s->v4l2dev == NULL || s->buffers == 0)
+ continue;
+ CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
+ s->name, s->s_flags,
+ (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+ (s->buffers * s->buf_size) / 1024, s->buffers);
+ }
+ CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
+ (long long)cx->mpg_data_received,
+ (long long)cx->vbi_data_inserted);
+ CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cx18_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, void *arg)
+{
+ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+ struct cx18 *cx = id->cx;
+ int ret;
+
+ /* check priority */
+ switch (cmd) {
+ case VIDIOC_S_CTRL:
+ case VIDIOC_S_STD:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_S_FMT:
+ case VIDIOC_S_CROP:
+ case VIDIOC_S_EXT_CTRLS:
+ ret = v4l2_prio_check(&cx->prio, &id->prio);
+ if (ret)
+ return ret;
+ }
+
+ switch (cmd) {
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_INT_S_AUDIO_ROUTING:
+ case VIDIOC_INT_RESET:
+ if (cx18_debug & CX18_DBGFLG_IOCTL) {
+ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+ v4l_printk_ioctl(cmd);
+ }
+ return cx18_debug_ioctls(filp, cmd, arg);
+
+ case VIDIOC_G_PRIORITY:
+ case VIDIOC_S_PRIORITY:
+ case VIDIOC_QUERYCAP:
+ case VIDIOC_ENUMINPUT:
+ case VIDIOC_G_INPUT:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_ENUM_FMT:
+ case VIDIOC_CROPCAP:
+ case VIDIOC_G_CROP:
+ case VIDIOC_S_CROP:
+ case VIDIOC_G_FREQUENCY:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_ENUMAUDIO:
+ case VIDIOC_S_AUDIO:
+ case VIDIOC_G_AUDIO:
+ case VIDIOC_G_SLICED_VBI_CAP:
+ case VIDIOC_LOG_STATUS:
+ case VIDIOC_G_ENC_INDEX:
+ case VIDIOC_ENCODER_CMD:
+ case VIDIOC_TRY_ENCODER_CMD:
+ if (cx18_debug & CX18_DBGFLG_IOCTL) {
+ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+ v4l_printk_ioctl(cmd);
+ }
+ return cx18_v4l2_ioctls(cx, filp, cmd, arg);
+
+ case VIDIOC_QUERYMENU:
+ case VIDIOC_QUERYCTRL:
+ case VIDIOC_S_CTRL:
+ case VIDIOC_G_CTRL:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+ if (cx18_debug & CX18_DBGFLG_IOCTL) {
+ printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+ v4l_printk_ioctl(cmd);
+ }
+ return cx18_control_ioctls(cx, cmd, arg);
+
+ case 0x00005401: /* Handle isatty() calls */
+ return -EINVAL;
+ default:
+ return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
+ cx18_v4l2_do_ioctl);
+ }
+ return 0;
+}
+
+int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+ struct cx18 *cx = id->cx;
+ int res;
+
+ mutex_lock(&cx->serialize_lock);
+ res = video_usercopy(inode, filp, cmd, arg, cx18_v4l2_do_ioctl);
+ mutex_unlock(&cx->serialize_lock);
+ return res;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.h b/linux/drivers/media/video/cx18/cx18-ioctl.h
new file mode 100644
index 000000000..9f4c7eb28
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-ioctl.h
@@ -0,0 +1,30 @@
+/*
+ * cx18 ioctl system call
+ *
+ * Derived from ivtv-ioctl.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+u16 cx18_service2vbi(int type);
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg);
+int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd,
+ void *arg);
diff --git a/linux/drivers/media/video/cx18/cx18-irq.c b/linux/drivers/media/video/cx18/cx18-irq.c
new file mode 100644
index 000000000..25114a5cb
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-irq.c
@@ -0,0 +1,181 @@
+/*
+ * cx18 interrupt handling
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-firmware.h"
+#include "cx18-fileops.h"
+#include "cx18-queue.h"
+#include "cx18-irq.h"
+#include "cx18-ioctl.h"
+#include "cx18-mailbox.h"
+#include "cx18-vbi.h"
+#include "cx18-scb.h"
+
+#define DMA_MAGIC_COOKIE 0x000001fe
+
+static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
+{
+ u32 handle = mb->args[0];
+ struct cx18_stream *s = NULL;
+ struct cx18_buffer *buf;
+ u32 off;
+ int i;
+ int id;
+
+ for (i = 0; i < CX18_MAX_STREAMS; i++) {
+ s = &cx->streams[i];
+ if ((handle == s->handle) && (s->dvb.enabled))
+ break;
+ if (s->v4l2dev && handle == s->handle)
+ break;
+ }
+ if (i == CX18_MAX_STREAMS) {
+ CX18_WARN("DMA done for unknown handle %d for stream %s\n",
+ handle, s->name);
+ mb->error = CXERR_NOT_OPEN;
+ mb->cmd = 0;
+ cx18_mb_ack(cx, mb);
+ return;
+ }
+
+ off = mb->args[1];
+ if (mb->args[2] != 1)
+ CX18_WARN("Ack struct = %d for %s\n",
+ mb->args[2], s->name);
+ id = read_enc(off);
+ buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
+ CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
+ if (buf) {
+ cx18_buf_sync_for_cpu(s, buf);
+ if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
+ /* process the buffer here */
+ CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n",
+ buf->bytesused);
+
+ dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
+ buf->bytesused);
+
+ cx18_buf_sync_for_device(s, buf);
+ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ 1, buf->id, s->buf_size);
+ } else
+ set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
+ } else {
+ CX18_WARN("Could not find buf %d for stream %s\n",
+ read_enc(off), s->name);
+ }
+ mb->error = 0;
+ mb->cmd = 0;
+ cx18_mb_ack(cx, mb);
+ wake_up(&cx->dma_waitq);
+ if (s->id != -1)
+ wake_up(&s->waitq);
+}
+
+static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
+{
+ char str[256] = { 0 };
+ char *p;
+
+ if (mb->args[1]) {
+ setup_page(mb->args[1]);
+ memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
+ str[252] = 0;
+ }
+ cx18_mb_ack(cx, mb);
+ CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
+ p = strchr(str, '.');
+ if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
+ CX18_INFO("FW version: %s\n", p - 1);
+}
+
+static void hpu_cmd(struct cx18 *cx, u32 sw1)
+{
+ struct cx18_mailbox mb;
+
+ if (sw1 & IRQ_CPU_TO_EPU) {
+ memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
+ mb.error = 0;
+
+ switch (mb.cmd) {
+ case CX18_EPU_DMA_DONE:
+ epu_dma_done(cx, &mb);
+ break;
+ case CX18_EPU_DEBUG:
+ epu_debug(cx, &mb);
+ break;
+ default:
+ CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd);
+ break;
+ }
+ }
+ if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU))
+ CX18_WARN("Unexpected interrupt %08x\n", sw1);
+}
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+{
+ struct cx18 *cx = (struct cx18 *)dev_id;
+ u32 sw1, sw1_mask;
+ u32 sw2, sw2_mask;
+ u32 hw2, hw2_mask;
+
+ spin_lock(&cx->dma_reg_lock);
+
+ hw2_mask = read_reg(HW2_INT_MASK5_PCI);
+ hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
+ sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
+ sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
+ sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
+ sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
+
+ write_reg(sw2&sw2_mask, SW2_INT_STATUS);
+ write_reg(sw1&sw1_mask, SW1_INT_STATUS);
+ write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
+
+ if (sw1 || sw2 || hw2)
+ CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
+
+ /* To do: interrupt-based I2C handling
+ if (hw2 & 0x00c00000) {
+ }
+ */
+
+ if (sw2) {
+ if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) |
+ readl(&cx->scb->cpu2epu_irq_ack)))
+ wake_up(&cx->mb_cpu_waitq);
+ if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) |
+ readl(&cx->scb->apu2epu_irq_ack)))
+ wake_up(&cx->mb_apu_waitq);
+ if (sw2 & readl(&cx->scb->epu2hpu_irq_ack))
+ wake_up(&cx->mb_epu_waitq);
+ if (sw2 & readl(&cx->scb->hpu2epu_irq_ack))
+ wake_up(&cx->mb_hpu_waitq);
+ }
+
+ if (sw1)
+ hpu_cmd(cx, sw1);
+ spin_unlock(&cx->dma_reg_lock);
+
+ return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-irq.h b/linux/drivers/media/video/cx18/cx18-irq.h
new file mode 100644
index 000000000..379f704f5
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-irq.h
@@ -0,0 +1,37 @@
+/*
+ * cx18 interrupt handling
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#define HW2_I2C1_INT (1 << 22)
+#define HW2_I2C2_INT (1 << 23)
+#define HW2_INT_CLR_STATUS 0xc730c4
+#define HW2_INT_MASK5_PCI 0xc730e4
+#define SW1_INT_SET 0xc73100
+#define SW1_INT_STATUS 0xc73104
+#define SW1_INT_ENABLE_PCI 0xc7311c
+#define SW2_INT_SET 0xc73140
+#define SW2_INT_STATUS 0xc73144
+#define SW2_INT_ENABLE_PCI 0xc7315c
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id);
+
+void cx18_irq_work_handler(struct work_struct *work);
+void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock);
+void cx18_unfinished_dma(unsigned long arg);
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c
new file mode 100644
index 000000000..2a5ccef91
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.c
@@ -0,0 +1,372 @@
+/*
+ * cx18 mailbox functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include <stdarg.h>
+
+#include "cx18-driver.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+
+#define API_FAST (1 << 2) /* Short timeout */
+#define API_SLOW (1 << 3) /* Additional 300ms timeout */
+
+#define APU 0
+#define CPU 1
+#define EPU 2
+#define HPU 3
+
+struct cx18_api_info {
+ u32 cmd;
+ u8 flags; /* Flags, see above */
+ u8 rpu; /* Processing unit */
+ const char *name; /* The name of the command */
+};
+
+#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
+
+static const struct cx18_api_info api_info[] = {
+ /* MPEG encoder API */
+ API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE, 0),
+ API_ENTRY(CPU, CX18_EPU_DEBUG, 0),
+ API_ENTRY(CPU, CX18_CREATE_TASK, 0),
+ API_ENTRY(CPU, CX18_DESTROY_TASK, 0),
+ API_ENTRY(CPU, CX18_CPU_CAPTURE_START, API_SLOW),
+ API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP, API_SLOW),
+ API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE, 0),
+ API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM, API_SLOW),
+ API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM, 0),
+ API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER, 0),
+ API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0),
+ API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
+ API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
+ API_ENTRY(0, 0, 0),
+};
+
+static const struct cx18_api_info *find_api_info(u32 cmd)
+{
+ int i;
+
+ for (i = 0; api_info[i].cmd; i++)
+ if (api_info[i].cmd == cmd)
+ return &api_info[i];
+ return NULL;
+}
+
+static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu,
+ u32 *state, u32 *irq, u32 *req)
+{
+ struct cx18_mailbox __iomem *mb = NULL;
+ int wait_count = 0;
+ u32 ack;
+
+ switch (rpu) {
+ case APU:
+ mb = &cx->scb->epu2apu_mb;
+ *state = readl(&cx->scb->apu_state);
+ *irq = readl(&cx->scb->epu2apu_irq);
+ break;
+
+ case CPU:
+ mb = &cx->scb->epu2cpu_mb;
+ *state = readl(&cx->scb->cpu_state);
+ *irq = readl(&cx->scb->epu2cpu_irq);
+ break;
+
+ case HPU:
+ mb = &cx->scb->epu2hpu_mb;
+ *state = readl(&cx->scb->hpu_state);
+ *irq = readl(&cx->scb->epu2hpu_irq);
+ break;
+ }
+
+ if (mb == NULL)
+ return mb;
+
+ do {
+ *req = readl(&mb->request);
+ ack = readl(&mb->ack);
+ wait_count++;
+ } while (*req != ack && wait_count < 600);
+
+ if (*req == ack) {
+ (*req)++;
+ if (*req == 0 || *req == 0xffffffff)
+ *req = 1;
+ return mb;
+ }
+ return NULL;
+}
+
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
+{
+ const struct cx18_api_info *info = find_api_info(mb->cmd);
+ struct cx18_mailbox __iomem *ack_mb;
+ u32 ack_irq;
+ u8 rpu = CPU;
+
+ if (info == NULL && mb->cmd) {
+ CX18_WARN("Cannot ack unknown command %x\n", mb->cmd);
+ return -EINVAL;
+ }
+ if (info)
+ rpu = info->rpu;
+
+ switch (rpu) {
+ case HPU:
+ ack_irq = IRQ_EPU_TO_HPU_ACK;
+ ack_mb = &cx->scb->hpu2epu_mb;
+ break;
+ case APU:
+ ack_irq = IRQ_EPU_TO_APU_ACK;
+ ack_mb = &cx->scb->apu2epu_mb;
+ break;
+ case CPU:
+ ack_irq = IRQ_EPU_TO_CPU_ACK;
+ ack_mb = &cx->scb->cpu2epu_mb;
+ break;
+ default:
+ CX18_WARN("Unknown RPU for command %x\n", mb->cmd);
+ return -EINVAL;
+ }
+
+ setup_page(SCB_OFFSET);
+ write_sync(mb->request, &ack_mb->ack);
+ write_reg(ack_irq, SW2_INT_SET);
+ return 0;
+}
+
+
+static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+ const struct cx18_api_info *info = find_api_info(cmd);
+ u32 state = 0, irq = 0, req, oldreq, err;
+ struct cx18_mailbox __iomem *mb;
+ wait_queue_head_t *waitq;
+ int timeout = 100;
+ int cnt = 0;
+ int sig = 0;
+ int i;
+
+ if (info == NULL) {
+ CX18_WARN("unknown cmd %x\n", cmd);
+ return -EINVAL;
+ }
+
+ if (cmd == CX18_CPU_DE_SET_MDL)
+ CX18_DEBUG_HI_API("%s\n", info->name);
+ else
+ CX18_DEBUG_API("%s\n", info->name);
+ setup_page(SCB_OFFSET);
+ mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
+
+ if (mb == NULL) {
+ CX18_ERR("mb %s busy\n", info->name);
+ return -EBUSY;
+ }
+
+ oldreq = req - 1;
+ writel(cmd, &mb->cmd);
+ for (i = 0; i < args; i++)
+ writel(data[i], &mb->args[i]);
+ writel(0, &mb->error);
+ writel(req, &mb->request);
+
+ switch (info->rpu) {
+ case APU: waitq = &cx->mb_apu_waitq; break;
+ case CPU: waitq = &cx->mb_cpu_waitq; break;
+ case EPU: waitq = &cx->mb_epu_waitq; break;
+ case HPU: waitq = &cx->mb_hpu_waitq; break;
+ default: return -EINVAL;
+ }
+ if (info->flags & API_FAST)
+ timeout /= 2;
+ write_reg(irq, SW1_INT_SET);
+
+ while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
+ if (cnt > 200 && !in_atomic())
+ sig = cx18_msleep_timeout(10, 1);
+ cnt++;
+ }
+ if (sig)
+ return -EINTR;
+ if (cnt == 660) {
+ writel(oldreq, &mb->request);
+ CX18_ERR("mb %s failed\n", info->name);
+ return -EINVAL;
+ }
+ for (i = 0; i < MAX_MB_ARGUMENTS; i++)
+ data[i] = readl(&mb->args[i]);
+ err = readl(&mb->error);
+ if (!in_atomic() && (info->flags & API_SLOW))
+ cx18_msleep_timeout(300, 0);
+ if (err)
+ CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
+ info->name);
+ return err ? -EIO : 0;
+}
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+ int res = cx18_api_call(cx, cmd, args, data);
+
+ /* Allow a single retry, probably already too late though.
+ If there is no free mailbox then that is usually an indication
+ of a more serious problem. */
+ return (res == -EBUSY) ? cx18_api_call(cx, cmd, args, data) : res;
+}
+
+static int cx18_set_filter_param(struct cx18_stream *s)
+{
+ struct cx18 *cx = s->cx;
+ u32 mode;
+ int ret;
+
+ mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
+ ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+ s->handle, 1, mode, cx->spatial_strength);
+ mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
+ ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+ s->handle, 0, mode, cx->temporal_strength);
+ ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+ s->handle, 2, cx->filter_mode >> 2, 0);
+ return ret;
+}
+
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+ u32 data[CX2341X_MBOX_MAX_DATA])
+{
+ struct cx18 *cx = priv;
+ struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
+ switch (cmd) {
+ case CX2341X_ENC_SET_OUTPUT_PORT:
+ return 0;
+ case CX2341X_ENC_SET_FRAME_RATE:
+ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
+ s->handle, 0, 0, 0, 0, data[0]);
+ case CX2341X_ENC_SET_FRAME_SIZE:
+ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
+ s->handle, data[1], data[0]);
+ case CX2341X_ENC_SET_STREAM_TYPE:
+ return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
+ s->handle, data[0]);
+ case CX2341X_ENC_SET_ASPECT_RATIO:
+ return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
+ s->handle, data[0]);
+
+ case CX2341X_ENC_SET_GOP_PROPERTIES:
+ return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
+ s->handle, data[0], data[1]);
+ case CX2341X_ENC_SET_GOP_CLOSURE:
+ return 0;
+ case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+ return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+ s->handle, data[0]);
+ case CX2341X_ENC_MUTE_AUDIO:
+ return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+ s->handle, data[0]);
+ case CX2341X_ENC_SET_BIT_RATE:
+ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
+ s->handle, data[0], data[1], data[2], data[3]);
+ case CX2341X_ENC_MUTE_VIDEO:
+ return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+ s->handle, data[0]);
+ case CX2341X_ENC_SET_FRAME_DROP_RATE:
+ return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
+ s->handle, data[0]);
+ case CX2341X_ENC_MISC:
+ return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
+ s->handle, data[0], data[1], data[2]);
+ case CX2341X_ENC_SET_DNR_FILTER_MODE:
+ cx->filter_mode = (data[0] & 3) | (data[1] << 2);
+ return cx18_set_filter_param(s);
+ case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+ cx->spatial_strength = data[0];
+ cx->temporal_strength = data[1];
+ return cx18_set_filter_param(s);
+ case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+ return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
+ s->handle, data[0], data[1]);
+ case CX2341X_ENC_SET_CORING_LEVELS:
+ return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
+ s->handle, data[0], data[1], data[2], data[3]);
+ }
+ CX18_WARN("Unknown cmd %x\n", cmd);
+ return 0;
+}
+
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
+ u32 cmd, int args, ...)
+{
+ va_list ap;
+ int i;
+
+ va_start(ap, args);
+ for (i = 0; i < args; i++)
+ data[i] = va_arg(ap, u32);
+ va_end(ap);
+ return cx18_api(cx, cmd, args, data);
+}
+
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
+{
+ u32 data[MAX_MB_ARGUMENTS];
+ va_list ap;
+ int i;
+
+ if (cx == NULL) {
+ CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
+ return 0;
+ }
+ if (args > MAX_MB_ARGUMENTS) {
+ CX18_ERR("args too big (cmd=%x)\n", cmd);
+ args = MAX_MB_ARGUMENTS;
+ }
+ va_start(ap, args);
+ for (i = 0; i < args; i++)
+ data[i] = va_arg(ap, u32);
+ va_end(ap);
+ return cx18_api(cx, cmd, args, data);
+}
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h
new file mode 100644
index 000000000..d99564153
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.h
@@ -0,0 +1,73 @@
+/*
+ * cx18 mailbox functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef _CX18_MAILBOX_H_
+#define _CX18_MAILBOX_H_
+
+/* mailbox max args */
+#define MAX_MB_ARGUMENTS 6
+/* compatibility, should be same as the define in cx2341x.h */
+#define CX2341X_MBOX_MAX_DATA 16
+
+#define MB_RESERVED_HANDLE_0 0
+#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
+
+struct cx18;
+
+/* The cx18_mailbox struct is the mailbox structure which is used for passing
+ messages between processors */
+struct cx18_mailbox {
+ /* The sender sets a handle in 'request' after he fills the command. The
+ 'request' should be different than 'ack'. The sender, also, generates
+ an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
+ receiver. */
+ u32 request;
+ /* The receiver detects a new command when 'req' is different than 'ack'.
+ He sets 'ack' to the same value as 'req' to clear the command. He, also,
+ generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
+ is the receiver. */
+ u32 ack;
+ u32 reserved[6];
+ /* 'cmd' identifies the command. The list of these commands are in
+ cx23418.h */
+ u32 cmd;
+ /* Each command can have up to 6 arguments */
+ u32 args[MAX_MB_ARGUMENTS];
+ /* The return code can be one of the codes in the file cx23418.h. If the
+ command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+ If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
+ code would indicate the task from which the error originated and will
+ be one of the errors in cx23418.h. In that case, the following
+ applies ((error & 0xff) != 0).
+ If the command is pending, the return will be passed in a MB from the
+ receiver to the sender. 'req' will be returned in args[0] */
+ u32 error;
+};
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
+ int args, ...);
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+ u32 data[CX2341X_MBOX_MAX_DATA]);
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb);
+
+#endif
diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c
new file mode 100644
index 000000000..6990b77c6
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-queue.c
@@ -0,0 +1,272 @@
+/*
+ * cx18 buffer queues
+ *
+ * Derived from ivtv-queue.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-streams.h"
+#include "cx18-queue.h"
+#include "cx18-scb.h"
+
+void cx18_buf_swap(struct cx18_buffer *buf)
+{
+ int i;
+
+ for (i = 0; i < buf->bytesused; i += 4)
+ swab32s((u32 *)(buf->buf + i));
+}
+
+void cx18_queue_init(struct cx18_queue *q)
+{
+ INIT_LIST_HEAD(&q->list);
+ q->buffers = 0;
+ q->length = 0;
+ q->bytesused = 0;
+}
+
+void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
+ struct cx18_queue *q)
+{
+ unsigned long flags = 0;
+
+ /* clear the buffer if it is going to be enqueued to the free queue */
+ if (q == &s->q_free) {
+ buf->bytesused = 0;
+ buf->readpos = 0;
+ buf->b_flags = 0;
+ }
+ spin_lock_irqsave(&s->qlock, flags);
+ list_add_tail(&buf->list, &q->list);
+ q->buffers++;
+ q->length += s->buf_size;
+ q->bytesused += buf->bytesused - buf->readpos;
+ spin_unlock_irqrestore(&s->qlock, flags);
+}
+
+struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
+{
+ struct cx18_buffer *buf = NULL;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&s->qlock, flags);
+ if (!list_empty(&q->list)) {
+ buf = list_entry(q->list.next, struct cx18_buffer, list);
+ list_del_init(q->list.next);
+ q->buffers--;
+ q->length -= s->buf_size;
+ q->bytesused -= buf->bytesused - buf->readpos;
+ }
+ spin_unlock_irqrestore(&s->qlock, flags);
+ return buf;
+}
+
+struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+ u32 bytesused)
+{
+ struct cx18 *cx = s->cx;
+ struct list_head *p;
+
+ list_for_each(p, &s->q_free.list) {
+ struct cx18_buffer *buf =
+ list_entry(p, struct cx18_buffer, list);
+
+ if (buf->id != id)
+ continue;
+ buf->bytesused = bytesused;
+ /* the transport buffers are handled differently,
+ so there is no need to move them to the full queue */
+ if (s->type == CX18_ENC_STREAM_TYPE_TS)
+ return buf;
+ s->q_free.buffers--;
+ s->q_free.length -= s->buf_size;
+ s->q_full.buffers++;
+ s->q_full.length += s->buf_size;
+ s->q_full.bytesused += buf->bytesused;
+ list_move_tail(&buf->list, &s->q_full.list);
+ return buf;
+ }
+ CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
+ return NULL;
+}
+
+static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
+ struct cx18_queue *to, int clear, int full)
+{
+ struct cx18_buffer *buf =
+ list_entry(from->list.next, struct cx18_buffer, list);
+
+ list_move_tail(from->list.next, &to->list);
+ from->buffers--;
+ from->length -= s->buf_size;
+ from->bytesused -= buf->bytesused - buf->readpos;
+ /* special handling for q_free */
+ if (clear)
+ buf->bytesused = buf->readpos = buf->b_flags = 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;
+ }
+ to->buffers++;
+ to->length += s->buf_size;
+ to->bytesused += buf->bytesused - buf->readpos;
+}
+
+/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
+ If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
+ If 'steal' != NULL, then buffers may also taken from that queue if
+ needed.
+
+ The buffer is automatically cleared if it goes to the free queue. It is
+ also cleared if buffers need to be taken from the 'steal' queue and
+ the 'from' queue is the free queue.
+
+ When 'from' is q_free, then needed_bytes is compared to the total
+ available buffer length, otherwise needed_bytes is compared to the
+ bytesused value. For the 'steal' queue the total available buffer
+ length is always used.
+
+ -ENOMEM is returned if the buffers could not be obtained, 0 if all
+ buffers where obtained from the 'from' list and if non-zero then
+ the number of stolen buffers is returned. */
+static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
+ struct cx18_queue *steal, struct cx18_queue *to,
+ int needed_bytes)
+{
+ unsigned long flags;
+ int rc = 0;
+ int from_free = from == &s->q_free;
+ int to_free = to == &s->q_free;
+ int bytes_available;
+
+ spin_lock_irqsave(&s->qlock, flags);
+ if (needed_bytes == 0) {
+ from_free = 1;
+ needed_bytes = from->length;
+ }
+
+ bytes_available = from_free ? from->length : from->bytesused;
+ bytes_available += steal ? steal->length : 0;
+
+ if (bytes_available < needed_bytes) {
+ spin_unlock_irqrestore(&s->qlock, flags);
+ return -ENOMEM;
+ }
+ 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 */
+ cx18_queue_move_buf(s, from, to, 1, 0);
+ }
+ } 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 */
+ cx18_queue_move_buf(s, from, to, to_free, rc);
+ }
+ }
+ spin_unlock_irqrestore(&s->qlock, flags);
+ return rc;
+}
+
+void cx18_flush_queues(struct cx18_stream *s)
+{
+ cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
+ cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+}
+
+int cx18_stream_alloc(struct cx18_stream *s)
+{
+ struct cx18 *cx = s->cx;
+ int i;
+
+ if (s->buffers == 0)
+ return 0;
+
+ CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n",
+ s->name, s->buffers, s->buf_size,
+ s->buffers * s->buf_size / 1024);
+
+ if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
+ (char *)cx->scb) > SCB_RESERVED_SIZE) {
+ unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
+ ((char *)cx->scb->cpu_mdl));
+
+ CX18_ERR("Too many buffers, cannot fit in SCB area\n");
+ CX18_ERR("Max buffers = %zd\n",
+ bufsz / sizeof(struct cx18_mdl));
+ return -ENOMEM;
+ }
+
+ s->mdl_offset = cx->mdl_offset;
+
+ /* allocate stream buffers. Initially all buffers are in q_free. */
+ for (i = 0; i < s->buffers; i++) {
+ struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer),
+ GFP_KERNEL|__GFP_NOWARN);
+
+ if (buf == NULL)
+ break;
+ buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
+ if (buf->buf == NULL) {
+ kfree(buf);
+ break;
+ }
+ buf->id = cx->buffer_id++;
+ INIT_LIST_HEAD(&buf->list);
+ buf->dma_handle = pci_map_single(s->cx->dev,
+ buf->buf, s->buf_size, s->dma);
+ cx18_buf_sync_for_cpu(s, buf);
+ cx18_enqueue(s, buf, &s->q_free);
+ }
+ if (i == s->buffers) {
+ cx->mdl_offset += s->buffers;
+ return 0;
+ }
+ CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+ cx18_stream_free(s);
+ return -ENOMEM;
+}
+
+void cx18_stream_free(struct cx18_stream *s)
+{
+ struct cx18_buffer *buf;
+
+ /* move all buffers to q_free */
+ cx18_flush_queues(s);
+
+ /* empty q_free */
+ while ((buf = cx18_dequeue(s, &s->q_free))) {
+ pci_unmap_single(s->cx->dev, buf->dma_handle,
+ s->buf_size, s->dma);
+ kfree(buf->buf);
+ kfree(buf);
+ }
+}
diff --git a/linux/drivers/media/video/cx18/cx18-queue.h b/linux/drivers/media/video/cx18/cx18-queue.h
new file mode 100644
index 000000000..91423b986
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-queue.h
@@ -0,0 +1,55 @@
+/*
+ * cx18 buffer queues
+ *
+ * Derived from ivtv-queue.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#define CX18_DMA_UNMAPPED ((u32) -1)
+
+/* cx18_buffer utility functions */
+
+static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
+ struct cx18_buffer *buf)
+{
+ pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle,
+ s->buf_size, s->dma);
+}
+
+static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
+ struct cx18_buffer *buf)
+{
+ pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle,
+ s->buf_size, s->dma);
+}
+
+void cx18_buf_swap(struct cx18_buffer *buf);
+
+/* cx18_queue utility functions */
+void cx18_queue_init(struct cx18_queue *q);
+void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
+ struct cx18_queue *q);
+struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
+struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+ u32 bytesused);
+void cx18_flush_queues(struct cx18_stream *s);
+
+/* cx18_stream utility functions */
+int cx18_stream_alloc(struct cx18_stream *s);
+void cx18_stream_free(struct cx18_stream *s);
diff --git a/linux/drivers/media/video/cx18/cx18-scb.c b/linux/drivers/media/video/cx18/cx18-scb.c
new file mode 100644
index 000000000..30bc803e3
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-scb.c
@@ -0,0 +1,121 @@
+/*
+ * cx18 System Control Block initialization
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-scb.h"
+
+void cx18_init_scb(struct cx18 *cx)
+{
+ setup_page(SCB_OFFSET);
+ memset_io(cx->scb, 0, 0x10000);
+
+ writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq);
+ writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+ writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq);
+ writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+ writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq);
+ writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+ writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq);
+ writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+
+ writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq);
+ writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+ writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq);
+ writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+ writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq);
+ writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+ writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq);
+ writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+
+ writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq);
+ writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+ writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq);
+ writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+ writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq);
+ writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+ writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq);
+ writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+
+ writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq);
+ writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+ writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq);
+ writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+ writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq);
+ writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+ writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq);
+ writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+
+ writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq);
+ writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+ writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq);
+ writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+ writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq);
+ writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+ writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq);
+ writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+ &cx->scb->apu2cpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+ &cx->scb->hpu2cpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+ &cx->scb->ppu2cpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+ &cx->scb->epu2cpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+ &cx->scb->cpu2apu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+ &cx->scb->hpu2apu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+ &cx->scb->ppu2apu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+ &cx->scb->epu2apu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+ &cx->scb->cpu2hpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+ &cx->scb->apu2hpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+ &cx->scb->ppu2hpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+ &cx->scb->epu2hpu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+ &cx->scb->cpu2ppu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+ &cx->scb->apu2ppu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+ &cx->scb->hpu2ppu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+ &cx->scb->epu2ppu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+ &cx->scb->cpu2epu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+ &cx->scb->apu2epu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+ &cx->scb->hpu2epu_mb_offset);
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+ &cx->scb->ppu2epu_mb_offset);
+
+ writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+ &cx->scb->ipc_offset);
+
+ writel(1, &cx->scb->hpu_state);
+ writel(1, &cx->scb->epu_state);
+}
diff --git a/linux/drivers/media/video/cx18/cx18-scb.h b/linux/drivers/media/video/cx18/cx18-scb.h
new file mode 100644
index 000000000..86b4cb15d
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-scb.h
@@ -0,0 +1,285 @@
+/*
+ * cx18 System Control Block initialization
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef CX18_SCB_H
+#define CX18_SCB_H
+
+#include "cx18-mailbox.h"
+
+/* NOTE: All ACK interrupts are in the SW2 register. All non-ACK interrupts
+ are in the SW1 register. */
+
+#define IRQ_APU_TO_CPU 0x00000001
+#define IRQ_CPU_TO_APU_ACK 0x00000001
+#define IRQ_HPU_TO_CPU 0x00000002
+#define IRQ_CPU_TO_HPU_ACK 0x00000002
+#define IRQ_PPU_TO_CPU 0x00000004
+#define IRQ_CPU_TO_PPU_ACK 0x00000004
+#define IRQ_EPU_TO_CPU 0x00000008
+#define IRQ_CPU_TO_EPU_ACK 0x00000008
+
+#define IRQ_CPU_TO_APU 0x00000010
+#define IRQ_APU_TO_CPU_ACK 0x00000010
+#define IRQ_HPU_TO_APU 0x00000020
+#define IRQ_APU_TO_HPU_ACK 0x00000020
+#define IRQ_PPU_TO_APU 0x00000040
+#define IRQ_APU_TO_PPU_ACK 0x00000040
+#define IRQ_EPU_TO_APU 0x00000080
+#define IRQ_APU_TO_EPU_ACK 0x00000080
+
+#define IRQ_CPU_TO_HPU 0x00000100
+#define IRQ_HPU_TO_CPU_ACK 0x00000100
+#define IRQ_APU_TO_HPU 0x00000200
+#define IRQ_HPU_TO_APU_ACK 0x00000200
+#define IRQ_PPU_TO_HPU 0x00000400
+#define IRQ_HPU_TO_PPU_ACK 0x00000400
+#define IRQ_EPU_TO_HPU 0x00000800
+#define IRQ_HPU_TO_EPU_ACK 0x00000800
+
+#define IRQ_CPU_TO_PPU 0x00001000
+#define IRQ_PPU_TO_CPU_ACK 0x00001000
+#define IRQ_APU_TO_PPU 0x00002000
+#define IRQ_PPU_TO_APU_ACK 0x00002000
+#define IRQ_HPU_TO_PPU 0x00004000
+#define IRQ_PPU_TO_HPU_ACK 0x00004000
+#define IRQ_EPU_TO_PPU 0x00008000
+#define IRQ_PPU_TO_EPU_ACK 0x00008000
+
+#define IRQ_CPU_TO_EPU 0x00010000
+#define IRQ_EPU_TO_CPU_ACK 0x00010000
+#define IRQ_APU_TO_EPU 0x00020000
+#define IRQ_EPU_TO_APU_ACK 0x00020000
+#define IRQ_HPU_TO_EPU 0x00040000
+#define IRQ_EPU_TO_HPU_ACK 0x00040000
+#define IRQ_PPU_TO_EPU 0x00080000
+#define IRQ_EPU_TO_PPU_ACK 0x00080000
+
+#define SCB_OFFSET 0xDC0000
+
+/* If Firmware uses fixed memory map, it shall not allocate the area
+ between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
+#define SCB_RESERVED_SIZE 0x10000
+
+
+/* This structure is used by EPU to provide memory descriptors in its memory */
+struct cx18_mdl {
+ u32 paddr; /* Physical address of a buffer segment */
+ u32 length; /* Length of the buffer segment */
+};
+
+/* This structure is used by CPU to provide completed buffers information */
+struct cx18_mdl_ack {
+ u32 id; /* ID of a completed MDL */
+ u32 data_used; /* Total data filled in the MDL for buffer 'id' */
+};
+
+struct cx18_scb {
+ /* These fields form the System Control Block which is used at boot time
+ for localizing the IPC data as well as the code positions for all
+ processors. The offsets are from the start of this struct. */
+
+ /* Offset where to find the Inter-Processor Communication data */
+ u32 ipc_offset;
+ u32 reserved01[7];
+ /* Offset where to find the start of the CPU code */
+ u32 cpu_code_offset;
+ u32 reserved02[3];
+ /* Offset where to find the start of the APU code */
+ u32 apu_code_offset;
+ u32 reserved03[3];
+ /* Offset where to find the start of the HPU code */
+ u32 hpu_code_offset;
+ u32 reserved04[3];
+ /* Offset where to find the start of the PPU code */
+ u32 ppu_code_offset;
+ u32 reserved05[3];
+
+ /* These fields form Inter-Processor Communication data which is used
+ by all processors to locate the information needed for communicating
+ with other processors */
+
+ /* Fields for CPU: */
+
+ /* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
+ u32 cpu_state;
+ u32 reserved1[7];
+ /* Offset to the mailbox used for sending commands from APU to CPU */
+ u32 apu2cpu_mb_offset;
+ /* Value to write to register SW1 register set (0xC7003100) after the
+ command is ready */
+ u32 apu2cpu_irq;
+ /* Value to write to register SW2 register set (0xC7003140) after the
+ command is cleared */
+ u32 apu2cpu_irq_ack;
+ u32 reserved2[13];
+
+ u32 hpu2cpu_mb_offset;
+ u32 hpu2cpu_irq;
+ u32 hpu2cpu_irq_ack;
+ u32 reserved3[13];
+
+ u32 ppu2cpu_mb_offset;
+ u32 ppu2cpu_irq;
+ u32 ppu2cpu_irq_ack;
+ u32 reserved4[13];
+
+ u32 epu2cpu_mb_offset;
+ u32 epu2cpu_irq;
+ u32 epu2cpu_irq_ack;
+ u32 reserved5[13];
+ u32 reserved6[8];
+
+ /* Fields for APU: */
+
+ u32 apu_state;
+ u32 reserved11[7];
+ u32 cpu2apu_mb_offset;
+ u32 cpu2apu_irq;
+ u32 cpu2apu_irq_ack;
+ u32 reserved12[13];
+
+ u32 hpu2apu_mb_offset;
+ u32 hpu2apu_irq;
+ u32 hpu2apu_irq_ack;
+ u32 reserved13[13];
+
+ u32 ppu2apu_mb_offset;
+ u32 ppu2apu_irq;
+ u32 ppu2apu_irq_ack;
+ u32 reserved14[13];
+
+ u32 epu2apu_mb_offset;
+ u32 epu2apu_irq;
+ u32 epu2apu_irq_ack;
+ u32 reserved15[13];
+ u32 reserved16[8];
+
+ /* Fields for HPU: */
+
+ u32 hpu_state;
+ u32 reserved21[7];
+ u32 cpu2hpu_mb_offset;
+ u32 cpu2hpu_irq;
+ u32 cpu2hpu_irq_ack;
+ u32 reserved22[13];
+
+ u32 apu2hpu_mb_offset;
+ u32 apu2hpu_irq;
+ u32 apu2hpu_irq_ack;
+ u32 reserved23[13];
+
+ u32 ppu2hpu_mb_offset;
+ u32 ppu2hpu_irq;
+ u32 ppu2hpu_irq_ack;
+ u32 reserved24[13];
+
+ u32 epu2hpu_mb_offset;
+ u32 epu2hpu_irq;
+ u32 epu2hpu_irq_ack;
+ u32 reserved25[13];
+ u32 reserved26[8];
+
+ /* Fields for PPU: */
+
+ u32 ppu_state;
+ u32 reserved31[7];
+ u32 cpu2ppu_mb_offset;
+ u32 cpu2ppu_irq;
+ u32 cpu2ppu_irq_ack;
+ u32 reserved32[13];
+
+ u32 apu2ppu_mb_offset;
+ u32 apu2ppu_irq;
+ u32 apu2ppu_irq_ack;
+ u32 reserved33[13];
+
+ u32 hpu2ppu_mb_offset;
+ u32 hpu2ppu_irq;
+ u32 hpu2ppu_irq_ack;
+ u32 reserved34[13];
+
+ u32 epu2ppu_mb_offset;
+ u32 epu2ppu_irq;
+ u32 epu2ppu_irq_ack;
+ u32 reserved35[13];
+ u32 reserved36[8];
+
+ /* Fields for EPU: */
+
+ u32 epu_state;
+ u32 reserved41[7];
+ u32 cpu2epu_mb_offset;
+ u32 cpu2epu_irq;
+ u32 cpu2epu_irq_ack;
+ u32 reserved42[13];
+
+ u32 apu2epu_mb_offset;
+ u32 apu2epu_irq;
+ u32 apu2epu_irq_ack;
+ u32 reserved43[13];
+
+ u32 hpu2epu_mb_offset;
+ u32 hpu2epu_irq;
+ u32 hpu2epu_irq_ack;
+ u32 reserved44[13];
+
+ u32 ppu2epu_mb_offset;
+ u32 ppu2epu_irq;
+ u32 ppu2epu_irq_ack;
+ u32 reserved45[13];
+ u32 reserved46[8];
+
+ u32 semaphores[8]; /* Semaphores */
+
+ u32 reserved50[32]; /* Reserved for future use */
+
+ struct cx18_mailbox apu2cpu_mb;
+ struct cx18_mailbox hpu2cpu_mb;
+ struct cx18_mailbox ppu2cpu_mb;
+ struct cx18_mailbox epu2cpu_mb;
+
+ struct cx18_mailbox cpu2apu_mb;
+ struct cx18_mailbox hpu2apu_mb;
+ struct cx18_mailbox ppu2apu_mb;
+ struct cx18_mailbox epu2apu_mb;
+
+ struct cx18_mailbox cpu2hpu_mb;
+ struct cx18_mailbox apu2hpu_mb;
+ struct cx18_mailbox ppu2hpu_mb;
+ struct cx18_mailbox epu2hpu_mb;
+
+ struct cx18_mailbox cpu2ppu_mb;
+ struct cx18_mailbox apu2ppu_mb;
+ struct cx18_mailbox hpu2ppu_mb;
+ struct cx18_mailbox epu2ppu_mb;
+
+ struct cx18_mailbox cpu2epu_mb;
+ struct cx18_mailbox apu2epu_mb;
+ struct cx18_mailbox hpu2epu_mb;
+ struct cx18_mailbox ppu2epu_mb;
+
+ struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][2];
+ struct cx18_mdl cpu_mdl[1];
+};
+
+void cx18_init_scb(struct cx18 *cx);
+
+#endif
diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c
new file mode 100644
index 000000000..7f695f36a
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-streams.c
@@ -0,0 +1,603 @@
+/*
+ * cx18 init/start/stop/exit stream functions
+ *
+ * Derived from ivtv-streams.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-ioctl.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-scb.h"
+#include "cx18-av-core.h"
+#include "cx18-dvb.h"
+
+#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
+
+static struct file_operations cx18_v4l2_enc_fops = {
+ .owner = THIS_MODULE,
+ .read = cx18_v4l2_read,
+ .open = cx18_v4l2_open,
+ .ioctl = cx18_v4l2_ioctl,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+ .compat_ioctl = v4l_compat_ioctl32,
+#endif
+ .release = cx18_v4l2_close,
+ .poll = cx18_v4l2_enc_poll,
+};
+
+/* offset from 0 to register ts v4l2 minors on */
+#define CX18_V4L2_ENC_TS_OFFSET 16
+/* offset from 0 to register pcm v4l2 minors on */
+#define CX18_V4L2_ENC_PCM_OFFSET 24
+/* offset from 0 to register yuv v4l2 minors on */
+#define CX18_V4L2_ENC_YUV_OFFSET 32
+
+static struct {
+ const char *name;
+ int vfl_type;
+ int minor_offset;
+ int dma;
+ enum v4l2_buf_type buf_type;
+ struct file_operations *fops;
+} cx18_stream_info[] = {
+ { /* CX18_ENC_STREAM_TYPE_MPG */
+ "encoder MPEG",
+ VFL_TYPE_GRABBER, 0,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_TS */
+ "TS",
+ VFL_TYPE_GRABBER, -1,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_YUV */
+ "encoder YUV",
+ VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_VBI */
+ "encoder VBI",
+ VFL_TYPE_VBI, 0,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_PCM */
+ "encoder PCM audio",
+ VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_IDX */
+ "encoder IDX",
+ VFL_TYPE_GRABBER, -1,
+ PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ &cx18_v4l2_enc_fops
+ },
+ { /* CX18_ENC_STREAM_TYPE_RAD */
+ "encoder radio",
+ VFL_TYPE_RADIO, 0,
+ PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
+ &cx18_v4l2_enc_fops
+ },
+};
+
+static void cx18_stream_init(struct cx18 *cx, int type)
+{
+ struct cx18_stream *s = &cx->streams[type];
+ struct video_device *dev = s->v4l2dev;
+ u32 max_size = cx->options.megabytes[type] * 1024 * 1024;
+
+ /* we need to keep v4l2dev, so restore it afterwards */
+ memset(s, 0, sizeof(*s));
+ s->v4l2dev = dev;
+
+ /* initialize cx18_stream fields */
+ s->cx = cx;
+ s->type = type;
+ s->name = cx18_stream_info[type].name;
+ s->handle = 0xffffffff;
+
+ s->dma = cx18_stream_info[type].dma;
+ s->buf_size = cx->stream_buf_size[type];
+ if (s->buf_size)
+ s->buffers = max_size / s->buf_size;
+ if (s->buffers > 63) {
+ /* Each stream has a maximum of 63 buffers,
+ ensure we do not exceed that. */
+ s->buffers = 63;
+ s->buf_size = (max_size / s->buffers) & ~0xfff;
+ }
+ spin_lock_init(&s->qlock);
+ init_waitqueue_head(&s->waitq);
+ s->id = -1;
+ cx18_queue_init(&s->q_free);
+ cx18_queue_init(&s->q_full);
+ cx18_queue_init(&s->q_io);
+}
+
+static int cx18_prep_dev(struct cx18 *cx, int type)
+{
+ struct cx18_stream *s = &cx->streams[type];
+ u32 cap = cx->v4l2_cap;
+ int minor_offset = cx18_stream_info[type].minor_offset;
+ int minor;
+
+ /* These four fields are always initialized. If v4l2dev == NULL, then
+ this stream is not in use. In that case no other fields but these
+ four can be used. */
+ s->v4l2dev = NULL;
+ s->cx = cx;
+ s->type = type;
+ s->name = cx18_stream_info[type].name;
+
+ /* Check whether the radio is supported */
+ if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
+ return 0;
+
+ /* Check whether VBI is supported */
+ if (type == CX18_ENC_STREAM_TYPE_VBI &&
+ !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
+ return 0;
+
+ /* card number + user defined offset + device offset */
+ minor = cx->num + cx18_first_minor + minor_offset;
+
+ /* User explicitly selected 0 buffers for these streams, so don't
+ create them. */
+ if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
+ cx->options.megabytes[type] == 0) {
+ CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
+ return 0;
+ }
+
+ cx18_stream_init(cx, type);
+
+ if (minor_offset == -1)
+ return 0;
+
+ /* allocate and initialize the v4l2 video device structure */
+ s->v4l2dev = video_device_alloc();
+ if (s->v4l2dev == NULL) {
+ CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
+ s->name);
+ return -ENOMEM;
+ }
+
+ s->v4l2dev->type =
+ VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
+ VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
+ snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18%d %s",
+ cx->num, s->name);
+
+ s->v4l2dev->minor = minor;
+ s->v4l2dev->dev = &cx->dev->dev;
+ s->v4l2dev->fops = cx18_stream_info[type].fops;
+ s->v4l2dev->release = video_device_release;
+
+ return 0;
+}
+
+/* Initialize v4l2 variables and register v4l2 devices */
+int cx18_streams_setup(struct cx18 *cx)
+{
+ int type;
+
+ /* Setup V4L2 Devices */
+ for (type = 0; type < CX18_MAX_STREAMS; type++) {
+ /* Prepare device */
+ if (cx18_prep_dev(cx, type))
+ break;
+
+ /* Allocate Stream */
+ if (cx18_stream_alloc(&cx->streams[type]))
+ break;
+ }
+ if (type == CX18_MAX_STREAMS)
+ return 0;
+
+ /* One or more streams could not be initialized. Clean 'em all up. */
+ cx18_streams_cleanup(cx, 0);
+ return -ENOMEM;
+}
+
+static int cx18_reg_dev(struct cx18 *cx, int type)
+{
+ struct cx18_stream *s = &cx->streams[type];
+ int vfl_type = cx18_stream_info[type].vfl_type;
+ int minor;
+
+ /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
+ * We need a VFL_TYPE_TS defined.
+ */
+ if (strcmp("TS", s->name) == 0) {
+ /* just return if no DVB is supported */
+ if ((cx->card->hw_all & CX18_HW_DVB) == 0)
+ return 0;
+ if (cx18_dvb_register(s) < 0) {
+ CX18_ERR("DVB failed to register\n");
+ return -EINVAL;
+ }
+ }
+
+ if (s->v4l2dev == NULL)
+ return 0;
+
+ minor = s->v4l2dev->minor;
+
+ /* Register device. First try the desired minor, then any free one. */
+ if (video_register_device(s->v4l2dev, vfl_type, minor) &&
+ video_register_device(s->v4l2dev, vfl_type, -1)) {
+ CX18_ERR("Couldn't register v4l2 device for %s minor %d\n",
+ s->name, minor);
+ video_device_release(s->v4l2dev);
+ s->v4l2dev = NULL;
+ return -ENOMEM;
+ }
+ minor = s->v4l2dev->minor;
+
+ switch (vfl_type) {
+ case VFL_TYPE_GRABBER:
+ CX18_INFO("Registered device video%d for %s (%d MB)\n",
+ minor, s->name, cx->options.megabytes[type]);
+ break;
+
+ case VFL_TYPE_RADIO:
+ CX18_INFO("Registered device radio%d for %s\n",
+ minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+ break;
+
+ case VFL_TYPE_VBI:
+ if (cx->options.megabytes[type])
+ CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
+ minor - MINOR_VFL_TYPE_VBI_MIN,
+ s->name, cx->options.megabytes[type]);
+ else
+ CX18_INFO("Registered device vbi%d for %s\n",
+ minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+ break;
+ }
+
+ return 0;
+}
+
+/* Register v4l2 devices */
+int cx18_streams_register(struct cx18 *cx)
+{
+ int type;
+ int err = 0;
+
+ /* Register V4L2 devices */
+ for (type = 0; type < CX18_MAX_STREAMS; type++)
+ err |= cx18_reg_dev(cx, type);
+
+ if (err == 0)
+ return 0;
+
+ /* One or more streams could not be initialized. Clean 'em all up. */
+ cx18_streams_cleanup(cx, 1);
+ return -ENOMEM;
+}
+
+/* Unregister v4l2 devices */
+void cx18_streams_cleanup(struct cx18 *cx, int unregister)
+{
+ struct video_device *vdev;
+ int type;
+
+ /* Teardown all streams */
+ for (type = 0; type < CX18_MAX_STREAMS; type++) {
+ if (cx->streams[type].dvb.enabled)
+ cx18_dvb_unregister(&cx->streams[type]);
+
+ vdev = cx->streams[type].v4l2dev;
+
+ cx->streams[type].v4l2dev = NULL;
+ if (vdev == NULL)
+ continue;
+
+ cx18_stream_free(&cx->streams[type]);
+
+ /* Unregister or release device */
+ if (unregister)
+ video_unregister_device(vdev);
+ else
+ video_device_release(vdev);
+ }
+}
+
+static void cx18_vbi_setup(struct cx18_stream *s)
+{
+ struct cx18 *cx = s->cx;
+ int raw = cx->vbi.sliced_in->service_set == 0;
+ u32 data[CX2341X_MBOX_MAX_DATA];
+ int lines;
+
+ if (cx->is_60hz) {
+ cx->vbi.count = 12;
+ cx->vbi.start[0] = 10;
+ cx->vbi.start[1] = 273;
+ } else { /* PAL/SECAM */
+ cx->vbi.count = 18;
+ cx->vbi.start[0] = 6;
+ cx->vbi.start[1] = 318;
+ }
+
+ /* setup VBI registers */
+ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
+
+ /* determine number of lines and total number of VBI bytes.
+ A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
+ The '- 1' byte is probably an unused U or V byte. Or something...
+ A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
+ header, 42 data bytes + checksum (to be confirmed) */
+ if (raw) {
+ lines = cx->vbi.count * 2;
+ } else {
+ lines = cx->is_60hz ? 24 : 38;
+ if (cx->is_60hz)
+ lines += 2;
+ }
+
+ cx->vbi.enc_size = lines *
+ (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
+
+ data[0] = s->handle;
+ /* Lines per field */
+ data[1] = (lines / 2) | ((lines / 2) << 16);
+ /* bytes per line */
+ data[2] = (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
+ /* Every X number of frames a VBI interrupt arrives
+ (frames as in 25 or 30 fps) */
+ data[3] = 1;
+ /* Setup VBI for the cx25840 digitizer */
+ if (raw) {
+ data[4] = 0x20602060;
+ data[5] = 0x30703070;
+ } else {
+ data[4] = 0xB0F0B0F0;
+ data[5] = 0xA0E0A0E0;
+ }
+
+ CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
+ data[0], data[1], data[2], data[3], data[4], data[5]);
+
+ if (s->type == CX18_ENC_STREAM_TYPE_VBI)
+ cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+}
+
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
+{
+ u32 data[MAX_MB_ARGUMENTS];
+ struct cx18 *cx = s->cx;
+ struct list_head *p;
+ int ts = 0;
+ int captype = 0;
+
+ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+ return -EINVAL;
+
+ CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+ switch (s->type) {
+ case CX18_ENC_STREAM_TYPE_MPG:
+ captype = CAPTURE_CHANNEL_TYPE_MPEG;
+ cx->mpg_data_received = cx->vbi_data_inserted = 0;
+ cx->dualwatch_jiffies = jiffies;
+ cx->dualwatch_stereo_mode = cx->params.audio_properties & 0x300;
+ cx->search_pack_header = 0;
+ break;
+
+ case CX18_ENC_STREAM_TYPE_TS:
+ captype = CAPTURE_CHANNEL_TYPE_TS;
+ ts = 1;
+ break;
+ case CX18_ENC_STREAM_TYPE_YUV:
+ captype = CAPTURE_CHANNEL_TYPE_YUV;
+ break;
+ case CX18_ENC_STREAM_TYPE_PCM:
+ captype = CAPTURE_CHANNEL_TYPE_PCM;
+ break;
+ case CX18_ENC_STREAM_TYPE_VBI:
+ captype = cx->vbi.sliced_in->service_set ?
+ CAPTURE_CHANNEL_TYPE_SLICED_VBI : CAPTURE_CHANNEL_TYPE_VBI;
+ cx->vbi.frame = 0;
+ cx->vbi.inserted_frame = 0;
+ memset(cx->vbi.sliced_mpeg_size,
+ 0, sizeof(cx->vbi.sliced_mpeg_size));
+ break;
+ default:
+ return -EINVAL;
+ }
+ s->buffers_stolen = 0;
+
+ /* mute/unmute video */
+ cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+ s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags));
+
+ /* Clear Streamoff flags in case left from last capture */
+ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+ cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
+ s->handle = data[0];
+ cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
+
+ if (atomic_read(&cx->ana_capturing) == 0 && !ts) {
+ /* Stuff from Windows, we don't know what it is */
+ cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12);
+
+ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
+ s->handle, cx->digitizer, cx->digitizer);
+
+ /* Setup VBI */
+ if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
+ cx18_vbi_setup(s);
+
+ /* assign program index info.
+ Mask 7: select I/P/B, Num_req: 400 max */
+ cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0);
+
+ /* Setup API for Stream */
+ cx2341x_update(cx, cx18_api_func, NULL, &cx->params);
+ }
+
+ if (atomic_read(&cx->tot_capturing) == 0) {
+ clear_bit(CX18_F_I_EOS, &cx->i_flags);
+ write_reg(7, CX18_DSP0_INTERRUPT_MASK);
+ }
+
+ cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
+ (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
+ (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
+
+ list_for_each(p, &s->q_free.list) {
+ struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
+
+ writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
+ writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
+ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ 1, buf->id, s->buf_size);
+ }
+ /* begin_capture */
+ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
+ CX18_DEBUG_WARN("Error starting capture!\n");
+ cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+ return -EINVAL;
+ }
+
+ /* you're live! sit back and await interrupts :) */
+ if (!ts)
+ atomic_inc(&cx->ana_capturing);
+ atomic_inc(&cx->tot_capturing);
+ return 0;
+}
+
+void cx18_stop_all_captures(struct cx18 *cx)
+{
+ int i;
+
+ for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
+ struct cx18_stream *s = &cx->streams[i];
+
+ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+ continue;
+ if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
+ cx18_stop_v4l2_encode_stream(s, 0);
+ }
+}
+
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
+{
+ struct cx18 *cx = s->cx;
+ unsigned long then;
+
+ if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+ return -EINVAL;
+
+ /* This function assumes that you are allowed to stop the capture
+ and that we are actually capturing */
+
+ CX18_DEBUG_INFO("Stop Capture\n");
+
+ if (atomic_read(&cx->tot_capturing) == 0)
+ return 0;
+
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
+ else
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+
+ then = jiffies;
+
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
+#if 0
+ /* only run these if we're shutting down the last cap */
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long duration;
+
+ then = jiffies;
+ add_wait_queue(&cx->cap_w, &wait);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* TODO: wait 2s for EOS interrupt */
+ while (!test_bit(CX18_F_I_EOS, &cx->i_flags) &&
+ time_before(jiffies, then + msecs_to_jiffies(2000)))
+ schedule_timeout(msecs_to_jiffies(10));
+
+ duration = jiffies_to_msecs(jiffies - then);
+
+ if (!test_bit(CX18_F_I_EOS, &cx->i_flags)) {
+ CX18_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
+ CX18_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
+ } else {
+ CX18_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&cx->cap_w, &wait);
+#else
+ CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
+#endif
+ }
+
+ if (s->type != CX18_ENC_STREAM_TYPE_TS)
+ atomic_dec(&cx->ana_capturing);
+ atomic_dec(&cx->tot_capturing);
+
+ /* Clear capture and no-read bits */
+ clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+ cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+ s->handle = 0xffffffff;
+
+ if (atomic_read(&cx->tot_capturing) > 0)
+ return 0;
+
+ write_reg(5, CX18_DSP0_INTERRUPT_MASK);
+ wake_up(&s->waitq);
+
+ return 0;
+}
+
+u32 cx18_find_handle(struct cx18 *cx)
+{
+ int i;
+
+ /* find first available handle to be used for global settings */
+ for (i = 0; i < CX18_MAX_STREAMS; i++) {
+ struct cx18_stream *s = &cx->streams[i];
+
+ if (s->v4l2dev && s->handle)
+ return s->handle;
+ }
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h
new file mode 100644
index 000000000..f327e947b
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-streams.h
@@ -0,0 +1,33 @@
+/*
+ * cx18 init/start/stop/exit stream functions
+ *
+ * Derived from ivtv-streams.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+u32 cx18_find_handle(struct cx18 *cx);
+int cx18_streams_setup(struct cx18 *cx);
+int cx18_streams_register(struct cx18 *cx);
+void cx18_streams_cleanup(struct cx18 *cx, int unregister);
+
+/* Capture related */
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
+
+void cx18_stop_all_captures(struct cx18 *cx);
diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c
new file mode 100644
index 000000000..22e76ee3f
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-vbi.c
@@ -0,0 +1,208 @@
+/*
+ * cx18 Vertical Blank Interval support functions
+ *
+ * Derived from ivtv-vbi.c
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-vbi.h"
+#include "cx18-ioctl.h"
+#include "cx18-queue.h"
+#include "cx18-av-core.h"
+
+static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
+{
+ int line = 0;
+ int i;
+ u32 linemask[2] = { 0, 0 };
+ unsigned short size;
+ static const u8 mpeg_hdr_data[] = {
+ 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
+ 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
+ 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
+ 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
+ };
+ const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
+ int idx = cx->vbi.frame % CX18_VBI_FRAMES;
+ u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
+
+ for (i = 0; i < lines; i++) {
+ struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
+ int f, l;
+
+ if (sdata->id == 0)
+ continue;
+
+ l = sdata->line - 6;
+ f = sdata->field;
+ if (f)
+ l += 18;
+ if (l < 32)
+ linemask[0] |= (1 << l);
+ else
+ linemask[1] |= (1 << (l - 32));
+ dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
+ memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
+ line++;
+ }
+ memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+ if (line == 36) {
+ /* All lines are used, so there is no space for the linemask
+ (the max size of the VBI data is 36 * 43 + 4 bytes).
+ So in this case we use the magic number 'ITV0'. */
+ memcpy(dst + sd, "ITV0", 4);
+ memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+ size = 4 + ((43 * line + 3) & ~3);
+ } else {
+ memcpy(dst + sd, "cx0", 4);
+ memcpy(dst + sd + 4, &linemask[0], 8);
+ size = 12 + ((43 * line + 3) & ~3);
+ }
+ dst[4+16] = (size + 10) >> 8;
+ dst[5+16] = (size + 10) & 0xff;
+ dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+ dst[10+16] = (pts_stamp >> 22) & 0xff;
+ dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+ dst[12+16] = (pts_stamp >> 7) & 0xff;
+ dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+ cx->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space
+ after the field.
+ Returns new compressed size. */
+static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
+{
+ u32 line_size = cx->vbi.raw_decoder_line_size;
+ u32 lines = cx->vbi.count;
+ u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
+ u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
+ u8 *q = buf;
+ u8 *p;
+ int i;
+
+ for (i = 0; i < lines; i++) {
+ p = buf + i * line_size;
+
+ /* Look for SAV code */
+ if (p[0] != 0xff || p[1] || p[2] ||
+ (p[3] != sav1 && p[3] != sav2))
+ break;
+ memcpy(q, p + 4, line_size - 4);
+ q += line_size - 4;
+ }
+ return lines * (line_size - 4);
+}
+
+
+/* Compressed VBI format, all found sliced blocks put next to one another
+ Returns new compressed size */
+static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
+ u32 size, u8 sav)
+{
+ u32 line_size = cx->vbi.sliced_decoder_line_size;
+ struct v4l2_decode_vbi_line vbi;
+ int i;
+
+ /* find the first valid line */
+ for (i = 0; i < size; i++, buf++) {
+ if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+ break;
+ }
+
+ size -= i;
+ if (size < line_size)
+ return line;
+ for (i = 0; i < size / line_size; i++) {
+ u8 *p = buf + i * line_size;
+
+ /* Look for SAV code */
+ if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
+ continue;
+ vbi.p = p + 4;
+ cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
+ if (vbi.type) {
+ cx->vbi.sliced_data[line].id = vbi.type;
+ cx->vbi.sliced_data[line].field = vbi.is_second_field;
+ cx->vbi.sliced_data[line].line = vbi.line;
+ memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
+ line++;
+ }
+ }
+ return line;
+}
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
+ u64 pts_stamp, int streamtype)
+{
+ u8 *p = (u8 *) buf->buf;
+ u32 size = buf->bytesused;
+ int lines;
+
+ if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
+ return;
+
+ /* Raw VBI data */
+ if (cx->vbi.sliced_in->service_set == 0) {
+ u8 type;
+
+ cx18_buf_swap(buf);
+
+ type = p[3];
+
+ size = buf->bytesused = compress_raw_buf(cx, p, size);
+
+ /* second field of the frame? */
+ if (type == cx->vbi.raw_decoder_sav_even_field) {
+ /* Dirty hack needed for backwards
+ compatibility of old VBI software. */
+ p += size - 4;
+ memcpy(p, &cx->vbi.frame, 4);
+ cx->vbi.frame++;
+ }
+ return;
+ }
+
+ /* Sliced VBI data with data insertion */
+ cx18_buf_swap(buf);
+
+ /* first field */
+ lines = compress_sliced_buf(cx, 0, p, size / 2,
+ cx->vbi.sliced_decoder_sav_odd_field);
+ /* second field */
+ /* experimentation shows that the second half does not always
+ begin at the exact address. So start a bit earlier
+ (hence 32). */
+ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
+ size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
+ /* always return at least one empty line */
+ if (lines == 0) {
+ cx->vbi.sliced_data[0].id = 0;
+ cx->vbi.sliced_data[0].line = 0;
+ cx->vbi.sliced_data[0].field = 0;
+ lines = 1;
+ }
+ buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
+ memcpy(p, &cx->vbi.sliced_data[0], size);
+
+ if (cx->vbi.insert_mpeg)
+ copy_vbi_data(cx, lines, pts_stamp);
+ cx->vbi.frame++;
+}
diff --git a/linux/drivers/media/video/cx18/cx18-vbi.h b/linux/drivers/media/video/cx18/cx18-vbi.h
new file mode 100644
index 000000000..c56ff7d28
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-vbi.h
@@ -0,0 +1,26 @@
+/*
+ * cx18 Vertical Blank Interval support functions
+ *
+ * Derived from ivtv-vbi.h
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
+ u64 pts_stamp, int streamtype);
+int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/linux/drivers/media/video/cx18/cx18-version.h b/linux/drivers/media/video/cx18/cx18-version.h
new file mode 100644
index 000000000..d5c7a6f96
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-version.h
@@ -0,0 +1,34 @@
+/*
+ * cx18 driver version information
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef CX18_VERSION_H
+#define CX18_VERSION_H
+
+#define CX18_DRIVER_NAME "cx18"
+#define CX18_DRIVER_VERSION_MAJOR 1
+#define CX18_DRIVER_VERSION_MINOR 0
+#define CX18_DRIVER_VERSION_PATCHLEVEL 0
+
+#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
+#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
+ CX18_DRIVER_VERSION_MINOR, CX18_DRIVER_VERSION_PATCHLEVEL)
+
+#endif
diff --git a/linux/drivers/media/video/cx18/cx18-video.c b/linux/drivers/media/video/cx18/cx18-video.c
new file mode 100644
index 000000000..2e5c41939
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-video.c
@@ -0,0 +1,45 @@
+/*
+ * cx18 video interface functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-video.h"
+#include "cx18-av-core.h"
+#include "cx18-cards.h"
+
+void cx18_video_set_io(struct cx18 *cx)
+{
+ struct v4l2_routing route;
+ int inp = cx->active_input;
+ u32 type;
+
+ route.input = cx->card->video_inputs[inp].video_input;
+ route.output = 0;
+ cx18_av_cmd(cx, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+
+ type = cx->card->video_inputs[inp].video_type;
+
+ if (type == CX18_CARD_INPUT_VID_TUNER)
+ route.input = 0; /* Tuner */
+ else if (type < CX18_CARD_INPUT_COMPOSITE1)
+ route.input = 2; /* S-Video */
+ else
+ route.input = 1; /* Composite */
+}
diff --git a/linux/drivers/media/video/cx18/cx18-video.h b/linux/drivers/media/video/cx18/cx18-video.h
new file mode 100644
index 000000000..529006a06
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx18-video.h
@@ -0,0 +1,22 @@
+/*
+ * cx18 video interface functions
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+void cx18_video_set_io(struct cx18 *cx);
diff --git a/linux/drivers/media/video/cx18/cx23418.h b/linux/drivers/media/video/cx18/cx23418.h
new file mode 100644
index 000000000..33f78da9d
--- /dev/null
+++ b/linux/drivers/media/video/cx18/cx23418.h
@@ -0,0 +1,458 @@
+/*
+ * cx18 header containing common defines.
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef CX23418_H
+#define CX23418_H
+
+#include <media/cx2341x.h>
+
+#define MGR_CMD_MASK 0x40000000
+/* The MSB of the command code indicates that this is the completion of a
+ command */
+#define MGR_CMD_MASK_ACK (MGR_CMD_MASK | 0x80000000)
+
+/* Description: This command creates a new instance of a certain task
+ IN[0] - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
+ the processor on which the task YYY will be created
+ OUT[0] - Task handle. This handle is passed along with commands to
+ dispatch to the right instance of the task
+ ReturnCode - One of the ERR_SYS_... */
+#define CX18_CREATE_TASK (MGR_CMD_MASK | 0x0001)
+
+/* Description: This command destroys an instance of a task
+ IN[0] - Task handle. Hanlde of the task to destroy
+ ReturnCode - One of the ERR_SYS_... */
+#define CX18_DESTROY_TASK (MGR_CMD_MASK | 0x0002)
+
+/* All commands for CPU have the following mask set */
+#define CPU_CMD_MASK 0x20000000
+#define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000)
+#define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000)
+#define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000)
+
+#define EPU_CMD_MASK 0x02000000
+#define EPU_CMD_MASK_DEBUG (EPU_CMD_MASK | 0x000000)
+#define EPU_CMD_MASK_DE (EPU_CMD_MASK | 0x040000)
+
+/* Description: This command indicates that a Memory Descriptor List has been
+ filled with the requested channel type
+ IN[0] - Task handle. Handle of the task
+ IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
+ IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
+ ReturnCode - One of the ERR_DE_... */
+#define CX18_EPU_DMA_DONE (EPU_CMD_MASK_DE | 0x0001)
+
+/* Something interesting happened
+ IN[0] - A value to log
+ IN[1] - An offset of a string in the MiniMe memory;
+ 0/zero/NULL means "I have nothing to say" */
+#define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Description: This command starts streaming with the set channel type
+ IN[0] - Task handle. Handle of the task to start
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_START (CPU_CMD_MASK_CAPTURE | 0x0002)
+
+/* Description: This command stops streaming with the set channel type
+ IN[0] - Task handle. Handle of the task to stop
+ IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_STOP (CPU_CMD_MASK_CAPTURE | 0x0003)
+
+/* Description: This command pauses streaming with the set channel type
+ IN[0] - Task handle. Handle of the task to pause
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_PAUSE (CPU_CMD_MASK_CAPTURE | 0x0007)
+
+/* Description: This command resumes streaming with the set channel type
+ IN[0] - Task handle. Handle of the task to resume
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_RESUME (CPU_CMD_MASK_CAPTURE | 0x0008)
+
+#define CAPTURE_CHANNEL_TYPE_NONE 0
+#define CAPTURE_CHANNEL_TYPE_MPEG 1
+#define CAPTURE_CHANNEL_TYPE_INDEX 2
+#define CAPTURE_CHANNEL_TYPE_YUV 3
+#define CAPTURE_CHANNEL_TYPE_PCM 4
+#define CAPTURE_CHANNEL_TYPE_VBI 5
+#define CAPTURE_CHANNEL_TYPE_SLICED_VBI 6
+#define CAPTURE_CHANNEL_TYPE_TS 7
+#define CAPTURE_CHANNEL_TYPE_MAX 15
+
+/* Description: This command sets the channel type. This can only be done
+ when stopped.
+ IN[0] - Task handle. Handle of the task to start
+ IN[1] - Channel Type. See Below.
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CHANNEL_TYPE (CPU_CMD_MASK_CAPTURE + 1)
+
+/* Description: Set stream output type
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - type
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_STREAM_OUTPUT_TYPE (CPU_CMD_MASK_CAPTURE | 0x0012)
+
+/* Description: Set video input resolution and frame rate
+ IN[0] - task handle
+ IN[1] - reserved
+ IN[2] - reserved
+ IN[3] - reserved
+ IN[4] - reserved
+ IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_IN (CPU_CMD_MASK_CAPTURE | 0x0004)
+
+/* Description: Set video frame rate
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - video bit rate mode
+ IN[2] - video average rate
+ IN[3] - video peak rate
+ IN[4] - system mux rate
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RATE (CPU_CMD_MASK_CAPTURE | 0x0005)
+
+/* Description: Set video output resolution
+ IN[0] - task handle
+ IN[1] - horizontal size
+ IN[2] - vertical size
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RESOLUTION (CPU_CMD_MASK_CAPTURE | 0x0006)
+
+/* Description: This command set filter parameters
+ IN[0] - Task handle. Handle of the task
+ IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
+ IN[2] - mode, temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
+ median: 0 = disable, 1 = horizontal, 2 = vertical,
+ 3 = horizontal/vertical, 4 = diagonal
+ IN[3] - strength, temporal 0 - 31, spatial 0 - 15
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_FILTER_PARAM (CPU_CMD_MASK_CAPTURE | 0x0009)
+
+/* Description: This command set spatial filter type
+ IN[0] - Task handle.
+ IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
+ 3 = 2D H/V separable, 4 = 2D symmetric non-separable
+ IN[2] - chroma type: 0 - diable, 1 = 1D horizontal
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SPATIAL_FILTER_TYPE (CPU_CMD_MASK_CAPTURE | 0x000C)
+
+/* Description: This command set coring levels for median filter
+ IN[0] - Task handle.
+ IN[1] - luma_high
+ IN[2] - luma_low
+ IN[3] - chroma_high
+ IN[4] - chroma_low
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E)
+
+/* Description: This command set the picture type mask for index file
+ IN[0] - 0 = disable index file output
+ 1 = output I picture
+ 2 = P picture
+ 4 = B picture
+ other = illegal */
+#define CX18_CPU_SET_INDEXTABLE (CPU_CMD_MASK_CAPTURE | 0x0010)
+
+/* Description: Set audio parameters
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - audio parameter
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PARAMETERS (CPU_CMD_MASK_CAPTURE | 0x0011)
+
+/* Description: Set video mute
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - bit31-24: muteYvalue
+ bit23-16: muteUvalue
+ bit15-8: muteVvalue
+ bit0: 1:mute, 0: unmute
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_MUTE (CPU_CMD_MASK_CAPTURE | 0x0013)
+
+/* Description: Set audio mute
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - mute/unmute
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_MUTE (CPU_CMD_MASK_CAPTURE | 0x0014)
+
+/* Description: Set stream output type
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - subType
+ SET_INITIAL_SCR 1
+ SET_QUALITY_MODE 2
+ SET_VIM_PROTECT_MODE 3
+ SET_PTS_CORRECTION 4
+ SET_USB_FLUSH_MODE 5
+ SET_MERAQPAR_ENABLE 6
+ SET_NAV_PACK_INSERTION 7
+ SET_SCENE_CHANGE_ENABLE 8
+ IN[2] - parameter 1
+ IN[3] - parameter 2
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MISC_PARAMETERS (CPU_CMD_MASK_CAPTURE | 0x0015)
+
+/* Description: Set raw VBI parameters
+ IN[0] - Task handle
+ IN[1] - No. of input lines per field:
+ bit[15:0]: field 1,
+ bit[31:16]: field 2
+ IN[2] - No. of input bytes per line
+ IN[3] - No. of output frames per transfer
+ IN[4] - start code
+ IN[5] - stop code
+ ReturnCode */
+#define CX18_CPU_SET_RAW_VBI_PARAM (CPU_CMD_MASK_CAPTURE | 0x0016)
+
+/* Description: Set capture line No.
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - height1
+ IN[2] - height2
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CAPTURE_LINE_NO (CPU_CMD_MASK_CAPTURE | 0x0017)
+
+/* Description: Set copyright
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - copyright
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_COPYRIGHT (CPU_CMD_MASK_CAPTURE | 0x0018)
+
+/* Description: Set audio PID
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - PID
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PID (CPU_CMD_MASK_CAPTURE | 0x0019)
+
+/* Description: Set video PID
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - PID
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_PID (CPU_CMD_MASK_CAPTURE | 0x001A)
+
+/* Description: Set Vertical Crop Line
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - Line
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VER_CROP_LINE (CPU_CMD_MASK_CAPTURE | 0x001B)
+
+/* Description: Set COP structure
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - M
+ IN[2] - N
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_GOP_STRUCTURE (CPU_CMD_MASK_CAPTURE | 0x001C)
+
+/* Description: Set Scene Change Detection
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - scene change
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SCENE_CHANGE_DETECTION (CPU_CMD_MASK_CAPTURE | 0x001D)
+
+/* Description: Set Aspect Ratio
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - AspectRatio
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_ASPECT_RATIO (CPU_CMD_MASK_CAPTURE | 0x001E)
+
+/* Description: Set Skip Input Frame
+ IN[0] - task handle. Handle of the task to start
+ IN[1] - skip input frames
+ ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SKIP_INPUT_FRAME (CPU_CMD_MASK_CAPTURE | 0x001F)
+
+/* Description: Set sliced VBI parameters -
+ Note This API will only apply to MPEG and Sliced VBI Channels
+ IN[0] - Task handle
+ IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
+ IN[2] - start / stop line
+ bit[15:0] start line number
+ bit[31:16] stop line number
+ IN[3] - number of output frames per interrupt
+ IN[4] - VBI insertion mode
+ bit 0: output user data, 1 - enable
+ bit 1: output private stream, 1 - enable
+ bit 2: mux option, 0 - in GOP, 1 - in picture
+ bit[7:0] private stream ID
+ IN[5] - insertion period while mux option is in picture
+ ReturnCode - VBI data offset */
+#define CX18_CPU_SET_SLICED_VBI_PARAM (CPU_CMD_MASK_CAPTURE | 0x0020)
+
+/* Description: Set the user data place holder
+ IN[0] - type of data (0 for user)
+ IN[1] - Stuffing period
+ IN[2] - ID data size in word (less than 10)
+ IN[3] - Pointer to ID buffer */
+#define CX18_CPU_SET_USERDATA_PLACE_HOLDER (CPU_CMD_MASK_CAPTURE | 0x0021)
+
+
+/* Description:
+ In[0] Task Handle
+ return parameter:
+ Out[0] Reserved
+ Out[1] Video PTS bit[32:2] of last output video frame.
+ Out[2] Video PTS bit[ 1:0] of last output video frame.
+ Out[3] Hardware Video PTS counter bit[31:0],
+ these bits get incremented on every 90kHz clock tick.
+ Out[4] Hardware Video PTS counter bit32,
+ these bits get incremented on every 90kHz clock tick.
+ ReturnCode */
+#define CX18_CPU_GET_ENC_PTS (CPU_CMD_MASK_CAPTURE | 0x0022)
+
+/* Below is the list of commands related to the data exchange */
+#define CPU_CMD_MASK_DE (CPU_CMD_MASK | 0x040000)
+
+/* Description: This command provides the physical base address of the local
+ DDR as viewed by EPU
+ IN[0] - Physical offset where EPU has the local DDR mapped
+ ReturnCode - One of the ERR_DE_... */
+#define CPU_CMD_DE_SetBase (CPU_CMD_MASK_DE | 0x0001)
+
+/* Description: This command provides the offsets in the device memory where
+ the 2 cx18_mdl_ack blocks reside
+ IN[0] - Task handle. Handle of the task to start
+ IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
+ local DDR.
+ IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
+ local DDR.
+ ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL_ACK (CPU_CMD_MASK_DE | 0x0002)
+
+/* Description: This command provides the offset to a Memory Descriptor List
+ IN[0] - Task handle. Handle of the task to start
+ IN[1] - Offset of the MDL from the beginning of the local DDR.
+ IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1]
+ IN[3] - Buffer ID
+ IN[4] - Total buffer length
+ ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL (CPU_CMD_MASK_DE | 0x0005)
+
+/* Description: This command requests return of all current Memory
+ Descriptor Lists to the driver
+ IN[0] - Task handle. Handle of the task to start
+ ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */
+
+/* Description: This command signals the cpu that the dat buffer has been
+ consumed and ready for re-use.
+ IN[0] - Task handle. Handle of the task
+ IN[1] - Offset of the data block from the beginning of the local DDR.
+ IN[2] - Number of bytes in the data block
+ ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_RELEASE_BUFFER (CPU_CMD_MASK_DE | 0x0007) */
+
+/* No Error / Success */
+#define CNXT_OK 0x000000
+
+/* Received unknown command */
+#define CXERR_UNK_CMD 0x000001
+
+/* First parameter in the command is invalid */
+#define CXERR_INVALID_PARAM1 0x000002
+
+/* Second parameter in the command is invalid */
+#define CXERR_INVALID_PARAM2 0x000003
+
+/* Device interface is not open/found */
+#define CXERR_DEV_NOT_FOUND 0x000004
+
+/* Requested function is not implemented/available */
+#define CXERR_NOTSUPPORTED 0x000005
+
+/* Invalid pointer is provided */
+#define CXERR_BADPTR 0x000006
+
+/* Unable to allocate memory */
+#define CXERR_NOMEM 0x000007
+
+/* Object/Link not found */
+#define CXERR_LINK 0x000008
+
+/* Device busy, command cannot be executed */
+#define CXERR_BUSY 0x000009
+
+/* File/device/handle is not open. */
+#define CXERR_NOT_OPEN 0x00000A
+
+/* Value is out of range */
+#define CXERR_OUTOFRANGE 0x00000B
+
+/* Buffer overflow */
+#define CXERR_OVERFLOW 0x00000C
+
+/* Version mismatch */
+#define CXERR_BADVER 0x00000D
+
+/* Operation timed out */
+#define CXERR_TIMEOUT 0x00000E
+
+/* Operation aborted */
+#define CXERR_ABORT 0x00000F
+
+/* Specified I2C device not found for read/write */
+#define CXERR_I2CDEV_NOTFOUND 0x000010
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_XFERERR 0x000011
+
+/* Chanel changing component not ready */
+#define CXERR_CHANNELNOTREADY 0x000012
+
+/* PPU (Presensation/Decoder) mail box is corrupted */
+#define CXERR_PPU_MB_CORRUPT 0x000013
+
+/* CPU (Capture/Encoder) mail box is corrupted */
+#define CXERR_CPU_MB_CORRUPT 0x000014
+
+/* APU (Audio) mail box is corrupted */
+#define CXERR_APU_MB_CORRUPT 0x000015
+
+/* Unable to open file for reading */
+#define CXERR_FILE_OPEN_READ 0x000016
+
+/* Unable to open file for writing */
+#define CXERR_FILE_OPEN_WRITE 0x000017
+
+/* Unable to find the I2C section specified */
+#define CXERR_I2C_BADSECTION 0x000018
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_DATALOW 0x000019
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_CLOCKLOW 0x00001A
+
+/* No Interrupt received from HW (for I2C access) */
+#define CXERR_NO_HW_I2C_INTR 0x00001B
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NOT_READY 0x00001C
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NO_ACK 0x00001D
+
+/* The are no buffers ready. Try again soon! */
+#define CXERR_NODATA_AGAIN 0x00001E
+
+/* The stream is stopping. Function not alllowed now! */
+#define CXERR_STOPPING_STATUS 0x00001F
+
+/* Trying to access hardware when the power is turned OFF */
+#define CXERR_DEVPOWER_OFF 0x000020
+
+#endif /* CX23418_H */
diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig
index 1fd326fe4..7bf14c9a1 100644
--- a/linux/drivers/media/video/cx23885/Kconfig
+++ b/linux/drivers/media/video/cx23885/Kconfig
@@ -1,6 +1,7 @@
config VIDEO_CX23885
tristate "Conexant cx23885 (2388x successor) support"
depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+ depends on HOTPLUG # due to FW_LOADER
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
@@ -8,14 +9,17 @@ config VIDEO_CX23885
select VIDEO_TVEEPROM
select VIDEO_IR
select VIDEOBUF_DVB
- select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+ select VIDEO_CX25840
+ select VIDEO_CX2341X
+ select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE
select DVB_S5H1409 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
- select DVB_PLL if !DVB_FE_CUSTOMISE
- select TUNER_XC2028 if !DVB_FE_CUSTOMIZE
- select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
- select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
- select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+ select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
---help---
This is a video4linux driver for Conexant 23885 based
TV cards.
diff --git a/linux/drivers/media/video/cx23885/Makefile b/linux/drivers/media/video/cx23885/Makefile
index 32c90be50..29c23b44c 100644
--- a/linux/drivers/media/video/cx23885/Makefile
+++ b/linux/drivers/media/video/cx23885/Makefile
@@ -1,8 +1,9 @@
-cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
+cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c
new file mode 100644
index 000000000..1585db931
--- /dev/null
+++ b/linux/drivers/media/video/cx23885/cx23885-417.c
@@ -0,0 +1,1772 @@
+/*
+ *
+ * Support for a cx23417 mpeg encoder via cx23885 host port.
+ *
+ * (c) 2004 Jelle Foks <jelle@foks.8m.com>
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2008 Steven Toth <stoth@hauppauge.com>
+ * - CX23885/7/8 support
+ *
+ * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx2341x.h>
+
+#include "cx23885.h"
+#include "media/cx2341x.h"
+
+#define CX23885_FIRM_IMAGE_SIZE 376836
+#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
+
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs, int, 0644);
+MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+static unsigned int mpeglines = 32;
+module_param(mpeglines, int, 0644);
+MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+static unsigned int mpeglinesize = 512;
+module_param(mpeglinesize, int, 0644);
+MODULE_PARM_DESC(mpeglinesize,
+ "number of bytes in each line of an MPEG buffer, range 512-1024");
+
+static unsigned int v4l_debug;
+module_param(v4l_debug, int, 0644);
+MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
+
+#define dprintk(level, fmt, arg...)\
+ do { if (v4l_debug >= level) \
+ printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
+ } while (0)
+
+static struct cx23885_tvnorm cx23885_tvnorms[] = {
+ {
+ .name = "NTSC-M",
+ .id = V4L2_STD_NTSC_M,
+ }, {
+ .name = "NTSC-JP",
+ .id = V4L2_STD_NTSC_M_JP,
+ }, {
+ .name = "PAL-BG",
+ .id = V4L2_STD_PAL_BG,
+ }, {
+ .name = "PAL-DK",
+ .id = V4L2_STD_PAL_DK,
+ }, {
+ .name = "PAL-I",
+ .id = V4L2_STD_PAL_I,
+ }, {
+ .name = "PAL-M",
+ .id = V4L2_STD_PAL_M,
+ }, {
+ .name = "PAL-N",
+ .id = V4L2_STD_PAL_N,
+ }, {
+ .name = "PAL-Nc",
+ .id = V4L2_STD_PAL_Nc,
+ }, {
+ .name = "PAL-60",
+ .id = V4L2_STD_PAL_60,
+ }, {
+ .name = "SECAM-L",
+ .id = V4L2_STD_SECAM_L,
+ }, {
+ .name = "SECAM-DK",
+ .id = V4L2_STD_SECAM_DK,
+ }
+};
+
+/* ------------------------------------------------------------------ */
+enum cx23885_capture_type {
+ CX23885_MPEG_CAPTURE,
+ CX23885_RAW_CAPTURE,
+ CX23885_RAW_PASSTHRU_CAPTURE
+};
+enum cx23885_capture_bits {
+ CX23885_RAW_BITS_NONE = 0x00,
+ CX23885_RAW_BITS_YUV_CAPTURE = 0x01,
+ CX23885_RAW_BITS_PCM_CAPTURE = 0x02,
+ CX23885_RAW_BITS_VBI_CAPTURE = 0x04,
+ CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+ CX23885_RAW_BITS_TO_HOST_CAPTURE = 0x10
+};
+enum cx23885_capture_end {
+ CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
+ CX23885_END_NOW, /* stop immediately, no irq */
+};
+enum cx23885_framerate {
+ CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+ CX23885_FRAMERATE_PAL_25 /* PAL: 25fps */
+};
+enum cx23885_stream_port {
+ CX23885_OUTPUT_PORT_MEMORY,
+ CX23885_OUTPUT_PORT_STREAMING,
+ CX23885_OUTPUT_PORT_SERIAL
+};
+enum cx23885_data_xfer_status {
+ CX23885_MORE_BUFFERS_FOLLOW,
+ CX23885_LAST_BUFFER,
+};
+enum cx23885_picture_mask {
+ CX23885_PICTURE_MASK_NONE,
+ CX23885_PICTURE_MASK_I_FRAMES,
+ CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
+ CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum cx23885_vbi_mode_bits {
+ CX23885_VBI_BITS_SLICED,
+ CX23885_VBI_BITS_RAW,
+};
+enum cx23885_vbi_insertion_bits {
+ CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+ CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+ CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+ CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+ CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum cx23885_dma_unit {
+ CX23885_DMA_BYTES,
+ CX23885_DMA_FRAMES,
+};
+enum cx23885_dma_transfer_status_bits {
+ CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
+ CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
+ CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum cx23885_pause {
+ CX23885_PAUSE_ENCODING,
+ CX23885_RESUME_ENCODING,
+};
+enum cx23885_copyright {
+ CX23885_COPYRIGHT_OFF,
+ CX23885_COPYRIGHT_ON,
+};
+enum cx23885_notification_type {
+ CX23885_NOTIFICATION_REFRESH,
+};
+enum cx23885_notification_status {
+ CX23885_NOTIFICATION_OFF,
+ CX23885_NOTIFICATION_ON,
+};
+enum cx23885_notification_mailbox {
+ CX23885_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum cx23885_field1_lines {
+ CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
+ CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
+ CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum cx23885_field2_lines {
+ CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
+ CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
+ CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum cx23885_custom_data_type {
+ CX23885_CUSTOM_EXTENSION_USR_DATA,
+ CX23885_CUSTOM_PRIVATE_PACKET,
+};
+enum cx23885_mute {
+ CX23885_UNMUTE,
+ CX23885_MUTE,
+};
+enum cx23885_mute_video_mask {
+ CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
+ CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
+ CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum cx23885_mute_video_shift {
+ CX23885_MUTE_VIDEO_V_SHIFT = 8,
+ CX23885_MUTE_VIDEO_U_SHIFT = 16,
+ CX23885_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* defines below are from ivtv-driver.h */
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+/* Registers */
+/* IVTV_REG_OFFSET */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
+#define IVTV_REG_SPU (0x9050)
+#define IVTV_REG_HW_BLOCKS (0x9054)
+#define IVTV_REG_VPU (0x9058)
+#define IVTV_REG_APU (0xA064)
+
+/**** Bit definitions for MC417_RWD and MC417_OEN registers ***
+ bits 31-16
++-----------+
+| Reserved |
++-----------+
+ bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8
++-------+-------+-------+-------+-------+-------+-------+-------+
+| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+#define MC417_MIWR 0x8000
+#define MC417_MIRD 0x4000
+#define MC417_MICS 0x2000
+#define MC417_MIRDY 0x1000
+#define MC417_MIADDR 0x0F00
+#define MC417_MIDATA 0x00FF
+
+/* MIADDR* nibble definitions */
+#define MCI_MEMORY_DATA_BYTE0 0x000
+#define MCI_MEMORY_DATA_BYTE1 0x100
+#define MCI_MEMORY_DATA_BYTE2 0x200
+#define MCI_MEMORY_DATA_BYTE3 0x300
+#define MCI_MEMORY_ADDRESS_BYTE2 0x400
+#define MCI_MEMORY_ADDRESS_BYTE1 0x500
+#define MCI_MEMORY_ADDRESS_BYTE0 0x600
+#define MCI_REGISTER_DATA_BYTE0 0x800
+#define MCI_REGISTER_DATA_BYTE1 0x900
+#define MCI_REGISTER_DATA_BYTE2 0xA00
+#define MCI_REGISTER_DATA_BYTE3 0xB00
+#define MCI_REGISTER_ADDRESS_BYTE0 0xC00
+#define MCI_REGISTER_ADDRESS_BYTE1 0xD00
+#define MCI_REGISTER_MODE 0xE00
+
+/* Read and write modes */
+#define MCI_MODE_REGISTER_READ 0
+#define MCI_MODE_REGISTER_WRITE 1
+#define MCI_MODE_MEMORY_READ 0
+#define MCI_MODE_MEMORY_WRITE 0x40
+
+/*** Bit definitions for MC417_CTL register ****
+ bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0
++--------+-------------+--------+--------------+------------+
+|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
++--------+-------------+--------+--------------+------------+
+***/
+#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)
+#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)
+#define MC417_UART_GPIO_EN 0x00000001
+
+/* Values for speed control */
+#define MC417_SPD_CTL_SLOW 0x1
+#define MC417_SPD_CTL_MEDIUM 0x0
+#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */
+
+/* Values for GPIO select */
+#define MC417_GPIO_SEL_GPIO3 0x3
+#define MC417_GPIO_SEL_GPIO2 0x2
+#define MC417_GPIO_SEL_GPIO1 0x1
+#define MC417_GPIO_SEL_GPIO0 0x0
+
+void cx23885_mc417_init(struct cx23885_dev *dev)
+{
+ u32 regval;
+
+ dprintk(2, "%s()\n", __func__);
+
+ /* Configure MC417_CTL register to defaults. */
+ regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST) |
+ MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3) |
+ MC417_UART_GPIO_EN;
+ cx_write(MC417_CTL, regval);
+
+ /* Configure MC417_OEN to defaults. */
+ regval = MC417_MIRDY;
+ cx_write(MC417_OEN, regval);
+
+ /* Configure MC417_RWD to defaults. */
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
+ cx_write(MC417_RWD, regval);
+}
+
+static int mc417_wait_ready(struct cx23885_dev *dev)
+{
+ u32 mi_ready;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+ for (;;) {
+ mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
+ if (mi_ready != 0)
+ return 0;
+ if (time_after(jiffies, timeout))
+ return -1;
+ udelay(1);
+ }
+}
+
+static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
+{
+ u32 regval;
+
+ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+ * which is an input.
+ */
+ cx_write(MC417_OEN, MC417_MIRDY);
+
+ /* Write data byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
+ (value & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+
+ /* Transition CS/WR to effect write transaction across bus. */
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
+ ((value >> 8) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
+ ((value >> 16) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 3 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
+ ((value >> 24) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+ (address & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+ ((address >> 8) & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Indicate that this is a write. */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+ MCI_MODE_REGISTER_WRITE;
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Wait for the trans to complete (MC417_MIRDY asserted). */
+ return mc417_wait_ready(dev);
+}
+
+static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
+{
+ int retval;
+ u32 regval;
+ u32 tempval;
+ u32 dataval;
+
+ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+ * which is an input.
+ */
+ cx_write(MC417_OEN, MC417_MIRDY);
+
+ /* Write address byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+ ((address & 0x00FF));
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+ ((address >> 8) & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Indicate that this is a register read. */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+ MCI_MODE_REGISTER_READ;
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Wait for the trans to complete (MC417_MIRDY asserted). */
+ retval = mc417_wait_ready(dev);
+
+ /* switch the DAT0-7 GPIO[10:3] to input mode */
+ cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+ /* Read data byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+ cx_write(MC417_RWD, regval);
+
+ /* Transition RD to effect read transaction across bus.
+ * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+ * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
+ * input only...)
+ */
+ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+ cx_write(MC417_RWD, regval);
+
+ /* Collect byte */
+ tempval = cx_read(MC417_RWD);
+ dataval = tempval & 0x000000FF;
+
+ /* Bring CS and RD high. */
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= ((tempval & 0x000000FF) << 8);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= ((tempval & 0x000000FF) << 16);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 3 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= ((tempval & 0x000000FF) << 24);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ *value = dataval;
+
+ return retval;
+}
+
+int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
+{
+ u32 regval;
+
+ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+ * which is an input.
+ */
+ cx_write(MC417_OEN, MC417_MIRDY);
+
+ /* Write data byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
+ (value & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+
+ /* Transition CS/WR to effect write transaction across bus. */
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
+ ((value >> 8) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
+ ((value >> 16) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write data byte 3 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
+ ((value >> 24) & 0x000000FF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+ MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+ ((address >> 8) & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+ (address & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Wait for the trans to complete (MC417_MIRDY asserted). */
+ return mc417_wait_ready(dev);
+}
+
+int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
+{
+ int retval;
+ u32 regval;
+ u32 tempval;
+ u32 dataval;
+
+ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
+ * which is an input.
+ */
+ cx_write(MC417_OEN, MC417_MIRDY);
+
+ /* Write address byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+ MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+ ((address >> 8) & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Write address byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+ (address & 0xFF);
+ cx_write(MC417_RWD, regval);
+ regval |= MC417_MICS | MC417_MIWR;
+ cx_write(MC417_RWD, regval);
+
+ /* Wait for the trans to complete (MC417_MIRDY asserted). */
+ retval = mc417_wait_ready(dev);
+
+ /* switch the DAT0-7 GPIO[10:3] to input mode */
+ cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+ /* Read data byte 3 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+ cx_write(MC417_RWD, regval);
+
+ /* Transition RD to effect read transaction across bus. */
+ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+ cx_write(MC417_RWD, regval);
+
+ /* Collect byte */
+ tempval = cx_read(MC417_RWD);
+ dataval = ((tempval & 0x000000FF) << 24);
+
+ /* Bring CS and RD high. */
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 2 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= ((tempval & 0x000000FF) << 16);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 1 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= ((tempval & 0x000000FF) << 8);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ /* Read data byte 0 */
+ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+ cx_write(MC417_RWD, regval);
+ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+ cx_write(MC417_RWD, regval);
+ tempval = cx_read(MC417_RWD);
+ dataval |= (tempval & 0x000000FF);
+ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+ cx_write(MC417_RWD, regval);
+
+ *value = dataval;
+
+ return retval;
+}
+
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+char *cmd_to_str(int cmd)
+{
+ switch (cmd) {
+ case CX2341X_ENC_PING_FW:
+ return "PING_FW";
+ case CX2341X_ENC_START_CAPTURE:
+ return "START_CAPTURE";
+ case CX2341X_ENC_STOP_CAPTURE:
+ return "STOP_CAPTURE";
+ case CX2341X_ENC_SET_AUDIO_ID:
+ return "SET_AUDIO_ID";
+ case CX2341X_ENC_SET_VIDEO_ID:
+ return "SET_VIDEO_ID";
+ case CX2341X_ENC_SET_PCR_ID:
+ return "SET_PCR_PID";
+ case CX2341X_ENC_SET_FRAME_RATE:
+ return "SET_FRAME_RATE";
+ case CX2341X_ENC_SET_FRAME_SIZE:
+ return "SET_FRAME_SIZE";
+ case CX2341X_ENC_SET_BIT_RATE:
+ return "SET_BIT_RATE";
+ case CX2341X_ENC_SET_GOP_PROPERTIES:
+ return "SET_GOP_PROPERTIES";
+ case CX2341X_ENC_SET_ASPECT_RATIO:
+ return "SET_ASPECT_RATIO";
+ case CX2341X_ENC_SET_DNR_FILTER_MODE:
+ return "SET_DNR_FILTER_PROPS";
+ case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+ return "SET_DNR_FILTER_PROPS";
+ case CX2341X_ENC_SET_CORING_LEVELS:
+ return "SET_CORING_LEVELS";
+ case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+ return "SET_SPATIAL_FILTER_TYPE";
+ case CX2341X_ENC_SET_VBI_LINE:
+ return "SET_VBI_LINE";
+ case CX2341X_ENC_SET_STREAM_TYPE:
+ return "SET_STREAM_TYPE";
+ case CX2341X_ENC_SET_OUTPUT_PORT:
+ return "SET_OUTPUT_PORT";
+ case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+ return "SET_AUDIO_PROPERTIES";
+ case CX2341X_ENC_HALT_FW:
+ return "HALT_FW";
+ case CX2341X_ENC_GET_VERSION:
+ return "GET_VERSION";
+ case CX2341X_ENC_SET_GOP_CLOSURE:
+ return "SET_GOP_CLOSURE";
+ case CX2341X_ENC_GET_SEQ_END:
+ return "GET_SEQ_END";
+ case CX2341X_ENC_SET_PGM_INDEX_INFO:
+ return "SET_PGM_INDEX_INFO";
+ case CX2341X_ENC_SET_VBI_CONFIG:
+ return "SET_VBI_CONFIG";
+ case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
+ return "SET_DMA_BLOCK_SIZE";
+ case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
+ return "GET_PREV_DMA_INFO_MB_10";
+ case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
+ return "GET_PREV_DMA_INFO_MB_9";
+ case CX2341X_ENC_SCHED_DMA_TO_HOST:
+ return "SCHED_DMA_TO_HOST";
+ case CX2341X_ENC_INITIALIZE_INPUT:
+ return "INITIALIZE_INPUT";
+ case CX2341X_ENC_SET_FRAME_DROP_RATE:
+ return "SET_FRAME_DROP_RATE";
+ case CX2341X_ENC_PAUSE_ENCODER:
+ return "PAUSE_ENCODER";
+ case CX2341X_ENC_REFRESH_INPUT:
+ return "REFRESH_INPUT";
+ case CX2341X_ENC_SET_COPYRIGHT:
+ return "SET_COPYRIGHT";
+ case CX2341X_ENC_SET_EVENT_NOTIFICATION:
+ return "SET_EVENT_NOTIFICATION";
+ case CX2341X_ENC_SET_NUM_VSYNC_LINES:
+ return "SET_NUM_VSYNC_LINES";
+ case CX2341X_ENC_SET_PLACEHOLDER:
+ return "SET_PLACEHOLDER";
+ case CX2341X_ENC_MUTE_VIDEO:
+ return "MUTE_VIDEO";
+ case CX2341X_ENC_MUTE_AUDIO:
+ return "MUTE_AUDIO";
+ case CX2341X_ENC_MISC:
+ return "MISC";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static int cx23885_mbox_func(void *priv,
+ u32 command,
+ int in,
+ int out,
+ u32 data[CX2341X_MBOX_MAX_DATA])
+{
+ struct cx23885_dev *dev = priv;
+ unsigned long timeout;
+ u32 value, flag, retval = 0;
+ int i;
+
+ dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
+ cmd_to_str(command));
+
+ /* this may not be 100% safe if we can't read any memory location
+ without side effects */
+ mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
+ if (value != 0x12345678) {
+ printk(KERN_ERR
+ "Firmware and/or mailbox pointer not initialized "
+ "or corrupted, signature = 0x%x, cmd = %s\n", value,
+ cmd_to_str(command));
+ return -1;
+ }
+
+ /* This read looks at 32 bits, but flag is only 8 bits.
+ * Seems we also bail if CMD or TIMEOUT bytes are set???
+ */
+ mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+ if (flag) {
+ printk(KERN_ERR "ERROR: Mailbox appears to be in use "
+ "(%x), cmd = %s\n", flag, cmd_to_str(command));
+ return -1;
+ }
+
+ flag |= 1; /* tell 'em we're working on it */
+ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+ /* write command + args + fill remaining with zeros */
+ /* command code */
+ mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
+ mc417_memory_write(dev, dev->cx23417_mailbox + 3,
+ IVTV_API_STD_TIMEOUT); /* timeout */
+ for (i = 0; i < in; i++) {
+ mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
+ dprintk(3, "API Input %d = %d\n", i, data[i]);
+ }
+ for (; i < CX2341X_MBOX_MAX_DATA; i++)
+ mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
+
+ flag |= 3; /* tell 'em we're done writing */
+ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+ /* wait for firmware to handle the API command */
+ timeout = jiffies + msecs_to_jiffies(10);
+ for (;;) {
+ mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+ if (0 != (flag & 4))
+ break;
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "ERROR: API Mailbox timeout\n");
+ return -1;
+ }
+ udelay(10);
+ }
+
+ /* read output values */
+ for (i = 0; i < out; i++) {
+ mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
+ dprintk(3, "API Output %d = %d\n", i, data[i]);
+ }
+
+ mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
+ dprintk(3, "API result = %d\n", retval);
+
+ flag = 0;
+ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+ return retval;
+}
+
+/* We don't need to call the API often, so using just one
+ * mailbox will probably suffice
+ */
+static int cx23885_api_cmd(struct cx23885_dev *dev,
+ u32 command,
+ u32 inputcnt,
+ u32 outputcnt,
+ ...)
+{
+ u32 data[CX2341X_MBOX_MAX_DATA];
+ va_list vargs;
+ int i, err;
+
+ dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
+
+ va_start(vargs, outputcnt);
+ for (i = 0; i < inputcnt; i++)
+ data[i] = va_arg(vargs, int);
+
+ err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
+ for (i = 0; i < outputcnt; i++) {
+ int *vptr = va_arg(vargs, int *);
+ *vptr = data[i];
+ }
+ va_end(vargs);
+
+ return err;
+}
+
+static int cx23885_find_mailbox(struct cx23885_dev *dev)
+{
+ u32 signature[4] = {
+ 0x12345678, 0x34567812, 0x56781234, 0x78123456
+ };
+ int signaturecnt = 0;
+ u32 value;
+ int i;
+
+ dprintk(2, "%s()\n", __func__);
+
+ for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
+ mc417_memory_read(dev, i, &value);
+ if (value == signature[signaturecnt])
+ signaturecnt++;
+ else
+ signaturecnt = 0;
+ if (4 == signaturecnt) {
+ dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
+ return i+1;
+ }
+ }
+ printk(KERN_ERR "Mailbox signature values not found!\n");
+ return -1;
+}
+
+static int cx23885_load_firmware(struct cx23885_dev *dev)
+{
+ static const unsigned char magic[8] = {
+ 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+ };
+ const struct firmware *firmware;
+ int i, retval = 0;
+ u32 value = 0;
+ u32 gpio_output = 0;
+ u32 checksum = 0;
+ u32 *dataptr;
+
+ dprintk(2, "%s()\n", __func__);
+
+ /* Save GPIO settings before reset of APU */
+ retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
+ retval |= mc417_memory_read(dev, 0x900C, &value);
+
+ retval = mc417_register_write(dev,
+ IVTV_REG_VPU, 0xFFFFFFED);
+ retval |= mc417_register_write(dev,
+ IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+ retval |= mc417_register_write(dev,
+ IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
+ retval |= mc417_register_write(dev,
+ IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+ retval |= mc417_register_write(dev,
+ IVTV_REG_APU, 0);
+
+ if (retval != 0) {
+ printk(KERN_ERR "%s: Error with mc417_register_write\n",
+ __func__);
+ return -1;
+ }
+
+ retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
+ &dev->pci->dev);
+
+ if (retval != 0) {
+ printk(KERN_ERR
+ "ERROR: Hotplug firmware request failed (%s).\n",
+ CX2341X_FIRM_ENC_FILENAME);
+ printk(KERN_ERR "Please fix your hotplug setup, the board will "
+ "not work without firmware loaded!\n");
+ return -1;
+ }
+
+ if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
+ printk(KERN_ERR "ERROR: Firmware size mismatch "
+ "(have %zd, expected %d)\n",
+ firmware->size, CX23885_FIRM_IMAGE_SIZE);
+ release_firmware(firmware);
+ return -1;
+ }
+
+ if (0 != memcmp(firmware->data, magic, 8)) {
+ printk(KERN_ERR
+ "ERROR: Firmware magic mismatch, wrong file?\n");
+ release_firmware(firmware);
+ return -1;
+ }
+
+ /* transfer to the chip */
+ dprintk(2, "Loading firmware ...\n");
+ dataptr = (u32 *)firmware->data;
+ for (i = 0; i < (firmware->size >> 2); i++) {
+ value = *dataptr;
+ checksum += ~value;
+ if (mc417_memory_write(dev, i, value) != 0) {
+ printk(KERN_ERR "ERROR: Loading firmware failed!\n");
+ release_firmware(firmware);
+ return -1;
+ }
+ dataptr++;
+ }
+
+ /* read back to verify with the checksum */
+ dprintk(1, "Verifying firmware ...\n");
+ for (i--; i >= 0; i--) {
+ if (mc417_memory_read(dev, i, &value) != 0) {
+ printk(KERN_ERR "ERROR: Reading firmware failed!\n");
+ release_firmware(firmware);
+ return -1;
+ }
+ checksum -= ~value;
+ }
+ if (checksum) {
+ printk(KERN_ERR
+ "ERROR: Firmware load failed (checksum mismatch).\n");
+ release_firmware(firmware);
+ return -1;
+ }
+ release_firmware(firmware);
+ dprintk(1, "Firmware upload successful.\n");
+
+ retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
+ IVTV_CMD_HW_BLOCKS_RST);
+
+ /* Restore GPIO settings, make sure EIO14 is enabled as an output. */
+ dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n",
+ __func__, gpio_output);
+ /* Power-up seems to have GPIOs AFU. This was causing digital side
+ * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at
+ * power-up.
+ * gpio_output |= (1<<14);
+ */
+ /* Note: GPIO14 is specific to the HVR1800 here */
+ gpio_output = 0x10ff0411 | (1<<14);
+ retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14));
+ dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n",
+ __func__, gpio_output);
+
+ dprintk(1, "%s: GPIO value EIO 0-15 was = 0x%x\n",
+ __func__, value);
+ value |= (1<<14);
+ dprintk(1, "%s: GPIO value EIO 0-15 now = 0x%x\n",
+ __func__, value);
+ retval |= mc417_register_write(dev, 0x900C, value);
+
+ retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+ retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+ if (retval < 0)
+ printk(KERN_ERR "%s: Error with mc417_register_write\n",
+ __func__);
+ return 0;
+}
+
+void cx23885_417_check_encoder(struct cx23885_dev *dev)
+{
+ u32 status, seq;
+
+ status = seq = 0;
+ cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
+ dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
+}
+
+static void cx23885_codec_settings(struct cx23885_dev *dev)
+{
+ dprintk(1, "%s()\n", __func__);
+
+ /* assign frame size */
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+ dev->ts1.height, dev->ts1.width);
+
+ dev->mpeg_params.width = dev->ts1.width;
+ dev->mpeg_params.height = dev->ts1.height;
+ dev->mpeg_params.is_50hz =
+ (dev->encodernorm.id & V4L2_STD_625_50) != 0;
+
+ cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
+
+ cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
+ cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
+}
+
+static int cx23885_initialize_codec(struct cx23885_dev *dev)
+{
+ int version;
+ int retval;
+ u32 i, data[7];
+
+ dprintk(1, "%s()\n", __func__);
+
+ retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+ if (retval < 0) {
+ dprintk(2, "%s() PING OK\n", __func__);
+ retval = cx23885_load_firmware(dev);
+ if (retval < 0) {
+ printk(KERN_ERR "%s() f/w load failed\n", __func__);
+ return retval;
+ }
+ dev->cx23417_mailbox = cx23885_find_mailbox(dev);
+ if (dev->cx23417_mailbox < 0) {
+ printk(KERN_ERR "%s() mailbox < 0, error\n",
+ __func__);
+ return -1;
+ }
+ retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "ERROR: cx23417 firmware ping failed!\n");
+ return -1;
+ }
+ retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
+ &version);
+ if (retval < 0) {
+ printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
+ "version failed!\n");
+ return -1;
+ }
+ dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
+ msleep(200);
+ }
+
+ cx23885_codec_settings(dev);
+ msleep(60);
+
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+ CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+ CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0);
+
+ /* Setup to capture VBI */
+ data[0] = 0x0001BD00;
+ data[1] = 1; /* frames per interrupt */
+ data[2] = 4; /* total bufs */
+ data[3] = 0x91559155; /* start codes */
+ data[4] = 0x206080C0; /* stop codes */
+ data[5] = 6; /* lines */
+ data[6] = 64; /* BPL */
+
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
+ data[2], data[3], data[4], data[5], data[6]);
+
+ for (i = 2; i <= 24; i++) {
+ int valid;
+
+ valid = ((i >= 19) && (i <= 21));
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
+ valid, 0 , 0, 0);
+ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
+ i | 0x80000000, valid, 0, 0, 0);
+ }
+
+ cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
+ msleep(60);
+
+ /* initialize the video input */
+ cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+ msleep(60);
+
+ /* Enable VIP style pixel invalidation so we work with scaled mode */
+ mc417_memory_write(dev, 2120, 0x00000080);
+
+ /* start capturing to the host interface */
+ cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+ CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+ msleep(10);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+ unsigned int *count, unsigned int *size)
+{
+ struct cx23885_fh *fh = q->priv_data;
+
+ fh->dev->ts1.ts_packet_size = mpeglinesize;
+ fh->dev->ts1.ts_packet_count = mpeglines;
+
+ *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+ *count = mpegbufs;
+
+ return 0;
+}
+
+static int bb_buf_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb, enum v4l2_field field)
+{
+ struct cx23885_fh *fh = q->priv_data;
+ return cx23885_buf_prepare(q, &fh->dev->ts1,
+ (struct cx23885_buffer *)vb,
+ field);
+}
+
+static void bb_buf_queue(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ struct cx23885_fh *fh = q->priv_data;
+ cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
+}
+
+static void bb_buf_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+{
+ cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static struct videobuf_queue_ops cx23885_qops = {
+ .buf_setup = bb_buf_setup,
+ .buf_prepare = bb_buf_prepare,
+ .buf_queue = bb_buf_queue,
+ .buf_release = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static const u32 *ctrl_classes[] = {
+ cx2341x_mpeg_ctrls,
+ NULL
+};
+
+static int cx23885_queryctrl(struct cx23885_dev *dev,
+ struct v4l2_queryctrl *qctrl)
+{
+ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ if (qctrl->id == 0)
+ return -EINVAL;
+
+ /* MPEG V4L2 controls */
+ if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
+ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+
+ return 0;
+}
+
+static int cx23885_querymenu(struct cx23885_dev *dev,
+ struct v4l2_querymenu *qmenu)
+{
+ struct v4l2_queryctrl qctrl;
+
+ qctrl.id = qmenu->id;
+ cx23885_queryctrl(dev, &qctrl);
+ return v4l2_ctrl_query_menu(qmenu, &qctrl,
+ cx2341x_ctrl_get_menu(qmenu->id));
+}
+
+int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio,
+ struct cx23885_dev *dev, unsigned int cmd, void *arg,
+ v4l2_kioctl driver_ioctl)
+{
+ int err;
+
+ switch (cmd) {
+ /* ---------- tv norms ---------- */
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+ unsigned int i;
+
+ i = e->index;
+ if (i >= ARRAY_SIZE(cx23885_tvnorms))
+ return -EINVAL;
+ err = v4l2_video_std_construct(e,
+ cx23885_tvnorms[e->index].id,
+ cx23885_tvnorms[e->index].name);
+ e->index = i;
+ if (err < 0)
+ return err;
+ return 0;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ *id = dev->encodernorm.id;
+ return 0;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
+ if (*id & cx23885_tvnorms[i].id)
+ break;
+ if (i == ARRAY_SIZE(cx23885_tvnorms))
+ return -EINVAL;
+ dev->encodernorm = cx23885_tvnorms[i];
+#if 0
+ /* Notify the video decoder and other i2c clients.
+ * This will likely need to be enabled for non NTSC
+ * formats.
+ */
+ cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_S_STD, id);
+ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, id);
+#endif
+
+ return 0;
+ }
+
+ /* ------ input switching ---------- */
+ case VIDIOC_ENUMINPUT:
+ {
+ struct cx23885_input *input;
+ struct v4l2_input *i = arg;
+ unsigned int n;
+
+ n = i->index;
+ if (n >= 4)
+ return -EINVAL;
+ input = &cx23885_boards[dev->board].input[n];
+ if (input->type == 0)
+ return -EINVAL;
+ memset(i, 0, sizeof(*i));
+ i->index = n;
+ /* FIXME
+ * strcpy(i->name, input->name); */
+ strcpy(i->name, "unset");
+ if (input->type == CX23885_VMUX_TELEVISION ||
+ input->type == CX23885_VMUX_CABLE)
+ i->type = V4L2_INPUT_TYPE_TUNER;
+ else
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+
+ for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
+ i->std |= cx23885_tvnorms[n].id;
+ return 0;
+ }
+ case VIDIOC_G_INPUT:
+ {
+ unsigned int *i = arg;
+
+ *i = dev->input;
+ return 0;
+ }
+ case VIDIOC_S_INPUT:
+ {
+ unsigned int *i = arg;
+
+ if (*i >= 4)
+ return -EINVAL;
+
+ return 0;
+ }
+
+ /* --- tuner ioctls ------------------------------------------ */
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (UNSET == dev->tuner_type)
+ return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
+ memset(t, 0, sizeof(*t));
+ strcpy(t->name, "Television");
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
+ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+
+ dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (UNSET == dev->tuner_type)
+ return -EINVAL;
+
+ /* Update the A/V core */
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+
+ return 0;
+ }
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ memset(f, 0, sizeof(*f));
+ if (UNSET == dev->tuner_type)
+ return -EINVAL;
+ f->type = V4L2_TUNER_ANALOG_TV;
+ f->frequency = dev->freq;
+
+ /* Assumption that tuner is always on bus 1 */
+ cx23885_call_i2c_clients(&dev->i2c_bus[1],
+ VIDIOC_G_FREQUENCY, f);
+
+ return 0;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
+ dev->tuner_type);
+ dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
+ f->tuner, f->type);
+ if (UNSET == dev->tuner_type)
+ return -EINVAL;
+ if (f->tuner != 0)
+ return -EINVAL;
+ if (f->type != V4L2_TUNER_ANALOG_TV)
+ return -EINVAL;
+ dev->freq = f->frequency;
+
+ /* Assumption that tuner is always on bus 1 */
+ cx23885_call_i2c_clients(&dev->i2c_bus[1],
+ VIDIOC_S_FREQUENCY, f);
+ return 0;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ /* Update the A/V core */
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg);
+ return 0;
+ }
+ default:
+ /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl
+ * (driver_ioctl) */
+ return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+ driver_ioctl);
+ }
+
+ return 0;
+}
+
+static int mpeg_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+ struct cx23885_tsport *tsport = &dev->ts1;
+
+ if (v4l_debug > 1)
+ v4l_print_ioctl(dev->name, cmd);
+
+ switch (cmd) {
+
+ /* --- capabilities ------------------------------------------ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap, 0, sizeof(*cap));
+ strcpy(cap->driver, dev->name);
+ strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+ sizeof(cap->card));
+ sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+ cap->version = CX23885_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ 0;
+ if (UNSET != dev->tuner_type)
+ cap->capabilities |= V4L2_CAP_TUNER;
+
+ return 0;
+ }
+
+ /* --- capture ioctls ---------------------------------------- */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ int index;
+
+ index = f->index;
+ if (index != 0)
+ return -EINVAL;
+
+ memset(f, 0, sizeof(*f));
+ f->index = index;
+ strlcpy(f->description, "MPEG", sizeof(f->description));
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->pixelformat = V4L2_PIX_FMT_MPEG;
+ return 0;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+
+ memset(f, 0, sizeof(*f));
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage =
+ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+ f->fmt.pix.colorspace = 0;
+ f->fmt.pix.width = dev->ts1.width;
+ f->fmt.pix.height = dev->ts1.height;
+ f->fmt.pix.field = fh->mpegq.field;
+ dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+ dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+ return 0;
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage =
+ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+ f->fmt.pix.sizeimage =
+ f->fmt.pix.colorspace = 0;
+ dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+ dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+ return 0;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage =
+ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+ f->fmt.pix.colorspace = 0;
+ dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+ return 0;
+ }
+
+ /* --- streaming capture ------------------------------------- */
+ case VIDIOC_REQBUFS:
+ return videobuf_reqbufs(&fh->mpegq, arg);
+
+ case VIDIOC_QUERYBUF:
+ return videobuf_querybuf(&fh->mpegq, arg);
+
+ case VIDIOC_QBUF:
+ return videobuf_qbuf(&fh->mpegq, arg);
+
+ case VIDIOC_DQBUF:
+ return videobuf_dqbuf(&fh->mpegq, arg,
+ file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_STREAMON:
+ return videobuf_streamon(&fh->mpegq);
+
+ case VIDIOC_STREAMOFF:
+ return videobuf_streamoff(&fh->mpegq);
+
+ case VIDIOC_G_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *f = arg;
+
+ if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+ return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd);
+ }
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *f = arg;
+ struct cx2341x_mpeg_params p;
+ int err;
+
+ if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+ p = dev->mpeg_params;
+ err = cx2341x_ext_ctrls(&p, 0, f, cmd);
+ if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
+ err = cx2341x_update(dev, cx23885_mbox_func,
+ &dev->mpeg_params, &p);
+ dev->mpeg_params = p;
+ }
+ return err;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+ CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+ CX23885_RAW_BITS_NONE);
+ cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+ mpeg_do_ioctl);
+ cx23885_initialize_codec(dev);
+
+ return 0;
+ }
+ case VIDIOC_LOG_STATUS:
+ {
+ char name[32 + 2];
+
+ snprintf(name, sizeof(name), "%s/2", dev->name);
+ printk(KERN_INFO
+ "%s/2: ============ START LOG STATUS ============\n",
+ dev->name);
+ cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
+ NULL);
+ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
+ NULL);
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
+ NULL);
+ cx2341x_log_status(&dev->mpeg_params, name);
+ printk(KERN_INFO
+ "%s/2: ============= END LOG STATUS =============\n",
+ dev->name);
+ return 0;
+ }
+ case VIDIOC_QUERYMENU:
+ return cx23885_querymenu(dev, arg);
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *c = arg;
+
+ return cx23885_queryctrl(dev, c);
+ }
+
+ default:
+ return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
+ mpeg_do_ioctl);
+ }
+ return 0;
+}
+
+static int mpeg_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+}
+
+static int mpeg_open(struct inode *inode, struct file *file)
+{
+ int minor = iminor(inode);
+ struct cx23885_dev *h, *dev = NULL;
+ struct list_head *list;
+ struct cx23885_fh *fh;
+
+ dprintk(2, "%s()\n", __func__);
+
+ list_for_each(list, &cx23885_devlist) {
+ h = list_entry(list, struct cx23885_dev, devlist);
+ if (h->v4l_device->minor == minor) {
+ dev = h;
+ break;
+ }
+ }
+
+ if (dev == NULL)
+ return -ENODEV;
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh)
+ return -ENOMEM;
+
+ file->private_data = fh;
+ fh->dev = dev;
+
+ videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
+ &dev->pci->dev, &dev->ts1.slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx23885_buffer),
+ fh);
+
+ return 0;
+}
+
+static int mpeg_release(struct inode *inode, struct file *file)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+
+ dprintk(2, "%s()\n", __func__);
+
+ /* FIXME: Review this crap */
+ /* Shut device down on last close */
+ if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+ if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
+ /* stop mpeg capture */
+ cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+ CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+ CX23885_RAW_BITS_NONE);
+
+ msleep(500);
+ cx23885_417_check_encoder(dev);
+
+ cx23885_cancel_buffers(&fh->dev->ts1);
+ }
+ }
+
+ if (fh->mpegq.streaming)
+ videobuf_streamoff(&fh->mpegq);
+ if (fh->mpegq.reading)
+ videobuf_read_stop(&fh->mpegq);
+
+ videobuf_mmap_free(&fh->mpegq);
+ file->private_data = NULL;
+ kfree(fh);
+
+ return 0;
+}
+
+static ssize_t mpeg_read(struct file *file, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+
+ dprintk(2, "%s()\n", __func__);
+
+ /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
+ /* Start mpeg encoder on first read. */
+ if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+ if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
+ if (cx23885_initialize_codec(dev) < 0)
+ return -EINVAL;
+ }
+ }
+
+ return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+ file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int mpeg_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+
+ dprintk(2, "%s\n", __func__);
+
+ return videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+
+ dprintk(2, "%s()\n", __func__);
+
+ return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static struct file_operations mpeg_fops = {
+ .owner = THIS_MODULE,
+ .open = mpeg_open,
+ .release = mpeg_release,
+ .read = mpeg_read,
+ .poll = mpeg_poll,
+ .mmap = mpeg_mmap,
+ .ioctl = mpeg_ioctl,
+ .llseek = no_llseek,
+};
+
+static struct video_device cx23885_mpeg_template = {
+ .name = "cx23885",
+ .type = VID_TYPE_CAPTURE |
+ VID_TYPE_TUNER |
+ VID_TYPE_SCALES |
+ VID_TYPE_MPEG_ENCODER,
+ .fops = &mpeg_fops,
+ .minor = -1,
+};
+
+void cx23885_417_unregister(struct cx23885_dev *dev)
+{
+ dprintk(1, "%s()\n", __func__);
+
+ if (dev->v4l_device) {
+ if (-1 != dev->v4l_device->minor)
+ video_unregister_device(dev->v4l_device);
+ else
+ video_device_release(dev->v4l_device);
+ dev->v4l_device = NULL;
+ }
+}
+
+static struct video_device *cx23885_video_dev_alloc(
+ struct cx23885_tsport *tsport,
+ struct pci_dev *pci,
+ struct video_device *template,
+ char *type)
+{
+ struct video_device *vfd;
+ struct cx23885_dev *dev = tsport->dev;
+
+ dprintk(1, "%s()\n", __func__);
+
+ vfd = video_device_alloc();
+ if (NULL == vfd)
+ return NULL;
+ *vfd = *template;
+ vfd->minor = -1;
+ snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+ type, cx23885_boards[tsport->dev->board].name);
+ vfd->dev = &pci->dev;
+ vfd->release = video_device_release;
+ return vfd;
+}
+
+int cx23885_417_register(struct cx23885_dev *dev)
+{
+ /* FIXME: Port1 hardcoded here */
+ int err = -ENODEV;
+ struct cx23885_tsport *tsport = &dev->ts1;
+
+ dprintk(1, "%s()\n", __func__);
+
+ if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
+ return err;
+
+ /* Set default TV standard */
+ dev->encodernorm = cx23885_tvnorms[0];
+
+ if (dev->encodernorm.id & V4L2_STD_525_60)
+ tsport->height = 480;
+ else
+ tsport->height = 576;
+
+ tsport->width = 720;
+ cx2341x_fill_defaults(&dev->mpeg_params);
+
+ dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+
+ /* Allocate and initialize V4L video device */
+ dev->v4l_device = cx23885_video_dev_alloc(tsport,
+ dev->pci, &cx23885_mpeg_template, "mpeg");
+ err = video_register_device(dev->v4l_device,
+ VFL_TYPE_GRABBER, -1);
+ if (err < 0) {
+ printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
+ return err;
+ }
+
+ /* Initialize MC417 registers */
+ cx23885_mc417_init(dev);
+
+ printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+ dev->name, dev->v4l_device->minor & 0x1f);
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c
index 8a4d5143f..7171e344a 100644
--- a/linux/drivers/media/video/cx23885/cx23885-cards.c
+++ b/linux/drivers/media/video/cx23885/cx23885-cards.c
@@ -74,6 +74,7 @@ struct cx23885_board cx23885_boards[] = {
[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
.name = "Hauppauge WinTV-HVR1800",
.porta = CX23885_ANALOG_VIDEO,
+ .portb = CX23885_MPEG_ENCODER,
.portc = CX23885_MPEG_DVB,
.tuner_type = TUNER_PHILIPS_TDA8290,
.tuner_addr = 0x42, /* 0x84 >> 1 */
@@ -131,6 +132,25 @@ struct cx23885_board cx23885_boards[] = {
.name = "Hauppauge WinTV-HVR1500",
.portc = CX23885_MPEG_DVB,
},
+ [CX23885_BOARD_HAUPPAUGE_HVR1200] = {
+ .name = "Hauppauge WinTV-HVR1200",
+ .portc = CX23885_MPEG_DVB,
+ },
+ [CX23885_BOARD_HAUPPAUGE_HVR1700] = {
+ .name = "Hauppauge WinTV-HVR1700",
+ .portc = CX23885_MPEG_DVB,
+ },
+ [CX23885_BOARD_HAUPPAUGE_HVR1400] = {
+ .name = "Hauppauge WinTV-HVR1400",
+ .portc = CX23885_MPEG_DVB,
+ },
+ [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
+ .name = "DViCO FusionHDTV7 Dual Express",
+#if 0
+ .portb = CX23885_MPEG_DVB,
+#endif
+ .portc = CX23885_MPEG_DVB,
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -182,6 +202,26 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x7717,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x71d1,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1200,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x71d3,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1200,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x8101,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1700,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x8010,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1400,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xd618,
+ .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -221,6 +261,33 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
/* Make sure we support the board model */
switch (tv.model)
{
+ case 71009:
+ /* WinTV-HVR1200 (PCIe, Retail, full height)
+ * DVB-T and basic analog */
+ case 71359:
+ /* WinTV-HVR1200 (PCIe, OEM, half height)
+ * DVB-T and basic analog */
+ case 71439:
+ /* WinTV-HVR1200 (PCIe, OEM, half height)
+ * DVB-T and basic analog */
+ case 71449:
+ /* WinTV-HVR1200 (PCIe, OEM, full height)
+ * DVB-T and basic analog */
+ case 71939:
+ /* WinTV-HVR1200 (PCIe, OEM, half height)
+ * DVB-T and basic analog */
+ case 71949:
+ /* WinTV-HVR1200 (PCIe, OEM, full height)
+ * DVB-T and basic analog */
+ case 71959:
+ /* WinTV-HVR1200 (PCIe, OEM, full height)
+ * DVB-T and basic analog */
+ case 71979:
+ /* WinTV-HVR1200 (PCIe, OEM, half height)
+ * DVB-T and basic analog */
+ case 71999:
+ /* WinTV-HVR1200 (PCIe, OEM, full height)
+ * DVB-T and basic analog */
case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */
case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
@@ -236,6 +303,15 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ case 80019:
+ /* WinTV-HVR1400 (Express Card, Retail, IR,
+ * DVB-T and Basic analog */
+ case 81509:
+ /* WinTV-HVR1700 (PCIe, OEM, No IR, half height)
+ * DVB-T and MPEG2 HW Encoder */
+ case 81519:
+ /* WinTV-HVR1700 (PCIe, OEM, No IR, full height)
+ * DVB-T and MPEG2 HW Encoder */
break;
default:
printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
@@ -265,7 +341,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
}
else {
printk(KERN_ERR
- "%s(): Unknow command.\n", __FUNCTION__);
+ "%s(): Unknow command.\n", __func__);
return -EINVAL;
}
break;
@@ -307,6 +383,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
/* GPIO-15-18 cx23417 READY, CS, RD, WR */
/* GPIO-19 IR_RX */
+ /* CX23417 GPIO's */
+ /* EIO15 Zilog Reset */
+ /* EIO14 S5H1409/CX24227 Reset */
+
/* Force the TDA8295A into reset and back */
cx_set(GP0_IO, 0x00040004);
mdelay(20);
@@ -315,6 +395,50 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx_set(GP0_IO, 0x00040004);
mdelay(20);
break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1200:
+ /* GPIO-0 tda10048 demodulator reset */
+ /* GPIO-2 tda18271 tuner reset */
+
+ /* Put the parts into reset and back */
+ cx_set(GP0_IO, 0x00050000);
+ mdelay(20);
+ cx_clear(GP0_IO, 0x00000005);
+ mdelay(20);
+ cx_set(GP0_IO, 0x00050005);
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ /* GPIO-0 TDA10048 demodulator reset */
+ /* GPIO-2 TDA8295A Reset */
+ /* GPIO-3-10 cx23417 data0-7 */
+ /* GPIO-11-14 cx23417 addr0-3 */
+ /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+
+ /* The following GPIO's are on the interna AVCore (cx25840) */
+ /* GPIO-19 IR_RX */
+ /* GPIO-20 IR_TX 416/DVBT Select */
+ /* GPIO-21 IIS DAT */
+ /* GPIO-22 IIS WCLK */
+ /* GPIO-23 IIS BCLK */
+
+ /* Put the parts into reset and back */
+ cx_set(GP0_IO, 0x00050000);
+ mdelay(20);
+ cx_clear(GP0_IO, 0x00000005);
+ mdelay(20);
+ cx_set(GP0_IO, 0x00050005);
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ /* GPIO-0 Dibcom7000p demodulator reset */
+ /* GPIO-2 xc3028L tuner reset */
+ /* GPIO-13 LED */
+
+ /* Put the parts into reset and back */
+ cx_set(GP0_IO, 0x00050000);
+ mdelay(20);
+ cx_clear(GP0_IO, 0x00000005);
+ mdelay(20);
+ cx_set(GP0_IO, 0x00050005);
+ break;
}
}
@@ -325,6 +449,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1200:
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
/* FIXME: Implement me */
break;
}
@@ -349,33 +475,69 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0x80);
break;
case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ case CX23885_BOARD_HAUPPAUGE_HVR1200:
+ case CX23885_BOARD_HAUPPAUGE_HVR1700:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xc0);
break;
}
switch (dev->board) {
+ case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ /* break omitted intentionally */
case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ /* Defaults for VID B - Analog encoder */
+ /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
+ ts1->gen_ctrl_val = 0x10e;
+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+
+ /* APB_TSVALERR_POL (active low)*/
+ ts1->vld_misc_val = 0x2000;
+ ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+
+ /* Defaults for VID C */
+ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
- case CX23885_BOARD_HAUPPAUGE_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ case CX23885_BOARD_HAUPPAUGE_HVR1200:
+ case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
default:
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
}
+ /* Certain boards support analog, or require the avcore to be
+ * loaded, ensure this happens.
+ */
+ switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+ case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ request_module("cx25840");
+ break;
+ }
}
/* ------------------------------------------------------------------ */
diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c
index 9408d2cd2..95289bb54 100644
--- a/linux/drivers/media/video/cx23885/cx23885-core.c
+++ b/linux/drivers/media/video/cx23885/cx23885-core.c
@@ -191,25 +191,25 @@ static struct sram_channel cx23887_sram_channels[] = {
static int cx23885_risc_decode(u32 risc)
{
static char *instr[16] = {
- [ RISC_SYNC >> 28 ] = "sync",
- [ RISC_WRITE >> 28 ] = "write",
- [ RISC_WRITEC >> 28 ] = "writec",
- [ RISC_READ >> 28 ] = "read",
- [ RISC_READC >> 28 ] = "readc",
- [ RISC_JUMP >> 28 ] = "jump",
- [ RISC_SKIP >> 28 ] = "skip",
- [ RISC_WRITERM >> 28 ] = "writerm",
- [ RISC_WRITECM >> 28 ] = "writecm",
- [ RISC_WRITECR >> 28 ] = "writecr",
+ [RISC_SYNC >> 28] = "sync",
+ [RISC_WRITE >> 28] = "write",
+ [RISC_WRITEC >> 28] = "writec",
+ [RISC_READ >> 28] = "read",
+ [RISC_READC >> 28] = "readc",
+ [RISC_JUMP >> 28] = "jump",
+ [RISC_SKIP >> 28] = "skip",
+ [RISC_WRITERM >> 28] = "writerm",
+ [RISC_WRITECM >> 28] = "writecm",
+ [RISC_WRITECR >> 28] = "writecr",
};
static int incr[16] = {
- [ RISC_WRITE >> 28 ] = 3,
- [ RISC_JUMP >> 28 ] = 3,
- [ RISC_SKIP >> 28 ] = 1,
- [ RISC_SYNC >> 28 ] = 1,
- [ RISC_WRITERM >> 28 ] = 3,
- [ RISC_WRITECM >> 28 ] = 3,
- [ RISC_WRITECR >> 28 ] = 4,
+ [RISC_WRITE >> 28] = 3,
+ [RISC_JUMP >> 28] = 3,
+ [RISC_SKIP >> 28] = 1,
+ [RISC_SYNC >> 28] = 1,
+ [RISC_WRITERM >> 28] = 3,
+ [RISC_WRITECM >> 28] = 3,
+ [RISC_WRITECR >> 28] = 4,
};
static char *bits[] = {
"12", "13", "14", "resync",
@@ -261,7 +261,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
}
if (bc != 1)
printk("%s: %d buffers handled (should be 1)\n",
- __FUNCTION__, bc);
+ __func__, bc);
}
int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -273,7 +273,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
if (ch->cmds_start == 0)
{
- dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,
+ dprintk(1, "%s() Erasing channel [%s]\n", __func__,
ch->name);
cx_write(ch->ptr1_reg, 0);
cx_write(ch->ptr2_reg, 0);
@@ -281,7 +281,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
cx_write(ch->cnt1_reg, 0);
return 0;
} else {
- dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,
+ dprintk(1, "%s() Configuring channel [%s]\n", __func__,
ch->name);
}
@@ -298,7 +298,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
/* write CDT */
for (i = 0; i < lines; i++) {
- dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,
+ dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
ch->fifo_start + bpl*i);
cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
cx_write(cdt + 16*i + 4, 0);
@@ -450,7 +450,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
static void cx23885_reset(struct cx23885_dev *dev)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
cx23885_shutdown(dev);
@@ -483,7 +483,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
static int cx23885_pci_quirks(struct cx23885_dev *dev)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
/* The cx23885 bridge has a weird bug which causes NMI to be asserted
* when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
@@ -514,11 +514,13 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
{
- dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno);
+ dprintk(1, "%s(portno=%d)\n", __func__, portno);
/* Transport bus init dma queue - Common settings */
port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */
port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */
+ port->vld_misc_val = 0x0;
+ port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4);
spin_lock_init(&port->slock);
port->dev = dev;
@@ -545,7 +547,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
port->reg_ts_clk_en = VID_B_TS_CLK_EN;
port->reg_src_sel = VID_B_SRC_SEL;
port->reg_ts_int_msk = VID_B_INT_MSK;
- port->reg_ts_int_stat = VID_B_INT_STAT;
+ port->reg_ts_int_stat = VID_B_INT_STAT;
port->sram_chno = SRAM_CH03; /* VID_B */
port->pci_irqmask = 0x02; /* VID_B bit1 */
break;
@@ -605,14 +607,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
break;
default:
printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
- __FUNCTION__, dev->hwrevision);
+ __func__, dev->hwrevision);
}
if (dev->hwrevision)
printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
- __FUNCTION__, dev->hwrevision);
+ __func__, dev->hwrevision);
else
printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
- __FUNCTION__, dev->hwrevision);
+ __func__, dev->hwrevision);
}
static int cx23885_dev_setup(struct cx23885_dev *dev)
@@ -645,7 +647,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
BUG();
dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
- __FUNCTION__, dev->bridge);
+ __func__, dev->bridge);
/* board config */
dev->board = UNSET;
@@ -698,10 +700,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
- if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
+ (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
cx23885_init_tsport(dev, &dev->ts1, 1);
- if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
+ (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
cx23885_init_tsport(dev, &dev->ts2, 2);
if (get_resources(dev) < 0) {
@@ -735,9 +739,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
dev->radio_addr = cx23885_boards[dev->board].radio_addr;
dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
- __FUNCTION__, dev->tuner_type, dev->tuner_addr);
+ __func__, dev->tuner_type, dev->tuner_addr);
dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
- __FUNCTION__, dev->radio_type, dev->radio_addr);
+ __func__, dev->radio_type, dev->radio_addr);
/* init hardware */
cx23885_reset(dev);
@@ -745,28 +749,43 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_i2c_register(&dev->i2c_bus[0]);
cx23885_i2c_register(&dev->i2c_bus[1]);
cx23885_i2c_register(&dev->i2c_bus[2]);
- cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
cx23885_card_setup(dev);
+ cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
cx23885_ir_init(dev);
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
if (cx23885_video_register(dev) < 0) {
printk(KERN_ERR "%s() Failed to register analog "
- "video adapters on VID_A\n", __FUNCTION__);
+ "video adapters on VID_A\n", __func__);
}
}
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
if (cx23885_dvb_register(&dev->ts1) < 0) {
printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
- __FUNCTION__);
+ __func__);
+ }
+ } else
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+ if (cx23885_417_register(dev) < 0) {
+ printk(KERN_ERR
+ "%s() Failed to register 417 on VID_B\n",
+ __func__);
}
}
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
if (cx23885_dvb_register(&dev->ts2) < 0) {
- printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
- __FUNCTION__);
+ printk(KERN_ERR
+ "%s() Failed to register dvb on VID_C\n",
+ __func__);
+ }
+ } else
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
+ if (cx23885_417_register(dev) < 0) {
+ printk(KERN_ERR
+ "%s() Failed to register 417 on VID_C\n",
+ __func__);
}
}
@@ -786,12 +805,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
cx23885_video_unregister(dev);
- if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
cx23885_dvb_unregister(&dev->ts1);
- if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+ cx23885_417_unregister(dev);
+
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
cx23885_dvb_unregister(&dev->ts2);
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+ cx23885_417_unregister(dev);
+
cx23885_i2c_unregister(&dev->i2c_bus[2]);
cx23885_i2c_unregister(&dev->i2c_bus[1]);
cx23885_i2c_unregister(&dev->i2c_bus[0]);
@@ -799,7 +824,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
iounmap(dev->lmmio);
}
-static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist,
+static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines)
@@ -859,7 +884,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int padding, unsigned int lines)
{
u32 instructions, fields;
- u32 *rp;
+ __le32 *rp;
int rc;
fields = 0;
@@ -900,7 +925,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
unsigned int lines)
{
u32 instructions;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -927,7 +952,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
- u32 *rp;
+ __le32 *rp;
int rc;
if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
@@ -961,50 +986,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
- dprintk(1, "%s() Register Dump\n", __FUNCTION__);
- dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() Register Dump\n", __func__);
+ dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__,
cx_read(DEV_CNTRL2));
- dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__,
cx_read(PCI_INT_MSK));
- dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__,
cx_read(AUDIO_INT_INT_MSK));
- dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__,
cx_read(AUD_INT_DMA_CTL));
- dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __func__,
cx_read(AUDIO_EXT_INT_MSK));
- dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __func__,
cx_read(AUD_EXT_DMA_CTL));
- dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() PAD_CTRL 0x%08X\n", __func__,
cx_read(PAD_CTRL));
- dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __func__,
cx_read(ALT_PIN_OUT_SEL));
- dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() GPIO2 0x%08X\n", __func__,
cx_read(GPIO2));
- dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__,
+ dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __func__,
port->reg_gpcnt, cx_read(port->reg_gpcnt));
- dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __func__,
port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
- dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __func__,
port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
- dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __func__,
port->reg_src_sel, cx_read(port->reg_src_sel));
- dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __func__,
port->reg_lngth, cx_read(port->reg_lngth));
- dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __func__,
port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
- dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __func__,
port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
- dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __func__,
port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
- dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __func__,
port->reg_sop_status, cx_read(port->reg_sop_status));
- dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
- dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __func__,
port->reg_vld_misc, cx_read(port->reg_vld_misc));
- dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __func__,
port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
- dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__,
+ dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __func__,
port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
}
@@ -1013,8 +1038,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
struct cx23885_buffer *buf)
{
struct cx23885_dev *dev = port->dev;
+ u32 reg;
- dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
+ dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
buf->vb.width, buf->vb.height, buf->vb.field);
/* setup fifo + format */
@@ -1032,21 +1058,24 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
- __FUNCTION__,
+ __func__,
cx23885_boards[dev->board].portb,
cx23885_boards[dev->board].portc );
return -EINVAL;
}
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+ cx23885_av_clk(dev, 0);
+
udelay(100);
/* If the port supports SRC SELECT, configure it */
if(port->reg_src_sel)
cx_write(port->reg_src_sel, port->src_sel_val);
- cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
+ cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
- cx_write(port->reg_vld_misc, 0x00);
+ cx_write(port->reg_vld_misc, port->vld_misc_val);
cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
udelay(100);
@@ -1055,11 +1084,26 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_write(port->reg_gpcnt_ctl, 3);
q->count = 1;
+ if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+ reg = cx_read(PAD_CTRL);
+ reg = reg & ~0x1; /* Clear TS1_OE */
+
+ /* FIXME, bit 2 writing here is questionable */
+ /* set TS1_SOP_OE and TS1_OE_HI */
+ reg = reg | 0xa;
+ cx_write(PAD_CTRL, reg);
+
+ /* FIXME and these two registers should be documented. */
+ cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
+ cx_write(ALT_PIN_OUT_SEL, 0x10100045);
+ }
+
switch(dev->bridge) {
case CX23885_BRIDGE_885:
case CX23885_BRIDGE_887:
/* enable irqs */
- dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
+ dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
cx_set(port->reg_dma_ctl, port->dma_ctl_val);
cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1070,6 +1114,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+ cx23885_av_clk(dev, 1);
+
if (debug > 4)
cx23885_tsport_reg_dump(port);
@@ -1079,12 +1126,38 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
static int cx23885_stop_dma(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
+ u32 reg;
+
+ dprintk(1, "%s()\n", __func__);
/* Stop interrupts and DMA */
cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+ if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+
+ reg = cx_read(PAD_CTRL);
+
+ /* Set TS1_OE */
+ reg = reg | 0x1;
+
+ /* clear TS1_SOP_OE and TS1_OE_HI */
+ reg = reg & ~0xa;
+ cx_write(PAD_CTRL, reg);
+#if 0
+ /*
+ * cx_write(CLK_DELAY, cx_read(CLK_DELAY) & ~0x80000011); ????
+ * cx_write(ALT_PIN_OUT_SEL, 0x10100045); ?? need to undo this?
+ */
+#endif
+ cx_write(port->reg_src_sel, 0);
+ cx_write(port->reg_gen_ctrl, 8);
+
+ }
+
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+ cx23885_av_clk(dev, 0);
+
return 0;
}
@@ -1094,13 +1167,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
struct cx23885_dev *dev = port->dev;
struct cx23885_buffer *buf;
- dprintk(5, "%s()\n", __FUNCTION__);
+ dprintk(5, "%s()\n", __func__);
if (list_empty(&q->active))
{
struct cx23885_buffer *prev;
prev = NULL;
- dprintk(5, "%s() queue is empty\n", __FUNCTION__);
+ dprintk(5, "%s() queue is empty\n", __func__);
for (;;) {
if (list_empty(&q->queued))
@@ -1155,7 +1228,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
int size = port->ts_packet_size * port->ts_packet_count;
int rc;
- dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+ dprintk(1, "%s: %p\n", __func__, buf);
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
@@ -1198,7 +1271,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
buf->count = cx88q->count++;
mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
dprintk(1, "[%p/%d] %s - first active\n",
- buf, buf->vb.i, __FUNCTION__);
+ buf, buf->vb.i, __func__);
} else {
dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1209,7 +1282,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
dprintk( 1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.i, __FUNCTION__);
+ buf, buf->vb.i, __func__);
}
}
@@ -1240,7 +1313,6 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
spin_unlock_irqrestore(&port->slock, flags);
}
-#if 0
void cx23885_cancel_buffers(struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
@@ -1251,14 +1323,13 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port)
cx23885_stop_dma(port);
do_cancel_buffers(port, "cancel", 0);
}
-#endif /* 0 */
static void cx23885_timeout(unsigned long data)
{
struct cx23885_tsport *port = (struct cx23885_tsport *)data;
struct cx23885_dev *dev = port->dev;
- dprintk(1, "%s()\n",__FUNCTION__);
+ dprintk(1, "%s()\n",__func__);
if (debug > 5)
cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
@@ -1267,16 +1338,77 @@ static void cx23885_timeout(unsigned long data)
do_cancel_buffers(port, "timeout", 1);
}
+int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
+{
+ /* FIXME: port1 assumption here. */
+ struct cx23885_tsport *port = &dev->ts1;
+ int count = 0;
+ int handled = 0;
+
+ if (status == 0)
+ return handled;
+
+ count = cx_read(port->reg_gpcnt);
+ dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n",
+ status, cx_read(port->reg_ts_int_msk), count);
+
+ if ((status & VID_B_MSK_BAD_PKT) ||
+ (status & VID_B_MSK_OPC_ERR) ||
+ (status & VID_B_MSK_VBI_OPC_ERR) ||
+ (status & VID_B_MSK_SYNC) ||
+ (status & VID_B_MSK_VBI_SYNC) ||
+ (status & VID_B_MSK_OF) ||
+ (status & VID_B_MSK_VBI_OF)) {
+ printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
+ "= 0x%x\n", dev->name, status);
+ if (status & VID_B_MSK_BAD_PKT)
+ dprintk(1, " VID_B_MSK_BAD_PKT\n");
+ if (status & VID_B_MSK_OPC_ERR)
+ dprintk(1, " VID_B_MSK_OPC_ERR\n");
+ if (status & VID_B_MSK_VBI_OPC_ERR)
+ dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n");
+ if (status & VID_B_MSK_SYNC)
+ dprintk(1, " VID_B_MSK_SYNC\n");
+ if (status & VID_B_MSK_VBI_SYNC)
+ dprintk(1, " VID_B_MSK_VBI_SYNC\n");
+ if (status & VID_B_MSK_OF)
+ dprintk(1, " VID_B_MSK_OF\n");
+ if (status & VID_B_MSK_VBI_OF)
+ dprintk(1, " VID_B_MSK_VBI_OF\n");
+
+ cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
+ cx23885_417_check_encoder(dev);
+ } else if (status & VID_B_MSK_RISCI1) {
+ dprintk(7, " VID_B_MSK_RISCI1\n");
+ spin_lock(&port->slock);
+ cx23885_wakeup(port, &port->mpegq, count);
+ spin_unlock(&port->slock);
+ } else if (status & VID_B_MSK_RISCI2) {
+ dprintk(7, " VID_B_MSK_RISCI2\n");
+ spin_lock(&port->slock);
+ cx23885_restart_queue(port, &port->mpegq);
+ spin_unlock(&port->slock);
+ }
+ if (status) {
+ cx_write(port->reg_ts_int_stat, status);
+ handled = 1;
+ }
+
+ return handled;
+}
+
static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
{
struct cx23885_dev *dev = port->dev;
int handled = 0;
u32 count;
- if ( (status & VID_BC_MSK_OPC_ERR) ||
- (status & VID_BC_MSK_BAD_PKT) ||
- (status & VID_BC_MSK_SYNC) ||
- (status & VID_BC_MSK_OF))
+ if ((status & VID_BC_MSK_OPC_ERR) ||
+ (status & VID_BC_MSK_BAD_PKT) ||
+ (status & VID_BC_MSK_SYNC) ||
+ (status & VID_BC_MSK_OF))
{
if (status & VID_BC_MSK_OPC_ERR)
dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
@@ -1290,7 +1422,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
} else if (status & VID_BC_MSK_RISCI1) {
@@ -1395,11 +1528,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
if (ts1_status) {
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
handled += cx23885_irq_ts(ts1, ts1_status);
+ else
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+ handled += cx23885_irq_417(dev, ts1_status);
}
if (ts2_status) {
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
handled += cx23885_irq_ts(ts2, ts2_status);
+ else
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+ handled += cx23885_irq_417(dev, ts2_status);
}
if (vida_status)
@@ -1439,7 +1578,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
"latency: %d, mmio: 0x%llx\n", dev->name,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
- dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));
+ dev->pci_lat,
+ (unsigned long long)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
if (!pci_dma_supported(pci_dev, 0xffffffff)) {
diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c
index 382558866..2c1ae4d38 100644
--- a/linux/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c
@@ -37,10 +37,11 @@
#include "tda18271.h"
#include "lgdt330x.h"
#include "xc5000.h"
-#include "dvb-pll.h"
+#include "tda10048.h"
#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
#include "tuner-simple.h"
+#include "dib7000p.h"
+#include "dibx000_common.h"
static unsigned int debug;
@@ -55,6 +56,8 @@ static unsigned int alt_tuner;
module_param(alt_tuner, int, 0644);
MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
/* ------------------------------------------------------------------ */
static int dvb_buf_setup(struct videobuf_queue *q,
@@ -106,6 +109,13 @@ static struct s5h1409_config hauppauge_generic_config = {
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
+static struct tda10048_config hauppauge_hvr1200_config = {
+ .demod_address = 0x10 >> 1,
+ .output_mode = TDA10048_SERIAL_OUTPUT,
+ .fwbulkwritelen = TDA10048_BULKWRITE_200,
+ .inversion = TDA10048_INVERSION_ON
+};
+
static struct s5h1409_config hauppauge_ezqam_config = {
.demod_address = 0x32 >> 1,
.output_mode = S5H1409_SERIAL_OUTPUT,
@@ -155,12 +165,28 @@ static struct s5h1409_config hauppauge_hvr1500q_config = {
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
+static struct s5h1409_config dvico_s5h1409_config = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_SERIAL_OUTPUT,
+ .gpio = S5H1409_GPIO_ON,
+ .qam_if = 44000,
+ .inversion = S5H1409_INVERSION_OFF,
+ .status_mode = S5H1409_DEMODLOCKING,
+ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
.i2c_address = 0x61,
.if_khz = 5380,
.tuner_callback = cx23885_tuner_callback
};
+static struct xc5000_config dvico_xc5000_tunerconfig = {
+ .i2c_address = 0x64,
+ .if_khz = 5380,
+ .tuner_callback = cx23885_tuner_callback
+};
+
static struct tda829x_config tda829x_no_probe = {
.probe_tuner = TDA829X_DONT_PROBE,
};
@@ -177,6 +203,96 @@ static struct tda18271_config hauppauge_tda18271_config = {
.gate = TDA18271_GATE_ANALOG,
};
+static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+ .gate = TDA18271_GATE_ANALOG,
+};
+
+static struct dibx000_agc_config xc3028_agc_config = {
+ BAND_VHF | BAND_UHF, /* band_caps */
+
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+ * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+ * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
+ * P_agc_nb_est=2, P_agc_write=0
+ */
+ (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+ (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+ 712, /* inv_gain */
+ 21, /* time_stabiliz */
+
+ 0, /* alpha_level */
+ 118, /* thlock */
+
+ 0, /* wbd_inv */
+ 2867, /* wbd_ref */
+ 0, /* wbd_sel */
+ 2, /* wbd_alpha */
+
+ 0, /* agc1_max */
+ 0, /* agc1_min */
+ 39718, /* agc2_max */
+ 9930, /* agc2_min */
+ 0, /* agc1_pt1 */
+ 0, /* agc1_pt2 */
+ 0, /* agc1_pt3 */
+ 0, /* agc1_slope1 */
+ 0, /* agc1_slope2 */
+ 0, /* agc2_pt1 */
+ 128, /* agc2_pt2 */
+ 29, /* agc2_slope1 */
+ 29, /* agc2_slope2 */
+
+ 17, /* alpha_mant */
+ 27, /* alpha_exp */
+ 23, /* beta_mant */
+ 51, /* beta_exp */
+
+ 1, /* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.000000
+ * With external clock = 30.000000 */
+static struct dibx000_bandwidth_config xc3028_bw_config = {
+ 60000, /* internal */
+ 30000, /* sampling */
+ 1, /* pll_cfg: prediv */
+ 8, /* pll_cfg: ratio */
+ 3, /* pll_cfg: range */
+ 1, /* pll_cfg: reset */
+ 0, /* pll_cfg: bypass */
+ 0, /* misc: refdiv */
+ 0, /* misc: bypclk_div */
+ 1, /* misc: IO_CLK_en_core */
+ 1, /* misc: ADClkSrc */
+ 0, /* misc: modulo */
+ (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+ (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+ 20452225, /* timf */
+ 30000000 /* xtal_hz */
+};
+
+static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
+ .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .tuner_is_baseband = 0,
+ .update_lna = NULL,
+
+ .agc_config_count = 1,
+ .agc = &xc3028_agc_config,
+ .bw = &xc3028_bw_config,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .pwm_freq_div = 0,
+ .agc_control = NULL,
+ .spur_protect = 0,
+
+ .output_mode = OUTMODE_MPEG2_SERIAL,
+};
+
static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
{
struct cx23885_tsport *port = ptr;
@@ -186,7 +302,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
/* GPIO-2 xc3028 tuner */
- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
cx_set(GP0_IO, 0x00040000);
cx_clear(GP0_IO, 0x00000004);
@@ -196,10 +312,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
msleep(5);
break;
case XC2028_RESET_CLK:
- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+ dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
break;
default:
- dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
+ dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
command, arg);
return -EINVAL;
}
@@ -285,12 +401,10 @@ static int dvb_register(struct cx23885_tsport *port)
port->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1500q_config,
&dev->i2c_bus[0].i2c_adap);
- if (port->dvb.frontend != NULL) {
- hauppauge_hvr1500q_tunerconfig.priv = i2c_bus;
+ if (port->dvb.frontend != NULL)
dvb_attach(xc5000_attach, port->dvb.frontend,
&i2c_bus->i2c_adap,
- &hauppauge_hvr1500q_tunerconfig);
- }
+ &hauppauge_hvr1500q_tunerconfig, i2c_bus);
break;
case CX23885_BOARD_HAUPPAUGE_HVR1500:
i2c_bus = &dev->i2c_bus[1];
@@ -307,7 +421,47 @@ static int dvb_register(struct cx23885_tsport *port)
static struct xc2028_ctrl ctl = {
.fname = "xc3028-v27.fw",
.max_len = 64,
- .scode_table = OREN538,
+ .scode_table = XC3028_FE_OREN538,
+ };
+
+ fe = dvb_attach(xc2028_attach,
+ port->dvb.frontend, &cfg);
+ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+ fe->ops.tuner_ops.set_config(fe, &ctl);
+ }
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1200:
+ case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ i2c_bus = &dev->i2c_bus[0];
+ port->dvb.frontend = dvb_attach(tda10048_attach,
+ &hauppauge_hvr1200_config,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL) {
+ dvb_attach(tda829x_attach, port->dvb.frontend,
+ &dev->i2c_bus[1].i2c_adap, 0x42,
+ &tda829x_no_probe);
+ dvb_attach(tda18271_attach, port->dvb.frontend,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_hvr1200_tuner_config);
+ }
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ i2c_bus = &dev->i2c_bus[0];
+ port->dvb.frontend = dvb_attach(dib7000p_attach,
+ &i2c_bus->i2c_adap,
+ 0x12, &hauppauge_hvr1400_dib7000_config);
+ if (port->dvb.frontend != NULL) {
+ struct dvb_frontend *fe;
+ struct xc2028_config cfg = {
+ .i2c_adap = &dev->i2c_bus[1].i2c_adap,
+ .i2c_addr = 0x64,
+ .callback = cx23885_hvr1500_xc3028_callback,
+ };
+ static struct xc2028_ctrl ctl = {
+ .fname = "xc3028L-v36.fw",
+ .max_len = 64,
+ .demod = 5000,
+ .d2633 = 1
};
fe = dvb_attach(xc2028_attach,
@@ -316,6 +470,17 @@ static int dvb_register(struct cx23885_tsport *port)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
break;
+ case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+ i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+ port->dvb.frontend = dvb_attach(s5h1409_attach,
+ &dvico_s5h1409_config,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL)
+ dvb_attach(xc5000_attach, port->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &dvico_xc5000_tunerconfig, i2c_bus);
+ break;
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->name);
@@ -334,7 +499,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* register everything */
return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
- &dev->pci->dev);
+ &dev->pci->dev, adapter_nr);
}
int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -342,7 +507,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
struct cx23885_dev *dev = port->dev;
int err;
- dprintk(1, "%s\n", __FUNCTION__);
+ dprintk(1, "%s\n", __func__);
dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
dev->board,
dev->name,
@@ -358,7 +523,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
sizeof(struct cx23885_buffer), port);
err = dvb_register(port);
if (err != 0)
- printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
+ printk("%s() dvb_register failed err = %d\n", __func__, err);
return err;
}
diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c
index ab83c88a9..ba8e27ca9 100644
--- a/linux/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c
@@ -88,10 +88,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
int retval, cnt;
if (joined_rlen)
- dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
+ dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
msg->len, joined_rlen);
else
- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+ dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
/* Deal with i2c probe functions with zero payload */
if (msg->len == 0) {
@@ -102,7 +102,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
if (!i2c_slave_did_ack(i2c_adap))
return -EIO;
- dprintk(1, "%s() returns 0\n", __FUNCTION__);
+ dprintk(1, "%s() returns 0\n", __func__);
return 0;
}
@@ -177,7 +177,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
if (i2c_debug && !joined)
- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
+ dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
/* Deal with i2c probe functions with zero payload */
if (msg->len == 0) {
@@ -189,7 +189,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
return -EIO;
- dprintk(1, "%s() returns 0\n", __FUNCTION__);
+ dprintk(1, "%s() returns 0\n", __func__);
return 0;
}
@@ -239,11 +239,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
struct cx23885_dev *dev = bus->dev;
int i, retval = 0;
- dprintk(1, "%s(num = %d)\n", __FUNCTION__, num);
+ dprintk(1, "%s(num = %d)\n", __func__, num);
for (i = 0 ; i < num; i++) {
dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
- __FUNCTION__, num, msgs[i].addr, msgs[i].len);
+ __func__, num, msgs[i].addr, msgs[i].len);
if (msgs[i].flags & I2C_M_RD) {
/* read */
retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
@@ -374,6 +374,8 @@ static struct i2c_client cx23885_i2c_client_template = {
};
static char *i2c_devs[128] = {
+ [0x10 >> 1] = "tda10048",
+ [0x12 >> 1] = "dib7000pc",
[ 0x1c >> 1 ] = "lgdt3303",
[ 0x86 >> 1 ] = "tda9887",
[ 0x32 >> 1 ] = "cx24227",
@@ -381,7 +383,8 @@ static char *i2c_devs[128] = {
[ 0x84 >> 1 ] = "tda8295",
[ 0xa0 >> 1 ] = "eeprom",
[ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
- [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
+ [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
+ [0xc8 >> 1] = "tuner/xc3028L",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -404,7 +407,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
{
struct cx23885_dev *dev = bus->dev;
- dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
+ dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
sizeof(bus->i2c_adap));
@@ -441,6 +444,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
return 0;
}
+void cx23885_av_clk(struct cx23885_dev *dev, int enable)
+{
+ /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+ char buffer[3];
+ struct i2c_msg msg;
+ dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+ /* Register 0x144 */
+ buffer[0] = 0x01;
+ buffer[1] = 0x44;
+ if (enable == 1)
+ buffer[2] = 0x05;
+ else
+ buffer[2] = 0x00;
+
+ msg.addr = 0x44;
+ msg.flags = I2C_M_TEN;
+ msg.len = 3;
+ msg.buf = buffer;
+
+ i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
/* ----------------------------------------------------------------------- */
/*
diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c
index 702d76493..fdbcd53ab 100644
--- a/linux/drivers/media/video/cx23885/cx23885-video.c
+++ b/linux/drivers/media/video/cx23885/cx23885-video.c
@@ -188,7 +188,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
if (formats[i].fourcc == fourcc)
return formats+i;
- printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
+ printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
return NULL;
}
@@ -342,13 +342,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
}
if (bc != 1)
printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
- __FUNCTION__, bc);
+ __func__, bc);
}
int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
{
dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
- __FUNCTION__,
+ __func__,
(unsigned int)norm,
v4l2_norm_to_name(norm));
@@ -369,7 +369,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
char *type)
{
struct video_device *vfd;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
vfd = video_device_alloc();
if (NULL == vfd)
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query);
static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
unsigned int bit)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (fh->resources & bit)
/* have it already allocated */
return 1;
@@ -444,7 +444,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
unsigned int bits)
{
BUG_ON((fh->resources & bits) != bits);
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
mutex_lock(&dev->lock);
fh->resources &= ~bits;
@@ -459,7 +459,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
memset(&route, 0, sizeof(route));
dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
- __FUNCTION__,
+ __func__,
input, INPUT(input)->vmux,
INPUT(input)->gpio0, INPUT(input)->gpio1,
INPUT(input)->gpio2, INPUT(input)->gpio3);
@@ -484,7 +484,7 @@ EXPORT_SYMBOL(cx23885_video_mux);
int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
unsigned int height, enum v4l2_field field)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
return 0;
}
@@ -492,7 +492,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q,
struct cx23885_buffer *buf)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
/* setup fifo + format */
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
@@ -518,7 +518,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
#ifdef CONFIG_PM
static int cx23885_stop_video_dma(struct cx23885_dev *dev)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
/* stop dma */
cx_clear(VID_A_DMA_CTL, 0x11);
@@ -536,7 +536,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev,
{
struct cx23885_buffer *buf, *prev;
struct list_head *item;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx23885_buffer,
@@ -652,13 +652,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (dev->tvnorm & V4L2_STD_NTSC) {
/* cx25840 transmits NTSC bottom field first */
dprintk(1, "%s() Creating NTSC risc\n",
- __FUNCTION__);
+ __func__);
line0_offset = buf->bpl;
line1_offset = 0;
} else {
/* All other formats are top field first */
dprintk(1, "%s() Creating PAL/SECAM risc\n",
- __FUNCTION__);
+ __func__);
line0_offset = 0;
line1_offset = buf->bpl;
}
@@ -979,7 +979,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
{
- dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
+ dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
return 0;
}
@@ -988,7 +988,7 @@ EXPORT_SYMBOL(cx23885_get_control);
int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
- " (disabled - no action)\n", __FUNCTION__);
+ " (disabled - no action)\n", __func__);
#if 0
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
#endif
@@ -1012,7 +1012,7 @@ static void init_controls(struct cx23885_dev *dev)
/* ------------------------------------------------------------------ */
/* VIDEO IOCTLS */
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx23885_fh *fh = priv;
@@ -1029,7 +1029,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -1080,15 +1080,15 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
int err;
- dprintk(2, "%s()\n", __FUNCTION__);
- err = vidioc_try_fmt_cap(file, priv, f);
+ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_vid_cap(file, priv, f);
if (0 != err)
return err;
@@ -1096,7 +1096,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height;
fh->vidq.field = f->fmt.pix.field;
- dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
+ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
fh->width, fh->height, fh->vidq.field);
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
return 0;
@@ -1125,7 +1125,7 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_cap(struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (unlikely(f->index >= ARRAY_SIZE(formats)))
@@ -1201,7 +1201,7 @@ static int vidioc_streamon(struct file *file, void *priv,
{
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = fh->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
return -EINVAL;
@@ -1218,7 +1218,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = fh->dev;
int err, res;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1236,7 +1236,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
mutex_lock(&dev->lock);
cx23885_set_tvnorm(dev, *tvnorms);
@@ -1259,7 +1259,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
[CX23885_VMUX_DEBUG] = "for debug only",
};
unsigned int n;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
n = i->index;
if (n >= 4)
@@ -1284,7 +1284,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
return cx23885_enum_input(dev, i);
}
@@ -1293,7 +1293,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
*i = dev->input;
- dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
+ dprintk(1, "%s() returns %d\n", __func__, *i);
return 0;
}
@@ -1301,10 +1301,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- dprintk(1, "%s(%d)\n", __FUNCTION__, i);
+ dprintk(1, "%s(%d)\n", __func__, i);
if (i >= 4) {
- dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
+ dprintk(1, "%s() -EINVAL\n", __func__);
return -EINVAL;
}
@@ -1594,7 +1594,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
return handled;
cx_write(VID_A_INT_STAT, status);
- dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
+ dprintk(2, "%s() status = 0x%08x\n", __func__, status);
/* risc op code error */
if (status & (1 << 16)) {
printk(KERN_WARNING "%s/0: video risc op code error\n",
@@ -1667,13 +1667,13 @@ static struct video_device cx23885_video_template = {
.fops = &video_fops,
.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_g_fmt_vbi = cx23885_vbi_fmt,
- .vidioc_try_fmt_vbi = cx23885_vbi_fmt,
- .vidioc_s_fmt_vbi = cx23885_vbi_fmt,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_g_fmt_vbi_cap = cx23885_vbi_fmt,
+ .vidioc_try_fmt_vbi_cap = cx23885_vbi_fmt,
+ .vidioc_s_fmt_vbi_cap = cx23885_vbi_fmt,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
@@ -1736,7 +1736,7 @@ static struct video_device cx23885_radio_template = {
void cx23885_video_unregister(struct cx23885_dev *dev)
{
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
cx_clear(PCI_INT_MSK, 1);
#if 0
@@ -1771,7 +1771,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
{
int err;
- dprintk(1, "%s()\n", __FUNCTION__);
+ dprintk(1, "%s()\n", __func__);
spin_lock_init(&dev->slock);
/* Initialize VBI template */
diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h
index d66fe2484..11ad18af6 100644
--- a/linux/drivers/media/video/cx23885/cx23885.h
+++ b/linux/drivers/media/video/cx23885/cx23885.h
@@ -33,6 +33,7 @@
#include "btcx-risc.h"
#include "cx23885-reg.h"
+#include "media/cx2341x.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
@@ -62,6 +63,10 @@
#define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4
#define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5
#define CX23885_BOARD_HAUPPAUGE_HVR1500 6
+#define CX23885_BOARD_HAUPPAUGE_HVR1200 7
+#define CX23885_BOARD_HAUPPAUGE_HVR1700 8
+#define CX23885_BOARD_HAUPPAUGE_HVR1400 9
+#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
#define CX23885_NORMS (\
@@ -157,6 +162,7 @@ typedef enum {
CX23885_MPEG_UNDEFINED = 0,
CX23885_MPEG_DVB,
CX23885_ANALOG_VIDEO,
+ CX23885_MPEG_ENCODER,
} port_t;
struct cx23885_board {
@@ -255,6 +261,8 @@ struct cx23885_tsport {
u32 gen_ctrl_val;
u32 ts_clk_en_val;
u32 src_sel_val;
+ u32 vld_misc_val;
+ u32 hw_sop_ctrl_val;
};
struct cx23885_dev {
@@ -319,6 +327,14 @@ struct cx23885_dev {
struct cx23885_dmaqueue vidq;
struct cx23885_dmaqueue vbiq;
spinlock_t slock;
+
+ /* MPEG Encoder ONLY settings */
+ u32 cx23417_mailbox;
+ struct cx2341x_mpeg_params mpeg_params;
+ struct video_device *v4l_device;
+ atomic_t v4l_reader_count;
+ struct cx23885_tvnorm encodernorm;
+
};
extern struct list_head cx23885_devlist;
@@ -438,6 +454,18 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus);
extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
void *arg);
+extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
+
+/* ----------------------------------------------------------- */
+/* cx23885-417.c */
+extern int cx23885_417_register(struct cx23885_dev *dev);
+extern void cx23885_417_unregister(struct cx23885_dev *dev);
+extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
+extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
+extern void cx23885_mc417_init(struct cx23885_dev *dev);
+extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
+extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
+
/* ----------------------------------------------------------- */
/* tv norms */
diff --git a/linux/drivers/media/video/cx25840/Kconfig b/linux/drivers/media/video/cx25840/Kconfig
index 7cf29a03e..448f4cd0c 100644
--- a/linux/drivers/media/video/cx25840/Kconfig
+++ b/linux/drivers/media/video/cx25840/Kconfig
@@ -1,6 +1,7 @@
config VIDEO_CX25840
tristate "Conexant CX2584x audio/video decoders"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
---help---
Support for the Conexant CX2584x audio/video decoders.
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c
index 82e7fb267..ca5cc0f51 100644
--- a/linux/drivers/media/video/cx25840/cx25840-core.c
+++ b/linux/drivers/media/video/cx25840/cx25840-core.c
@@ -462,7 +462,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
int chroma = vid_input & 0xf00;
if ((vid_input & ~0xff0) ||
- luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
+ luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 ||
chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
v4l_err(client, "0x%04x is not a valid video input!\n",
vid_input);
@@ -1238,7 +1238,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
/* ----------------------------------------------------------------------- */
-static int cx25840_probe(struct i2c_client *client)
+static int cx25840_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct cx25840_state *state;
u32 id;
@@ -1297,6 +1298,12 @@ static int cx25840_probe(struct i2c_client *client)
state->id = id;
state->rev = device_id;
+ if (state->is_cx23885) {
+ /* Drive GPIO2 direction and values */
+ cx25840_write(client, 0x160, 0x1d);
+ cx25840_write(client, 0x164, 0x00);
+ }
+
return 0;
}
@@ -1306,10 +1313,21 @@ static int cx25840_remove(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id cx25840_id[] = {
+ { "cx25840", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cx25840_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "cx25840",
.driverid = I2C_DRIVERID_CX25840,
.command = cx25840_command,
.probe = cx25840_probe,
.remove = cx25840_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = cx25840_id,
+#endif
};
diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig
index bcf6d9ba0..10e20d819 100644
--- a/linux/drivers/media/video/cx88/Kconfig
+++ b/linux/drivers/media/video/cx88/Kconfig
@@ -2,7 +2,6 @@ config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
depends on VIDEO_DEV && PCI && I2C && INPUT
select I2C_ALGOBIT
- select FW_LOADER
select VIDEO_BTCX
select VIDEOBUF_DMA_SG
select VIDEO_TUNER
@@ -34,8 +33,9 @@ config VIDEO_CX88_ALSA
config VIDEO_CX88_BLACKBIRD
tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
- depends on VIDEO_CX88
+ depends on VIDEO_CX88 && HOTPLUG
select VIDEO_CX2341X
+ select FW_LOADER
---help---
This adds support for MPEG encoder cards based on the
Blackbird reference design, using the Conexant 2388x
@@ -57,7 +57,8 @@ config VIDEO_CX88_DVB
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
- select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
---help---
This adds support for DVB/ATSC cards based on the
Conexant 2388x chip.
diff --git a/linux/drivers/media/video/cx88/Makefile b/linux/drivers/media/video/cx88/Makefile
index 532cee35e..6ec30f242 100644
--- a/linux/drivers/media/video/cx88/Makefile
+++ b/linux/drivers/media/video/cx88/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c
index 56adb9c19..9e87bcb98 100644
--- a/linux/drivers/media/video/cx88/cx88-alsa.c
+++ b/linux/drivers/media/video/cx88/cx88-alsa.c
@@ -553,7 +553,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
#endif
count = atomic_read(&chip->count);
-// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
+// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
// count, new, count & (runtime->periods-1),
// runtime->period_size * (count & (runtime->periods-1)));
return runtime->period_size * (count & (runtime->periods-1));
@@ -755,10 +755,8 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
static int snd_cx88_free(snd_cx88_card_t *chip)
{
- if (chip->irq >= 0){
- synchronize_irq(chip->irq);
+ if (chip->irq >= 0)
free_irq(chip->irq, chip);
- }
cx88_core_put(chip->core,chip->pci);
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c
index ab409da51..781beeb7f 100644
--- a/linux/drivers/media/video/cx88/cx88-blackbird.c
+++ b/linux/drivers/media/video/cx88/cx88-blackbird.c
@@ -319,7 +319,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
u32 value, flag, retval;
int i;
- dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
+ dprintk(1,"%s: 0x%X\n", __func__, command);
/* this may not be 100% safe if we can't read any memory location
without side effects */
@@ -556,10 +556,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
if (retval < 0)
return retval;
- dev->mailbox = blackbird_find_mailbox(dev);
- if (dev->mailbox < 0)
+ retval = blackbird_find_mailbox(dev);
+ if (retval < 0)
return -1;
+ dev->mailbox = retval;
+
retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
dprintk(0, "ERROR: Firmware ping failed!\n");
@@ -757,7 +759,7 @@ static int vidioc_querycap (struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_cap (struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
@@ -769,7 +771,7 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_fh *fh = priv;
@@ -788,7 +790,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_try_fmt_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_fh *fh = priv;
@@ -804,7 +806,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_s_fmt_cap (struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_fh *fh = priv;
@@ -1081,7 +1083,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
dev = cx8802_get_device(inode);
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
if (dev == NULL)
return -ENODEV;
@@ -1091,7 +1093,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
if (drv) {
err = drv->request_acquire(drv);
if(err != 0) {
- dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+ dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
return err;
}
}
@@ -1205,10 +1207,10 @@ static struct video_device cx8802_mpeg_template =
.minor = -1,
.vidioc_querymenu = vidioc_querymenu,
.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_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
@@ -1313,7 +1315,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
struct cx8802_dev *dev = core->dvbdev;
int err;
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
core->boardnr,
core->name,
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index fcecfeed9..1fb39e08e 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -71,6 +71,9 @@ MODULE_PARM_DESC(latency,"pci latency timer");
/* ------------------------------------------------------------------ */
/* board config info */
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
@@ -1410,6 +1413,10 @@ static const struct cx88_board cx88_boards[] = {
}},
/* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xe780,
+ },
},
[CX88_BOARD_ADSTECH_PTV_390] = {
.name = "ADS Tech Instant Video PCI",
@@ -1536,10 +1543,16 @@ static const struct cx88_board cx88_boards[] = {
},
},
[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
- .name = "PowerColor Real Angel 330",
+ .name = "PowerColor RA330", /* Long names may confuse LIRC. */
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.input = { {
+ .type = CX88_VMUX_DEBUG,
+ .vmux = 3, /* Due to the way the cx88 driver is written, */
+ .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */
+ .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */
+ .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */
+ }, { /* from the tuner on boot for a little while. */
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00ff,
@@ -1637,6 +1650,7 @@ static const struct cx88_board cx88_boards[] = {
.vmux = 2,
.gpio0 = 0x16d9,
}},
+ .mpeg = CX88_MPEG_DVB,
},
[CX88_BOARD_PROLINK_PV_8000GT] = {
.name = "Prolink Pixelview MPEG 8000GT",
@@ -2466,8 +2480,9 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
switch (core->boardnr) {
case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
- /* Doesn't work with firmware version 2.7 */
- ctl->fname = "xc3028-v25.fw";
+ /* Now works with firmware version 2.7 */
+ if (core->i2c_algo.udelay < 16)
+ core->i2c_algo.udelay = 16;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
ctl->scode_table = XC3028_FE_ZARLINK456;
@@ -2491,25 +2506,31 @@ EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
static void cx88_card_setup(struct cx88_core *core)
{
static u8 eeprom[256];
+ struct tuner_setup tun_setup;
+ unsigned int mode_mask = T_RADIO |
+ T_ANALOG_TV |
+ T_DIGITAL_TV;
+
+ memset(&tun_setup, 0, sizeof(tun_setup));
if (0 == core->i2c_rc) {
core->i2c_client.addr = 0xa0 >> 1;
- tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
+ tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
}
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_ROSLYN:
if (0 == core->i2c_rc)
- hauppauge_eeprom(core,eeprom+8);
+ hauppauge_eeprom(core, eeprom+8);
break;
case CX88_BOARD_GDI:
if (0 == core->i2c_rc)
- gdi_eeprom(core,eeprom);
+ gdi_eeprom(core, eeprom);
break;
case CX88_BOARD_WINFAST2000XP_EXPERT:
if (0 == core->i2c_rc)
- leadtek_eeprom(core,eeprom);
+ leadtek_eeprom(core, eeprom);
break;
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
@@ -2519,7 +2540,7 @@ static void cx88_card_setup(struct cx88_core *core)
case CX88_BOARD_HAUPPAUGE_HVR3000:
case CX88_BOARD_HAUPPAUGE_HVR1300:
if (0 == core->i2c_rc)
- hauppauge_eeprom(core,eeprom);
+ hauppauge_eeprom(core, eeprom);
break;
case CX88_BOARD_KWORLD_DVBS_100:
cx_write(MO_GP0_IO, 0x000007f8);
@@ -2600,6 +2621,35 @@ static void cx88_card_setup(struct cx88_core *core)
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
}
+ } /*end switch() */
+
+
+ /* Setup tuners */
+ if ((core->board.radio_type != UNSET)) {
+ tun_setup.mode_mask = T_RADIO;
+ tun_setup.type = core->board.radio_type;
+ tun_setup.addr = core->board.radio_addr;
+ tun_setup.tuner_callback = cx88_tuner_callback;
+ cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+ mode_mask &= ~T_RADIO;
+ }
+
+ if (core->board.tuner_type != TUNER_ABSENT) {
+ tun_setup.mode_mask = mode_mask;
+ tun_setup.type = core->board.tuner_type;
+ tun_setup.addr = core->board.tuner_addr;
+ tun_setup.tuner_callback = cx88_tuner_callback;
+
+ cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+
+ if (core->board.tda9887_conf) {
+ struct v4l2_priv_tun_config tda9887_cfg;
+
+ tda9887_cfg.tuner = TUNER_TDA9887;
+ tda9887_cfg.priv = &core->board.tda9887_conf;
+
+ cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg);
}
if (core->board.tuner_type == TUNER_XC2028) {
@@ -2617,6 +2667,7 @@ static void cx88_card_setup(struct cx88_core *core)
ctl.fname);
cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
}
+ cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
}
/* ------------------------------------------------------------------ */
@@ -2755,7 +2806,6 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
if (TUNER_ABSENT != core->board.tuner_type)
request_module("tuner");
- cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
cx88_card_setup(core);
cx88_ir_init(core, pci);
diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c
index a580d3706..5d6265c1d 100644
--- a/linux/drivers/media/video/cx88/cx88-core.c
+++ b/linux/drivers/media/video/cx88/cx88-core.c
@@ -73,7 +73,7 @@ static DEFINE_MUTEX(devlist);
/* @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,
+static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines, unsigned int lpi)
@@ -133,7 +133,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int bpl, unsigned int padding, unsigned int lines)
{
u32 instructions,fields;
- u32 *rp;
+ __le32 *rp;
int rc;
fields = 0;
@@ -171,7 +171,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
unsigned int lines, unsigned int lpi)
{
u32 instructions;
- u32 *rp;
+ __le32 *rp;
int rc;
/* estimate risc mem: worst case is one write per page border +
@@ -196,7 +196,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value)
{
- u32 *rp;
+ __le32 *rp;
int rc;
if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
@@ -575,7 +575,7 @@ void cx88_wakeup(struct cx88_core *core,
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
}
if (bc != 1)
- printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
+ printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
}
void cx88_shutdown(struct cx88_core *core)
@@ -604,7 +604,7 @@ void cx88_shutdown(struct cx88_core *core)
int cx88_reset(struct cx88_core *core)
{
- dprintk(1,"%s\n",__FUNCTION__);
+ dprintk(1,"%s\n",__func__);
cx88_shutdown(core);
/* clear irq status */
diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c
index ab31fdc80..fc5807aeb 100644
--- a/linux/drivers/media/video/cx88/cx88-dvb.c
+++ b/linux/drivers/media/video/cx88/cx88-dvb.c
@@ -46,9 +46,9 @@
#include "nxt200x.h"
#include "cx24123.h"
#include "isl6421.h"
-#include "tuner-xc2028-types.h"
#include "tuner-simple.h"
#include "tda9887.h"
+#include "s5h1411.h"
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -59,6 +59,8 @@ static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
@@ -283,7 +285,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
struct cx8802_dev *dev= fe->dvb->priv;
struct cx88_core *core = dev->core;
- dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
+ dprintk(1, "%s: index = %d\n", __func__, index);
if (index == 0)
cx_clear(MO_GP0_IO, 8);
else
@@ -381,7 +383,7 @@ static int cx88_pci_nano_callback(void *ptr, int command, int arg)
switch (command) {
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
+ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
switch (core->boardnr) {
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
@@ -397,10 +399,10 @@ static int cx88_pci_nano_callback(void *ptr, int command, int arg)
break;
case XC2028_RESET_CLK:
- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
+ dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
break;
default:
- dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
+ dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
command, arg);
return -EINVAL;
}
@@ -469,6 +471,22 @@ static struct zl10353_config cx88_geniatech_x8000_mt = {
#endif
};
+static struct s5h1411_config dvico_fusionhdtv7_config = {
+ .output_mode = S5H1411_SERIAL_OUTPUT,
+ .gpio = S5H1411_GPIO_ON,
+ .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+ .qam_if = S5H1411_IF_44000,
+ .vsb_if = S5H1411_IF_44000,
+ .inversion = S5H1411_INVERSION_OFF,
+ .status_mode = S5H1411_DEMODLOCKING
+};
+
+static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
+ .i2c_address = 0xc2 >> 1,
+ .if_khz = 5380,
+ .tuner_callback = cx88_tuner_callback,
+};
+
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
struct dvb_frontend *fe;
@@ -498,9 +516,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
if (!fe) {
printk(KERN_ERR "%s/2: xc3028 attach failed\n",
dev->core->name);
- dvb_frontend_detach(dev->dvb.frontend);
- dvb_unregister_frontend(dev->dvb.frontend);
- dev->dvb.frontend = NULL;
return -EINVAL;
}
@@ -512,20 +527,23 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
static int dvb_register(struct cx8802_dev *dev)
{
+ struct cx88_core *core = dev->core;
+
/* init struct videobuf_dvb */
- dev->dvb.name = dev->core->name;
+ dev->dvb.name = core->name;
dev->ts_gen_cntrl = 0x0c;
/* init frontend */
- switch (dev->core->boardnr) {
+ switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
dev->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- &dev->core->i2c_adap,
- DVB_PLL_THOMSON_DTT759X);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x61, &core->i2c_adap,
+ DVB_PLL_THOMSON_DTT759X))
+ goto frontend_detach;
}
break;
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
@@ -534,11 +552,12 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_WINFAST_DTV1000:
dev->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- &dev->core->i2c_adap,
- DVB_PLL_THOMSON_DTT7579);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x60, &core->i2c_adap,
+ DVB_PLL_THOMSON_DTT7579))
+ goto frontend_detach;
}
break;
case CX88_BOARD_WINFAST_DTV2000H:
@@ -548,29 +567,32 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_HAUPPAUGE_HVR3000:
dev->dvb.frontend = dvb_attach(cx22702_attach,
&hauppauge_hvr_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_PHILIPS_FMD1216ME_MK3);
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
dev->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- NULL, DVB_PLL_THOMSON_DTT7579);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+ goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
dev->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- NULL, DVB_PLL_THOMSON_DTT7579);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
@@ -578,28 +600,31 @@ static int dvb_register(struct cx8802_dev *dev)
* compatible, with a slightly different MT352 AGC gain. */
dev->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_dual,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, DVB_PLL_THOMSON_DTT7579);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+ goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
dev->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, DVB_PLL_THOMSON_DTT7579);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
dev->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, DVB_PLL_LG_Z201);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x61, NULL, DVB_PLL_LG_Z201))
+ goto frontend_detach;
}
break;
case CX88_BOARD_KWORLD_DVB_T:
@@ -607,10 +632,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_ADSTECH_DVB_T_PCI:
dev->dvb.frontend = dvb_attach(mt352_attach,
&dntv_live_dvbt_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- NULL, DVB_PLL_UNKNOWN_1);
+ if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ 0x61, NULL, DVB_PLL_UNKNOWN_1))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
@@ -619,32 +645,35 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
&dev->vp3054->adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_PHILIPS_FMD1216ME_MK3);
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3))
+ goto frontend_detach;
}
#else
- printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
+ printk(KERN_ERR "%s/2: built without vp3054 support\n",
+ core->name);
#endif
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
dev->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_hybrid,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_THOMSON_FE6600);
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_THOMSON_FE6600))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
dev->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_xc3028,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend == NULL)
dev->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_mt352_xc3028,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
/*
* On this board, the demod provides the I2C bus pullup.
* We must not permit gate_ctrl to be performed, or
@@ -657,19 +686,18 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_PCHDTV_HD3000:
dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_THOMSON_DTT761X);
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_THOMSON_DTT761X))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
dev->ts_gen_cntrl = 0x08;
- {
- /* Do a hardware reset of chip before using it. */
- struct cx88_core *core = dev->core;
+ /* Do a hardware reset of chip before using it. */
cx_clear(MO_GP0_IO, 1);
mdelay(100);
cx_set(MO_GP0_IO, 1);
@@ -679,146 +707,144 @@ static int dvb_register(struct cx8802_dev *dev)
fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_MICROTUNE_4042FI5);
- }
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_MICROTUNE_4042FI5))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
dev->ts_gen_cntrl = 0x08;
- {
- /* Do a hardware reset of chip before using it. */
- struct cx88_core *core = dev->core;
+ /* Do a hardware reset of chip before using it. */
cx_clear(MO_GP0_IO, 1);
mdelay(100);
cx_set(MO_GP0_IO, 9);
mdelay(200);
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_THOMSON_DTT761X);
- }
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_THOMSON_DTT761X))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
dev->ts_gen_cntrl = 0x08;
- {
- /* Do a hardware reset of chip before using it. */
- struct cx88_core *core = dev->core;
+ /* Do a hardware reset of chip before using it. */
cx_clear(MO_GP0_IO, 1);
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_5_gold,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_LG_TDVS_H06XF);
- dvb_attach(tda9887_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x43);
- }
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_LG_TDVS_H06XF))
+ goto frontend_detach;
+ if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x43))
+ goto frontend_detach;
}
break;
case CX88_BOARD_PCHDTV_HD5500:
dev->ts_gen_cntrl = 0x08;
- {
- /* Do a hardware reset of chip before using it. */
- struct cx88_core *core = dev->core;
+ /* Do a hardware reset of chip before using it. */
cx_clear(MO_GP0_IO, 1);
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&pchdtv_hd5500,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_LG_TDVS_H06XF);
- dvb_attach(tda9887_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x43);
- }
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_LG_TDVS_H06XF))
+ goto frontend_detach;
+ if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x43))
+ goto frontend_detach;
}
break;
case CX88_BOARD_ATI_HDTVWONDER:
dev->dvb.frontend = dvb_attach(nxt200x_attach,
&ati_hdtvwonder,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dvb_attach(simple_tuner_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_PHILIPS_TUV1236D);
+ if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_PHILIPS_TUV1236D))
+ goto frontend_detach;
}
break;
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
dev->dvb.frontend = dvb_attach(cx24123_attach,
&hauppauge_novas_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend) {
- dvb_attach(isl6421_attach, dev->dvb.frontend,
- &dev->core->i2c_adap, 0x08, 0x00, 0x00);
+ if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
+ &core->i2c_adap, 0x08, 0x00, 0x00))
+ goto frontend_detach;
}
break;
case CX88_BOARD_KWORLD_DVBS_100:
dev->dvb.frontend = dvb_attach(cx24123_attach,
&kworld_dvbs_100_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend) {
- dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+ core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
}
break;
case CX88_BOARD_GENIATECH_DVBS:
dev->dvb.frontend = dvb_attach(cx24123_attach,
&geniatech_dvbs_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend) {
- dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+ core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
}
break;
case CX88_BOARD_PINNACLE_PCTV_HD_800i:
dev->dvb.frontend = dvb_attach(s5h1409_attach,
&pinnacle_pctv_hd_800i_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
/* tuner_config.video_dev must point to
* i2c_adap.algo_data
*/
- pinnacle_pctv_hd_800i_tuner_config.priv =
- dev->core->i2c_adap.algo_data;
- dvb_attach(xc5000_attach, dev->dvb.frontend,
- &dev->core->i2c_adap,
- &pinnacle_pctv_hd_800i_tuner_config);
+ if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ &core->i2c_adap,
+ &pinnacle_pctv_hd_800i_tuner_config,
+ core->i2c_adap.algo_data))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
dev->dvb.frontend = dvb_attach(s5h1409_attach,
&dvico_hdtv5_pci_nano_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (dev->dvb.frontend != NULL) {
struct dvb_frontend *fe;
struct xc2028_config cfg = {
- .i2c_adap = &dev->core->i2c_adap,
+ .i2c_adap = &core->i2c_adap,
.i2c_addr = 0x61,
.callback = cx88_pci_nano_callback,
};
static struct xc2028_ctrl ctl = {
.fname = "xc3028-v27.fw",
.max_len = 64,
- .scode_table = OREN538,
+ .scode_table = XC3028_FE_OREN538,
};
fe = dvb_attach(xc2028_attach,
@@ -830,35 +856,50 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_PINNACLE_HYBRID_PCTV:
dev->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_geniatech_x8000_mt,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
- return -EINVAL;
+ goto frontend_detach;
break;
case CX88_BOARD_GENIATECH_X8000_MT:
dev->ts_gen_cntrl = 0x00;
dev->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_geniatech_x8000_mt,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
- return -EINVAL;
+ goto frontend_detach;
break;
case CX88_BOARD_KWORLD_ATSC_120:
dev->dvb.frontend = dvb_attach(s5h1409_attach,
&kworld_atsc_120_config,
- &dev->core->i2c_adap);
+ &core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
- return -EINVAL;
+ goto frontend_detach;
+ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+ dev->dvb.frontend = dvb_attach(s5h1411_attach,
+ &dvico_fusionhdtv7_config,
+ &core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+ /* tuner_config.video_dev must point to
+ * i2c_adap.algo_data
+ */
+ if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ &core->i2c_adap,
+ &dvico_fusionhdtv7_tuner_config,
+ core->i2c_adap.algo_data))
+ goto frontend_detach;
+ }
break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
- dev->core->name);
+ core->name);
break;
}
if (NULL == dev->dvb.frontend) {
printk(KERN_ERR
"%s/2: frontend initialization failed\n",
- dev->core->name);
+ core->name);
return -EINVAL;
}
@@ -866,10 +907,18 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
/* Put the analog decoder in standby to keep it quiet */
- cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+ cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
/* register everything */
- return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
+ &dev->pci->dev, adapter_nr);
+
+frontend_detach:
+ if (dev->dvb.frontend) {
+ dvb_frontend_detach(dev->dvb.frontend);
+ dev->dvb.frontend = NULL;
+ }
+ return -EINVAL;
}
/* ----------------------------------------------------------- */
@@ -879,7 +928,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
int err = 0;
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -902,7 +951,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
int err = 0;
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -923,7 +972,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
struct cx8802_dev *dev = drv->core->dvbdev;
int err;
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
core->boardnr,
core->name,
@@ -961,7 +1010,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
struct cx8802_dev *dev = drv->core->dvbdev;
/* dvb */
- videobuf_dvb_unregister(&dev->dvb);
+ if (dev->dvb.frontend)
+ videobuf_dvb_unregister(&dev->dvb);
vp3054_i2c_remove(dev);
diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c
index 44d01352e..800ea0d64 100644
--- a/linux/drivers/media/video/cx88/cx88-i2c.c
+++ b/linux/drivers/media/video/cx88/cx88-i2c.c
@@ -102,7 +102,6 @@ static int cx8800_bit_getsda(void *data)
static int attach_inform(struct i2c_client *client)
{
- struct tuner_setup tun_setup;
struct cx88_core *core = i2c_get_adapdata(client->adapter);
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
@@ -112,37 +111,7 @@ static int attach_inform(struct i2c_client *client)
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
client->driver->driver.name, client->addr, client->name);
#endif
- if (!client->driver->command)
- return 0;
-
- 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->board.radio_type;
- tun_setup.addr = core->board.radio_addr;
- tun_setup.tuner_callback = cx88_tuner_callback;
- client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
- }
- }
- 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->board.tuner_type;
- tun_setup.addr = core->board.tuner_addr;
- tun_setup.tuner_callback = cx88_tuner_callback;
- client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
- }
- }
-
- if (core->board.tda9887_conf) {
- struct v4l2_priv_tun_config tda9887_cfg;
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &core->board.tda9887_conf;
-
- client->driver->command(client, TUNER_SET_CONFIG, &tda9887_cfg);
- }
return 0;
}
diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c
index 6ec40f79f..c8dba3dfa 100644
--- a/linux/drivers/media/video/cx88/cx88-mpeg.c
+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c
@@ -175,7 +175,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
udelay(100);
} else {
- printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
+ printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
core->board.mpeg );
return -EINVAL;
}
@@ -279,7 +279,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
int rc;
- dprintk(1, "%s: %p\n", __FUNCTION__, buf);
+ dprintk(1, "%s: %p\n", __func__, buf);
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
@@ -321,7 +321,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
buf->count = cx88q->count++;
mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(1,"[%p/%d] %s - first active\n",
- buf, buf->vb.i, __FUNCTION__);
+ buf, buf->vb.i, __func__);
#if 0
udelay(100);
#endif
@@ -334,7 +334,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.i, __FUNCTION__);
+ buf, buf->vb.i, __func__);
#if 0
udelay(100);
#endif
@@ -380,7 +380,7 @@ static void cx8802_timeout(unsigned long data)
{
struct cx8802_dev *dev = (struct cx8802_dev*)data;
- dprintk(1, "%s\n",__FUNCTION__);
+ dprintk(1, "%s\n",__func__);
if (debug)
cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -683,7 +683,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
}
mutex_unlock(&drv->core->lock);
- mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+ mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
}
return 0;
@@ -699,7 +699,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
{
drv->advise_release(drv);
core->active_type_id = CX88_BOARD_NONE;
- mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+ mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
}
mutex_unlock(&drv->core->lock);
@@ -873,7 +873,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
dev = pci_get_drvdata(pci_dev);
- dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, "%s\n", __func__);
if (!list_empty(&dev->drvlist)) {
struct cx8802_driver *drv, *tmp;
diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c
index d2e1fdb91..b4dab2647 100644
--- a/linux/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c
@@ -271,12 +271,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
mode |= EN_FMRADIO_EN_RDS;
if (sap) {
- dprintk("%s SAP (status: unknown)\n", __FUNCTION__);
+ dprintk("%s SAP (status: unknown)\n", __func__);
set_audio_start(core, SEL_SAP);
set_audio_registers(core, btsc_sap);
set_audio_finish(core, mode);
} else {
- dprintk("%s (status: known-good)\n", __FUNCTION__);
+ dprintk("%s (status: known-good)\n", __func__);
set_audio_start(core, SEL_BTSC);
set_audio_registers(core, btsc);
set_audio_finish(core, mode);
@@ -357,16 +357,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
set_audio_start(core,SEL_NICAM);
switch (core->tvaudio) {
case WW_L:
- dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__);
+ dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
set_audio_registers(core, nicam_l);
break;
case WW_I:
- dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__);
+ dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
set_audio_registers(core, nicam_bgdki_common);
set_audio_registers(core, nicam_i);
break;
default:
- dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__);
+ dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
set_audio_registers(core, nicam_bgdki_common);
set_audio_registers(core, nicam_default);
break;
@@ -606,28 +606,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
set_audio_start(core, SEL_A2);
switch (core->tvaudio) {
case WW_BG:
- dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__);
+ dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
set_audio_registers(core, a2_bgdk_common);
set_audio_registers(core, a2_bg);
set_audio_registers(core, a2_deemph50);
break;
case WW_DK:
- dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__);
+ dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
set_audio_registers(core, a2_bgdk_common);
set_audio_registers(core, a2_dk);
set_audio_registers(core, a2_deemph50);
break;
case WW_I:
- dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__);
+ dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
set_audio_registers(core, a1_i);
set_audio_registers(core, a2_deemph50);
break;
case WW_L:
- dprintk("%s AM-L (status: devel)\n", __FUNCTION__);
+ dprintk("%s AM-L (status: devel)\n", __func__);
set_audio_registers(core, am_l);
break;
default:
- dprintk("%s Warning: wrong value\n", __FUNCTION__);
+ dprintk("%s Warning: wrong value\n", __func__);
return;
break;
};
@@ -643,7 +643,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
{ /* end of list */ },
};
- dprintk("%s (status: unknown)\n", __FUNCTION__);
+ dprintk("%s (status: unknown)\n", __func__);
set_audio_start(core, SEL_EIAJ);
set_audio_registers(core, eiaj);
@@ -697,7 +697,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
{ /* end of list */ },
};
- dprintk("%s (status: unknown)\n", __FUNCTION__);
+ dprintk("%s (status: unknown)\n", __func__);
set_audio_start(core, SEL_FMRADIO);
switch (deemph) {
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index b25402467..c9f7d0048 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1294,7 +1294,7 @@ static void init_controls(struct cx88_core *core)
/* ------------------------------------------------------------------ */
/* VIDEO IOCTLS */
-static int vidioc_g_fmt_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8800_fh *fh = priv;
@@ -1310,7 +1310,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_try_fmt_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
@@ -1361,11 +1361,11 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_s_fmt_cap (struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8800_fh *fh = priv;
- int err = vidioc_try_fmt_cap (file,priv,f);
+ int err = vidioc_try_fmt_vid_cap (file,priv,f);
if (0 != err)
return err;
@@ -1399,7 +1399,7 @@ static int vidioc_querycap (struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_cap (struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (unlikely(f->index >= ARRAY_SIZE(formats)))
@@ -1977,13 +1977,13 @@ static struct video_device cx8800_video_template =
.fops = &video_fops,
.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_g_fmt_vbi = cx8800_vbi_fmt,
- .vidioc_try_fmt_vbi = cx8800_vbi_fmt,
- .vidioc_s_fmt_vbi = cx8800_vbi_fmt,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
+ .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
+ .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
diff --git a/linux/drivers/media/video/dpc7146.c b/linux/drivers/media/video/dpc7146.c
index 258d46407..4bfb3076b 100644
--- a/linux/drivers/media/video/dpc7146.c
+++ b/linux/drivers/media/video/dpc7146.c
@@ -132,7 +132,7 @@ static int dpc_probe(struct saa7146_dev* dev)
device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients);
/* check if all devices are present */
- if( 0 == dpc->saa7111a ) {
+ if (!dpc->saa7111a) {
DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
i2c_del_adapter(&dpc->i2c_adapter);
kfree(dpc);
diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig
index 0f7a0bd86..16a5af30e 100644
--- a/linux/drivers/media/video/em28xx/Kconfig
+++ b/linux/drivers/media/video/em28xx/Kconfig
@@ -1,11 +1,13 @@
config VIDEO_EM28XX
- tristate "Empia EM2800/2820/2840 USB video capture support"
+ tristate "Empia EM28xx USB video capture support"
depends on VIDEO_DEV && I2C && INPUT
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
+ select VIDEOBUF_VMALLOC
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
---help---
This is a video4linux driver for Empia 28xx based TV cards.
@@ -27,3 +29,12 @@ config VIDEO_EM28XX_ALSA
To compile this driver as a module, choose M here: the
module will be called em28xx-alsa
+config VIDEO_EM28XX_DVB
+ tristate "DVB/ATSC Support for em28xx based TV cards"
+ depends on VIDEO_EM28XX && DVB_CORE
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+ select VIDEOBUF_DVB
+ ---help---
+ This adds support for DVB cards based on the
+ Empiatech em28xx chips.
diff --git a/linux/drivers/media/video/em28xx/Makefile b/linux/drivers/media/video/em28xx/Makefile
index 092455099..8137a8c94 100644
--- a/linux/drivers/media/video/em28xx/Makefile
+++ b/linux/drivers/media/video/em28xx/Makefile
@@ -5,8 +5,10 @@ em28xx-alsa-objs := em28xx-audio.o
obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
+obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c
index 37e893455..609e28e77 100644
--- a/linux/drivers/media/video/em28xx/em28xx-audio.c
+++ b/linux/drivers/media/video/em28xx/em28xx-audio.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
#define dprintk(fmt, arg...) do { \
if (debug) \
printk(KERN_INFO "em28xx-audio %s: " fmt, \
- __FUNCTION__, ##arg); \
+ __func__, ##arg); \
} while (0)
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c
index 06a4e4a2b..c877c855e 100644
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c
@@ -37,7 +37,6 @@
#include <media/v4l2-common.h>
#include "em28xx.h"
-#include "tuner-xc2028.h"
static int tuner = -1;
module_param(tuner, int, 0444);
@@ -53,26 +52,6 @@ struct em28xx_hash_table {
unsigned int tuner;
};
-/* Boards supported by driver */
-
-#define EM2800_BOARD_UNKNOWN 0
-#define EM2820_BOARD_UNKNOWN 1
-#define EM2820_BOARD_TERRATEC_CINERGY_250 2
-#define EM2820_BOARD_PINNACLE_USB_2 3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
-#define EM2820_BOARD_MSI_VOX_USB_2 5
-#define EM2800_BOARD_TERRATEC_CINERGY_200 6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
-#define EM2800_BOARD_KWORLD_USB2800 8
-#define EM2820_BOARD_PINNACLE_DVC_90 9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS 11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF 12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
-#define EM2800_BOARD_VGEAR_POCKETTV 15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
-
struct em28xx_board em28xx_boards[] = {
[EM2800_BOARD_UNKNOWN] = {
.name = "Unknown EM2800 video grabber",
@@ -194,6 +173,27 @@ struct em28xx_board em28xx_boards[] = {
.amux = 1,
} },
},
+ [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
+ .name = "Hauppauge WinTV HVR 900 (R2)",
+ .vchannels = 3,
+ .tda9887_conf = TDA9887_PRESENT,
+ .tuner_type = TUNER_XC2028,
+ .mts_firmware = 1,
+ .decoder = EM28XX_TVP5150,
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = TVP5150_COMPOSITE0,
+ .amux = 0,
+ }, {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = TVP5150_COMPOSITE1,
+ .amux = 1,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = TVP5150_SVIDEO,
+ .amux = 1,
+ } },
+ },
[EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
.name = "Hauppauge WinTV HVR 950",
.vchannels = 3,
@@ -201,6 +201,30 @@ struct em28xx_board em28xx_boards[] = {
.tuner_type = TUNER_XC2028,
.mts_firmware = 1,
.has_12mhz_i2s = 1,
+ .has_dvb = 1,
+ .decoder = EM28XX_TVP5150,
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = TVP5150_COMPOSITE0,
+ .amux = 0,
+ }, {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = TVP5150_COMPOSITE1,
+ .amux = 1,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = TVP5150_SVIDEO,
+ .amux = 1,
+ } },
+ },
+ [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
+ .name = "Pinnacle PCTV HD Pro Stick",
+ .vchannels = 3,
+ .tda9887_conf = TDA9887_PRESENT,
+ .tuner_type = TUNER_XC2028,
+ .mts_firmware = 1,
+ .has_12mhz_i2s = 1,
+ .has_dvb = 1,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
@@ -215,9 +239,6 @@ struct em28xx_board em28xx_boards[] = {
.vmux = TVP5150_SVIDEO,
.amux = 1,
} },
-
- /* gpio's 4, 1, 0 */
- .analog_gpio = 0x003d2d,
},
[EM2880_BOARD_TERRATEC_HYBRID_XS] = {
.name = "Terratec Hybrid XS",
@@ -440,11 +461,19 @@ struct usb_device_id em28xx_id_table [] = {
.driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
{ USB_DEVICE(0x2304, 0x021a),
.driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+ { USB_DEVICE(0x2304, 0x0227),
+ .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
{ USB_DEVICE(0x2040, 0x6500),
.driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
{ USB_DEVICE(0x2040, 0x6502),
- .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
- { USB_DEVICE(0x2040, 0x6513),
+ .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 },
+ { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */
+ .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+ { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */
+ .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+ { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */
+ .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+ { USB_DEVICE(0x2040, 0x651f), /* HCW HVR-850 */
.driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
{ USB_DEVICE(0x0ccd, 0x0042),
.driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS },
@@ -454,7 +483,36 @@ struct usb_device_id em28xx_id_table [] = {
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
-/* EEPROM hash table for devices with generic USB IDs */
+/*
+ * Reset sequences for analog/digital modes
+ */
+
+/* Board Hauppauge WinTV HVR 900 analog */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
+ {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10},
+ {0x05, 0xff, 0x10, 10},
+ { -1, -1, -1, -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 digital */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
+ {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10},
+ {EM2880_R04_GPO, 0x04, 0x0f, 10},
+ {EM2880_R04_GPO, 0x0c, 0x0f, 10},
+ { -1, -1, -1, -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 tuner_callback */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
+ {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
+ {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10},
+ {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
+ { -1, -1, -1, -1},
+};
+
+/*
+ * EEPROM hash table for devices with generic USB IDs
+ */
static struct em28xx_hash_table em28xx_eeprom_hash [] = {
/* P/N: SA 60002070465 Tuner: TVF7533-MF */
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
@@ -466,79 +524,120 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
};
+int em28xx_tuner_callback(void *ptr, int command, int arg)
+{
+ int rc = 0;
+ struct em28xx *dev = ptr;
+
+ if (dev->tuner_type != TUNER_XC2028)
+ return 0;
+
+ if (command != XC2028_TUNER_RESET)
+ return 0;
+
+ if (dev->mode == EM28XX_ANALOG_MODE)
+ rc = em28xx_gpio_set(dev, dev->tun_analog_gpio);
+ else
+ rc = em28xx_gpio_set(dev, dev->tun_digital_gpio);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
+
+static void em28xx_set_model(struct em28xx *dev)
+{
+ dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+ dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
+ dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+ dev->decoder = em28xx_boards[dev->model].decoder;
+ dev->video_inputs = em28xx_boards[dev->model].vchannels;
+ dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+ dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+ dev->has_dvb = em28xx_boards[dev->model].has_dvb;
+}
+
/* Since em28xx_pre_card_setup() requires a proper dev->model,
* this won't work for boards with generic PCI IDs
*/
void em28xx_pre_card_setup(struct em28xx *dev)
{
+ int rc;
+
+ rc = em28xx_read_reg(dev, EM2880_R04_GPO);
+ if (rc >= 0)
+ dev->reg_gpo = rc;
+
+ dev->wait_after_write = 5;
+ rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+ if (rc > 0) {
+ switch (rc) {
+ case CHIP_ID_EM2883:
+ em28xx_info("chip ID is em2882/em2883\n");
+ dev->wait_after_write = 0;
+ break;
+ default:
+ em28xx_info("em28xx chip ID = %d\n", rc);
+ }
+ }
+ em28xx_set_model(dev);
+
/* request some modules */
switch (dev->model) {
case EM2880_BOARD_TERRATEC_PRODIGY_XS:
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
case EM2880_BOARD_TERRATEC_HYBRID_XS:
- em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
- em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
- em28xx_write_regs(dev, 0x08, "\xff", 1);
- em28xx_write_regs(dev, 0x04, "\x00", 1);
- msleep(100);
- em28xx_write_regs(dev, 0x04, "\x08", 1);
- msleep(100);
- em28xx_write_regs(dev, 0x08, "\xff", 1);
- msleep(50);
- em28xx_write_regs(dev, 0x08, "\x2d", 1);
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+ em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
+ em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
msleep(50);
- em28xx_write_regs(dev, 0x08, "\x3d", 1);
+
+ /* Sets GPO/GPIO sequences for this device */
+ dev->analog_gpio = hauppauge_wintv_hvr_900_analog;
+ dev->digital_gpio = hauppauge_wintv_hvr_900_digital;
+ dev->tun_analog_gpio = hauppauge_wintv_hvr_900_tuner_callback;
+ dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
+
break;
}
+
+ em28xx_gpio_set(dev, dev->tun_analog_gpio);
+ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+
+ /* Unlock device */
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
}
-static int em28xx_tuner_callback(void *ptr, int command, int arg)
+static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
{
- int rc = 0;
- struct em28xx *dev = ptr;
+ memset(ctl, 0, sizeof(*ctl));
- if (dev->tuner_type != TUNER_XC2028)
- return 0;
-
- switch (command) {
- case XC2028_TUNER_RESET:
- {
- /* GPIO and initialization codes for analog TV and radio
- This code should be complemented for DTV, since reset
- codes are different.
- */
-
- dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
- dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
-
- if (dev->analog_gpio) {
- char gpio0 = dev->analog_gpio & 0xff;
- char gpio1 = (dev->analog_gpio >> 8) & 0xff;
- char gpio4 = dev->analog_gpio >> 24;
-
- if (gpio4) {
- dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
- msleep(140);
- }
-
- msleep(6);
- dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
- msleep(10);
- dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
- msleep(5);
- }
+ ctl->fname = XC2028_DEFAULT_FIRMWARE;
+ ctl->max_len = 64;
+ ctl->mts = em28xx_boards[dev->model].mts_firmware;
+ switch (dev->model) {
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+ ctl->demod = XC3028_FE_ZARLINK456;
break;
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
+ /* djh - Not sure which demod we need here */
+ ctl->demod = XC3028_FE_DEFAULT;
+ break;
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+ /* FIXME: Better to specify the needed IF */
+ ctl->demod = XC3028_FE_DEFAULT;
+ break;
+ default:
+ ctl->demod = XC3028_FE_OREN538;
}
- }
- return rc;
}
static void em28xx_config_tuner(struct em28xx *dev)
{
struct v4l2_priv_tun_config xc2028_cfg;
- struct xc2028_ctrl ctl;
struct tuner_setup tun_setup;
struct v4l2_frequency f;
@@ -553,11 +652,9 @@ static void em28xx_config_tuner(struct em28xx *dev)
em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
if (dev->tuner_type == TUNER_XC2028) {
- memset(&ctl, 0, sizeof(ctl));
+ struct xc2028_ctrl ctl;
- ctl.fname = XC2028_DEFAULT_FIRMWARE;
- ctl.max_len = 64;
- ctl.mts = em28xx_boards[dev->model].mts_firmware;
+ em28xx_setup_xc3028(dev, &ctl);
xc2028_cfg.tuner = TUNER_XC2028;
xc2028_cfg.priv = &ctl;
@@ -655,19 +752,6 @@ static int em28xx_hint_board(struct em28xx *dev)
return -1;
}
-
-static void em28xx_set_model(struct em28xx *dev)
-{
- dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
- dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
- dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
- dev->decoder = em28xx_boards[dev->model].decoder;
- dev->video_inputs = em28xx_boards[dev->model].vchannels;
- dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
- dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
- dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
-}
-
/* ----------------------------------------------------------------------- */
void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
{
@@ -720,6 +804,7 @@ void em28xx_card_setup(struct em28xx *dev)
switch (dev->model) {
case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
{
struct tveeprom tv;
diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c
index 1f6abc803..1a30e361c 100644
--- a/linux/drivers/media/video/em28xx/em28xx-core.c
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c
@@ -38,7 +38,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
#define em28xx_coredbg(fmt, arg...) do {\
if (core_debug) \
printk(KERN_INFO "%s %s :"fmt, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
+ dev->name, __func__ , ##arg); } while (0)
static unsigned int reg_debug;
module_param(reg_debug,int,0644);
@@ -47,139 +47,17 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
#define em28xx_regdbg(fmt, arg...) do {\
if (reg_debug) \
printk(KERN_INFO "%s %s :"fmt, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
-
-static unsigned int isoc_debug;
-module_param(isoc_debug,int,0644);
-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
-
-#define em28xx_isocdbg(fmt, arg...) do {\
- if (isoc_debug) \
- printk(KERN_INFO "%s %s :"fmt, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
+ dev->name, __func__ , ##arg); } while (0)
static int alt = EM28XX_PINOUT;
module_param(alt, int, 0644);
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
-#include <linux/mm.h>
-static void *rvmalloc(size_t size)
-{
- void *mem;
- unsigned long adr;
-
- size = PAGE_ALIGN(size);
-
- mem = vmalloc_32((unsigned long)size);
- if (!mem)
- return NULL;
-
- adr = (unsigned long)mem;
- while (size > 0) {
- SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- return mem;
-}
-
-static void rvfree(void *mem, size_t size)
-{
- unsigned long adr;
-
- if (!mem)
- return;
-
- size = PAGE_ALIGN(size);
-
- adr = (unsigned long)mem;
- while (size > 0) {
- ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- vfree(mem);
-}
-#endif
-
-/*
- * em28xx_request_buffers()
- * allocate a number of buffers
- */
-u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
-{
- const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
- void *buff = NULL;
- u32 i;
- em28xx_coredbg("requested %i buffers with size %zi\n",
- count, imagesize);
- if (count > EM28XX_NUM_FRAMES)
- count = EM28XX_NUM_FRAMES;
-
- dev->num_frames = count;
- while (dev->num_frames > 0) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
- if ((buff = rvmalloc(dev->num_frames * imagesize))) {
-#else
- if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
-#endif
- memset(buff, 0, dev->num_frames * imagesize);
- break;
- }
- dev->num_frames--;
- }
-
- for (i = 0; i < dev->num_frames; i++) {
- dev->frame[i].bufmem = buff + i * imagesize;
- dev->frame[i].buf.index = i;
- dev->frame[i].buf.m.offset = i * imagesize;
- dev->frame[i].buf.length = dev->frame_size;
- dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- dev->frame[i].buf.sequence = 0;
- dev->frame[i].buf.field = V4L2_FIELD_NONE;
- dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
- dev->frame[i].buf.flags = 0;
- }
- return dev->num_frames;
-}
-
-/*
- * em28xx_queue_unusedframes()
- * add all frames that are not currently in use to the inbuffer queue
- */
-void em28xx_queue_unusedframes(struct em28xx *dev)
-{
- unsigned long lock_flags;
- u32 i;
-
- for (i = 0; i < dev->num_frames; i++)
- if (dev->frame[i].state == F_UNUSED) {
- dev->frame[i].state = F_QUEUED;
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- list_add_tail(&dev->frame[i].frame, &dev->inqueue);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
- }
-}
-
-/*
- * em28xx_release_buffers()
- * free frame buffers
- */
-void em28xx_release_buffers(struct em28xx *dev)
-{
- if (dev->num_frames) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
- rvfree(dev->frame[0].bufmem,
- dev->num_frames * PAGE_ALIGN(dev->frame[0].buf.length));
-#else
- vfree(dev->frame[0].bufmem);
-#endif
- dev->num_frames = 0;
- }
-}
+/* FIXME */
+#define em28xx_isocdbg(fmt, arg...) do {\
+ if (core_debug) \
+ printk(KERN_INFO "%s %s :"fmt, \
+ dev->name, __func__ , ##arg); } while (0)
/*
* em28xx_read_reg_req()
@@ -199,11 +77,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, buf, len, HZ);
- if (reg_debug){
+ if (reg_debug) {
printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
- for (byte = 0; byte < len; byte++) {
+ for (byte = 0; byte < len; byte++)
printk(" %02x", (unsigned char)buf[byte]);
- }
+
printk("\n");
}
@@ -256,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
unsigned char *bufs;
if (dev->state & DEV_DISCONNECTED)
- return(-ENODEV);
+ return -ENODEV;
+
+ if (len < 1)
+ return -EINVAL;
bufs = kmalloc(len, GFP_KERNEL);
@@ -265,8 +146,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
if (reg_debug) {
int i;
for (i = 0; i < len; ++i)
- printk (" %02x", (unsigned char)buf[i]);
- printk ("\n");
+ printk(" %02x", (unsigned char)buf[i]);
+ printk("\n");
}
if (!bufs)
@@ -275,14 +156,32 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, bufs, len, HZ);
- msleep(5); /* FIXME: magic number */
+ if (dev->wait_after_write)
+ msleep(dev->wait_after_write);
+
kfree(bufs);
return ret;
}
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
{
- return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+ int rc;
+
+ rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+
+ /* Stores GPO/GPIO values at the cache, if changed
+ Only write values should be stored, since input on a GPIO
+ register will return the input bits.
+ Not sure what happens on reading GPO register.
+ */
+ if (rc >= 0) {
+ if (reg == EM2880_R04_GPO)
+ dev->reg_gpo = buf[0];
+ else if (reg == EM28XX_R08_GPIO)
+ dev->reg_gpio = buf[0];
+ }
+
+ return rc;
}
/*
@@ -295,9 +194,20 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
{
int oldval;
u8 newval;
- if ((oldval = em28xx_read_reg(dev, reg)) < 0)
+
+ /* Uses cache for gpo/gpio registers */
+ if (reg == EM2880_R04_GPO)
+ oldval = dev->reg_gpo;
+ else if (reg == EM28XX_R08_GPIO)
+ oldval = dev->reg_gpio;
+ else
+ oldval = em28xx_read_reg(dev, reg);
+
+ if (oldval < 0)
return oldval;
+
newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
+
return em28xx_write_regs(dev, reg, &newval, 1);
}
@@ -309,20 +219,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
{
int ret, i;
u8 addr = reg & 0x7f;
- if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
+
+ ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2);
+ if (ret < 0)
return ret;
- if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
+
+ ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
+ if (ret < 0)
return ret;
/* Wait up to 50 ms for AC97 command to complete */
for (i = 0; i < 10; i++) {
- if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
+ ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
+ if (ret < 0)
return ret;
+
if (!(ret & 0x01))
return 0;
msleep(5);
}
- em28xx_warn ("AC97 command still being executed: not handled properly!\n");
+ em28xx_warn("AC97 command still being executed: not handled properly!\n");
return 0;
}
@@ -340,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
else
input = EM2800_AUDIO_SRC_TUNER;
- ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
+ ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
if (ret < 0)
return ret;
}
@@ -366,7 +282,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
}
}
- ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
+ ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
if (ret < 0)
return ret;
msleep(5);
@@ -374,11 +290,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
/* Sets AC97 mixer registers
This is seems to be needed, even for non-ac97 configs
*/
- ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
+ ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
if (ret < 0)
return ret;
- ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
+ ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
return ret;
}
@@ -394,7 +310,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Mute */
s[1] |= 0x80;
- ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+ ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
if (ret < 0)
return ret;
@@ -405,7 +321,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (!dev->mute)
xclk |= 0x80;
- ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
+ ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7);
if (ret < 0)
return ret;
msleep(10);
@@ -416,7 +332,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Unmute device */
if (!dev->mute)
s[1] &= ~0x80;
- ret = em28xx_write_ac97(dev, MASTER_AC97, s);
+ ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
return ret;
}
@@ -424,50 +340,68 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
int em28xx_colorlevels_set_default(struct em28xx *dev)
{
- em28xx_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */
- em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */
- em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */
- em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1);
- em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1);
- em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1);
-
- em28xx_write_regs(dev, GAMMA_REG, "\x20", 1);
- em28xx_write_regs(dev, RGAIN_REG, "\x20", 1);
- em28xx_write_regs(dev, GGAIN_REG, "\x20", 1);
- em28xx_write_regs(dev, BGAIN_REG, "\x20", 1);
- em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1);
- em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1);
- return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1);
+ em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1); /* contrast */
+ em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1); /* brightness */
+ em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1); /* saturation */
+ em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1);
+ em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1);
+ em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1);
+
+ em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1);
+ em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1);
+ em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1);
+ em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1);
+ em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1);
+ em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1);
+ return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1);
}
int em28xx_capture_start(struct em28xx *dev, int start)
{
- int ret;
+ int rc;
/* FIXME: which is the best order? */
/* video registers are sampled by VREF */
- if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00,
- 0x10)) < 0)
- return ret;
+ rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
+ start ? 0x10 : 0x00, 0x10);
+ if (rc < 0)
+ return rc;
+
+ if (!start) {
+ /* disable video capture */
+ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1);
+ return rc;
+ }
+
/* enable video capture */
- return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1);
+ rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+
+ if (dev->mode == EM28XX_ANALOG_MODE)
+ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1);
+ else
+ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1);
+
+ msleep(6);
+
+ return rc;
}
int em28xx_outfmt_set_yuv422(struct em28xx *dev)
{
- em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1);
- em28xx_write_regs(dev, VINMODE_REG, "\x10", 1);
- return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
+ em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1);
+ em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1);
+ return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1);
}
static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
u8 ymin, u8 ymax)
{
- em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
+ em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
+ xmin, ymin, xmax, ymax);
- em28xx_write_regs(dev, XMIN_REG, &xmin, 1);
- em28xx_write_regs(dev, XMAX_REG, &xmax, 1);
- em28xx_write_regs(dev, YMIN_REG, &ymin, 1);
- return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
+ em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
+ em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
+ em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
+ return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
}
static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
@@ -477,34 +411,36 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
u8 cheight = height;
u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
- em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7),
+ em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
+ (width | (overflow & 2) << 7),
(height | (overflow & 1) << 8));
- em28xx_write_regs(dev, HSTART_REG, &hstart, 1);
- em28xx_write_regs(dev, VSTART_REG, &vstart, 1);
- em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1);
- em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1);
- return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
+ em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
+ em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
+ em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
+ em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
+ return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
}
static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
{
u8 mode;
/* the em2800 scaler only supports scaling down to 50% */
- if(dev->is_em2800)
+ if (dev->is_em2800)
mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
else {
u8 buf[2];
buf[0] = h;
buf[1] = h >> 8;
- em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);
+ em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
buf[0] = v;
buf[1] = v >> 8;
- em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);
- /* it seems that both H and V scalers must be active to work correctly */
+ em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
+ /* it seems that both H and V scalers must be active
+ to work correctly */
mode = (h || v)? 0x30: 0x00;
}
- return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);
+ return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
}
/* FIXME: this only function read values from dev */
@@ -520,396 +456,280 @@ int em28xx_resolution_set(struct em28xx *dev)
return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
}
-
-/******************* isoc transfer handling ****************************/
-
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-static void em28xx_isoc_dump(struct urb *urb, struct pt_regs *regs)
-#else
-static void em28xx_isoc_dump(struct urb *urb)
-#endif
+int em28xx_set_alternate(struct em28xx *dev)
{
- int len = 0;
- int ntrans = 0;
+ int errCode, prev_alt = dev->alt;
int i;
+ unsigned int min_pkt_size = dev->width * 2 + 4;
- printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
- urb->start_frame, urb->number_of_packets,
- urb->error_count);
- for (i = 0; i < urb->number_of_packets; i++) {
- unsigned char *buf =
- urb->transfer_buffer +
- urb->iso_frame_desc[i].offset;
- int alen = urb->iso_frame_desc[i].actual_length;
- if (alen > 0) {
- if (buf[0] == 0x88) {
- ntrans++;
- len += alen;
- } else if (buf[0] == 0x22) {
- printk(KERN_DEBUG
- "= l=%d nt=%d bpp=%d\n",
- len - 4 * ntrans, ntrans,
- ntrans == 0 ? 0 : len / ntrans);
- ntrans = 1;
- len = alen;
- } else
- printk(KERN_DEBUG "!\n");
+ /* When image size is bigger than a certain value,
+ the frame size should be increased, otherwise, only
+ green screen will be received.
+ */
+ if (dev->width * 2 * dev->height > 720 * 240 * 2)
+ min_pkt_size *= 2;
+
+ for (i = 0; i < dev->num_alt; i++) {
+ /* stop when the selected alt setting offers enough bandwidth */
+ if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+ dev->alt = i;
+ break;
+ /* otherwise make sure that we end up with the maximum bandwidth
+ because the min_pkt_size equation might be wrong...
+ */
+ } else if (dev->alt_max_pkt_size[i] >
+ dev->alt_max_pkt_size[dev->alt])
+ dev->alt = i;
+ }
+
+ if (dev->alt != prev_alt) {
+ em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+ min_pkt_size, dev->alt);
+ dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+ em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+ dev->alt, dev->max_pkt_size);
+ errCode = usb_set_interface(dev->udev, 0, dev->alt);
+ if (errCode < 0) {
+ em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
+ dev->alt, errCode);
+ return errCode;
}
- printk(KERN_DEBUG " n=%d s=%d al=%d %x\n", i,
- urb->iso_frame_desc[i].status,
- urb->iso_frame_desc[i].actual_length,
- (unsigned int)
- *((unsigned char *)(urb->transfer_buffer +
- urb->iso_frame_desc[i].
- offset)));
}
+ return 0;
}
-#endif
-static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
- unsigned long *lock_flags, unsigned char buf)
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
{
- if (!(buf & 0x01)) {
- if ((*f)->state == F_GRABBING) {
- /*previous frame is incomplete */
- if ((*f)->fieldbytesused < dev->field_size) {
- (*f)->state = F_ERROR;
- em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
- dev->field_size-(*f)->fieldbytesused);
- } else {
- (*f)->state = F_DONE;
- (*f)->buf.bytesused = dev->frame_size;
- }
- }
- if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
- /* move current frame to outqueue and get next free buffer from inqueue */
- spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
- list_move_tail(&(*f)->frame, &dev->outqueue);
- if (!list_empty(&dev->inqueue))
- (*f) = list_entry(dev-> inqueue.next,
- struct em28xx_frame_t,frame);
- else
- (*f) = NULL;
- spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
- }
- if (!(*f)) {
- em28xx_isocdbg ("new frame but no buffer is free");
- return -1;
- }
- do_gettimeofday(&(*f)->buf.timestamp);
- (*f)->buf.sequence = ++dev->frame_count;
- (*f)->buf.field = V4L2_FIELD_INTERLACED;
- (*f)->state = F_GRABBING;
- (*f)->buf.bytesused = 0;
- (*f)->top_field = 1;
- (*f)->fieldbytesused = 0;
- } else {
- /* acquiring bottom field */
- if ((*f)->state == F_GRABBING) {
- if (!(*f)->top_field) {
- (*f)->state = F_ERROR;
- em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
- } else if ((*f)-> fieldbytesused < dev->field_size - 172) {
- (*f)->state = F_ERROR;
- em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
- dev->field_size-(*f)->fieldbytesused);
- } else {
- (*f)->top_field = 0;
- (*f)->fieldbytesused = 0;
- }
+ int rc = 0;
+
+ if (!gpio)
+ return rc;
+
+ dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+ if (dev->mode == EM28XX_ANALOG_MODE)
+ dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
+ else
+ dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1);
+ msleep(6);
+
+ /* Send GPIO reset sequences specified at board entry */
+ while (gpio->sleep >= 0) {
+ if (gpio->reg >= 0) {
+ rc = em28xx_write_reg_bits(dev,
+ gpio->reg,
+ gpio->val,
+ gpio->mask);
+ if (rc < 0)
+ return rc;
}
+ if (gpio->sleep > 0)
+ msleep(gpio->sleep);
+
+ gpio++;
}
- return (0);
+ return rc;
}
-static inline void em28xx_isoc_video_copy(struct em28xx *dev,
- struct em28xx_frame_t **f, unsigned char *buf, int len)
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
{
- void *fieldstart, *startwrite, *startread;
- int linesdone, currlinedone, offset, lencopy,remain;
+ if (dev->mode == set_mode)
+ return 0;
- if(dev->frame_size != (*f)->buf.length){
- em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
- return;
+ if (set_mode == EM28XX_MODE_UNDEFINED) {
+ dev->mode = set_mode;
+ return 0;
}
- if ((*f)->fieldbytesused + len > dev->field_size)
- len =dev->field_size - (*f)->fieldbytesused;
-
- if (buf[0] != 0x88 && buf[0] != 0x22) {
- em28xx_isocdbg("frame is not complete\n");
- startread = buf;
- len+=4;
- } else
- startread = buf + 4;
-
- remain = len;
+#if 0
+ /* Resource is locked */
+ if (dev->mode != EM28XX_MODE_UNDEFINED)
+ return -EINVAL;
+#endif
+ dev->mode = set_mode;
- if ((*f)->top_field)
- fieldstart = (*f)->bufmem;
+ if (dev->mode == EM28XX_DIGITAL_MODE)
+ return em28xx_gpio_set(dev, dev->digital_gpio);
else
- fieldstart = (*f)->bufmem + dev->bytesperline;
-
- linesdone = (*f)->fieldbytesused / dev->bytesperline;
- currlinedone = (*f)->fieldbytesused % dev->bytesperline;
- offset = linesdone * dev->bytesperline * 2 + currlinedone;
- startwrite = fieldstart + offset;
- lencopy = dev->bytesperline - currlinedone;
- lencopy = lencopy > remain ? remain : lencopy;
-
- memcpy(startwrite, startread, lencopy);
- remain -= lencopy;
-
- while (remain > 0) {
- startwrite += lencopy + dev->bytesperline;
- startread += lencopy;
- if (dev->bytesperline > remain)
- lencopy = remain;
- else
- lencopy = dev->bytesperline;
-
- memcpy(startwrite, startread, lencopy);
- remain -= lencopy;
- }
-
- (*f)->fieldbytesused += len;
+ return em28xx_gpio_set(dev, dev->analog_gpio);
}
+EXPORT_SYMBOL_GPL(em28xx_set_mode);
+
+/* ------------------------------------------------------------------
+ URB control
+ ------------------------------------------------------------------*/
/*
- * em28xx_isoIrq()
- * handles the incoming isoc urbs and fills the frames from our inqueue
+ * IRQ callback, called by URB callback
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void em28xx_irq_callback(struct urb *urb, struct pt_regs *regs)
#else
-static void em28xx_isocIrq(struct urb *urb)
+static void em28xx_irq_callback(struct urb *urb)
#endif
{
- struct em28xx *dev = urb->context;
- int i, status;
- struct em28xx_frame_t **f;
- unsigned long lock_flags;
-
- if (!dev)
- return;
-#ifdef ENABLE_DEBUG_ISOC_FRAMES
- if (isoc_debug>1)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
- em28xx_isoc_dump(urb, regs);
-#else
- em28xx_isoc_dump(urb);
-#endif
-#endif
-
- if (urb->status == -ENOENT)
- return;
-
- f = &dev->frame_current;
-
- if (dev->stream == STREAM_INTERRUPT) {
- dev->stream = STREAM_OFF;
- if ((*f))
- (*f)->state = F_QUEUED;
- em28xx_isocdbg("stream interrupted");
- wake_up_interruptible(&dev->wait_stream);
- }
-
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
- return;
-
- if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
- if (!(*f))
- (*f) = list_entry(dev->inqueue.next,
- struct em28xx_frame_t, frame);
-
- for (i = 0; i < urb->number_of_packets; i++) {
- unsigned char *buf = urb->transfer_buffer +
- urb->iso_frame_desc[i].offset;
- int len = urb->iso_frame_desc[i].actual_length - 4;
-
- if (urb->iso_frame_desc[i].status) {
- em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
- urb->iso_frame_desc[i].actual_length,
- urb->iso_frame_desc[i].status);
- if (urb->iso_frame_desc[i].status != -EPROTO)
- continue;
- }
- if (urb->iso_frame_desc[i].actual_length <= 0) {
- em28xx_isocdbg("packet %d is empty",i);
- continue;
- }
- if (urb->iso_frame_desc[i].actual_length >
- urb->iso_frame_desc[i].length) {
- em28xx_isocdbg("packet bigger than packet size");
- continue;
- }
- /*new frame */
- if (buf[0] == 0x22 && buf[1] == 0x5a) {
- em28xx_isocdbg("Video frame, length=%i!",len);
-
- if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
- break;
- } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
- em28xx_isocdbg("VBI HEADER!!!");
- }
+ struct em28xx_dmaqueue *dma_q = urb->context;
+ struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+ int rc, i;
- /* actual copying */
- if ((*f)->state == F_GRABBING) {
- em28xx_isoc_video_copy(dev,f,buf, len);
- }
- }
- }
+ /* Copy data from URB */
+ spin_lock(&dev->slock);
+ rc = dev->isoc_ctl.isoc_copy(dev, urb);
+ spin_unlock(&dev->slock);
+ /* Reset urb buffers */
for (i = 0; i < urb->number_of_packets; i++) {
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
}
-
urb->status = 0;
- if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
- em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
- dev->state |= DEV_MISCONFIGURED;
+
+ urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (urb->status) {
+ em28xx_isocdbg("urb resubmit failed (error=%i)\n",
+ urb->status);
}
- wake_up_interruptible(&dev->wait_frame);
- return;
}
/*
- * em28xx_uninit_isoc()
- * deallocates the buffers and urbs allocated during em28xx_init_iosc()
+ * Stop and Deallocate URBs
*/
void em28xx_uninit_isoc(struct em28xx *dev)
{
+ struct urb *urb;
int i;
- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
- if (dev->urb[i]) {
- usb_kill_urb(dev->urb[i]);
- if (dev->transfer_buffer[i]) {
+ em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
+
+ dev->isoc_ctl.nfields = -1;
+ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+ urb = dev->isoc_ctl.urb[i];
+ if (urb) {
+ usb_kill_urb(urb);
+ usb_unlink_urb(urb);
+ if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
- dev->urb[i]->transfer_buffer_length,
- dev->transfer_buffer[i],
- dev->urb[i]->transfer_dma);
+ urb->transfer_buffer_length,
+ dev->isoc_ctl.transfer_buffer[i],
+ urb->transfer_dma);
}
- usb_free_urb(dev->urb[i]);
+ usb_free_urb(urb);
+ dev->isoc_ctl.urb[i] = NULL;
}
- dev->urb[i] = NULL;
- dev->transfer_buffer[i] = NULL;
+ dev->isoc_ctl.transfer_buffer[i] = NULL;
}
+
+ kfree(dev->isoc_ctl.urb);
+ kfree(dev->isoc_ctl.transfer_buffer);
+
+ dev->isoc_ctl.urb = NULL;
+ dev->isoc_ctl.transfer_buffer = NULL;
+ dev->isoc_ctl.num_bufs = 0;
+
em28xx_capture_start(dev, 0);
}
+EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
/*
- * em28xx_init_isoc()
- * allocates transfer buffers and submits the urbs for isoc transfer
+ * Allocate URBs and start IRQ
*/
-int em28xx_init_isoc(struct em28xx *dev)
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+ int num_bufs, int max_pkt_size,
+ int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
{
- /* change interface to 3 which allows the biggest packet sizes */
- int i, errCode;
- int sb_size;
-
- em28xx_set_alternate(dev);
- sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
-
- /* reset streaming vars */
- dev->frame_current = NULL;
- dev->frame_count = 0;
-
- /* allocate urbs */
- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
- struct urb *urb;
- int j;
- /* allocate transfer buffer */
- urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
- if (!urb){
- em28xx_errdev("cannot alloc urb %i\n", i);
+ struct em28xx_dmaqueue *dma_q = &dev->vidq;
+ int i;
+ int sb_size, pipe;
+ struct urb *urb;
+ int j, k;
+ int rc;
+
+ em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
+
+ /* De-allocates all pending stuff */
+ em28xx_uninit_isoc(dev);
+
+ dev->isoc_ctl.isoc_copy = isoc_copy;
+ dev->isoc_ctl.num_bufs = num_bufs;
+
+ dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ if (!dev->isoc_ctl.urb) {
+ em28xx_errdev("cannot alloc memory for usb buffers\n");
+ return -ENOMEM;
+ }
+
+ dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+ GFP_KERNEL);
+ if (!dev->isoc_ctl.transfer_buffer) {
+ em28xx_errdev("cannot allocate memory for usbtransfer\n");
+ kfree(dev->isoc_ctl.urb);
+ return -ENOMEM;
+ }
+
+ dev->isoc_ctl.max_pkt_size = max_pkt_size;
+ dev->isoc_ctl.buf = NULL;
+
+ sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
+
+ /* allocate urbs and transfer buffers */
+ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+ urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+ if (!urb) {
+ em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
em28xx_uninit_isoc(dev);
return -ENOMEM;
}
- dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
- GFP_KERNEL,
- &urb->transfer_dma);
- if (!dev->transfer_buffer[i]) {
- em28xx_errdev
- ("unable to allocate %i bytes for transfer buffer %i\n",
- sb_size, i);
+ dev->isoc_ctl.urb[i] = urb;
+
+ dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
+ sb_size, GFP_KERNEL, &urb->transfer_dma);
+ if (!dev->isoc_ctl.transfer_buffer[i]) {
+ em28xx_err("unable to allocate %i bytes for transfer"
+ " buffer %i%s\n",
+ sb_size, i,
+ in_interrupt()?" while in int":"");
em28xx_uninit_isoc(dev);
- usb_free_urb(urb);
return -ENOMEM;
}
- memset(dev->transfer_buffer[i], 0, sb_size);
- urb->dev = dev->udev;
- urb->context = dev;
- urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
- urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
- urb->interval = 1;
- urb->transfer_buffer = dev->transfer_buffer[i];
- urb->complete = em28xx_isocIrq;
- urb->number_of_packets = EM28XX_NUM_PACKETS;
- urb->transfer_buffer_length = sb_size;
- for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
- urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
- urb->iso_frame_desc[j].length = dev->max_pkt_size;
+ memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+ /* FIXME: this is a hack - should be
+ 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
+ should also be using 'desc.bInterval'
+ */
+ pipe = usb_rcvisocpipe(dev->udev,
+ dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
+
+ usb_fill_int_urb(urb, dev->udev, pipe,
+ dev->isoc_ctl.transfer_buffer[i], sb_size,
+ em28xx_irq_callback, dma_q, 1);
+
+ urb->number_of_packets = max_packets;
+ urb->transfer_flags = URB_ISO_ASAP;
+
+ k = 0;
+ for (j = 0; j < max_packets; j++) {
+ urb->iso_frame_desc[j].offset = k;
+ urb->iso_frame_desc[j].length =
+ dev->isoc_ctl.max_pkt_size;
+ k += dev->isoc_ctl.max_pkt_size;
}
- dev->urb[i] = urb;
}
- /* submit urbs */
- em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
- EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
- errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
- if (errCode) {
- em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
- errCode);
- em28xx_uninit_isoc(dev);
- return errCode;
- }
- }
+ init_waitqueue_head(&dma_q->wq);
- return 0;
-}
+ em28xx_capture_start(dev, 1);
-int em28xx_set_alternate(struct em28xx *dev)
-{
- int errCode, prev_alt = dev->alt;
- int i;
- unsigned int min_pkt_size = dev->bytesperline + 4;
-
- /* When image size is bigger than a certain value,
- the frame size should be increased, otherwise, only
- green screen will be received.
- */
- if (dev->frame_size > 720*240*2)
- min_pkt_size *= 2;
-
- for (i = 0; i < dev->num_alt; i++) {
- /* stop when the selected alt setting offers enough bandwidth */
- if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
- dev->alt = i;
- break;
- /* otherwise make sure that we end up with the maximum bandwidth
- because the min_pkt_size equation might be wrong...
- */
- } else if (dev->alt_max_pkt_size[i] >
- dev->alt_max_pkt_size[dev->alt])
- dev->alt = i;
- }
-
- if (dev->alt != prev_alt) {
- em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
- min_pkt_size, dev->alt);
- dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
- em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
- dev->alt, dev->max_pkt_size);
- errCode = usb_set_interface(dev->udev, 0, dev->alt);
- if (errCode < 0) {
- em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
- dev->alt, errCode);
- return errCode;
+ /* submit urbs and enables IRQ */
+ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+ rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+ if (rc) {
+ em28xx_err("submit of urb %i failed (error=%i)\n", i,
+ rc);
+ em28xx_uninit_isoc(dev);
+ return rc;
}
}
+
return 0;
}
+EXPORT_SYMBOL_GPL(em28xx_init_isoc);
diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c
new file mode 100644
index 000000000..c61c764e1
--- /dev/null
+++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c
@@ -0,0 +1,528 @@
+/*
+ DVB device driver for em28xx
+
+ (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
+ - Fixes for the driver to properly work with HVR-950
+ - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
+
+ (c) 2008 Aidan Thornton <makosoft@googlemail.com>
+
+ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
+ (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include "compat.h"
+
+#include "em28xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+
+#include "lgdt330x.h"
+#include "zl10353.h"
+#include "drx397xD.h"
+
+MODULE_DESCRIPTION("driver for em28xx based DVB cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do { \
+if (debug >= level) \
+ printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+#define EM28XX_DVB_NUM_BUFS 5
+#define EM28XX_DVB_MAX_PACKETSIZE 564
+#define EM28XX_DVB_MAX_PACKETS 64
+
+struct em28xx_dvb {
+ struct dvb_frontend *frontend;
+
+ /* feed count management */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
+ struct mutex lock;
+#else
+ struct semaphore lock;
+#endif
+ int nfeeds;
+
+ /* general boilerplate stuff */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ struct dvb_adapter adapter;
+#else
+ struct dvb_adapter *adapter;
+#endif
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dmx_frontend fe_hw;
+ struct dmx_frontend fe_mem;
+ struct dvb_net net;
+};
+
+
+static inline void print_err_status(struct em28xx *dev,
+ int packet, int status)
+{
+ char *errmsg = "Unknown";
+
+ switch (status) {
+ case -ENOENT:
+ errmsg = "unlinked synchronuously";
+ break;
+ case -ECONNRESET:
+ errmsg = "unlinked asynchronuously";
+ break;
+ case -ENOSR:
+ errmsg = "Buffer error (overrun)";
+ break;
+ case -EPIPE:
+ errmsg = "Stalled (device not responding)";
+ break;
+ case -EOVERFLOW:
+ errmsg = "Babble (bad cable?)";
+ break;
+ case -EPROTO:
+ errmsg = "Bit-stuff error (bad cable?)";
+ break;
+ case -EILSEQ:
+ errmsg = "CRC/Timeout (could be anything)";
+ break;
+ case -ETIME:
+ errmsg = "Device does not respond";
+ break;
+ }
+ if (packet < 0) {
+ dprintk(1, "URB status %d [%s].\n", status, errmsg);
+ } else {
+ dprintk(1, "URB packet %d, status %d [%s].\n",
+ packet, status, errmsg);
+ }
+}
+
+static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+ int i;
+
+ if (!dev)
+ return 0;
+
+ if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ return 0;
+
+ if (urb->status < 0) {
+ print_err_status(dev, -1, urb->status);
+ if (urb->status == -ENOENT)
+ return 0;
+ }
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ int status = urb->iso_frame_desc[i].status;
+
+ if (status < 0) {
+ print_err_status(dev, i, status);
+ if (urb->iso_frame_desc[i].status != -EPROTO)
+ continue;
+ }
+
+ dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
+ urb->iso_frame_desc[i].offset,
+ urb->iso_frame_desc[i].actual_length);
+ }
+
+ return 0;
+}
+
+static int start_streaming(struct em28xx_dvb *dvb)
+{
+ int rc;
+ struct em28xx *dev = dvb->adapter.priv;
+
+ usb_set_interface(dev->udev, 0, 1);
+ rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+ if (rc < 0)
+ return rc;
+
+ return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
+ EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
+ dvb_isoc_copy);
+}
+
+static int stop_streaming(struct em28xx_dvb *dvb)
+{
+ struct em28xx *dev = dvb->adapter.priv;
+
+ em28xx_uninit_isoc(dev);
+
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
+ return 0;
+}
+
+static int start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct em28xx_dvb *dvb = demux->priv;
+ int rc, ret;
+
+ if (!demux->dmx.frontend)
+ return -EINVAL;
+
+ mutex_lock(&dvb->lock);
+ dvb->nfeeds++;
+ rc = dvb->nfeeds;
+
+ if (dvb->nfeeds == 1) {
+ ret = start_streaming(dvb);
+ if (ret < 0)
+ rc = ret;
+ }
+
+ mutex_unlock(&dvb->lock);
+ return rc;
+}
+
+static int stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct em28xx_dvb *dvb = demux->priv;
+ int err = 0;
+
+ mutex_lock(&dvb->lock);
+ dvb->nfeeds--;
+
+ if (0 == dvb->nfeeds)
+ err = stop_streaming(dvb);
+
+ mutex_unlock(&dvb->lock);
+ return err;
+}
+
+
+
+/* ------------------------------------------------------------------ */
+static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+ struct em28xx *dev = fe->dvb->priv;
+
+ if (acquire)
+ return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+ else
+ return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct lgdt330x_config em2880_lgdt3303_dev = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+};
+
+static struct zl10353_config em28xx_zl10353_with_xc3028 = {
+ .demod_address = (0x1e >> 1),
+ .no_tuner = 1,
+ .parallel_ts = 1,
+ .if2 = 45600,
+};
+
+#ifdef EM28XX_DRX397XD_SUPPORT
+/* [TODO] djh - not sure yet what the device config needs to contain */
+static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
+ .demod_address = (0xe0 >> 1),
+};
+#endif
+
+/* ------------------------------------------------------------------ */
+
+static int attach_xc3028(u8 addr, struct em28xx *dev)
+{
+ struct dvb_frontend *fe;
+ struct xc2028_config cfg;
+
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.i2c_adap = &dev->i2c_adap;
+ cfg.i2c_addr = addr;
+ cfg.callback = em28xx_tuner_callback;
+
+ if (!dev->dvb->frontend) {
+ printk(KERN_ERR "%s/2: dvb frontend not attached. "
+ "Can't attach xc3028\n",
+ dev->name);
+ return -EINVAL;
+ }
+
+ fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg);
+ if (!fe) {
+ printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+ dev->name);
+ dvb_frontend_detach(dev->dvb->frontend);
+ dev->dvb->frontend = NULL;
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int register_dvb(struct em28xx_dvb *dvb,
+ struct module *module,
+ struct em28xx *dev,
+ struct device *device)
+{
+ int result;
+
+ mutex_init(&dvb->lock);
+
+ /* register adapter */
+ result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+ adapter_nr);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+ dev->name, result);
+ goto fail_adapter;
+ }
+
+ /* Ensure all frontends negotiate bus access */
+ dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb->adapter.priv = dev;
+
+ /* register frontend */
+ result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+#else
+ dvb->adapter->priv = dev;
+
+ /* register frontend */
+ result = dvb_register_frontend(dvb->adapter, dvb->frontend);
+#endif
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
+ dev->name, result);
+ goto fail_frontend;
+ }
+
+ /* register demux stuff */
+ dvb->demux.dmx.capabilities =
+ DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING;
+ dvb->demux.priv = dvb;
+ dvb->demux.filternum = 256;
+ dvb->demux.feednum = 256;
+ dvb->demux.start_feed = start_feed;
+ dvb->demux.stop_feed = stop_feed;
+
+ result = dvb_dmx_init(&dvb->demux);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+ dev->name, result);
+ goto fail_dmx;
+ }
+
+ dvb->dmxdev.filternum = 256;
+ dvb->dmxdev.demux = &dvb->demux.dmx;
+ dvb->dmxdev.capabilities = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+#else
+ result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter);
+#endif
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+ dev->name, result);
+ goto fail_dmxdev;
+ }
+
+ dvb->fe_hw.source = DMX_FRONTEND_0;
+ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+ dev->name, result);
+ goto fail_fe_hw;
+ }
+
+ dvb->fe_mem.source = DMX_MEMORY_FE;
+ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+ dev->name, result);
+ goto fail_fe_mem;
+ }
+
+ result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
+ dev->name, result);
+ goto fail_fe_conn;
+ }
+
+ /* register network adapter */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+#else
+ dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx);
+#endif
+ return 0;
+
+fail_fe_conn:
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+ dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+ dvb_dmx_release(&dvb->demux);
+fail_dmx:
+ dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+ dvb_frontend_detach(dvb->frontend);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_unregister_adapter(&dvb->adapter);
+#else
+ dvb_unregister_adapter(dvb->adapter);
+#endif
+fail_adapter:
+ return result;
+}
+
+static void unregister_dvb(struct em28xx_dvb *dvb)
+{
+ dvb_net_release(&dvb->net);
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+ dvb_dmxdev_release(&dvb->dmxdev);
+ dvb_dmx_release(&dvb->demux);
+ dvb_unregister_frontend(dvb->frontend);
+ dvb_frontend_detach(dvb->frontend);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12))
+ dvb_unregister_adapter(&dvb->adapter);
+#else
+ dvb_unregister_adapter(dvb->adapter);
+#endif
+}
+
+
+static int dvb_init(struct em28xx *dev)
+{
+ int result = 0;
+ struct em28xx_dvb *dvb;
+
+ dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
+
+ if (dvb == NULL) {
+ printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
+ return -ENOMEM;
+ }
+ dev->dvb = dvb;
+
+ em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+ /* init frontend */
+ switch (dev->model) {
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+ dvb->frontend = dvb_attach(lgdt330x_attach,
+ &em2880_lgdt3303_dev,
+ &dev->i2c_adap);
+ if (attach_xc3028(0x61, dev) < 0) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ break;
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+ dvb->frontend = dvb_attach(zl10353_attach,
+ &em28xx_zl10353_with_xc3028,
+ &dev->i2c_adap);
+ if (attach_xc3028(0x61, dev) < 0) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ break;
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
+#ifdef EM28XX_DRX397XD_SUPPORT
+ /* We don't have the config structure properly populated, so
+ this is commented out for now */
+ dvb->frontend = dvb_attach(drx397xD_attach,
+ &em28xx_drx397xD_with_xc3028,
+ &dev->i2c_adap);
+ if (attach_xc3028(0x61, dev) < 0) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ break;
+#endif
+ default:
+ printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+ " isn't supported yet\n",
+ dev->name);
+ break;
+ }
+ if (NULL == dvb->frontend) {
+ printk(KERN_ERR
+ "%s/2: frontend initialization failed\n",
+ dev->name);
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ /* register everything */
+ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+ if (result < 0)
+ goto out_free;
+
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+ printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
+ return 0;
+
+out_free:
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+ kfree(dvb);
+ dev->dvb = NULL;
+ return result;
+}
+
+static int dvb_fini(struct em28xx *dev)
+{
+ if (dev->dvb) {
+ unregister_dvb(dev->dvb);
+ dev->dvb = NULL;
+ }
+
+ return 0;
+}
+
+static struct em28xx_ops dvb_ops = {
+ .id = EM28XX_DVB,
+ .name = "Em28xx dvb Extension",
+ .init = dvb_init,
+ .fini = dvb_fini,
+};
+
+static int __init em28xx_dvb_register(void)
+{
+ return em28xx_register_extension(&dvb_ops);
+}
+
+static void __exit em28xx_dvb_unregister(void)
+{
+ em28xx_unregister_extension(&dvb_ops);
+}
+
+module_init(em28xx_dvb_register);
+module_exit(em28xx_dvb_unregister);
diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c
index e13743d67..c22e73019 100644
--- a/linux/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c
@@ -41,11 +41,21 @@ static unsigned int i2c_debug;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
- printk(fmt, ##args); } while (0)
-#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
- printk(KERN_DEBUG "%s at %s: " fmt, \
- dev->name, __FUNCTION__ , ##args); } while (0)
+
+#define dprintk1(lvl, fmt, args...) \
+do { \
+ if (i2c_debug >= lvl) { \
+ printk(fmt, ##args); \
+ } \
+} while (0)
+
+#define dprintk2(lvl, fmt, args...) \
+do { \
+ if (i2c_debug >= lvl) { \
+ printk(KERN_DEBUG "%s at %s: " fmt, \
+ dev->name, __func__ , ##args); \
+ } \
+} while (0)
/*
* em2800_i2c_send_max4()
@@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
return 0;
for (i = 0; i < num; i++) {
addr = msgs[i].addr << 1;
- dprintk2(2,"%s %s addr=%x len=%d:",
+ dprintk2(2, "%s %s addr=%x len=%d:",
(msgs[i].flags & I2C_M_RD) ? "read" : "write",
i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
- if (!msgs[i].len) { /* no len: check only for device presence */
+ if (!msgs[i].len) { /* no len: check only for device presence */
if (dev->is_em2800)
rc = em2800_i2c_check_for_device(dev, addr);
else
rc = em28xx_i2c_check_for_device(dev, addr);
if (rc < 0) {
- dprintk2(2," no device\n");
+ dprintk2(2, " no device\n");
return rc;
}
@@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
rc = em28xx_i2c_recv_bytes(dev, addr,
msgs[i].buf,
msgs[i].len);
- if (i2c_debug>=2) {
- for (byte = 0; byte < msgs[i].len; byte++) {
+ if (i2c_debug >= 2) {
+ for (byte = 0; byte < msgs[i].len; byte++)
printk(" %02x", msgs[i].buf[byte]);
- }
}
} else {
/* write bytes */
- if (i2c_debug>=2) {
+ if (i2c_debug >= 2) {
for (byte = 0; byte < msgs[i].len; byte++)
printk(" %02x", msgs[i].buf[byte]);
}
@@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
}
if (rc < 0)
goto err;
- if (i2c_debug>=2)
+ if (i2c_debug >= 2)
printk("\n");
}
return num;
- err:
- dprintk2(2," ERROR: %i\n", rc);
+err:
+ dprintk2(2, " ERROR: %i\n", rc);
return rc;
}
@@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
return -1;
buf = 0;
- if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
+
+ err = i2c_master_send(&dev->i2c_client, &buf, 1);
+ if (err != 1) {
printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
dev->name, err);
return -1;
@@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
break;
}
printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
- em_eeprom->string_idx_table,em_eeprom->string1,
- em_eeprom->string2,em_eeprom->string3);
+ em_eeprom->string_idx_table,
+ em_eeprom->string1,
+ em_eeprom->string2,
+ em_eeprom->string3);
return 0;
}
@@ -441,58 +454,61 @@ static int attach_inform(struct i2c_client *client)
struct em28xx *dev = client->adapter->algo_data;
switch (client->addr << 1) {
- case 0x86:
- case 0x84:
- case 0x96:
- case 0x94:
- {
- struct v4l2_priv_tun_config tda9887_cfg;
-
- struct tuner_setup tun_setup;
-
- tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
- tun_setup.type = TUNER_TDA9887;
- tun_setup.addr = client->addr;
-
- em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &dev->tda9887_conf;
- em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
- &tda9887_cfg);
- break;
- }
- case 0x42:
- dprintk1(1,"attach_inform: saa7114 detected.\n");
- break;
- case 0x4a:
- dprintk1(1,"attach_inform: saa7113 detected.\n");
- break;
- case 0xa0:
- dprintk1(1,"attach_inform: eeprom detected.\n");
- break;
- case 0x60:
- case 0x8e:
- {
- struct IR_i2c *ir = i2c_get_clientdata(client);
- dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
- em28xx_set_ir(dev,ir);
- break;
- }
- case 0x80:
- case 0x88:
- dprintk1(1,"attach_inform: msp34xx detected.\n");
- break;
- case 0xb8:
- case 0xba:
- dprintk1(1,"attach_inform: tvp5150 detected.\n");
- break;
+ case 0x86:
+ case 0x84:
+ case 0x96:
+ case 0x94:
+ {
+ struct v4l2_priv_tun_config tda9887_cfg;
+
+ struct tuner_setup tun_setup;
+
+ tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+ tun_setup.type = TUNER_TDA9887;
+ tun_setup.addr = client->addr;
+
+ em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
+ &tun_setup);
+
+ tda9887_cfg.tuner = TUNER_TDA9887;
+ tda9887_cfg.priv = &dev->tda9887_conf;
+ em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
+ &tda9887_cfg);
+ break;
+ }
+ case 0x42:
+ dprintk1(1, "attach_inform: saa7114 detected.\n");
+ break;
+ case 0x4a:
+ dprintk1(1, "attach_inform: saa7113 detected.\n");
+ break;
+ case 0xa0:
+ dprintk1(1, "attach_inform: eeprom detected.\n");
+ break;
+ case 0x60:
+ case 0x8e:
+ {
+ struct IR_i2c *ir = i2c_get_clientdata(client);
+ dprintk1(1, "attach_inform: IR detected (%s).\n",
+ ir->phys);
+ em28xx_set_ir(dev, ir);
+ break;
+ }
+ case 0x80:
+ case 0x88:
+ dprintk1(1, "attach_inform: msp34xx detected.\n");
+ break;
+ case 0xb8:
+ case 0xba:
+ dprintk1(1, "attach_inform: tvp5150 detected.\n");
+ break;
- default:
- if (!dev->tuner_addr)
- dev->tuner_addr = client->addr;
+ default:
+ if (!dev->tuner_addr)
+ dev->tuner_addr = client->addr;
- dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
+ dprintk1(1, "attach inform: detected I2C address %x\n",
+ client->addr << 1);
}
@@ -522,7 +538,7 @@ static struct i2c_adapter em28xx_adap_template = {
static struct i2c_client em28xx_client_template = {
.name = "em28xx internal",
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
.flags = I2C_CLIENT_ALLOW_USE,
#endif
};
diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c
index 5c78eceff..49c40f083 100644
--- a/linux/drivers/media/video/em28xx/em28xx-input.c
+++ b/linux/drivers/media/video/em28xx/em28xx-input.c
@@ -33,10 +33,12 @@
static unsigned int ir_debug;
module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
-#define dprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
+#define dprintk(fmt, arg...) \
+ if (ir_debug) { \
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+ }
/* ----------------------------------------------------------------------- */
@@ -45,7 +47,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ if (1 != i2c_master_recv(&ir->c, &b, 1)) {
dprintk("read error\n");
return -EIO;
}
@@ -75,29 +77,30 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char code;
/* poll IR chip */
- if (2 != i2c_master_recv(&ir->c,buf,2))
+ if (2 != i2c_master_recv(&ir->c, buf, 2))
return -EIO;
/* Does eliminate repeated parity code */
- if (buf[1]==0xff)
+ if (buf[1] == 0xff)
return 0;
#if 0
/* avoid reapeating keystrokes */
- if (buf[1]==ir->old)
+ if (buf[1] == ir->old)
return 0;
#endif
- ir->old=buf[1];
+ ir->old = buf[1];
/* Rearranges bits to the right order */
- code= ((buf[0]&0x01)<<5) | /* 0010 0000 */
+ code = ((buf[0]&0x01)<<5) | /* 0010 0000 */
((buf[0]&0x02)<<3) | /* 0001 0000 */
((buf[0]&0x04)<<1) | /* 0000 1000 */
((buf[0]&0x08)>>1) | /* 0000 0100 */
((buf[0]&0x10)>>3) | /* 0000 0010 */
((buf[0]&0x20)>>5); /* 0000 0001 */
- dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]);
+ dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
+ code, buf[0]);
/* return key */
*ir_key = code;
@@ -112,15 +115,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
/* poll IR chip */
- if (3 != i2c_master_recv(&ir->c,buf,3)) {
+ if (3 != i2c_master_recv(&ir->c, buf, 3)) {
dprintk("read error\n");
return -EIO;
}
dprintk("key %02x\n", buf[2]&0x3f);
- if (buf[0]!=0x00){
+ if (buf[0] != 0x00)
return 0;
- }
*ir_key = buf[2]&0x3f;
*ir_raw = buf[2]&0x3f;
diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h
new file mode 100644
index 000000000..9058bed07
--- /dev/null
+++ b/linux/drivers/media/video/em28xx/em28xx-reg.h
@@ -0,0 +1,88 @@
+#define EM_GPIO_0 (1 << 0)
+#define EM_GPIO_1 (1 << 1)
+#define EM_GPIO_2 (1 << 2)
+#define EM_GPIO_3 (1 << 3)
+#define EM_GPIO_4 (1 << 4)
+#define EM_GPIO_5 (1 << 5)
+#define EM_GPIO_6 (1 << 6)
+#define EM_GPIO_7 (1 << 7)
+
+#define EM_GPO_0 (1 << 0)
+#define EM_GPO_1 (1 << 1)
+#define EM_GPO_2 (1 << 2)
+#define EM_GPO_3 (1 << 3)
+
+/* em2800 registers */
+#define EM2800_R08_AUDIOSRC 0x08
+
+/* em28xx registers */
+
+ /* GPIO/GPO registers */
+#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */
+#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */
+
+#define EM28XX_R06_I2C_CLK 0x06
+#define EM28XX_R0A_CHIPID 0x0a
+#define EM28XX_R0C_USBSUSP 0x0c /* */
+
+#define EM28XX_R0E_AUDIOSRC 0x0e
+#define EM28XX_R0F_XCLK 0x0f
+
+#define EM28XX_R10_VINMODE 0x10
+#define EM28XX_R11_VINCTRL 0x11
+#define EM28XX_R12_VINENABLE 0x12 /* */
+
+#define EM28XX_R14_GAMMA 0x14
+#define EM28XX_R15_RGAIN 0x15
+#define EM28XX_R16_GGAIN 0x16
+#define EM28XX_R17_BGAIN 0x17
+#define EM28XX_R18_ROFFSET 0x18
+#define EM28XX_R19_GOFFSET 0x19
+#define EM28XX_R1A_BOFFSET 0x1a
+
+#define EM28XX_R1B_OFLOW 0x1b
+#define EM28XX_R1C_HSTART 0x1c
+#define EM28XX_R1D_VSTART 0x1d
+#define EM28XX_R1E_CWIDTH 0x1e
+#define EM28XX_R1F_CHEIGHT 0x1f
+
+#define EM28XX_R20_YGAIN 0x20
+#define EM28XX_R21_YOFFSET 0x21
+#define EM28XX_R22_UVGAIN 0x22
+#define EM28XX_R23_UOFFSET 0x23
+#define EM28XX_R24_VOFFSET 0x24
+#define EM28XX_R25_SHARPNESS 0x25
+
+#define EM28XX_R26_COMPR 0x26
+#define EM28XX_R27_OUTFMT 0x27
+
+#define EM28XX_R28_XMIN 0x28
+#define EM28XX_R29_XMAX 0x29
+#define EM28XX_R2A_YMIN 0x2a
+#define EM28XX_R2B_YMAX 0x2b
+
+#define EM28XX_R30_HSCALELOW 0x30
+#define EM28XX_R31_HSCALEHIGH 0x31
+#define EM28XX_R32_VSCALELOW 0x32
+#define EM28XX_R33_VSCALEHIGH 0x33
+
+#define EM28XX_R40_AC97LSB 0x40
+#define EM28XX_R41_AC97MSB 0x41
+#define EM28XX_R42_AC97ADDR 0x42
+#define EM28XX_R43_AC97BUSY 0x43
+
+/* em202 registers */
+#define EM28XX_R02_MASTER_AC97 0x02
+#define EM28XX_R10_LINE_IN_AC97 0x10
+#define EM28XX_R14_VIDEO_AC97 0x14
+
+/* register settings */
+#define EM2800_AUDIO_SRC_TUNER 0x0d
+#define EM2800_AUDIO_SRC_LINE 0x0c
+#define EM28XX_AUDIO_SRC_TUNER 0xc0
+#define EM28XX_AUDIO_SRC_LINE 0x80
+
+/* FIXME: Need to be populated with the other chip ID's */
+enum em28xx_chip_id {
+ CHIP_ID_EM2883 = 36,
+};
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 4999897ed..546d776ab 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -1,5 +1,6 @@
/*
- em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+ em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+ video capture devices
Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
Markus Rechberger <mrechberger@gmail.com>
@@ -33,7 +34,7 @@
#include <linux/i2c.h>
#include <linux/version.h>
#include <linux/mm.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
#include <linux/mutex.h>
#endif
@@ -41,7 +42,7 @@
#include <media/v4l2-common.h>
#include <media/msp3400.h>
#include <media/tuner.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
#include "i2c-compat.h"
#endif
@@ -57,7 +58,19 @@
#define em28xx_videodbg(fmt, arg...) do {\
if (video_debug) \
printk(KERN_INFO "%s %s :"fmt, \
- dev->name, __FUNCTION__ , ##arg); } while (0)
+ dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define em28xx_isocdbg(fmt, arg...) \
+do {\
+ if (isoc_debug) { \
+ printk(KERN_INFO "%s %s :"fmt, \
+ dev->name, __func__ , ##arg); \
+ } \
+ } while (0)
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -70,13 +83,13 @@ static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
MODULE_PARM(card, "1-" __stringify(EM28XX_MAXBOARDS) "i");
MODULE_PARM(video_nr, "1-" __stringify(EM28XX_MAXBOARDS) "i");
MODULE_PARM(vbi_nr, "1-" __stringify(EM28XX_MAXBOARDS) "i");
MODULE_PARM(radio_nr, "1-" __stringify(EM28XX_MAXBOARDS) "i");
#else
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
static int dummy;
module_param_array(card, int, dummy, 0444);
module_param_array(video_nr, int, dummy, 0444);
@@ -95,8 +108,8 @@ MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
MODULE_PARM_DESC(radio_nr, "radio device numbers");
static unsigned int video_debug;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
static unsigned long em28xx_devused;
@@ -113,7 +126,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.step = 0x1,
.default_value = 0x1f,
.flags = 0,
- },{
+ }, {
.id = V4L2_CID_AUDIO_MUTE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Mute",
@@ -127,8 +140,395 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
static struct usb_driver em28xx_usb_driver;
+/* ------------------------------------------------------------------
+ DMA and thread functions
+ ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct em28xx *dev,
+ struct em28xx_dmaqueue *dma_q,
+ struct em28xx_buffer *buf)
+{
+ /* Advice that buffer was filled */
+ em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+ buf->vb.state = VIDEOBUF_DONE;
+ buf->vb.field_count++;
+ do_gettimeofday(&buf->vb.ts);
+
+ dev->isoc_ctl.buf = NULL;
+
+ list_del(&buf->vb.queue);
+ wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void em28xx_copy_video(struct em28xx *dev,
+ struct em28xx_dmaqueue *dma_q,
+ struct em28xx_buffer *buf,
+ unsigned char *p,
+ unsigned char *outp, unsigned long len)
+{
+ void *fieldstart, *startwrite, *startread;
+ int linesdone, currlinedone, offset, lencopy, remain;
+ int bytesperline = dev->width << 1;
+
+ if (dma_q->pos + len > buf->vb.size)
+ len = buf->vb.size - dma_q->pos;
+
+ if (p[0] != 0x88 && p[0] != 0x22) {
+ em28xx_isocdbg("frame is not complete\n");
+ len += 4;
+ } else
+ p += 4;
+
+ startread = p;
+ remain = len;
+
+ /* Interlaces frame */
+ if (buf->top_field)
+ fieldstart = outp;
+ else
+ fieldstart = outp + bytesperline;
+
+ linesdone = dma_q->pos / bytesperline;
+ currlinedone = dma_q->pos % bytesperline;
+ offset = linesdone * bytesperline * 2 + currlinedone;
+ startwrite = fieldstart + offset;
+ lencopy = bytesperline - currlinedone;
+ lencopy = lencopy > remain ? remain : lencopy;
+
+ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+ em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
+ ((char *)startwrite + lencopy) -
+ ((char *)outp + buf->vb.size));
+ lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
+ }
+ if (lencopy <= 0)
+ return;
+ memcpy(startwrite, startread, lencopy);
+
+ remain -= lencopy;
+
+ while (remain > 0) {
+ startwrite += lencopy + bytesperline;
+ startread += lencopy;
+ if (bytesperline > remain)
+ lencopy = remain;
+ else
+ lencopy = bytesperline;
+
+ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+ em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
+ ((char *)startwrite + lencopy) -
+ ((char *)outp + buf->vb.size));
+ lencopy = remain = (char *)outp + buf->vb.size -
+ (char *)startwrite;
+ }
+ if (lencopy <= 0)
+ break;
+
+ memcpy(startwrite, startread, lencopy);
+
+ remain -= lencopy;
+ }
+
+ dma_q->pos += len;
+}
+
+static inline void print_err_status(struct em28xx *dev,
+ int packet, int status)
+{
+ char *errmsg = "Unknown";
+
+ switch (status) {
+ case -ENOENT:
+ errmsg = "unlinked synchronuously";
+ break;
+ case -ECONNRESET:
+ errmsg = "unlinked asynchronuously";
+ break;
+ case -ENOSR:
+ errmsg = "Buffer error (overrun)";
+ break;
+ case -EPIPE:
+ errmsg = "Stalled (device not responding)";
+ break;
+ case -EOVERFLOW:
+ errmsg = "Babble (bad cable?)";
+ break;
+ case -EPROTO:
+ errmsg = "Bit-stuff error (bad cable?)";
+ break;
+ case -EILSEQ:
+ errmsg = "CRC/Timeout (could be anything)";
+ break;
+ case -ETIME:
+ errmsg = "Device does not respond";
+ break;
+ }
+ if (packet < 0) {
+ em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+ } else {
+ em28xx_isocdbg("URB packet %d, status %d [%s].\n",
+ packet, status, errmsg);
+ }
+}
-/********************* v4l2 interface ******************************************/
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
+ struct em28xx_buffer **buf)
+{
+ struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+#if 1
+ char *outp;
+#endif
+
+ if (list_empty(&dma_q->active)) {
+ em28xx_isocdbg("No active queue to serve\n");
+ dev->isoc_ctl.buf = NULL;
+ *buf = NULL;
+ return;
+ }
+
+ /* Get the next buffer */
+ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+
+#if 1
+ /* Cleans up buffer - Usefull for testing for frame/URB loss */
+ outp = videobuf_to_vmalloc(&(*buf)->vb);
+ memset(outp, 0, (*buf)->vb.size);
+#endif
+
+ dev->isoc_ctl.buf = *buf;
+
+ return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+ struct em28xx_buffer *buf;
+ struct em28xx_dmaqueue *dma_q = urb->context;
+ unsigned char *outp = NULL;
+ int i, len = 0, rc = 1;
+ unsigned char *p;
+
+ if (!dev)
+ return 0;
+
+ if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ return 0;
+
+ if (urb->status < 0) {
+ print_err_status(dev, -1, urb->status);
+ if (urb->status == -ENOENT)
+ return 0;
+ }
+
+ buf = dev->isoc_ctl.buf;
+ if (buf != NULL)
+ outp = videobuf_to_vmalloc(&buf->vb);
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ int status = urb->iso_frame_desc[i].status;
+
+ if (status < 0) {
+ print_err_status(dev, i, status);
+ if (urb->iso_frame_desc[i].status != -EPROTO)
+ continue;
+ }
+
+ len = urb->iso_frame_desc[i].actual_length - 4;
+
+ if (urb->iso_frame_desc[i].actual_length <= 0) {
+ /* em28xx_isocdbg("packet %d is empty",i); - spammy */
+ continue;
+ }
+ if (urb->iso_frame_desc[i].actual_length >
+ dev->max_pkt_size) {
+ em28xx_isocdbg("packet bigger than packet size");
+ continue;
+ }
+
+ p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+ /* FIXME: incomplete buffer checks where removed to make
+ logic simpler. Impacts of those changes should be evaluated
+ */
+ if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
+ em28xx_isocdbg("VBI HEADER!!!\n");
+ /* FIXME: Should add vbi copy */
+ continue;
+ }
+ if (p[0] == 0x22 && p[1] == 0x5a) {
+ em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
+ len, (p[2] & 1)? "odd" : "even");
+
+ if (!(p[2] & 1)) {
+ if (buf != NULL)
+ buffer_filled(dev, dma_q, buf);
+ get_next_buf(dma_q, &buf);
+ if (buf == NULL)
+ outp = NULL;
+ else
+ outp = videobuf_to_vmalloc(&buf->vb);
+ }
+
+ if (buf != NULL) {
+ if (p[2] & 1)
+ buf->top_field = 0;
+ else
+ buf->top_field = 1;
+ }
+
+ dma_q->pos = 0;
+ }
+ if (buf != NULL)
+ em28xx_copy_video(dev, dma_q, buf, p, outp, len);
+ }
+ return rc;
+}
+
+/* ------------------------------------------------------------------
+ Videobuf operations
+ ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = fh->dev;
+ struct v4l2_frequency f;
+
+ *size = 16 * fh->dev->width * fh->dev->height >> 3;
+ if (0 == *count)
+ *count = EM28XX_DEF_BUF;
+
+ if (*count < EM28XX_MIN_BUF)
+ *count = EM28XX_MIN_BUF;
+
+ /* Ask tuner to go to analog mode */
+ memset(&f, 0, sizeof(f));
+ f.frequency = dev->ctl_freq;
+
+ em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+
+ return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
+{
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = fh->dev;
+ unsigned long flags = 0;
+ if (in_interrupt())
+ BUG();
+
+ /* We used to wait for the buffer to finish here, but this didn't work
+ because, as we were keeping the state as VIDEOBUF_QUEUED,
+ videobuf_queue_cancel marked it as finished for us.
+ (Also, it could wedge forever if the hardware was misconfigured.)
+
+ This should be safe; by the time we get here, the buffer isn't
+ queued anymore. If we ever start marking the buffers as
+ VIDEOBUF_ACTIVE, it won't be, though.
+ */
+ spin_lock_irqsave(&dev->slock, flags);
+ if (dev->isoc_ctl.buf == buf)
+ dev->isoc_ctl.buf = NULL;
+ spin_unlock_irqrestore(&dev->slock, flags);
+
+ videobuf_vmalloc_free(&buf->vb);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+ struct em28xx *dev = fh->dev;
+ int rc = 0, urb_init = 0;
+
+ /* FIXME: It assumes depth = 16 */
+ /* The only currently supported format is 16 bits/pixel */
+ buf->vb.size = 16 * dev->width * dev->height >> 3;
+
+ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ return -EINVAL;
+
+ buf->vb.width = dev->width;
+ buf->vb.height = dev->height;
+ buf->vb.field = field;
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ rc = videobuf_iolock(vq, &buf->vb, NULL);
+ if (rc < 0)
+ goto fail;
+ }
+
+ if (!dev->isoc_ctl.num_bufs)
+ urb_init = 1;
+
+ if (urb_init) {
+ rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
+ EM28XX_NUM_BUFS, dev->max_pkt_size,
+ em28xx_isoc_copy);
+ if (rc < 0)
+ goto fail;
+ }
+
+ buf->vb.state = VIDEOBUF_PREPARED;
+ return 0;
+
+fail:
+ free_buffer(vq, buf);
+ return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = fh->dev;
+ struct em28xx_dmaqueue *vidq = &dev->vidq;
+
+ buf->vb.state = VIDEOBUF_QUEUED;
+ list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+ struct em28xx_fh *fh = vq->priv_data;
+ struct em28xx *dev = (struct em28xx *)fh->dev;
+
+ em28xx_isocdbg("em28xx: called buffer_release\n");
+
+ free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops em28xx_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+/********************* v4l2 interface **************************************/
/*
* em28xx_config()
@@ -144,9 +544,9 @@ static int em28xx_config(struct em28xx *dev)
#if 1
/* enable vbi capturing */
-/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
-/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
- em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
+/* em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
+/* em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
+ em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
#endif
dev->mute = 1; /* maybe not the right place... */
@@ -174,23 +574,6 @@ static void em28xx_config_i2c(struct em28xx *dev)
em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
}
-/*
- * em28xx_empty_framequeues()
- * prepare queues for incoming and outgoing frames
- */
-static void em28xx_empty_framequeues(struct em28xx *dev)
-{
- u32 i;
-
- INIT_LIST_HEAD(&dev->inqueue);
- INIT_LIST_HEAD(&dev->outqueue);
-
- for (i = 0; i < EM28XX_NUM_FRAMES; i++) {
- dev->frame[i].state = F_UNUSED;
- dev->frame[i].buf.bytesused = 0;
- }
-}
-
static void video_mux(struct em28xx *dev, int index)
{
struct v4l2_routing route;
@@ -203,12 +586,15 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
if (dev->has_msp34xx) {
- if (dev->i2s_speed)
- em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
+ if (dev->i2s_speed) {
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
+ &dev->i2s_speed);
+ }
route.input = dev->ctl_ainput;
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
- em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
+ &route);
}
em28xx_audio_analog_set(dev);
@@ -224,15 +610,12 @@ static int res_get(struct em28xx_fh *fh)
if (fh->stream_on)
return rc;
- mutex_lock(&dev->lock);
-
if (dev->stream_on)
- rc = -EINVAL;
- else {
- dev->stream_on = 1;
- fh->stream_on = 1;
- }
+ return -EINVAL;
+ mutex_lock(&dev->lock);
+ dev->stream_on = 1;
+ fh->stream_on = 1;
mutex_unlock(&dev->lock);
return rc;
}
@@ -253,33 +636,6 @@ static void res_free(struct em28xx_fh *fh)
}
/*
- * em28xx_vm_open()
- */
-static void em28xx_vm_open(struct vm_area_struct *vma)
-{
- struct em28xx_frame_t *f = vma->vm_private_data;
- f->vma_use_count++;
-}
-
-/*
- * em28xx_vm_close()
- */
-static void em28xx_vm_close(struct vm_area_struct *vma)
-{
- /* NOTE: buffers are not freed here */
- struct em28xx_frame_t *f = vma->vm_private_data;
-
- if (f->vma_use_count)
- f->vma_use_count--;
-}
-
-static struct vm_operations_struct em28xx_vm_ops = {
- .open = em28xx_vm_open,
- .close = em28xx_vm_close,
-};
-
-
-/*
* em28xx_get_ctrl()
* return the current saturation, brightness or contrast, mute state
*/
@@ -318,34 +674,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
}
}
-/*
- * em28xx_stream_interrupt()
- * stops streaming
- */
-static int em28xx_stream_interrupt(struct em28xx *dev)
-{
- int rc = 0;
-
- /* stop reading from the device */
-
- dev->stream = STREAM_INTERRUPT;
- rc = wait_event_timeout(dev->wait_stream,
- (dev->stream == STREAM_OFF) ||
- (dev->state & DEV_DISCONNECTED),
- EM28XX_URB_TIMEOUT);
-
- if (rc) {
- dev->state |= DEV_MISCONFIGURED;
- em28xx_videodbg("device is misconfigured; close and "
- "open /dev/video%d again\n",
- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
- return rc;
- }
-
- return 0;
-}
-
-
static int check_dev(struct em28xx *dev)
{
if (dev->state & DEV_DISCONNECTED) {
@@ -381,7 +709,7 @@ static void get_scale(struct em28xx *dev,
IOCTL vidioc handling
------------------------------------------------------------------*/
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct em28xx_fh *fh = priv;
@@ -392,8 +720,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- f->fmt.pix.bytesperline = dev->bytesperline;
- f->fmt.pix.sizeimage = dev->frame_size;
+ f->fmt.pix.bytesperline = dev->width * 2;
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
@@ -404,7 +732,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct em28xx_fh *fh = priv;
@@ -464,64 +792,49 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- int rc, i;
+ int rc;
rc = check_dev(dev);
if (rc < 0)
return rc;
- vidioc_try_fmt_cap(file, priv, f);
+ vidioc_try_fmt_vid_cap(file, priv, f);
mutex_lock(&dev->lock);
- for (i = 0; i < dev->num_frames; i++)
- if (dev->frame[i].vma_use_count) {
- em28xx_videodbg("VIDIOC_S_FMT failed. "
- "Unmap the buffers first.\n");
- rc = -EINVAL;
- goto err;
- }
-
- /* stop io in case it is already in progress */
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0)
- goto err;
+ if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+ em28xx_errdev("%s queue busy\n", __func__);
+ rc = -EBUSY;
+ goto out;
}
- em28xx_release_buffers(dev);
- dev->io = IO_NONE;
+ if (dev->stream_on && !fh->stream_on) {
+ em28xx_errdev("%s device in use by another fh\n", __func__);
+ rc = -EBUSY;
+ goto out;
+ }
/* set new image size */
dev->width = f->fmt.pix.width;
dev->height = f->fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
- /* FIXME: This is really weird! Why capture is starting with
- this ioctl ???
- */
- em28xx_uninit_isoc(dev);
em28xx_set_alternate(dev);
- em28xx_capture_start(dev, 1);
em28xx_resolution_set(dev);
- em28xx_init_isoc(dev);
+
rc = 0;
-err:
+out:
mutex_unlock(&dev->lock);
return rc;
}
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
@@ -539,16 +852,13 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
/* Adjusts width/height, if needed */
f.fmt.pix.width = dev->width;
f.fmt.pix.height = dev->height;
- vidioc_try_fmt_cap(file, priv, &f);
+ vidioc_try_fmt_vid_cap(file, priv, &f);
mutex_lock(&dev->lock);
/* set new image size */
dev->width = f.fmt.pix.width;
dev->height = f.fmt.pix.height;
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1;
- dev->bytesperline = dev->width * 2;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_resolution_set(dev);
@@ -641,11 +951,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
index = dev->ctl_ainput;
- if (index == 0) {
+ if (index == 0)
strcpy(a->name, "Television");
- } else {
+ else
strcpy(a->name, "Line In");
- }
+
a->capability = V4L2_AUDCAP_STEREO;
a->index = index;
@@ -856,9 +1166,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int em28xx_reg_len(int reg)
{
switch (reg) {
- case AC97LSB_REG:
- case HSCALELOW_REG:
- case VSCALELOW_REG:
+ case EM28XX_R40_AC97LSB:
+ case EM28XX_R30_HSCALELOW:
+ case EM28XX_R32_VSCALELOW:
return 2;
default:
return 1;
@@ -882,13 +1192,13 @@ static int vidioc_g_register(struct file *file, void *priv,
reg->val = ret;
} else {
- u64 val = 0;
+ __le64 val = 0;
ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
reg->reg, (char *)&val, 2);
if (ret < 0)
return ret;
- reg->val = cpu_to_le64((__u64)val);
+ reg->val = le64_to_cpu(val);
}
return 0;
@@ -899,9 +1209,9 @@ static int vidioc_s_register(struct file *file, void *priv,
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- u64 buf;
+ __le64 buf;
- buf = le64_to_cpu((__u64)reg->val);
+ buf = cpu_to_le64(reg->val);
return em28xx_write_regs(dev, reg->reg, (char *)&buf,
em28xx_reg_len(reg->reg));
@@ -940,23 +1250,11 @@ static int vidioc_streamon(struct file *file, void *priv,
if (rc < 0)
return rc;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
- return -EINVAL;
-
- if (list_empty(&dev->inqueue))
- return -EINVAL;
-
- mutex_lock(&dev->lock);
- if (unlikely(res_get(fh) < 0)) {
- mutex_unlock(&dev->lock);
+ if (unlikely(res_get(fh) < 0))
return -EBUSY;
- }
- dev->stream = STREAM_ON; /* FIXME: Start video capture here? */
-
- mutex_unlock(&dev->lock);
- return 0;
+ return (videobuf_streamon(&fh->vb_vidq));
}
static int vidioc_streamoff(struct file *file, void *priv,
@@ -970,23 +1268,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
if (rc < 0)
return rc;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (type != fh->type)
return -EINVAL;
- mutex_lock(&dev->lock);
-
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0) {
- mutex_unlock(&dev->lock);
- return rc;
- }
- }
-
- em28xx_empty_framequeues(dev);
+ videobuf_streamoff(&fh->vb_vidq);
+ res_free(fh);
- mutex_unlock(&dev->lock);
return 0;
}
@@ -1017,7 +1306,7 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_cap(struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *fmtd)
{
if (fmtd->index != 0)
@@ -1032,7 +1321,7 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
}
/* Sliced VBI ioctls */
-static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv,
+static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct em28xx_fh *fh = priv;
@@ -1056,7 +1345,7 @@ static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv,
return rc;
}
-static int vidioc_try_set_vbi_capture(struct file *file, void *priv,
+static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct em28xx_fh *fh = priv;
@@ -1080,7 +1369,7 @@ static int vidioc_try_set_vbi_capture(struct file *file, void *priv,
#if 0
/* RAW VBI ioctls */
-static int vidioc_g_fmt_vbi(struct file *file, void *priv,
+static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
format->fmt.vbi.sampling_rate = 6750000 * 4;
@@ -1096,7 +1385,7 @@ static int vidioc_g_fmt_vbi(struct file *file, void *priv,
return 0;
}
-static int vidioc_try_set_vbi(struct file *file, void *priv,
+static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
format->type = V4L2_BUF_TYPE_VBI_CAPTURE;
@@ -1117,53 +1406,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- u32 i;
int rc;
rc = check_dev(dev);
if (rc < 0)
return rc;
- if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- rb->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- if (dev->io == IO_READ) {
- em28xx_videodbg("method is set to read;"
- " close and open the device again to"
- " choose the mmap I/O method\n");
- return -EINVAL;
- }
-
- for (i = 0; i < dev->num_frames; i++)
- if (dev->frame[i].vma_use_count) {
- em28xx_videodbg("VIDIOC_REQBUFS failed; "
- "previous buffers are still mapped\n");
- return -EINVAL;
- }
-
- mutex_lock(&dev->lock);
-
- if (dev->stream == STREAM_ON) {
- em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
- rc = em28xx_stream_interrupt(dev);
- if (rc < 0) {
- mutex_unlock(&dev->lock);
- return rc;
- }
- }
-
- em28xx_empty_framequeues(dev);
-
- em28xx_release_buffers(dev);
- if (rb->count)
- rb->count = em28xx_request_buffers(dev, rb->count);
-
- dev->frame_current = NULL;
- dev->io = rb->count ? IO_MMAP : IO_NONE;
-
- mutex_unlock(&dev->lock);
- return 0;
+ return (videobuf_reqbufs(&fh->vb_vidq, rb));
}
static int vidioc_querybuf(struct file *file, void *priv,
@@ -1177,52 +1426,20 @@ static int vidioc_querybuf(struct file *file, void *priv,
if (rc < 0)
return rc;
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b->index >= dev->num_frames || dev->io != IO_MMAP)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
-
- if (dev->frame[b->index].vma_use_count)
- b->flags |= V4L2_BUF_FLAG_MAPPED;
-
- if (dev->frame[b->index].state == F_DONE)
- b->flags |= V4L2_BUF_FLAG_DONE;
- else if (dev->frame[b->index].state != F_UNUSED)
- b->flags |= V4L2_BUF_FLAG_QUEUED;
-
- mutex_unlock(&dev->lock);
- return 0;
+ return (videobuf_querybuf(&fh->vb_vidq, b));
}
static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- unsigned long lock_flags;
int rc;
rc = check_dev(dev);
if (rc < 0)
return rc;
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP ||
- b->index >= dev->num_frames)
- return -EINVAL;
-
- if (dev->frame[b->index].state != F_UNUSED)
- return -EAGAIN;
-
- dev->frame[b->index].state = F_QUEUED;
-
- /* add frame to fifo */
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
- return 0;
+ return (videobuf_qbuf(&fh->vb_vidq, b));
}
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1230,46 +1447,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
int rc;
- struct em28xx_frame_t *f;
- unsigned long lock_flags;
rc = check_dev(dev);
if (rc < 0)
return rc;
- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
- return -EINVAL;
-
- if (list_empty(&dev->outqueue)) {
- if (dev->stream == STREAM_OFF)
- return -EINVAL;
-
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- rc = wait_event_interruptible(dev->wait_frame,
- (!list_empty(&dev->outqueue)) ||
- (dev->state & DEV_DISCONNECTED));
- if (rc)
- return rc;
-
- if (dev->state & DEV_DISCONNECTED)
- return -ENODEV;
- }
-
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
- list_del(dev->outqueue.next);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
- f->state = F_UNUSED;
- memcpy(b, &f->buf, sizeof(*b));
+ return (videobuf_dqbuf(&fh->vb_vidq, b,
+ file->f_flags & O_NONBLOCK));
+}
- if (f->vma_use_count)
- b->flags |= V4L2_BUF_FLAG_MAPPED;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+ struct em28xx_fh *fh = priv;
- return 0;
+ return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
}
+#endif
+
/* ----------------------------------------------------------- */
/* RADIO ESPECIFIC IOCTLS */
@@ -1375,17 +1570,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
{
int minor = iminor(inode);
int errCode = 0, radio = 0;
- struct em28xx *h,*dev = NULL;
+ struct em28xx *h, *dev = NULL;
struct em28xx_fh *fh;
+ enum v4l2_buf_type fh_type = 0;
list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor) {
dev = h;
- dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
}
if (h->vbi_dev->minor == minor) {
dev = h;
- dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
}
if (h->radio_dev &&
h->radio_dev->minor == minor) {
@@ -1397,10 +1593,17 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
return -ENODEV;
em28xx_videodbg("open minor=%d type=%s users=%d\n",
- minor,v4l2_type_names[dev->type],dev->users);
+ minor, v4l2_type_names[fh_type], dev->users);
- fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+#if 0
+ errCode = em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+ if (errCode < 0) {
+ em28xx_errdev("Device locked on digital mode. Can't open analog\n");
+ return -EBUSY;
+ }
+#endif
+ fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
if (!fh) {
em28xx_errdev("em28xx-video.c: Out of memory?!\n");
return -ENOMEM;
@@ -1408,32 +1611,28 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
mutex_lock(&dev->lock);
fh->dev = dev;
fh->radio = radio;
+ fh->type = fh_type;
filp->private_data = fh;
- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
- dev->frame_size = dev->width * dev->height * 2;
- dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
- dev->bytesperline = dev->width * 2;
dev->hscale = 0;
dev->vscale = 0;
+ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
em28xx_set_alternate(dev);
- em28xx_capture_start(dev, 1);
em28xx_resolution_set(dev);
+ /* Needed, since GPIO might have disabled power of
+ some i2c device
+ */
+ em28xx_config_i2c(dev);
+
#if 0
/* device needs to be initialized before isoc transfer */
video_mux(dev, 0);
#endif
-
- /* start the transfer */
- errCode = em28xx_init_isoc(dev);
- if (errCode)
- goto err;
-
- em28xx_empty_framequeues(dev);
}
if (fh->radio) {
em28xx_videodbg("video_open: setting radio device\n");
@@ -1445,8 +1644,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
dev->users++;
-err:
+ videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
+ NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+ sizeof(struct em28xx_buffer), fh);
+
mutex_unlock(&dev->lock);
+
return errCode;
}
@@ -1489,12 +1692,13 @@ static void em28xx_release_resources(struct em28xx *dev)
usb_put_dev(dev->udev);
/* Mark device as unused */
- em28xx_devused&=~(1<<dev->devno);
+ em28xx_devused &= ~(1<<dev->devno);
}
/*
* em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
*/
static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
{
@@ -1511,9 +1715,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
mutex_lock(&dev->lock);
if (dev->users == 1) {
- em28xx_uninit_isoc(dev);
- em28xx_release_buffers(dev);
- dev->io = IO_NONE;
+ videobuf_stop(&fh->vb_vidq);
+ videobuf_mmap_free(&fh->vb_vidq);
/* the device is already disconnect,
free the remaining resources */
@@ -1524,6 +1727,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
return 0;
}
+ /* do this before setting alternate! */
+ em28xx_uninit_isoc(dev);
+ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
/* set alternate 0 */
dev->alt = 0;
em28xx_videodbg("setting alternate 0\n");
@@ -1545,135 +1752,29 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
* will allocate buffers when called for the first time
*/
static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
- loff_t * f_pos)
+em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *pos)
{
- struct em28xx_frame_t *f, *i;
- unsigned long lock_flags;
- int ret = 0;
struct em28xx_fh *fh = filp->private_data;
struct em28xx *dev = fh->dev;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
/* FIXME: read() is not prepared to allow changing the video
resolution while streaming. Seems a bug at em28xx_set_fmt
*/
- if (unlikely(res_get(fh) < 0))
- return -EBUSY;
+ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ if (unlikely(res_get(fh)))
+ return -EBUSY;
- mutex_lock(&dev->lock);
-
- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
-
- if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
- em28xx_videodbg("not supported yet! ...\n");
- if (copy_to_user(buf, "", 1)) {
- mutex_unlock(&dev->lock);
- return -EFAULT;
- }
- mutex_unlock(&dev->lock);
- return (1);
+ return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+ filp->f_flags & O_NONBLOCK);
}
- if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
- em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
- em28xx_videodbg("not supported yet! ...\n");
- if (copy_to_user(buf, "", 1)) {
- mutex_unlock(&dev->lock);
- return -EFAULT;
- }
- mutex_unlock(&dev->lock);
- return (1);
- }
-
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("device not present\n");
- mutex_unlock(&dev->lock);
- return -ENODEV;
- }
-
- if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg("device misconfigured; close and open it again\n");
- mutex_unlock(&dev->lock);
- return -EIO;
- }
-
- if (dev->io == IO_MMAP) {
- em28xx_videodbg ("IO method is set to mmap; close and open"
- " the device again to choose the read method\n");
- mutex_unlock(&dev->lock);
- return -EINVAL;
- }
-
- if (dev->io == IO_NONE) {
- if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
- em28xx_errdev("read failed, not enough memory\n");
- mutex_unlock(&dev->lock);
- return -ENOMEM;
- }
- dev->io = IO_READ;
- dev->stream = STREAM_ON;
- em28xx_queue_unusedframes(dev);
- }
-
- if (!count) {
- mutex_unlock(&dev->lock);
- return 0;
- }
-
- if (list_empty(&dev->outqueue)) {
- if (filp->f_flags & O_NONBLOCK) {
- mutex_unlock(&dev->lock);
- return -EAGAIN;
- }
- ret = wait_event_interruptible
- (dev->wait_frame,
- (!list_empty(&dev->outqueue)) ||
- (dev->state & DEV_DISCONNECTED));
- if (ret) {
- mutex_unlock(&dev->lock);
- return ret;
- }
- if (dev->state & DEV_DISCONNECTED) {
- mutex_unlock(&dev->lock);
- return -ENODEV;
- }
- dev->video_bytesread = 0;
- }
-
- f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
-
- em28xx_queue_unusedframes(dev);
-
- if (count > f->buf.length)
- count = f->buf.length;
-
- if ((dev->video_bytesread + count) > dev->frame_size)
- count = dev->frame_size - dev->video_bytesread;
-
- if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
- em28xx_err("Error while copying to user\n");
- return -EFAULT;
- }
- dev->video_bytesread += count;
-
- if (dev->video_bytesread == dev->frame_size) {
- spin_lock_irqsave(&dev->queue_lock, lock_flags);
- list_for_each_entry(i, &dev->outqueue, frame)
- i->state = F_UNUSED;
- INIT_LIST_HEAD(&dev->outqueue);
- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
-
- em28xx_queue_unusedframes(dev);
- dev->video_bytesread = 0;
- }
-
- *f_pos += count;
-
- mutex_unlock(&dev->lock);
-
- return count;
+ return 0;
}
/*
@@ -1682,46 +1783,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
*/
static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
{
- unsigned int mask = 0;
struct em28xx_fh *fh = filp->private_data;
struct em28xx *dev = fh->dev;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
if (unlikely(res_get(fh) < 0))
return POLLERR;
- mutex_lock(&dev->lock);
-
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("device not present\n");
- } else if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg("device is misconfigured; close and open it again\n");
- } else {
- if (dev->io == IO_NONE) {
- if (!em28xx_request_buffers
- (dev, EM28XX_NUM_READ_FRAMES)) {
- em28xx_warn
- ("poll() failed, not enough memory\n");
- } else {
- dev->io = IO_READ;
- dev->stream = STREAM_ON;
- }
- }
-
- if (dev->io == IO_READ) {
- em28xx_queue_unusedframes(dev);
- poll_wait(filp, &dev->wait_frame, wait);
-
- if (!list_empty(&dev->outqueue))
- mask |= POLLIN | POLLRDNORM;
-
- mutex_unlock(&dev->lock);
-
- return mask;
- }
- }
+ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+ return POLLERR;
- mutex_unlock(&dev->lock);
- return POLLERR;
+ return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
}
/*
@@ -1731,69 +1807,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct em28xx_fh *fh = filp->private_data;
struct em28xx *dev = fh->dev;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long start = vma->vm_start;
- void *pos;
- u32 i;
+ int rc;
if (unlikely(res_get(fh) < 0))
return -EBUSY;
- mutex_lock(&dev->lock);
-
- if (dev->state & DEV_DISCONNECTED) {
- em28xx_videodbg("mmap: device not present\n");
- mutex_unlock(&dev->lock);
- return -ENODEV;
- }
-
- if (dev->state & DEV_MISCONFIGURED) {
- em28xx_videodbg ("mmap: Device is misconfigured; close and "
- "open it again\n");
- mutex_unlock(&dev->lock);
- return -EIO;
- }
-
- if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
- mutex_unlock(&dev->lock);
- return -EINVAL;
- }
-
- if (size > PAGE_ALIGN(dev->frame[0].buf.length))
- size = PAGE_ALIGN(dev->frame[0].buf.length);
-
- for (i = 0; i < dev->num_frames; i++) {
- if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
- break;
- }
- if (i == dev->num_frames) {
- em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
- mutex_unlock(&dev->lock);
- return -EINVAL;
- }
-
- /* VM_IO is eventually going to replace PageReserved altogether */
- vma->vm_flags |= VM_IO;
- vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
- pos = dev->frame[i].bufmem;
- while (size > 0) { /* size is page-aligned */
- if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
- em28xx_videodbg("mmap: vm_insert_page failed\n");
- mutex_unlock(&dev->lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
+ rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
- vma->vm_ops = &em28xx_vm_ops;
- vma->vm_private_data = &dev->frame[i];
+ em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+ (unsigned long)vma->vm_start,
+ (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+ rc);
- em28xx_vm_open(vma);
- mutex_unlock(&dev->lock);
- return 0;
+ return rc;
}
static const struct file_operations em28xx_v4l_fops = {
@@ -1827,22 +1857,22 @@ static const struct video_device em28xx_video_template = {
.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_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
#if 0
- .vidioc_g_fmt_vbi = vidioc_g_fmt_vbi,
- .vidioc_try_fmt_vbi = vidioc_s_fmt_vbi,
- .vidioc_s_fmt_vbi = vidioc_s_fmt_vbi,
+ .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
+ .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
+ .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
#endif
.vidioc_g_audio = vidioc_g_audio,
.vidioc_s_audio = vidioc_s_audio,
.vidioc_cropcap = vidioc_cropcap,
- .vidioc_g_fmt_vbi_capture = vidioc_g_fmt_vbi_capture,
- .vidioc_try_fmt_vbi_capture = vidioc_try_set_vbi_capture,
- .vidioc_s_fmt_vbi_capture = vidioc_try_set_vbi_capture,
+ .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
+ .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
+ .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
@@ -1865,6 +1895,9 @@ static const struct video_device em28xx_video_template = {
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
#endif
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ .vidiocgmbuf = vidiocgmbuf,
+#endif
.tvnorms = V4L2_STD_ALL,
.current_norm = V4L2_STD_PAL,
@@ -1893,7 +1926,7 @@ static struct video_device em28xx_radio_template = {
#endif
};
-/******************************** usb interface *****************************************/
+/******************************** usb interface ******************************/
static LIST_HEAD(em28xx_extension_devlist);
@@ -1952,6 +1985,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
vfd->release = video_device_release;
#endif
vfd->type = type;
+ vfd->debug = video_debug;
snprintf(vfd->name, sizeof(vfd->name), "%s %s",
dev->name, type_name);
@@ -1975,7 +2009,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->udev = udev;
mutex_init(&dev->lock);
- spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->slock);
init_waitqueue_head(&dev->open);
init_waitqueue_head(&dev->wait_frame);
init_waitqueue_head(&dev->wait_stream);
@@ -1987,10 +2021,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->em28xx_read_reg_req = em28xx_read_reg_req;
dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
- errCode = em28xx_read_reg(dev, CHIPID_REG);
- if (errCode >= 0)
- em28xx_info("em28xx chip ID = %d\n", errCode);
-
em28xx_pre_card_setup(dev);
errCode = em28xx_config(dev);
@@ -2023,10 +2053,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->width = maxw;
dev->height = maxh;
dev->interlaced = EM28XX_INTERLACED_DEFAULT;
- dev->field_size = dev->width * dev->height;
- dev->frame_size =
- dev->interlaced ? dev->field_size << 1 : dev->field_size;
- dev->bytesperline = dev->width * 2;
dev->hscale = 0;
dev->vscale = 0;
dev->ctl_input = 2;
@@ -2082,6 +2108,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->radio_dev->minor & 0x1f);
}
+ /* init video dma queues */
+ INIT_LIST_HEAD(&dev->vidq.active);
+ INIT_LIST_HEAD(&dev->vidq.queued);
+
#if 0
video_set_drvdata(dev->vbi_dev, dev);
#endif
@@ -2134,6 +2164,9 @@ static void request_module_async(struct work_struct *work)
request_module("snd-usb-audio");
else
request_module("em28xx-alsa");
+
+ if (dev->has_dvb)
+ request_module("em28xx-dvb");
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
@@ -2172,22 +2205,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
ifnum = interface->altsetting[0].desc.bInterfaceNumber;
/* Check to see next free device and mark as used */
- nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
- em28xx_devused|=1<<nr;
+ nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+ em28xx_devused |= 1<<nr;
/* Don't register audio interfaces */
if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
- udev->descriptor.idVendor,udev->descriptor.idProduct,
+ udev->descriptor.idVendor,
+ udev->descriptor.idProduct,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
- udev->descriptor.idVendor,udev->descriptor.idProduct,
+ udev->descriptor.idVendor,
+ udev->descriptor.idProduct,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
@@ -2197,18 +2232,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_ISOC) {
em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENODEV;
}
if (nr >= EM28XX_MAXBOARDS) {
- printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
- em28xx_devused&=~(1<<nr);
+ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+ EM28XX_MAXBOARDS);
+ em28xx_devused &= ~(1<<nr);
return -ENOMEM;
}
@@ -2216,7 +2252,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
return -ENOMEM;
}
@@ -2240,14 +2276,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* compute alternate max packet sizes */
uif = udev->actconfig->interface[0];
- dev->num_alt=uif->num_altsetting;
- em28xx_info("Alternate settings: %i\n",dev->num_alt);
-// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
- dev->alt_max_pkt_size = kmalloc(32*
- dev->num_alt,GFP_KERNEL);
+ dev->num_alt = uif->num_altsetting;
+ em28xx_info("Alternate settings: %i\n", dev->num_alt);
+/* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
+ dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
+
if (dev->alt_max_pkt_size == NULL) {
em28xx_errdev("out of memory!\n");
- em28xx_devused&=~(1<<nr);
+ em28xx_devused &= ~(1<<nr);
kfree(dev);
return -ENOMEM;
}
@@ -2257,11 +2293,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
wMaxPacketSize);
dev->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- em28xx_info("Alternate setting %i, max size= %i\n",i,
- dev->alt_max_pkt_size[i]);
+ em28xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->alt_max_pkt_size[i]);
}
- if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
+ if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
dev->model = card[nr];
/* allocate device struct */
@@ -2297,7 +2333,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
em28xx_info("disconnecting %s\n", dev->vdev->name);
- /* wait until all current v4l2 io is finished then deallocate resources */
+ /* wait until all current v4l2 io is finished then deallocate
+ resources */
mutex_lock(&dev->lock);
wake_up_interruptible_all(&dev->open);
@@ -2334,7 +2371,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
}
static struct usb_driver em28xx_usb_driver = {
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
.owner = THIS_MODULE,
#endif
.name = "em28xx",
diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h
index 980989f11..ed879653b 100644
--- a/linux/drivers/media/video/em28xx/em28xx.h
+++ b/linux/drivers/media/video/em28xx/em28xx.h
@@ -27,13 +27,43 @@
#include "compat.h"
#include <linux/videodev2.h>
+#include <media/videobuf-vmalloc.h>
+
#include <linux/i2c.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
#include <linux/mutex.h>
#endif
#include <media/ir-kbd-i2c.h>
-
-#define UNSET -1
+#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+#include "tuner-xc2028.h"
+#include "em28xx-reg.h"
+
+/* Boards supported by driver */
+#define EM2800_BOARD_UNKNOWN 0
+#define EM2820_BOARD_UNKNOWN 1
+#define EM2820_BOARD_TERRATEC_CINERGY_250 2
+#define EM2820_BOARD_PINNACLE_USB_2 3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
+#define EM2820_BOARD_MSI_VOX_USB_2 5
+#define EM2800_BOARD_TERRATEC_CINERGY_200 6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
+#define EM2800_BOARD_KWORLD_USB2800 8
+#define EM2820_BOARD_PINNACLE_DVC_90 9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS 11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF 12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
+#define EM2800_BOARD_VGEAR_POCKETTV 15
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
+#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18
+
+/* Limits minimum and default number of buffers */
+#define EM28XX_MIN_BUF 4
+#define EM28XX_DEF_BUF 8
/* maximum number of em28xx boards */
#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
@@ -84,31 +114,78 @@
/* time in msecs to wait for i2c writes to finish */
#define EM2800_I2C_WRITE_TIMEOUT 20
-/* the various frame states */
-enum em28xx_frame_state {
- F_UNUSED = 0,
- F_QUEUED,
- F_GRABBING,
- F_DONE,
- F_ERROR,
+enum em28xx_mode {
+ EM28XX_MODE_UNDEFINED,
+ EM28XX_ANALOG_MODE,
+ EM28XX_DIGITAL_MODE,
};
-/* stream states */
enum em28xx_stream_state {
STREAM_OFF,
STREAM_INTERRUPT,
STREAM_ON,
};
-/* frames */
-struct em28xx_frame_t {
- void *bufmem;
- struct v4l2_buffer buf;
- enum em28xx_frame_state state;
+struct em28xx;
+
+struct em28xx_usb_isoc_ctl {
+ /* max packet size of isoc transaction */
+ int max_pkt_size;
+
+ /* number of allocated urbs */
+ int num_bufs;
+
+ /* urb for isoc transfers */
+ struct urb **urb;
+
+ /* transfer buffers for isoc transfer */
+ char **transfer_buffer;
+
+ /* Last buffer command and region */
+ u8 cmd;
+ int pos, size, pktsize;
+
+ /* Last field: ODD or EVEN? */
+ int field;
+
+ /* Stores incomplete commands */
+ u32 tmp_buf;
+ int tmp_buf_len;
+
+ /* Stores already requested buffers */
+ struct em28xx_buffer *buf;
+
+ /* Stores the number of received fields */
+ int nfields;
+
+ /* isoc urb callback */
+ int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
+
+};
+
+struct em28xx_fmt {
+ char *name;
+ u32 fourcc; /* v4l2 format id */
+};
+
+/* buffer for one video frame */
+struct em28xx_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct videobuf_buffer vb;
+
struct list_head frame;
- unsigned long vma_use_count;
int top_field;
- int fieldbytesused;
+ int receiving;
+};
+
+struct em28xx_dmaqueue {
+ struct list_head active;
+ struct list_head queued;
+
+ wait_queue_head_t wq;
+
+ /* Counters to control buffer fill */
+ int pos;
};
/* io methods */
@@ -155,6 +232,12 @@ enum em28xx_decoder {
EM28XX_SAA7114
};
+struct em28xx_reg_seq {
+ int reg;
+ unsigned char val, mask;
+ int sleep;
+};
+
struct em28xx_board {
char *name;
int vchannels;
@@ -168,8 +251,7 @@ struct em28xx_board {
unsigned int mts_firmware:1;
unsigned int has_12mhz_i2s:1;
unsigned int max_range_640_480:1;
-
- unsigned int analog_gpio;
+ unsigned int has_dvb:1;
enum em28xx_decoder decoder;
@@ -202,7 +284,10 @@ enum em28xx_dev_state {
#define EM28XX_NUM_AUDIO_PACKETS 64
#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
#define EM28XX_CAPTURE_STREAM_EN 1
+
+/* em28xx extensions */
#define EM28XX_AUDIO 0x10
+#define EM28XX_DVB 0x20
struct em28xx_audio {
char name[50];
@@ -228,13 +313,24 @@ struct em28xx_audio {
spinlock_t slock;
};
+struct em28xx;
+
+struct em28xx_fh {
+ struct em28xx *dev;
+ unsigned int stream_on:1; /* Locks streams */
+ int radio;
+
+ struct videobuf_queue vb_vidq;
+
+ enum v4l2_buf_type type;
+};
+
/* main device struct */
struct em28xx {
/* generic device properties */
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
- unsigned int analog_gpio;
unsigned int is_em2800:1;
unsigned int has_msp34xx:1;
unsigned int has_tda9887:1;
@@ -242,6 +338,16 @@ struct em28xx {
unsigned int has_audio_class:1;
unsigned int has_12mhz_i2s:1;
unsigned int max_range_640_480:1;
+ unsigned int has_dvb:1;
+
+ /* Some older em28xx chips needs a waiting time after writing */
+ unsigned int wait_after_write;
+
+ /* GPIO sequences for analog and digital mode */
+ struct em28xx_reg_seq *analog_gpio, *digital_gpio;
+
+ /* GPIO sequences for tuner callbacks */
+ struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio;
int video_inputs; /* number of video inputs */
struct list_head devlist;
@@ -266,40 +372,32 @@ struct em28xx {
int mute;
int volume;
/* frame properties */
- struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */
- int num_frames; /* number of frames currently in use */
- unsigned int frame_count; /* total number of transfered frames */
- struct em28xx_frame_t *frame_current; /* the frame that is being filled */
int width; /* current frame width */
int height; /* current frame height */
- int frame_size; /* current frame size */
- int field_size; /* current field size */
- int bytesperline;
int hscale; /* horizontal scale factor (see datasheet) */
int vscale; /* vertical scale factor (see datasheet) */
int interlaced; /* 1=interlace fileds, 0=just top fileds */
- int type;
unsigned int video_bytesread; /* Number of bytes read */
unsigned long hash; /* eeprom hash - for boards with generic ID */
- unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
+ unsigned long i2c_hash; /* i2c devicelist hash -
+ for boards with generic ID */
struct em28xx_audio *adev;
/* states */
enum em28xx_dev_state state;
- enum em28xx_stream_state stream;
enum em28xx_io_method io;
struct work_struct request_module_wk;
/* locks */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)
struct mutex lock;
#else
struct semaphore lock, fileop_lock;
#endif
- spinlock_t queue_lock;
+ /* spinlock_t queue_lock; */
struct list_head inqueue, outqueue;
wait_queue_head_t open, wait_frame, wait_stream;
struct video_device *vbi_dev;
@@ -307,6 +405,11 @@ struct em28xx {
unsigned char eedata[256];
+ /* Isoc control struct */
+ struct em28xx_dmaqueue vidq;
+ struct em28xx_usb_isoc_ctl isoc_ctl;
+ spinlock_t slock;
+
/* usb transfer */
struct usb_device *udev; /* the usb device */
int alt; /* alternate */
@@ -316,20 +419,21 @@ struct em28xx {
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
/* helper funcs that call usb_control_msg */
- int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf,
- int len);
- int (*em28xx_read_reg) (struct em28xx * dev, u16 reg);
- int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg,
+ int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
char *buf, int len);
- int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg,
+ int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+ int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+ char *buf, int len);
+ int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
char *buf, int len);
- int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
-};
+ int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
-struct em28xx_fh {
- struct em28xx *dev;
- unsigned int stream_on:1; /* Locks streams */
- int radio;
+ enum em28xx_mode mode;
+
+ /* Caches GPO and GPIO registers */
+ unsigned char reg_gpo, reg_gpio;
+
+ struct em28xx_dvb *dvb;
};
struct em28xx_ops {
@@ -366,22 +470,27 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
int em28xx_capture_start(struct em28xx *dev, int start);
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
int em28xx_resolution_set(struct em28xx *dev);
-int em28xx_init_isoc(struct em28xx *dev);
-void em28xx_uninit_isoc(struct em28xx *dev);
int em28xx_set_alternate(struct em28xx *dev);
+int em28xx_init_isoc(struct em28xx *dev, int max_packets,
+ int num_bufs, int max_pkt_size,
+ int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
+void em28xx_uninit_isoc(struct em28xx *dev);
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
/* Provided by em28xx-video.c */
int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev);
/* Provided by em28xx-cards.c */
-extern int em2800_variant_detect(struct usb_device* udev,int model);
+extern int em2800_variant_detect(struct usb_device *udev, int model);
extern void em28xx_pre_card_setup(struct em28xx *dev);
extern void em28xx_card_setup(struct em28xx *dev);
extern struct em28xx_board em28xx_boards[];
extern struct usb_device_id em28xx_id_table[];
extern const unsigned int em28xx_bcount;
void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
+int em28xx_tuner_callback(void *ptr, int command, int arg);
/* Provided by em28xx-input.c */
/* TODO: Check if the standard get_key handlers on ir-common can be used */
@@ -390,71 +499,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw);
-/* em2800 registers */
-#define EM2800_AUDIOSRC_REG 0x08
-
-/* em28xx registers */
-#define I2C_CLK_REG 0x06
-#define CHIPID_REG 0x0a
-#define USBSUSP_REG 0x0c /* */
-
-#define AUDIOSRC_REG 0x0e
-#define XCLK_REG 0x0f
-
-#define VINMODE_REG 0x10
-#define VINCTRL_REG 0x11
-#define VINENABLE_REG 0x12 /* */
-
-#define GAMMA_REG 0x14
-#define RGAIN_REG 0x15
-#define GGAIN_REG 0x16
-#define BGAIN_REG 0x17
-#define ROFFSET_REG 0x18
-#define GOFFSET_REG 0x19
-#define BOFFSET_REG 0x1a
-
-#define OFLOW_REG 0x1b
-#define HSTART_REG 0x1c
-#define VSTART_REG 0x1d
-#define CWIDTH_REG 0x1e
-#define CHEIGHT_REG 0x1f
-
-#define YGAIN_REG 0x20
-#define YOFFSET_REG 0x21
-#define UVGAIN_REG 0x22
-#define UOFFSET_REG 0x23
-#define VOFFSET_REG 0x24
-#define SHARPNESS_REG 0x25
-
-#define COMPR_REG 0x26
-#define OUTFMT_REG 0x27
-
-#define XMIN_REG 0x28
-#define XMAX_REG 0x29
-#define YMIN_REG 0x2a
-#define YMAX_REG 0x2b
-
-#define HSCALELOW_REG 0x30
-#define HSCALEHIGH_REG 0x31
-#define VSCALELOW_REG 0x32
-#define VSCALEHIGH_REG 0x33
-
-#define AC97LSB_REG 0x40
-#define AC97MSB_REG 0x41
-#define AC97ADDR_REG 0x42
-#define AC97BUSY_REG 0x43
-
-/* em202 registers */
-#define MASTER_AC97 0x02
-#define LINE_IN_AC97 0x10
-#define VIDEO_AC97 0x14
-
-/* register settings */
-#define EM2800_AUDIO_SRC_TUNER 0x0d
-#define EM2800_AUDIO_SRC_LINE 0x0c
-#define EM28XX_AUDIO_SRC_TUNER 0xc0
-#define EM28XX_AUDIO_SRC_LINE 0x80
-
/* printk macros */
#define em28xx_err(fmt, arg...) do {\
@@ -471,80 +515,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
printk(KERN_WARNING "%s: "fmt,\
dev->name , ##arg); } while (0)
-inline static int em28xx_compression_disable(struct em28xx *dev)
+static inline int em28xx_compression_disable(struct em28xx *dev)
{
/* side effect of disabling scaler and mixer */
- return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
+ return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1);
}
-inline static int em28xx_contrast_get(struct em28xx *dev)
+static inline int em28xx_contrast_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
+ return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
}
-inline static int em28xx_brightness_get(struct em28xx *dev)
+static inline int em28xx_brightness_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, YOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
}
-inline static int em28xx_saturation_get(struct em28xx *dev)
+static inline int em28xx_saturation_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
+ return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
}
-inline static int em28xx_u_balance_get(struct em28xx *dev)
+static inline int em28xx_u_balance_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, UOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
}
-inline static int em28xx_v_balance_get(struct em28xx *dev)
+static inline int em28xx_v_balance_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, VOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
}
-inline static int em28xx_gamma_get(struct em28xx *dev)
+static inline int em28xx_gamma_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
+ return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
}
-inline static int em28xx_contrast_set(struct em28xx *dev, s32 val)
+static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
}
-inline static int em28xx_brightness_set(struct em28xx *dev, s32 val)
+static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
}
-inline static int em28xx_saturation_set(struct em28xx *dev, s32 val)
+static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
}
-inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
}
-inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
}
-inline static int em28xx_gamma_set(struct em28xx *dev, s32 val)
+static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
}
/*FIXME: maxw should be dependent of alt mode */
-inline static unsigned int norm_maxw(struct em28xx *dev)
+static inline unsigned int norm_maxw(struct em28xx *dev)
{
if (dev->max_range_640_480)
return 640;
@@ -552,7 +596,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev)
return 720;
}
-inline static unsigned int norm_maxh(struct em28xx *dev)
+static inline unsigned int norm_maxh(struct em28xx *dev)
{
if (dev->max_range_640_480)
return 480;
diff --git a/linux/drivers/media/video/et61x251/et61x251.h b/linux/drivers/media/video/et61x251/et61x251.h
index d22fbd34a..64ff5de0d 100644
--- a/linux/drivers/media/video/et61x251/et61x251.h
+++ b/linux/drivers/media/video/et61x251/et61x251.h
@@ -206,7 +206,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
- __FILE__, __FUNCTION__, __LINE__ , ## args); \
+ __FILE__, __func__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -216,7 +216,7 @@ do { \
pr_info("et61x251: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
- __FUNCTION__, __LINE__ , ## args); \
+ __func__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -232,7 +232,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
__LINE__ , ## args)
#undef PDBGG
diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c
index 27e1da696..4d08f0225 100644
--- a/linux/drivers/media/video/et61x251/et61x251_core.c
+++ b/linux/drivers/media/video/et61x251/et61x251_core.c
@@ -34,7 +34,7 @@
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/page-flags.h>
-#include <linux/byteorder/generic.h>
+#include <asm/byteorder.h>
#include <asm/page.h>
#include <asm/uaccess.h>
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index 198e0a18b..9a8795523 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -40,7 +40,6 @@
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/workqueue.h>
-#include <asm/semaphore.h>
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
@@ -155,7 +154,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
}
if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
- dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
+ dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
buf[0], buf[1], buf[2], buf[3]);
/* no key pressed or signal from other ir remote */
@@ -531,8 +530,11 @@ static int ir_probe(struct i2c_adapter *adap)
static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
static const int probe_cx23885[] = { 0x6b, -1 };
const int *probe;
- struct i2c_client *c;
- unsigned char buf;
+ struct i2c_msg msg = {
+ .flags = I2C_M_RD,
+ .len = 0,
+ .buf = NULL,
+ };
int i, rc;
switch (adap->id) {
@@ -558,23 +560,17 @@ static int ir_probe(struct i2c_adapter *adap)
return 0;
}
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return -ENOMEM;
-
- c->adapter = adap;
for (i = 0; -1 != probe[i]; i++) {
- c->addr = probe[i];
- rc = i2c_master_recv(c, &buf, 0);
+ msg.addr = probe[i];
+ rc = i2c_transfer(adap, &msg, 1);
dprintk(1,"probe 0x%02x @ %s: %s\n",
probe[i], adap->name,
- (0 == rc) ? "yes" : "no");
- if (0 == rc) {
+ (1 == rc) ? "yes" : "no");
+ if (1 == rc) {
ir_attach(adap, probe[i], 0, 0);
break;
}
}
- kfree(c);
return 0;
}
diff --git a/linux/drivers/media/video/ivtv/Kconfig b/linux/drivers/media/video/ivtv/Kconfig
index 270906fc3..5d7ee8fcd 100644
--- a/linux/drivers/media/video/ivtv/Kconfig
+++ b/linux/drivers/media/video/ivtv/Kconfig
@@ -1,6 +1,8 @@
config VIDEO_IVTV
tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
+ depends on INPUT # due to VIDEO_IR
+ depends on HOTPLUG # due to FW_LOADER
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_IR
@@ -10,6 +12,7 @@ config VIDEO_IVTV
select VIDEO_CX25840
select VIDEO_MSP3400
select VIDEO_SAA711X
+ select VIDEO_SAA717X
select VIDEO_SAA7127
select VIDEO_TVAUDIO
select VIDEO_CS53L32A
diff --git a/linux/drivers/media/video/ivtv/Makefile b/linux/drivers/media/video/ivtv/Makefile
index a0389014f..26ce0d6ea 100644
--- a/linux/drivers/media/video/ivtv/Makefile
+++ b/linux/drivers/media/video/ivtv/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c
index 92e4b85f9..03455fb30 100644
--- a/linux/drivers/media/video/ivtv/ivtv-cards.c
+++ b/linux/drivers/media/video/ivtv/ivtv-cards.c
@@ -40,6 +40,8 @@
#define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM)
+
/* usual i2c tuner addresses to probe */
static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
.radio = { I2C_CLIENT_END },
@@ -298,7 +300,7 @@ static const struct ivtv_card ivtv_card_mpg600 = {
.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
.tuners = {
/* The PAL tuner is confirmed */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_mpg600,
@@ -339,7 +341,7 @@ static const struct ivtv_card ivtv_card_mpg160 = {
.lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 },
.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_mpg160,
@@ -375,7 +377,7 @@ static const struct ivtv_card ivtv_card_pg600 = {
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
},
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_pg600,
@@ -416,7 +418,7 @@ static const struct ivtv_card ivtv_card_avc2410 = {
on the country/region setting of the user to decide which tuner
is available. */
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
.tuner = TUNER_PHILIPS_FM1236_MK3 },
{ .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
@@ -490,7 +492,7 @@ static const struct ivtv_card ivtv_card_tg5000tv = {
.gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
.composite = 0x0010, .svideo = 0x0020 },
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_tg5000tv,
.i2c = &ivtv_i2c_std,
@@ -521,7 +523,7 @@ static const struct ivtv_card ivtv_card_va2000 = {
{ IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
},
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_va2000,
.i2c = &ivtv_i2c_std,
@@ -565,7 +567,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.pci_list = ivtv_pci_cx23416gyc,
@@ -597,7 +599,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.i2c = &ivtv_i2c_std,
@@ -627,7 +629,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
.gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
.f44100 = 0x4000, .f48000 = 0x8000 },
.tuners = {
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.i2c = &ivtv_i2c_std,
@@ -667,7 +669,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
.gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
.tuners = {
/* This card has the Panasonic VP27 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
},
.pci_list = ivtv_pci_gv_mvprx,
.i2c = &ivtv_i2c_std,
@@ -704,7 +706,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
.gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
.tuners = {
/* This card has the Panasonic VP27 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
},
.pci_list = ivtv_pci_gv_mvprx2e,
.i2c = &ivtv_i2c_std,
@@ -739,7 +741,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
.gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
.tuners = {
/* This card has a Philips FQ1216ME MK3 tuner */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
},
.pci_list = ivtv_pci_gotview_pci_dvd,
.i2c = &ivtv_i2c_std,
@@ -778,7 +780,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
.gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
.tuners = {
/* This card has a Philips FQ1216ME MK5 tuner */
- { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+ { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
},
.pci_list = ivtv_pci_gotview_pci_dvd2,
.i2c = &ivtv_i2c_std,
@@ -856,7 +858,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
.gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
.composite = 0x0010, .svideo = 0x0020},
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
},
.pci_list = ivtv_pci_dctmvtvp1,
.i2c = &ivtv_i2c_std,
@@ -875,6 +877,7 @@ 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",
+ .comment = "only Composite and S-Video inputs are supported, not the tuner\n",
.v4l2_capabilities = IVTV_CAP_ENCODER,
.hw_video = IVTV_HW_CX25840,
.hw_audio = IVTV_HW_CX25840,
@@ -894,7 +897,7 @@ static const struct ivtv_card ivtv_card_pg600v2 = {
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
- .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
+ .xceive_pin = 12,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
@@ -941,7 +944,7 @@ static const struct ivtv_card ivtv_card_club3d = {
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
- .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
+ .xceive_pin = 12,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
@@ -965,34 +968,22 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = {
.hw_video = IVTV_HW_CX25840,
.hw_audio = IVTV_HW_CX25840,
.hw_audio_ctrl = IVTV_HW_CX25840,
-#if 0
- /* XC2028 support has problems with fw loading on this card,
- so don't support this tuner for this card until this issue
- has been solved. */
.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 },
+ { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
+ { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
},
.audio_inputs = {
+ { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
},
/* enable line-in */
- .gpio_init = { .direction = 0xf000, .initial_value = 0x5000 },
+ .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+ .xceive_pin = 10,
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
-#else
- .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
- .video_inputs = {
- { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
- { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
- },
- .audio_inputs = {
- { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
- },
- .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */
-#endif
.pci_list = ivtv_pci_avertv_mce116,
.i2c = &ivtv_i2c_std,
};
@@ -1030,7 +1021,7 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = {
.gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
.tuners = {
/* This card has a Partsnic PTI-5NF05 tuner */
- { .std = V4L2_STD_525_60, .tuner = TUNER_TCL_2002N },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_TCL_2002N },
},
.pci_list = ivtv_pci_aver_pvr150,
.i2c = &ivtv_i2c_radio,
@@ -1098,12 +1089,83 @@ static const struct ivtv_card ivtv_card_asus_falcon2 = {
},
.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
.tuners = {
- { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+ { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
},
.pci_list = ivtv_pci_asus_falcon2,
.i2c = &ivtv_i2c_std,
};
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M104 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
+ { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
+ { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_m104 = {
+ .type = IVTV_CARD_AVER_M104,
+ .name = "AVerMedia M104",
+ .comment = "Not yet supported!\n",
+ .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
+ .hw_video = IVTV_HW_CX25840,
+ .hw_audio = IVTV_HW_CX25840,
+ .hw_audio_ctrl = IVTV_HW_CX25840,
+ .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+ .video_inputs = {
+ { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+ },
+ .audio_inputs = {
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
+ },
+ .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+ /* enable line-in + reset tuner */
+ .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+ .xceive_pin = 10,
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .pci_list = ivtv_pci_aver_m104,
+ .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Buffalo PC-MV5L/PCI cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = {
+ { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b },
+ { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_buffalo = {
+ .type = IVTV_CARD_BUFFALO_MV5L,
+ .name = "Buffalo PC-MV5L/PCI",
+ .v4l2_capabilities = IVTV_CAP_ENCODER,
+ .hw_video = IVTV_HW_CX25840,
+ .hw_audio = IVTV_HW_CX25840,
+ .hw_audio_ctrl = IVTV_HW_CX25840,
+ .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+ .video_inputs = {
+ { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
+ { IVTV_CARD_INPUT_SVIDEO1, 1,
+ CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+ { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+ },
+ .audio_inputs = {
+ { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+ { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
+ },
+ .xceive_pin = 12,
+ .tuners = {
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .pci_list = ivtv_pci_buffalo,
+ .i2c = &ivtv_i2c_std,
+};
+
static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_pvr250,
&ivtv_card_pvr350,
@@ -1129,6 +1191,8 @@ static const struct ivtv_card *ivtv_card_list[] = {
&ivtv_card_asus_falcon2,
&ivtv_card_aver_pvr150,
&ivtv_card_aver_ezmaker,
+ &ivtv_card_aver_m104,
+ &ivtv_card_buffalo,
/* Variations of standard cards but with the same PCI IDs.
These cards must come last in this list. */
@@ -1160,7 +1224,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
if (index >= itv->nof_inputs)
return -EINVAL;
input->index = index;
- strcpy(input->name, input_strs[card_input->video_type - 1]);
+ strlcpy(input->name, input_strs[card_input->video_type - 1],
+ sizeof(input->name));
input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
input->audioset = (1 << itv->nof_audio_inputs) - 1;
@@ -1177,7 +1242,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
if (index >= itv->card->nof_outputs)
return -EINVAL;
output->index = index;
- strcpy(output->name, card_output->name);
+ strlcpy(output->name, card_output->name, sizeof(output->name));
output->type = V4L2_OUTPUT_TYPE_ANALOG;
output->audioset = 1;
output->std = V4L2_STD_ALL;
@@ -1196,7 +1261,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
memset(audio, 0, sizeof(*audio));
if (index >= itv->nof_audio_inputs)
return -EINVAL;
- strcpy(audio->name, input_strs[aud_input->audio_type - 1]);
+ strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+ sizeof(audio->name));
audio->index = index;
audio->capability = V4L2_AUDCAP_STEREO;
return 0;
@@ -1207,6 +1273,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud
memset(aud_output, 0, sizeof(*aud_output));
if (itv->card->video_outputs == NULL || index != 0)
return -EINVAL;
- strcpy(aud_output->name, "A/V Audio Out");
+ strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
return 0;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.h b/linux/drivers/media/video/ivtv/ivtv-cards.h
index 9186fa2ee..381af1bce 100644
--- a/linux/drivers/media/video/ivtv/ivtv-cards.h
+++ b/linux/drivers/media/video/ivtv/ivtv-cards.h
@@ -48,7 +48,9 @@
#define IVTV_CARD_ASUS_FALCON2 21 /* ASUS Falcon2 */
#define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */
#define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */
-#define IVTV_CARD_LAST 23
+#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */
+#define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */
+#define IVTV_CARD_LAST 25
/* Variants of existing cards but with the same PCI IDs. The driver
detects these based on other device information.
@@ -244,6 +246,7 @@ struct ivtv_card_tuner_i2c {
struct ivtv_card {
int type;
char *name;
+ char *comment;
u32 v4l2_capabilities;
u32 hw_video; /* hardware used to process video */
u32 hw_audio; /* hardware used to process audio */
@@ -256,6 +259,7 @@ struct ivtv_card {
int nof_outputs;
const struct ivtv_card_output *video_outputs;
u8 gr_config; /* config byte for the ghost reduction device */
+ u8 xceive_pin; /* XCeive tuner GPIO reset pin */
/* GPIO card-specific settings */
struct ivtv_gpio_init gpio_init;
diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c
index 8c02fa661..c7e449f63 100644
--- a/linux/drivers/media/video/ivtv/ivtv-controls.c
+++ b/linux/drivers/media/video/ivtv/ivtv-controls.c
@@ -181,12 +181,12 @@ static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fm
return 0;
}
/* Need sliced data for mpeg insertion */
- if (get_service_set(itv->vbi.sliced_in) == 0) {
+ if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) {
if (itv->is_60hz)
itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
else
itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
- expand_service_set(itv->vbi.sliced_in, itv->is_50hz);
+ ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz);
}
return 0;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c
index b8b0ac859..094f5524f 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.c
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.c
@@ -190,6 +190,8 @@ MODULE_PARM_DESC(cardtype,
"\t\t\t22 = ASUS Falcon2\n"
"\t\t\t23 = AverMedia PVR-150 Plus\n"
"\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+ "\t\t\t25 = AverMedia M104 (not yet working)\n"
+ "\t\t\t26 = Buffalo PC-MV5L/PCI\n"
"\t\t\t 0 = Autodetect (default)\n"
"\t\t\t-1 = Ignore this card\n\t\t");
MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
@@ -856,6 +858,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
return 0;
}
+#ifdef MODULE
static u32 ivtv_request_module(struct ivtv *itv, u32 hw,
const char *name, u32 id)
{
@@ -868,14 +871,16 @@ static u32 ivtv_request_module(struct ivtv *itv, u32 hw,
IVTV_DEBUG_INFO("Loaded module %s\n", name);
return hw;
}
+#endif
static void ivtv_load_and_init_modules(struct ivtv *itv)
{
u32 hw = itv->card->hw_all;
unsigned i;
+#ifdef MODULE
/* load modules */
-#ifndef CONFIG_VIDEO_TUNER
+#ifndef CONFIG_MEDIA_TUNER
hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER);
#endif
#ifndef CONFIG_VIDEO_CX25840
@@ -887,7 +892,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
#ifndef CONFIG_VIDEO_SAA7127
hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
#endif
+#ifndef CONFIG_VIDEO_SAA717X
hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
+#endif
#ifndef CONFIG_VIDEO_UPD64031A
hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
#endif
@@ -912,6 +919,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
#ifndef CONFIG_VIDEO_M52790
hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790);
#endif
+#endif
/* check which i2c devices are actually found */
for (i = 0; i < 32; i++) {
@@ -1016,7 +1024,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
ivtv_cards[ivtv_cards_active] = itv;
itv->dev = dev;
itv->num = ivtv_cards_active++;
- snprintf(itv->name, sizeof(itv->name) - 1, "ivtv%d", itv->num);
+ snprintf(itv->name, sizeof(itv->name), "ivtv%d", itv->num);
IVTV_INFO("Initializing card #%d\n", itv->num);
spin_unlock(&ivtv_cards_lock);
@@ -1050,7 +1058,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_ENCODER_SIZE);
if (!itv->enc_mem) {
IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
retval = -ENOMEM;
goto free_mem;
}
@@ -1062,7 +1070,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_DECODER_SIZE);
if (!itv->dec_mem) {
IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
retval = -ENOMEM;
goto free_mem;
}
@@ -1078,7 +1086,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (!itv->reg_mem) {
IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
- IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+ IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
retval = -ENOMEM;
goto free_io;
}
@@ -1099,6 +1107,13 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
The PCI IDs are not always reliable. */
ivtv_process_eeprom(itv);
}
+ if (itv->card->comment)
+ IVTV_INFO("%s", itv->card->comment);
+ if (itv->card->v4l2_capabilities == 0) {
+ /* card was detected but is not supported */
+ retval = -ENODEV;
+ goto free_i2c;
+ }
if (itv->std == 0) {
itv->std = V4L2_STD_NTSC_M;
@@ -1197,13 +1212,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
}
- retval = ivtv_streams_setup(itv);
- if (retval) {
- IVTV_ERR("Error %d setting up streams\n", retval);
- goto free_i2c;
- }
-
- IVTV_DEBUG_IRQ("Masking interrupts\n");
/* clear interrupt mask, effectively disabling interrupts */
ivtv_set_irq_mask(itv, 0xffffffff);
@@ -1212,32 +1220,38 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv);
if (retval) {
IVTV_ERR("Failed to register irq %d\n", retval);
- goto free_streams;
+ goto free_i2c;
+ }
+
+ retval = ivtv_streams_setup(itv);
+ if (retval) {
+ IVTV_ERR("Error %d setting up streams\n", retval);
+ goto free_irq;
}
retval = ivtv_streams_register(itv);
if (retval) {
IVTV_ERR("Error %d registering devices\n", retval);
- goto free_irq;
+ goto free_streams;
}
IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
return 0;
- free_irq:
+free_streams:
+ ivtv_streams_cleanup(itv, 1);
+free_irq:
free_irq(itv->dev->irq, (void *)itv);
- free_streams:
- ivtv_streams_cleanup(itv);
- free_i2c:
+free_i2c:
exit_ivtv_i2c(itv);
- free_io:
+free_io:
ivtv_iounmap(itv);
- free_mem:
+free_mem:
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
- free_workqueue:
+free_workqueue:
destroy_workqueue(itv->irq_work_queues);
- err:
+err:
if (retval == 0)
retval = -ENODEV;
IVTV_ERR("Error %d on initialization\n", retval);
@@ -1368,7 +1382,7 @@ static void ivtv_remove(struct pci_dev *pci_dev)
flush_workqueue(itv->irq_work_queues);
destroy_workqueue(itv->irq_work_queues);
- ivtv_streams_cleanup(itv);
+ ivtv_streams_cleanup(itv, 1);
ivtv_udma_free(itv);
exit_ivtv_i2c(itv);
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h
index ba8763f62..5134d8a09 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.h
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.h
@@ -262,6 +262,12 @@ struct ivtv_mailbox_data {
/* Scatter-Gather array element, used in DMA transfers */
struct ivtv_sg_element {
+ __le32 src;
+ __le32 dst;
+ __le32 size;
+};
+
+struct ivtv_sg_host_element {
u32 src;
u32 dst;
u32 size;
@@ -356,8 +362,8 @@ struct ivtv_stream {
u16 dma_xfer_cnt;
/* Base Dev SG Array for cx23415/6 */
- struct ivtv_sg_element *sg_pending;
- struct ivtv_sg_element *sg_processing;
+ struct ivtv_sg_host_element *sg_pending;
+ struct ivtv_sg_host_element *sg_processing;
struct ivtv_sg_element *sg_dma;
dma_addr_t sg_handle;
int sg_pending_size;
diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c
index d949a8133..db813e071 100644
--- a/linux/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c
@@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
/* Process pending program info updates and pending VBI data */
ivtv_update_pgm_info(itv);
- if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
+ if (time_after(jiffies,
+ itv->dualwatch_jiffies +
+ msecs_to_jiffies(1000))) {
itv->dualwatch_jiffies = jiffies;
ivtv_dualwatch(itv);
}
@@ -585,7 +587,7 @@ retry:
since we may get here before the stream has been fully set-up */
if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
while (count >= itv->dma_data_req_size) {
- if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) {
+ if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) {
bytes_written += itv->dma_data_req_size;
user_buf += itv->dma_data_req_size;
count -= itv->dma_data_req_size;
@@ -753,8 +755,10 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
IVTV_DEBUG_HI_FILE("Encoder poll\n");
poll_wait(filp, &s->waitq, wait);
- if (eof || s->q_full.length || s->q_io.length)
+ if (s->q_full.length || s->q_io.length)
return POLLIN | POLLRDNORM;
+ if (eof)
+ return POLLHUP;
return 0;
}
@@ -983,6 +987,8 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
/* Find which card this open was on */
spin_lock(&ivtv_cards_lock);
for (x = 0; itv == NULL && x < ivtv_cards_active; x++) {
+ if (ivtv_cards[x] == NULL)
+ continue;
/* find out which stream this open was on */
for (y = 0; y < IVTV_MAX_STREAMS; y++) {
s = &ivtv_cards[x]->streams[y];
diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c
index 688cd3856..bc22905ea 100644
--- a/linux/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c
@@ -128,20 +128,17 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
{
struct i2c_algo_bit_data *algo = dev;
struct ivtv *itv = algo->data;
- int curdir, curout;
+ u32 curout;
if (cmd != XC2028_TUNER_RESET)
return 0;
IVTV_DEBUG_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);
+ curout &= ~(1 << itv->card->xceive_pin);
write_reg(curout, IVTV_REG_GPIO_OUT);
schedule_timeout_interruptible(msecs_to_jiffies(1));
- curout |= (1 << 12);
+ curout |= 1 << itv->card->xceive_pin;
write_reg(curout, IVTV_REG_GPIO_OUT);
schedule_timeout_interruptible(msecs_to_jiffies(1));
return 0;
@@ -149,15 +146,20 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
void ivtv_gpio_init(struct ivtv *itv)
{
- if (itv->card->gpio_init.direction == 0)
+ u16 pin = 0;
+
+ if (itv->card->xceive_pin)
+ pin = 1 << itv->card->xceive_pin;
+
+ if ((itv->card->gpio_init.direction | pin) == 0)
return;
IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
/* init output data then direction */
- write_reg(itv->card->gpio_init.initial_value, IVTV_REG_GPIO_OUT);
- write_reg(itv->card->gpio_init.direction, IVTV_REG_GPIO_DIR);
+ write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
+ write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
}
static struct v4l2_queryctrl gpio_ctrl_mute = {
diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c
index 1f421a574..b9e38c849 100644
--- a/linux/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c
@@ -136,7 +136,7 @@ static const u8 hw_addrs[] = {
};
/* This array should match the IVTV_HW_ defines */
-static const char * const hw_drivernames[] = {
+static const char * const hw_devicenames[] = {
"cx25840",
"saa7115",
"saa7127",
@@ -145,7 +145,7 @@ static const char * const hw_drivernames[] = {
"wm8775",
"cs53l32a",
"tveeprom",
- "saa7115",
+ "saa7114",
"upd64031a",
"upd64083",
"saa717x",
@@ -168,7 +168,12 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
return -1;
id = hw_driverids[idx];
memset(&info, 0, sizeof(info));
- strcpy(info.driver_name, hw_drivernames[idx]);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+ strlcpy(info.driver_name, hw_devicenames[idx],
+ sizeof(info.driver_name));
+#else
+ strlcpy(info.type, hw_devicenames[idx], sizeof(info.type));
+#endif
info.addr = hw_addrs[idx];
for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {}
@@ -178,10 +183,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
}
if (id != I2C_DRIVERID_TUNER) {
- c = i2c_new_device(&itv->i2c_adap, &info);
- if (c->driver == NULL)
+ if (id == I2C_DRIVERID_UPD64031A ||
+ id == I2C_DRIVERID_UPD64083) {
+ unsigned short addrs[2] = { info.addr, I2C_CLIENT_END };
+
+ c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs);
+ } else
+ c = i2c_new_device(&itv->i2c_adap, &info);
+ if (c && c->driver == NULL)
i2c_unregister_device(c);
- else
+ else if (c)
itv->i2c_clients[i] = c;
return itv->i2c_clients[i] ? 0 : -ENODEV;
}
@@ -679,7 +690,7 @@ static const char *ivtv_i2c_id_name(u32 id)
for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
if (hw_driverids[i] == id)
- return hw_drivernames[i];
+ return hw_devicenames[i];
return "unknown device";
}
@@ -690,7 +701,7 @@ static const char *ivtv_i2c_hw_name(u32 hw)
for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
if (1 << i == hw)
- return hw_drivernames[i];
+ return hw_devicenames[i];
return "unknown device";
}
@@ -792,7 +803,7 @@ int init_ivtv_i2c(struct ivtv *itv)
* same size and GPIO must be the last entry.
*/
if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) ||
- ARRAY_SIZE(hw_drivernames) != ARRAY_SIZE(hw_addrs) ||
+ ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1)) ||
hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) {
IVTV_ERR("Mismatched I2C hardware arrays\n");
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
index 873296394..7101a0ea5 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -38,7 +38,7 @@
#include <linux/dvb/audio.h>
#include <linux/i2c-id.h>
-u16 service2vbi(int type)
+u16 ivtv_service2vbi(int type)
{
switch (type) {
case V4L2_SLICED_TELETEXT_B:
@@ -88,7 +88,7 @@ static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
return 0;
}
-void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
{
u16 set = fmt->service_set;
int f, l;
@@ -115,7 +115,7 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
return set != 0;
}
-u16 get_service_set(struct v4l2_sliced_vbi_format *fmt)
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
{
int f, l;
u16 set = 0;
@@ -243,20 +243,31 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
int fact = new_speed < 0 ? -1 : 1;
int s;
- if (new_speed < 0) new_speed = -new_speed;
- if (cur_speed < 0) cur_speed = -cur_speed;
+ if (cur_speed == 0)
+ cur_speed = 1000;
+ if (new_speed < 0)
+ new_speed = -new_speed;
+ if (cur_speed < 0)
+ cur_speed = -cur_speed;
if (cur_speed <= new_speed) {
- if (new_speed > 1500) return fact * 2000;
- if (new_speed > 1000) return fact * 1500;
+ if (new_speed > 1500)
+ return fact * 2000;
+ if (new_speed > 1000)
+ return fact * 1500;
}
else {
- if (new_speed >= 2000) return fact * 2000;
- if (new_speed >= 1500) return fact * 1500;
- if (new_speed >= 1000) return fact * 1000;
- }
- if (new_speed == 0) return 1000;
- if (new_speed == 1 || new_speed == 1000) return fact * new_speed;
+ if (new_speed >= 2000)
+ return fact * 2000;
+ if (new_speed >= 1500)
+ return fact * 1500;
+ if (new_speed >= 1000)
+ return fact * 1000;
+ }
+ if (new_speed == 0)
+ return 1000;
+ if (new_speed == 1 || new_speed == 1000)
+ return fact * new_speed;
s = new_speed;
new_speed = 1000 / new_speed;
@@ -455,7 +466,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
}
- vbifmt->service_set = get_service_set(vbifmt);
+ vbifmt->service_set = ivtv_get_service_set(vbifmt);
break;
}
@@ -470,12 +481,12 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
V4L2_SLICED_VBI_525;
- expand_service_set(vbifmt, itv->is_50hz);
+ ivtv_expand_service_set(vbifmt, itv->is_50hz);
break;
}
itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
- vbifmt->service_set = get_service_set(vbifmt);
+ vbifmt->service_set = ivtv_get_service_set(vbifmt);
break;
}
case V4L2_BUF_TYPE_VBI_OUTPUT:
@@ -635,9 +646,9 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
if (vbifmt->service_set)
- expand_service_set(vbifmt, itv->is_50hz);
+ ivtv_expand_service_set(vbifmt, itv->is_50hz);
set = check_service_set(vbifmt, itv->is_50hz);
- vbifmt->service_set = get_service_set(vbifmt);
+ vbifmt->service_set = ivtv_get_service_set(vbifmt);
if (!set_fmt)
return 0;
@@ -747,9 +758,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
struct v4l2_capability *vcap = arg;
memset(vcap, 0, sizeof(*vcap));
- strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
- strcpy(vcap->card, itv->card_name); /* card type */
- strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
+ strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
+ strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
+ strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
vcap->version = IVTV_DRIVER_VERSION; /* version */
vcap->capabilities = itv->v4l2_cap; /* capabilities */
@@ -1023,7 +1034,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_std_60hz : ivtv_std_50hz;
vs->index = idx;
vs->id = enum_stds[idx].std;
- strcpy(vs->name, enum_stds[idx].name);
+ strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
break;
}
@@ -1107,10 +1118,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
- strcpy(vt->name, "ivtv Radio Tuner");
+ strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
vt->type = V4L2_TUNER_RADIO;
} else {
- strcpy(vt->name, "ivtv TV Tuner");
+ strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
vt->type = V4L2_TUNER_ANALOG_TV;
}
break;
@@ -1644,6 +1655,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
v4l_printk_ioctl(cmd);
+ printk("\n");
}
return ivtv_debug_ioctls(filp, cmd, arg);
@@ -1687,6 +1699,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
v4l_printk_ioctl(cmd);
+ printk("\n");
}
return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
@@ -1700,6 +1713,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
v4l_printk_ioctl(cmd);
+ printk("\n");
}
return ivtv_control_ioctls(itv, cmd, arg);
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.h b/linux/drivers/media/video/ivtv/ivtv-ioctl.h
index a03351b68..4e67f0ed1 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.h
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.h
@@ -21,9 +21,9 @@
#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);
+u16 ivtv_service2vbi(int type);
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg);
int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg);
diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c
index 0e417d860..d5ac766c1 100644
--- a/linux/drivers/media/video/ivtv/ivtv-irq.c
+++ b/linux/drivers/media/video/ivtv/ivtv-irq.c
@@ -237,14 +237,14 @@ static void dma_post(struct ivtv_stream *s)
struct ivtv_buffer *buf = NULL;
struct list_head *p;
u32 offset;
- u32 *u32buf;
+ __le32 *u32buf;
int x = 0;
IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) {
buf = list_entry(p, struct ivtv_buffer, list);
- u32buf = (u32 *)buf->buf;
+ u32buf = (__le32 *)buf->buf;
/* Sync Buffer */
ivtv_buf_sync_for_cpu(s, buf);
@@ -390,7 +390,7 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
ivtv_stream_sync_for_device(s);
write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
add_timer(&itv->dma_timer);
}
@@ -406,7 +406,7 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
ivtv_stream_sync_for_device(s);
write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+ itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
add_timer(&itv->dma_timer);
}
@@ -450,7 +450,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
}
s->dma_xfer_cnt++;
- memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
s->sg_processing_size = s->sg_pending_size;
s->sg_pending_size = 0;
s->sg_processed = 0;
@@ -479,7 +479,7 @@ 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);
s->dma_xfer_cnt++;
- memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+ memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
s->sg_processing_size = s->sg_pending_size;
s->sg_pending_size = 0;
s->sg_processed = 0;
diff --git a/linux/drivers/media/video/ivtv/ivtv-mailbox.c b/linux/drivers/media/video/ivtv/ivtv-mailbox.c
index 13a6c374d..1b5c0ac09 100644
--- a/linux/drivers/media/video/ivtv/ivtv-mailbox.c
+++ b/linux/drivers/media/video/ivtv/ivtv-mailbox.c
@@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
/* Sleep before a retry, if not atomic */
if (!(flags & API_NO_WAIT_MB)) {
- if (jiffies - then > msecs_to_jiffies(10*retries))
+ if (time_after(jiffies,
+ then + msecs_to_jiffies(10*retries)))
break;
ivtv_msleep_timeout(10, 0);
}
@@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
data, then just return 0 as there is no need to issue this command again.
Just an optimization to prevent unnecessary use of mailboxes. */
if (itv->api_cache[cmd].last_jiffies &&
- jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) &&
+ time_before(jiffies,
+ itv->api_cache[cmd].last_jiffies +
+ msecs_to_jiffies(1800000)) &&
!memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
itv->api_cache[cmd].last_jiffies = jiffies;
return 0;
@@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
}
}
while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
- if (jiffies - then > api_timeout) {
+ if (time_after(jiffies, then + api_timeout)) {
IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
/* reset the mailbox, but it is likely too late already */
write_sync(0, &mbox->flags);
@@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
else
ivtv_msleep_timeout(1, 0);
}
- if (jiffies - then > msecs_to_jiffies(100))
+ if (time_after(jiffies, then + msecs_to_jiffies(100)))
IVTV_DEBUG_WARN("%s took %u jiffies\n",
api_info[cmd].name,
jiffies_to_msecs(jiffies - then));
diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.c b/linux/drivers/media/video/ivtv/ivtv-queue.c
index 3e1deec67..71bd13e22 100644
--- a/linux/drivers/media/video/ivtv/ivtv-queue.c
+++ b/linux/drivers/media/video/ivtv/ivtv-queue.c
@@ -193,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_host_element) * s->buffers;
int i;
if (s->buffers == 0)
@@ -203,14 +203,14 @@ 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);
- s->sg_pending = kzalloc(SGsize, GFP_KERNEL);
+ s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
if (s->sg_pending == NULL) {
IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
return -ENOMEM;
}
s->sg_pending_size = 0;
- s->sg_processing = kzalloc(SGsize, GFP_KERNEL);
+ s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
if (s->sg_processing == NULL) {
IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
kfree(s->sg_pending);
@@ -219,7 +219,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
}
s->sg_processing_size = 0;
- s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), GFP_KERNEL);
+ s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
+ GFP_KERNEL|__GFP_NOWARN);
if (s->sg_dma == NULL) {
IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
kfree(s->sg_pending);
@@ -235,11 +236,12 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
/* allocate stream buffers. Initially all buffers are in q_free. */
for (i = 0; i < s->buffers; i++) {
- struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), GFP_KERNEL);
+ struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
+ GFP_KERNEL|__GFP_NOWARN);
if (buf == NULL)
break;
- buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL);
+ buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
if (buf->buf == NULL) {
kfree(buf);
break;
diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c
index 24d98ecf3..01f546083 100644
--- a/linux/drivers/media/video/ivtv/ivtv-streams.c
+++ b/linux/drivers/media/video/ivtv/ivtv-streams.c
@@ -44,23 +44,29 @@
#include "ivtv-streams.h"
static const struct file_operations ivtv_v4l2_enc_fops = {
- .owner = THIS_MODULE,
- .read = ivtv_v4l2_read,
- .write = ivtv_v4l2_write,
- .open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
- .release = ivtv_v4l2_close,
- .poll = ivtv_v4l2_enc_poll,
+ .owner = THIS_MODULE,
+ .read = ivtv_v4l2_read,
+ .write = ivtv_v4l2_write,
+ .open = ivtv_v4l2_open,
+ .ioctl = ivtv_v4l2_ioctl,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+ .compat_ioctl = v4l_compat_ioctl32,
+#endif
+ .release = ivtv_v4l2_close,
+ .poll = ivtv_v4l2_enc_poll,
};
static const struct file_operations ivtv_v4l2_dec_fops = {
- .owner = THIS_MODULE,
- .read = ivtv_v4l2_read,
- .write = ivtv_v4l2_write,
- .open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
- .release = ivtv_v4l2_close,
- .poll = ivtv_v4l2_dec_poll,
+ .owner = THIS_MODULE,
+ .read = ivtv_v4l2_read,
+ .write = ivtv_v4l2_write,
+ .open = ivtv_v4l2_open,
+ .ioctl = ivtv_v4l2_ioctl,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+ .compat_ioctl = v4l_compat_ioctl32,
+#endif
+ .release = ivtv_v4l2_close,
+ .poll = ivtv_v4l2_dec_poll,
};
#define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */
@@ -244,7 +250,7 @@ int ivtv_streams_setup(struct ivtv *itv)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
- ivtv_streams_cleanup(itv);
+ ivtv_streams_cleanup(itv, 0);
return -ENOMEM;
}
@@ -304,12 +310,12 @@ int ivtv_streams_register(struct ivtv *itv)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
- ivtv_streams_cleanup(itv);
+ ivtv_streams_cleanup(itv, 1);
return -ENOMEM;
}
/* Unregister v4l2 devices */
-void ivtv_streams_cleanup(struct ivtv *itv)
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
{
int type;
@@ -322,8 +328,11 @@ void ivtv_streams_cleanup(struct ivtv *itv)
continue;
ivtv_stream_free(&itv->streams[type]);
- /* Unregister device */
- video_unregister_device(vdev);
+ /* Unregister or release device */
+ if (unregister)
+ video_unregister_device(vdev);
+ else
+ video_device_release(vdev);
}
}
@@ -768,7 +777,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
/* wait 2s for EOS interrupt */
while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
- jiffies < then + msecs_to_jiffies (2000)) {
+ time_before(jiffies,
+ then + msecs_to_jiffies(2000))) {
schedule_timeout(msecs_to_jiffies(10));
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.h b/linux/drivers/media/video/ivtv/ivtv-streams.h
index 3d76a415f..a653a5136 100644
--- a/linux/drivers/media/video/ivtv/ivtv-streams.h
+++ b/linux/drivers/media/video/ivtv/ivtv-streams.h
@@ -23,7 +23,7 @@
int ivtv_streams_setup(struct ivtv *itv);
int ivtv_streams_register(struct ivtv *itv);
-void ivtv_streams_cleanup(struct ivtv *itv);
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
/* Capture related */
int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
diff --git a/linux/drivers/media/video/ivtv/ivtv-vbi.c b/linux/drivers/media/video/ivtv/ivtv-vbi.c
index c151bcf55..71798f0da 100644
--- a/linux/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/linux/drivers/media/video/ivtv/ivtv-vbi.c
@@ -169,7 +169,8 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
linemask[0] |= (1 << l);
else
linemask[1] |= (1 << (l - 32));
- dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id);
+ dst[sd + 12 + line * 43] =
+ ivtv_service2vbi(itv->vbi.sliced_data[i].id);
memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
line++;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-version.h b/linux/drivers/media/video/ivtv/ivtv-version.h
index 0f1d4cc4b..442f43f11 100644
--- a/linux/drivers/media/video/ivtv/ivtv-version.h
+++ b/linux/drivers/media/video/ivtv/ivtv-version.h
@@ -22,7 +22,7 @@
#define IVTV_DRIVER_NAME "ivtv"
#define IVTV_DRIVER_VERSION_MAJOR 1
-#define IVTV_DRIVER_VERSION_MINOR 2
+#define IVTV_DRIVER_VERSION_MINOR 3
#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
#define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c
index 393d917cd..3092ff1d0 100644
--- a/linux/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c
@@ -908,7 +908,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
}
/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
- yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL);
+ yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
if (yi->blanking_ptr) {
yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
} else {
@@ -1098,8 +1098,8 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
ivtv_yuv_next_free(itv);
/* Copy V4L2 parameters to an ivtv_dma_frame struct... */
- dma_args.y_source = 0L;
- dma_args.uv_source = 0L;
+ dma_args.y_source = NULL;
+ dma_args.uv_source = NULL;
dma_args.src.left = 0;
dma_args.src.top = 0;
dma_args.src.width = yi->v4l2_src_w;
@@ -1116,7 +1116,7 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
}
/* Attempt to dma a frame from a user buffer */
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src)
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{
struct yuv_playback_info *yi = &itv->yuv_info;
struct ivtv_dma_frame dma_args;
diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.h b/linux/drivers/media/video/ivtv/ivtv-yuv.h
index 2fe5f1250..ca5173fbf 100644
--- a/linux/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/linux/drivers/media/video/ivtv/ivtv-yuv.h
@@ -35,7 +35,7 @@ extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
int ivtv_yuv_filter_check(struct ivtv *itv);
void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src);
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src);
void ivtv_yuv_frame_complete(struct ivtv *itv);
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
void ivtv_yuv_close(struct ivtv *itv);
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index 3b23fc05f..e8dbee443 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -367,6 +367,87 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
}
+static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ void *dst;
+ int err = 0;
+ unsigned long total_size;
+ struct ivtv *itv = (struct ivtv *) info->par;
+ unsigned long dma_offset =
+ IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
+ unsigned long dma_size;
+ u16 lead = 0, tail = 0;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
+ total_size = info->screen_size;
+
+ if (total_size == 0)
+ total_size = info->fix.smem_len;
+
+ if (p > total_size)
+ return -EFBIG;
+
+ if (count > total_size) {
+ err = -EFBIG;
+ count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
+
+ count = total_size - p;
+ }
+
+ dst = (void __force *) (info->screen_base + p);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ if (!access_ok(VERIFY_READ, buf, count)) {
+ IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
+ (unsigned long)buf);
+ err = -EFAULT;
+ }
+
+ if (!err) {
+ /* If transfer size > threshold and both src/dst
+ addresses are aligned, use DMA */
+ if (count >= 4096 && ((u32)buf & 3) == ((u32)dst & 3)) {
+ /* Odd address = can't DMA. Align */
+ if ((u32)dst & 3) {
+ lead = 4 - ((u32)dst & 3);
+ memcpy(dst, buf, lead);
+ buf += lead;
+ dst += lead;
+ }
+ /* DMA resolution is 32 bits */
+ if ((count - lead) & 3)
+ tail = (count - lead) & 3;
+ /* DMA the data */
+ dma_size = count - lead - tail;
+ err = ivtvfb_prep_dec_dma_to_device(itv,
+ p + lead + dma_offset, (void *)buf, dma_size);
+ dst += dma_size;
+ buf += dma_size;
+ /* Copy any leftover data */
+ if (tail)
+ memcpy(dst, buf, tail);
+ } else {
+ memcpy(dst, buf, count);
+ }
+ }
+
+ if (!err)
+ *ppos += count;
+
+ return (err) ? err : count;
+}
+
static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
DEFINE_WAIT(wait);
@@ -532,7 +613,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, "cx23415 TV out");
+ strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
fix->smem_start = oi->video_pbase;
fix->smem_len = oi->video_buffer_size;
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -824,6 +905,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
static struct fb_ops ivtvfb_ops = {
.owner = THIS_MODULE,
+ .fb_write = ivtvfb_write,
.fb_check_var = ivtvfb_check_var,
.fb_set_par = ivtvfb_set_par,
.fb_setcolreg = ivtvfb_setcolreg,
@@ -948,7 +1030,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
}
/* Allocate the pseudo palette */
- oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ oi->ivtvfb_info.pseudo_palette =
+ kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
if (!oi->ivtvfb_info.pseudo_palette) {
IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
@@ -1056,7 +1139,8 @@ static int ivtvfb_init_card(struct ivtv *itv)
return -EBUSY;
}
- itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC);
+ itv->osd_info = kzalloc(sizeof(struct osd_info),
+ GFP_ATOMIC|__GFP_NOWARN);
if (itv->osd_info == NULL) {
IVTVFB_ERR("Failed to allocate memory for osd_info\n");
return -ENOMEM;
diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c
index fa49d8f3e..77536ccfc 100644
--- a/linux/drivers/media/video/m52790.c
+++ b/linux/drivers/media/video/m52790.c
@@ -140,7 +140,8 @@ static int m52790_command(struct i2c_client *client, unsigned int cmd,
/* i2c implementation */
-static int m52790_probe(struct i2c_client *client)
+static int m52790_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct m52790_state *state;
@@ -148,8 +149,10 @@ static int m52790_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "m52790");
+#endif
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
@@ -172,12 +175,23 @@ static int m52790_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id m52790_id[] = {
+ { "m52790", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, m52790_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "m52790",
.driverid = I2C_DRIVERID_M52790,
.command = m52790_command,
.probe = m52790_probe,
.remove = m52790_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = m52790_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c
index f96330be7..07295afff 100644
--- a/linux/drivers/media/video/meye.c
+++ b/linux/drivers/media/video/meye.c
@@ -43,15 +43,10 @@
#include <linux/meye.h>
MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
-MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera");
+MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
MODULE_LICENSE("GPL");
MODULE_VERSION(MEYE_DRIVER_VERSION);
-/* force usage of V4L1 API */
-static int forcev4l1; /* = 0 */
-module_param(forcev4l1, int, 0644);
-MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2");
-
/* number of grab buffers */
static unsigned int gbuffers = 2;
module_param(gbuffers, int, 0444);
@@ -881,803 +876,737 @@ static int meye_release(struct inode *inode, struct file *file)
return 0;
}
-static int meye_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int meyeioc_g_params(struct meye_params *p)
{
- switch (cmd) {
+ *p = meye.params;
+ return 0;
+}
- case VIDIOCGCAP: {
- struct video_capability *b = arg;
- strcpy(b->name,meye.video_dev->name);
- b->type = VID_TYPE_CAPTURE;
- b->channels = 1;
- b->audios = 0;
- b->maxwidth = 640;
- b->maxheight = 480;
- b->minwidth = 320;
- b->minheight = 240;
- break;
- }
+static int meyeioc_s_params(struct meye_params *jp)
+{
+ if (jp->subsample > 1)
+ return -EINVAL;
- case VIDIOCGCHAN: {
- struct video_channel *v = arg;
- v->flags = 0;
- v->tuners = 0;
- v->type = VIDEO_TYPE_CAMERA;
- if (v->channel != 0)
- return -EINVAL;
- strcpy(v->name,"Camera");
- break;
- }
+ if (jp->quality > 10)
+ return -EINVAL;
- case VIDIOCSCHAN: {
- struct video_channel *v = arg;
- if (v->channel != 0)
- return -EINVAL;
- break;
- }
+ if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+ return -EINVAL;
- case VIDIOCGPICT: {
- struct video_picture *p = arg;
- *p = meye.picture;
- break;
- }
+ if (jp->framerate > 31)
+ return -EINVAL;
- case VIDIOCSPICT: {
- struct video_picture *p = arg;
- if (p->depth != 16)
- return -EINVAL;
- if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
- return -EINVAL;
- mutex_lock(&meye.lock);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
- p->brightness >> 10);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
- p->hue >> 10);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
- p->colour >> 10);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
- p->contrast >> 10);
- meye.picture = *p;
- mutex_unlock(&meye.lock);
- break;
- }
+ mutex_lock(&meye.lock);
- case VIDIOCSYNC: {
- int *i = arg;
- int unused;
+ if (meye.params.subsample != jp->subsample ||
+ meye.params.quality != jp->quality)
+ mchip_hic_stop(); /* need restart */
+
+ meye.params = *jp;
+ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+ meye.params.sharpness);
+ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+ meye.params.agc);
+ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+ meye.params.picture);
+ mutex_unlock(&meye.lock);
- if (*i < 0 || *i >= gbuffers)
- return -EINVAL;
+ return 0;
+}
- mutex_lock(&meye.lock);
+static int meyeioc_qbuf_capt(int *nb)
+{
+ if (!meye.grab_fbuffer)
+ return -EINVAL;
- switch (meye.grab_buffer[*i].state) {
+ if (*nb >= gbuffers)
+ return -EINVAL;
- case MEYE_BUF_UNUSED:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- case MEYE_BUF_USING:
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
- if (wait_event_interruptible(meye.proc_list,
- (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
- mutex_unlock(&meye.lock);
- return -EINTR;
- }
- /* fall through */
- case MEYE_BUF_DONE:
- meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
- kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
- }
- mutex_unlock(&meye.lock);
- break;
+ if (*nb < 0) {
+ /* stop capture */
+ mchip_hic_stop();
+ return 0;
}
- case VIDIOCMCAPTURE: {
- struct video_mmap *vm = arg;
- int restart = 0;
-
- if (vm->frame >= gbuffers || vm->frame < 0)
- return -EINVAL;
- if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
- return -EINVAL;
- if (vm->height * vm->width * 2 > gbufsize)
- return -EINVAL;
- if (!meye.grab_fbuffer)
- return -EINVAL;
- if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED)
- return -EBUSY;
-
- mutex_lock(&meye.lock);
- if (vm->width == 640 && vm->height == 480) {
- if (meye.params.subsample) {
- meye.params.subsample = 0;
- restart = 1;
- }
- } else if (vm->width == 320 && vm->height == 240) {
- if (!meye.params.subsample) {
- meye.params.subsample = 1;
- restart = 1;
- }
- } else {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
+ if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+ return -EBUSY;
- if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
- mchip_continuous_start();
- meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
- kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
- mutex_unlock(&meye.lock);
- break;
- }
+ mutex_lock(&meye.lock);
- case VIDIOCGMBUF: {
- struct video_mbuf *vm = arg;
- int i;
+ if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+ mchip_cont_compression_start();
- memset(vm, 0 , sizeof(*vm));
- vm->size = gbufsize * gbuffers;
- vm->frames = gbuffers;
- for (i = 0; i < gbuffers; i++)
- vm->offsets[i] = i * gbufsize;
- break;
- }
+ meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+ kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+ mutex_unlock(&meye.lock);
- case MEYEIOC_G_PARAMS: {
- struct meye_params *p = arg;
- *p = meye.params;
- break;
- }
+ return 0;
+}
- case MEYEIOC_S_PARAMS: {
- struct meye_params *jp = arg;
- if (jp->subsample > 1)
- return -EINVAL;
- if (jp->quality > 10)
- return -EINVAL;
- if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
- return -EINVAL;
- if (jp->framerate > 31)
- return -EINVAL;
- mutex_lock(&meye.lock);
- if (meye.params.subsample != jp->subsample ||
- meye.params.quality != jp->quality)
- mchip_hic_stop(); /* need restart */
- meye.params = *jp;
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
- meye.params.sharpness);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
- meye.params.agc);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
- meye.params.picture);
- mutex_unlock(&meye.lock);
- break;
- }
+static int meyeioc_sync(struct file *file, void *fh, int *i)
+{
+ int unused;
- case MEYEIOC_QBUF_CAPT: {
- int *nb = arg;
-
- if (!meye.grab_fbuffer)
- return -EINVAL;
- if (*nb >= gbuffers)
- return -EINVAL;
- if (*nb < 0) {
- /* stop capture */
- mchip_hic_stop();
- return 0;
- }
- if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
- return -EBUSY;
- mutex_lock(&meye.lock);
- if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
- mchip_cont_compression_start();
- meye.grab_buffer[*nb].state = MEYE_BUF_USING;
- kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
+ if (*i < 0 || *i >= gbuffers)
+ return -EINVAL;
+
+ mutex_lock(&meye.lock);
+ switch (meye.grab_buffer[*i].state) {
+
+ case MEYE_BUF_UNUSED:
mutex_unlock(&meye.lock);
- break;
+ return -EINVAL;
+ case MEYE_BUF_USING:
+ if (file->f_flags & O_NONBLOCK) {
+ mutex_unlock(&meye.lock);
+ return -EAGAIN;
+ }
+ if (wait_event_interruptible(meye.proc_list,
+ (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+ mutex_unlock(&meye.lock);
+ return -EINTR;
+ }
+ /* fall through */
+ case MEYE_BUF_DONE:
+ meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+ kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
}
+ *i = meye.grab_buffer[*i].size;
+ mutex_unlock(&meye.lock);
+ return 0;
+}
- case MEYEIOC_SYNC: {
- int *i = arg;
- int unused;
+static int meyeioc_stillcapt(void)
+{
+ if (!meye.grab_fbuffer)
+ return -EINVAL;
- if (*i < 0 || *i >= gbuffers)
- return -EINVAL;
+ if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+ return -EBUSY;
- mutex_lock(&meye.lock);
- switch (meye.grab_buffer[*i].state) {
+ mutex_lock(&meye.lock);
+ meye.grab_buffer[0].state = MEYE_BUF_USING;
+ mchip_take_picture();
- case MEYE_BUF_UNUSED:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- case MEYE_BUF_USING:
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
- if (wait_event_interruptible(meye.proc_list,
- (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
- mutex_unlock(&meye.lock);
- return -EINTR;
- }
- /* fall through */
- case MEYE_BUF_DONE:
- meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
- kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
- }
- *i = meye.grab_buffer[*i].size;
- mutex_unlock(&meye.lock);
- break;
- }
+ mchip_get_picture(meye.grab_fbuffer,
+ mchip_hsize() * mchip_vsize() * 2);
- case MEYEIOC_STILLCAPT: {
+ meye.grab_buffer[0].state = MEYE_BUF_DONE;
+ mutex_unlock(&meye.lock);
- if (!meye.grab_fbuffer)
- return -EINVAL;
- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
- return -EBUSY;
- mutex_lock(&meye.lock);
- meye.grab_buffer[0].state = MEYE_BUF_USING;
+ return 0;
+}
+
+static int meyeioc_stilljcapt(int *len)
+{
+ if (!meye.grab_fbuffer)
+ return -EINVAL;
+
+ if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+ return -EBUSY;
+
+ mutex_lock(&meye.lock);
+ meye.grab_buffer[0].state = MEYE_BUF_USING;
+ *len = -1;
+
+ while (*len == -1) {
mchip_take_picture();
- mchip_get_picture(
- meye.grab_fbuffer,
- mchip_hsize() * mchip_vsize() * 2);
- meye.grab_buffer[0].state = MEYE_BUF_DONE;
- mutex_unlock(&meye.lock);
- break;
+ *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
}
- case MEYEIOC_STILLJCAPT: {
- int *len = arg;
-
- if (!meye.grab_fbuffer)
- return -EINVAL;
- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
- return -EBUSY;
- mutex_lock(&meye.lock);
- meye.grab_buffer[0].state = MEYE_BUF_USING;
- *len = -1;
- while (*len == -1) {
- mchip_take_picture();
- *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
- }
- meye.grab_buffer[0].state = MEYE_BUF_DONE;
- mutex_unlock(&meye.lock);
- break;
- }
+ meye.grab_buffer[0].state = MEYE_BUF_DONE;
+ mutex_unlock(&meye.lock);
+ return 0;
+}
- case VIDIOC_QUERYCAP: {
- struct v4l2_capability *cap = arg;
+static int vidioc_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ memset(cap, 0, sizeof(*cap));
+ strcpy(cap->driver, "meye");
+ strcpy(cap->card, "meye");
+ sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
- if (forcev4l1)
- return -EINVAL;
+ cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+ MEYE_DRIVER_MINORVERSION;
- memset(cap, 0, sizeof(*cap));
- strcpy(cap->driver, "meye");
- strcpy(cap->card, "meye");
- sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
- cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
- MEYE_DRIVER_MINORVERSION;
- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_STREAMING;
- break;
- }
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING;
+
+ return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+ if (i->index != 0)
+ return -EINVAL;
- case VIDIOC_ENUMINPUT: {
- struct v4l2_input *i = arg;
+ memset(i, 0, sizeof(*i));
+ i->index = 0;
+ strcpy(i->name, "Camera");
+ i->type = V4L2_INPUT_TYPE_CAMERA;
- if (i->index != 0)
- return -EINVAL;
- memset(i, 0, sizeof(*i));
- i->index = 0;
- strcpy(i->name, "Camera");
- i->type = V4L2_INPUT_TYPE_CAMERA;
+ return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+ struct v4l2_queryctrl *c)
+{
+ switch (c->id) {
+
+ case V4L2_CID_BRIGHTNESS:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Brightness");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 32;
+ c->flags = 0;
+ break;
+ case V4L2_CID_HUE:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Hue");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 32;
+ c->flags = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Contrast");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 32;
+ c->flags = 0;
+ break;
+ case V4L2_CID_SATURATION:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Saturation");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 32;
+ c->flags = 0;
+ break;
+ case V4L2_CID_AGC:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Agc");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 48;
+ c->flags = 0;
break;
+ case V4L2_CID_MEYE_SHARPNESS:
+ case V4L2_CID_SHARPNESS:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Sharpness");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 32;
+
+ /* Continue to report legacy private SHARPNESS ctrl but
+ * say it is disabled in preference to ctrl in the spec
+ */
+ c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
+ V4L2_CTRL_FLAG_DISABLED;
+ break;
+ case V4L2_CID_PICTURE:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Picture");
+ c->minimum = 0;
+ c->maximum = 63;
+ c->step = 1;
+ c->default_value = 0;
+ c->flags = 0;
+ break;
+ case V4L2_CID_JPEGQUAL:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "JPEG quality");
+ c->minimum = 0;
+ c->maximum = 10;
+ c->step = 1;
+ c->default_value = 8;
+ c->flags = 0;
+ break;
+ case V4L2_CID_FRAMERATE:
+ c->type = V4L2_CTRL_TYPE_INTEGER;
+ strcpy(c->name, "Framerate");
+ c->minimum = 0;
+ c->maximum = 31;
+ c->step = 1;
+ c->default_value = 0;
+ c->flags = 0;
+ break;
+ default:
+ return -EINVAL;
}
- case VIDIOC_G_INPUT: {
- int *i = arg;
+ return 0;
+}
- *i = 0;
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+ mutex_lock(&meye.lock);
+ switch (c->id) {
+ case V4L2_CID_BRIGHTNESS:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+ meye.picture.brightness = c->value << 10;
+ break;
+ case V4L2_CID_HUE:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+ meye.picture.hue = c->value << 10;
+ break;
+ case V4L2_CID_CONTRAST:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+ meye.picture.contrast = c->value << 10;
+ break;
+ case V4L2_CID_SATURATION:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+ meye.picture.colour = c->value << 10;
+ break;
+ case V4L2_CID_AGC:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+ meye.params.agc = c->value;
+ break;
+ case V4L2_CID_SHARPNESS:
+ case V4L2_CID_MEYE_SHARPNESS:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+ meye.params.sharpness = c->value;
+ break;
+ case V4L2_CID_PICTURE:
+ sony_pic_camera_command(
+ SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+ meye.params.picture = c->value;
+ break;
+ case V4L2_CID_JPEGQUAL:
+ meye.params.quality = c->value;
+ break;
+ case V4L2_CID_FRAMERATE:
+ meye.params.framerate = c->value;
break;
+ default:
+ mutex_unlock(&meye.lock);
+ return -EINVAL;
}
+ mutex_unlock(&meye.lock);
- case VIDIOC_S_INPUT: {
- int *i = arg;
+ return 0;
+}
- if (*i != 0)
- return -EINVAL;
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+ mutex_lock(&meye.lock);
+ switch (c->id) {
+ case V4L2_CID_BRIGHTNESS:
+ c->value = meye.picture.brightness >> 10;
+ break;
+ case V4L2_CID_HUE:
+ c->value = meye.picture.hue >> 10;
+ break;
+ case V4L2_CID_CONTRAST:
+ c->value = meye.picture.contrast >> 10;
+ break;
+ case V4L2_CID_SATURATION:
+ c->value = meye.picture.colour >> 10;
+ break;
+ case V4L2_CID_AGC:
+ c->value = meye.params.agc;
+ break;
+ case V4L2_CID_SHARPNESS:
+ case V4L2_CID_MEYE_SHARPNESS:
+ c->value = meye.params.sharpness;
break;
+ case V4L2_CID_PICTURE:
+ c->value = meye.params.picture;
+ break;
+ case V4L2_CID_JPEGQUAL:
+ c->value = meye.params.quality;
+ break;
+ case V4L2_CID_FRAMERATE:
+ c->value = meye.params.framerate;
+ break;
+ default:
+ mutex_unlock(&meye.lock);
+ return -EINVAL;
}
+ mutex_unlock(&meye.lock);
- case VIDIOC_QUERYCTRL: {
- struct v4l2_queryctrl *c = arg;
+ return 0;
+}
- switch (c->id) {
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ if (f->index > 1)
+ return -EINVAL;
- case V4L2_CID_BRIGHTNESS:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Brightness");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 32;
- c->flags = 0;
- break;
- case V4L2_CID_HUE:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Hue");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 32;
- c->flags = 0;
- break;
- case V4L2_CID_CONTRAST:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Contrast");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 32;
- c->flags = 0;
- break;
- case V4L2_CID_SATURATION:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Saturation");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 32;
- c->flags = 0;
- break;
- case V4L2_CID_AGC:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Agc");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 48;
- c->flags = 0;
- break;
- case V4L2_CID_MEYE_SHARPNESS:
- case V4L2_CID_SHARPNESS:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Sharpness");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 32;
-
- /* Continue to report legacy private SHARPNESS ctrl but
- * say it is disabled in preference to ctrl in the spec
- */
- c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
- V4L2_CTRL_FLAG_DISABLED;
- break;
- case V4L2_CID_PICTURE:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Picture");
- c->minimum = 0;
- c->maximum = 63;
- c->step = 1;
- c->default_value = 0;
- c->flags = 0;
- break;
- case V4L2_CID_JPEGQUAL:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "JPEG quality");
- c->minimum = 0;
- c->maximum = 10;
- c->step = 1;
- c->default_value = 8;
- c->flags = 0;
- break;
- case V4L2_CID_FRAMERATE:
- c->type = V4L2_CTRL_TYPE_INTEGER;
- strcpy(c->name, "Framerate");
- c->minimum = 0;
- c->maximum = 31;
- c->step = 1;
- c->default_value = 0;
- c->flags = 0;
- break;
- default:
- return -EINVAL;
- }
- break;
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (f->index == 0) {
+ /* standard YUV 422 capture */
+ memset(f, 0, sizeof(*f));
+ f->index = 0;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->flags = 0;
+ strcpy(f->description, "YUV422");
+ f->pixelformat = V4L2_PIX_FMT_YUYV;
+ } else {
+ /* compressed MJPEG capture */
+ memset(f, 0, sizeof(*f));
+ f->index = 1;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->flags = V4L2_FMT_FLAG_COMPRESSED;
+ strcpy(f->description, "MJPEG");
+ f->pixelformat = V4L2_PIX_FMT_MJPEG;
}
- case VIDIOC_S_CTRL: {
- struct v4l2_control *c = arg;
+ return 0;
+}
- mutex_lock(&meye.lock);
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
- meye.picture.brightness = c->value << 10;
- break;
- case V4L2_CID_HUE:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
- meye.picture.hue = c->value << 10;
- break;
- case V4L2_CID_CONTRAST:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
- meye.picture.contrast = c->value << 10;
- break;
- case V4L2_CID_SATURATION:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
- meye.picture.colour = c->value << 10;
- break;
- case V4L2_CID_AGC:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
- meye.params.agc = c->value;
- break;
- case V4L2_CID_SHARPNESS:
- case V4L2_CID_MEYE_SHARPNESS:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
- meye.params.sharpness = c->value;
- break;
- case V4L2_CID_PICTURE:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
- meye.params.picture = c->value;
- break;
- case V4L2_CID_JPEGQUAL:
- meye.params.quality = c->value;
- break;
- case V4L2_CID_FRAMERATE:
- meye.params.framerate = c->value;
- break;
- default:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- mutex_unlock(&meye.lock);
- break;
+static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+ f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+ return -EINVAL;
+
+ if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+ f->fmt.pix.field != V4L2_FIELD_NONE)
+ return -EINVAL;
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ if (f->fmt.pix.width <= 320) {
+ f->fmt.pix.width = 320;
+ f->fmt.pix.height = 240;
+ } else {
+ f->fmt.pix.width = 640;
+ f->fmt.pix.height = 480;
}
- case VIDIOC_G_CTRL: {
- struct v4l2_control *c = arg;
+ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+ f->fmt.pix.sizeimage = f->fmt.pix.height *
+ f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = 0;
+ f->fmt.pix.priv = 0;
- mutex_lock(&meye.lock);
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- c->value = meye.picture.brightness >> 10;
- break;
- case V4L2_CID_HUE:
- c->value = meye.picture.hue >> 10;
- break;
- case V4L2_CID_CONTRAST:
- c->value = meye.picture.contrast >> 10;
- break;
- case V4L2_CID_SATURATION:
- c->value = meye.picture.colour >> 10;
- break;
- case V4L2_CID_AGC:
- c->value = meye.params.agc;
- break;
- case V4L2_CID_SHARPNESS:
- case V4L2_CID_MEYE_SHARPNESS:
- c->value = meye.params.sharpness;
- break;
- case V4L2_CID_PICTURE:
- c->value = meye.params.picture;
- break;
- case V4L2_CID_JPEGQUAL:
- c->value = meye.params.quality;
- break;
- case V4L2_CID_FRAMERATE:
- c->value = meye.params.framerate;
- break;
- default:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- mutex_unlock(&meye.lock);
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ switch (meye.mchip_mode) {
+ case MCHIP_HIC_MODE_CONT_OUT:
+ default:
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ break;
+ case MCHIP_HIC_MODE_CONT_COMP:
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
break;
}
- case VIDIOC_ENUM_FMT: {
- struct v4l2_fmtdesc *f = arg;
-
- if (f->index > 1)
- return -EINVAL;
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (f->index == 0) {
- /* standard YUV 422 capture */
- memset(f, 0, sizeof(*f));
- f->index = 0;
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- f->flags = 0;
- strcpy(f->description, "YUV422");
- f->pixelformat = V4L2_PIX_FMT_YUYV;
- } else {
- /* compressed MJPEG capture */
- memset(f, 0, sizeof(*f));
- f->index = 1;
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- f->flags = V4L2_FMT_FLAG_COMPRESSED;
- strcpy(f->description, "MJPEG");
- f->pixelformat = V4L2_PIX_FMT_MJPEG;
- }
- break;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.width = mchip_hsize();
+ f->fmt.pix.height = mchip_vsize();
+ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+ f->fmt.pix.sizeimage = f->fmt.pix.height *
+ f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = 0;
+ f->fmt.pix.priv = 0;
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+ f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+ return -EINVAL;
+
+ if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+ f->fmt.pix.field != V4L2_FIELD_NONE)
+ return -EINVAL;
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ mutex_lock(&meye.lock);
+
+ if (f->fmt.pix.width <= 320) {
+ f->fmt.pix.width = 320;
+ f->fmt.pix.height = 240;
+ meye.params.subsample = 1;
+ } else {
+ f->fmt.pix.width = 640;
+ f->fmt.pix.height = 480;
+ meye.params.subsample = 0;
}
- case VIDIOC_TRY_FMT: {
- struct v4l2_format *f = arg;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
- return -EINVAL;
- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
- f->fmt.pix.field != V4L2_FIELD_NONE)
- return -EINVAL;
- f->fmt.pix.field = V4L2_FIELD_NONE;
- if (f->fmt.pix.width <= 320) {
- f->fmt.pix.width = 320;
- f->fmt.pix.height = 240;
- } else {
- f->fmt.pix.width = 640;
- f->fmt.pix.height = 480;
- }
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+ break;
+ case V4L2_PIX_FMT_MJPEG:
+ meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
break;
}
- case VIDIOC_G_FMT: {
- struct v4l2_format *f = arg;
+ mutex_unlock(&meye.lock);
+ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+ f->fmt.pix.sizeimage = f->fmt.pix.height *
+ f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = 0;
+ f->fmt.pix.priv = 0;
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- switch (meye.mchip_mode) {
- case MCHIP_HIC_MODE_CONT_OUT:
- default:
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- break;
- case MCHIP_HIC_MODE_CONT_COMP:
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
- break;
- }
- f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.width = mchip_hsize();
- f->fmt.pix.height = mchip_vsize();
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
- break;
- }
+ return 0;
+}
- case VIDIOC_S_FMT: {
- struct v4l2_format *f = arg;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
- return -EINVAL;
- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
- f->fmt.pix.field != V4L2_FIELD_NONE)
- return -EINVAL;
- f->fmt.pix.field = V4L2_FIELD_NONE;
- mutex_lock(&meye.lock);
- if (f->fmt.pix.width <= 320) {
- f->fmt.pix.width = 320;
- f->fmt.pix.height = 240;
- meye.params.subsample = 1;
- } else {
- f->fmt.pix.width = 640;
- f->fmt.pix.height = 480;
- meye.params.subsample = 0;
- }
- switch (f->fmt.pix.pixelformat) {
- case V4L2_PIX_FMT_YUYV:
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
- break;
- case V4L2_PIX_FMT_MJPEG:
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
- break;
- }
- mutex_unlock(&meye.lock);
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
+static int vidioc_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *req)
+{
+ int i;
- break;
- }
+ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
- case VIDIOC_REQBUFS: {
- struct v4l2_requestbuffers *req = arg;
- int i;
+ if (req->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
- if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (req->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
- if (meye.grab_fbuffer && req->count == gbuffers) {
- /* already allocated, no modifications */
- break;
- }
- mutex_lock(&meye.lock);
- if (meye.grab_fbuffer) {
- for (i = 0; i < gbuffers; i++)
- if (meye.vma_use_count[i]) {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
- meye.grab_fbuffer = NULL;
- }
- gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
- req->count = gbuffers;
- meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
- if (!meye.grab_fbuffer) {
- printk(KERN_ERR "meye: v4l framebuffer allocation"
- " failed\n");
- mutex_unlock(&meye.lock);
- return -ENOMEM;
- }
- for (i = 0; i < gbuffers; i++)
- meye.vma_use_count[i] = 0;
- mutex_unlock(&meye.lock);
- break;
+ if (meye.grab_fbuffer && req->count == gbuffers) {
+ /* already allocated, no modifications */
+ return 0;
}
- case VIDIOC_QUERYBUF: {
- struct v4l2_buffer *buf = arg;
- int index = buf->index;
-
- if (index < 0 || index >= gbuffers)
- return -EINVAL;
- memset(buf, 0, sizeof(*buf));
- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf->index = index;
- buf->bytesused = meye.grab_buffer[index].size;
- buf->flags = V4L2_BUF_FLAG_MAPPED;
- if (meye.grab_buffer[index].state == MEYE_BUF_USING)
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
- if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
- buf->flags |= V4L2_BUF_FLAG_DONE;
- buf->field = V4L2_FIELD_NONE;
- buf->timestamp = meye.grab_buffer[index].timestamp;
- buf->sequence = meye.grab_buffer[index].sequence;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = index * gbufsize;
- buf->length = gbufsize;
- break;
+ mutex_lock(&meye.lock);
+ if (meye.grab_fbuffer) {
+ for (i = 0; i < gbuffers; i++)
+ if (meye.vma_use_count[i]) {
+ mutex_unlock(&meye.lock);
+ return -EINVAL;
+ }
+ rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+ meye.grab_fbuffer = NULL;
}
- case VIDIOC_QBUF: {
- struct v4l2_buffer *buf = arg;
-
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
- if (buf->index < 0 || buf->index >= gbuffers)
- return -EINVAL;
- if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
- return -EINVAL;
- mutex_lock(&meye.lock);
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
- buf->flags &= ~V4L2_BUF_FLAG_DONE;
- meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
- kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+ gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+ req->count = gbuffers;
+ meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+
+ if (!meye.grab_fbuffer) {
+ printk(KERN_ERR "meye: v4l framebuffer allocation"
+ " failed\n");
mutex_unlock(&meye.lock);
- break;
+ return -ENOMEM;
}
- case VIDIOC_DQBUF: {
- struct v4l2_buffer *buf = arg;
- int reqnr;
+ for (i = 0; i < gbuffers; i++)
+ meye.vma_use_count[i] = 0;
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
+ mutex_unlock(&meye.lock);
- mutex_lock(&meye.lock);
- if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
- if (wait_event_interruptible(meye.proc_list,
- kfifo_len(meye.doneq) != 0) < 0) {
- mutex_unlock(&meye.lock);
- return -EINTR;
- }
- if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
- sizeof(int))) {
- mutex_unlock(&meye.lock);
- return -EBUSY;
- }
- if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- buf->index = reqnr;
- buf->bytesused = meye.grab_buffer[reqnr].size;
- buf->flags = V4L2_BUF_FLAG_MAPPED;
- buf->field = V4L2_FIELD_NONE;
- buf->timestamp = meye.grab_buffer[reqnr].timestamp;
- buf->sequence = meye.grab_buffer[reqnr].sequence;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = reqnr * gbufsize;
- buf->length = gbufsize;
- meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+ return 0;
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+ int index = buf->index;
+
+ if (index < 0 || index >= gbuffers)
+ return -EINVAL;
+
+ memset(buf, 0, sizeof(*buf));
+
+ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf->index = index;
+ buf->bytesused = meye.grab_buffer[index].size;
+ buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+ if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+ buf->flags |= V4L2_BUF_FLAG_QUEUED;
+
+ if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+ buf->flags |= V4L2_BUF_FLAG_DONE;
+
+ buf->field = V4L2_FIELD_NONE;
+ buf->timestamp = meye.grab_buffer[index].timestamp;
+ buf->sequence = meye.grab_buffer[index].sequence;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = index * gbufsize;
+ buf->length = gbufsize;
+
+ return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (buf->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+
+ if (buf->index < 0 || buf->index >= gbuffers)
+ return -EINVAL;
+
+ if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+ return -EINVAL;
+
+ mutex_lock(&meye.lock);
+ buf->flags |= V4L2_BUF_FLAG_QUEUED;
+ buf->flags &= ~V4L2_BUF_FLAG_DONE;
+ meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+ kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
+ mutex_unlock(&meye.lock);
+
+ return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+ int reqnr;
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (buf->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+
+ mutex_lock(&meye.lock);
+
+ if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
mutex_unlock(&meye.lock);
- break;
+ return -EAGAIN;
}
- case VIDIOC_STREAMON: {
- mutex_lock(&meye.lock);
- switch (meye.mchip_mode) {
- case MCHIP_HIC_MODE_CONT_OUT:
- mchip_continuous_start();
- break;
- case MCHIP_HIC_MODE_CONT_COMP:
- mchip_cont_compression_start();
- break;
- default:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
+ if (wait_event_interruptible(meye.proc_list,
+ kfifo_len(meye.doneq) != 0) < 0) {
mutex_unlock(&meye.lock);
- break;
+ return -EINTR;
}
- case VIDIOC_STREAMOFF: {
- int i;
+ if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
+ sizeof(int))) {
+ mutex_unlock(&meye.lock);
+ return -EBUSY;
+ }
- mutex_lock(&meye.lock);
- mchip_hic_stop();
- kfifo_reset(meye.grabq);
- kfifo_reset(meye.doneq);
- for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
- meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+ if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
mutex_unlock(&meye.lock);
- break;
+ return -EINVAL;
}
- /*
- * XXX what about private snapshot ioctls ?
- * Do they need to be converted to V4L2 ?
- */
+ buf->index = reqnr;
+ buf->bytesused = meye.grab_buffer[reqnr].size;
+ buf->flags = V4L2_BUF_FLAG_MAPPED;
+ buf->field = V4L2_FIELD_NONE;
+ buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+ buf->sequence = meye.grab_buffer[reqnr].sequence;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = reqnr * gbufsize;
+ buf->length = gbufsize;
+ meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+ mutex_unlock(&meye.lock);
+
+ return 0;
+}
+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+ mutex_lock(&meye.lock);
+
+ switch (meye.mchip_mode) {
+ case MCHIP_HIC_MODE_CONT_OUT:
+ mchip_continuous_start();
+ break;
+ case MCHIP_HIC_MODE_CONT_COMP:
+ mchip_cont_compression_start();
+ break;
default:
- return -ENOIOCTLCMD;
+ mutex_unlock(&meye.lock);
+ return -EINVAL;
}
+ mutex_unlock(&meye.lock);
+
return 0;
}
-static int meye_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
{
- return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
+ mutex_lock(&meye.lock);
+ mchip_hic_stop();
+ kfifo_reset(meye.grabq);
+ kfifo_reset(meye.doneq);
+
+ for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+ meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+
+ mutex_unlock(&meye.lock);
+ return 0;
+}
+
+static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+ switch (cmd) {
+ case MEYEIOC_G_PARAMS:
+ return meyeioc_g_params((struct meye_params *) arg);
+
+ case MEYEIOC_S_PARAMS:
+ return meyeioc_s_params((struct meye_params *) arg);
+
+ case MEYEIOC_QBUF_CAPT:
+ return meyeioc_qbuf_capt((int *) arg);
+
+ case MEYEIOC_SYNC:
+ return meyeioc_sync(file, fh, (int *) arg);
+
+ case MEYEIOC_STILLCAPT:
+ return meyeioc_stillcapt();
+
+ case MEYEIOC_STILLJCAPT:
+ return meyeioc_stilljcapt((int *) arg);
+
+ default:
+ return -EINVAL;
+ }
+
}
static unsigned int meye_poll(struct file *file, poll_table *wait)
@@ -1765,7 +1694,7 @@ static const struct file_operations meye_fops = {
.open = meye_open,
.release = meye_release,
.mmap = meye_mmap,
- .ioctl = meye_ioctl,
+ .ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
#endif
@@ -1780,6 +1709,24 @@ static struct video_device meye_template = {
.fops = &meye_fops,
.release = video_device_release,
.minor = -1,
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_default = vidioc_default,
};
#ifdef CONFIG_PM
diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c
index ef780ed60..5ea4fd801 100644
--- a/linux/drivers/media/video/msp3400-driver.c
+++ b/linux/drivers/media/video/msp3400-driver.c
@@ -410,7 +410,7 @@ int msp_sleep(struct msp_state *state, int timeout)
}
/* ------------------------------------------------------------------------ */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
{
if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -558,7 +558,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
kernel pointer here... */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
@@ -849,7 +849,7 @@ static int msp_resume(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
-static int msp_probe(struct i2c_client *client)
+static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct msp_state *state;
int (*thread_func)(void *data) = NULL;
@@ -859,7 +859,12 @@ static int msp_probe(struct i2c_client *client)
int msp_product, msp_prod_hi, msp_prod_lo;
int msp_rom;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "msp3400");
+#else
+ if (!id)
+ strlcpy(client->name, "msp3400", sizeof(client->name));
+#endif
if (msp_reset(client) == -1) {
v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
@@ -912,9 +917,11 @@ static int msp_probe(struct i2c_client *client)
msp_revision = (state->rev1 & 0x0f) + '@';
msp_hard = ((state->rev1 >> 8) & 0xff) + '@';
msp_rom = state->rev2 & 0x1f;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d",
msp_family, msp_product,
msp_revision, msp_hard, msp_rom);
+#endif
/* Rev B=2, C=3, D=4, G=7 */
state->ident = msp_family * 10000 + 4000 + msp_product * 10 +
msp_revision - '@';
@@ -979,7 +986,9 @@ static int msp_probe(struct i2c_client *client)
}
/* hello world :-) */
- v4l_info(client, "%s found @ 0x%x (%s)\n", client->name,
+ v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n",
+ msp_family, msp_product,
+ msp_revision, msp_hard, msp_rom,
client->addr << 1, client->adapter->name);
v4l_info(client, "%s ", client->name);
if (state->has_nicam && state->has_radio)
@@ -1057,6 +1066,14 @@ static int msp_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id msp_id[] = {
+ { "msp3400", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, msp_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "msp3400",
.driverid = I2C_DRIVERID_MSP3400,
@@ -1065,6 +1082,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.remove = msp_remove,
.suspend = msp_suspend,
.resume = msp_resume,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = msp_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c
index 2ea133e8a..ee4349954 100644
--- a/linux/drivers/media/video/mt9m001.c
+++ b/linux/drivers/media/video/mt9m001.c
@@ -12,15 +12,12 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/log2.h>
+#include <linux/gpio.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/soc_camera.h>
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-#include <asm/gpio.h>
-#endif
-
/* mt9m001 i2c address 0x5d
* The platform has to define i2c_board_info
* and call i2c_register_board_info() */
@@ -123,7 +120,7 @@ static int mt9m001_init(struct soc_camera_device *icd)
int ret;
/* Disable chip, synchronous option update */
- dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__);
+ dev_dbg(icd->vdev->dev, "%s\n", __func__);
ret = reg_write(icd, MT9M001_RESET, 1);
if (ret >= 0)
@@ -372,7 +369,7 @@ static int mt9m001_set_register(struct soc_camera_device *icd,
}
#endif
-const struct v4l2_queryctrl mt9m001_controls[] = {
+static const struct v4l2_queryctrl mt9m001_controls[] = {
{
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -620,7 +617,8 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
soc_camera_video_stop(&mt9m001->icd);
}
-static int mt9m001_probe(struct i2c_client *client)
+static int mt9m001_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct mt9m001 *mt9m001;
struct soc_camera_device *icd;
@@ -696,12 +694,19 @@ static int mt9m001_remove(struct i2c_client *client)
return 0;
}
+static const struct i2c_device_id mt9m001_id[] = {
+ { "mt9m001", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m001_id);
+
static struct i2c_driver mt9m001_i2c_driver = {
.driver = {
.name = "mt9m001",
},
.probe = mt9m001_probe,
.remove = mt9m001_remove,
+ .id_table = mt9m001_id,
};
static int __init mt9m001_mod_init(void)
diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c
index d4b9e2744..1658fe590 100644
--- a/linux/drivers/media/video/mt9v022.c
+++ b/linux/drivers/media/video/mt9v022.c
@@ -13,15 +13,12 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/log2.h>
+#include <linux/gpio.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/soc_camera.h>
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-#include <asm/gpio.h>
-#endif
-
/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
* The platform has to define i2c_board_info
* and call i2c_register_board_info() */
@@ -91,7 +88,7 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
struct mt9v022 {
struct i2c_client *client;
struct soc_camera_device icd;
- int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+ int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
int switch_gpio;
u16 chip_control;
unsigned char datawidth;
@@ -452,7 +449,7 @@ static int mt9v022_set_register(struct soc_camera_device *icd,
}
#endif
-const struct v4l2_queryctrl mt9v022_controls[] = {
+static const struct v4l2_queryctrl mt9v022_controls[] = {
{
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -745,7 +742,8 @@ static void mt9v022_video_remove(struct soc_camera_device *icd)
soc_camera_video_stop(&mt9v022->icd);
}
-static int mt9v022_probe(struct i2c_client *client)
+static int mt9v022_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct mt9v022 *mt9v022;
struct soc_camera_device *icd;
@@ -818,12 +816,19 @@ static int mt9v022_remove(struct i2c_client *client)
return 0;
}
+static const struct i2c_device_id mt9v022_id[] = {
+ { "mt9v022", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v022_id);
+
static struct i2c_driver mt9v022_i2c_driver = {
.driver = {
.name = "mt9v022",
},
.probe = mt9v022_probe,
.remove = mt9v022_remove,
+ .id_table = mt9v022_id,
};
static int __init mt9v022_mod_init(void)
diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c
index 97cc92c82..bf2462a58 100644
--- a/linux/drivers/media/video/mxb.c
+++ b/linux/drivers/media/video/mxb.c
@@ -222,9 +222,8 @@ static int mxb_probe(struct saa7146_dev* dev)
device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients);
/* check if all devices are present */
- if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c
- || 0 == mxb->tda9840 || 0 == mxb->saa7111a || 0 == mxb->tuner ) {
-
+ if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
+ !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
printk("mxb: did not find all i2c devices. aborting\n");
i2c_del_adapter(&mxb->i2c_adapter);
kfree(mxb);
diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c
index cba851d18..9676c1d6f 100644
--- a/linux/drivers/media/video/ov511.c
+++ b/linux/drivers/media/video/ov511.c
@@ -41,7 +41,6 @@
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
-#include <asm/semaphore.h>
#include <asm/processor.h>
#include <linux/mm.h>
#include <linux/device.h>
@@ -5838,7 +5837,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
- ov->vdev->dev = &dev->dev;
+ ov->vdev->dev = &intf->dev;
video_set_drvdata(ov->vdev, ov);
for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
diff --git a/linux/drivers/media/video/ov511.h b/linux/drivers/media/video/ov511.h
index 2fb0d992c..e797d3c9c 100644
--- a/linux/drivers/media/video/ov511.h
+++ b/linux/drivers/media/video/ov511.h
@@ -18,7 +18,7 @@
#ifdef OV511_DEBUG
#define PDEBUG(level, fmt, args...) \
if (debug >= (level)) info("[%s:%d] " fmt, \
- __FUNCTION__, __LINE__ , ## args)
+ __func__, __LINE__ , ## args)
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
#endif
diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h
index 50c7763d4..9afa4fe47 100644
--- a/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/linux/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -24,11 +24,11 @@ extern int ovcamchip_debug;
#define PDEBUG(level, fmt, args...) \
if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+ __func__, __LINE__ , ## args)
#define DDEBUG(level, dev, fmt, args...) \
if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+ __func__, __LINE__ , ## args)
/* Number of times to retry chip detection. Increase this if you are getting
* "Failed to init camera chip" */
diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig
index 6fc1b8be1..4482b2c72 100644
--- a/linux/drivers/media/video/pvrusb2/Kconfig
+++ b/linux/drivers/media/video/pvrusb2/Kconfig
@@ -1,6 +1,8 @@
config VIDEO_PVRUSB2
tristate "Hauppauge WinTV-PVR USB2 support"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_MEDIA # Avoids pvrusb = Y / DVB = M
+ depends on HOTPLUG # due to FW_LOADER
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
@@ -9,6 +11,7 @@ config VIDEO_PVRUSB2
select VIDEO_CX25840
select VIDEO_MSP3400
select VIDEO_WM8775
+ select VIDEO_CS53L32A
---help---
This is a video4linux driver for Conexant 23416 based
usb2 personal video recorder devices.
@@ -16,32 +19,6 @@ config VIDEO_PVRUSB2
To compile this driver as a module, choose M here: the
module will be called pvrusb2
-config VIDEO_PVRUSB2_ONAIR_CREATOR
- bool "pvrusb2 driver support for OnAir Creator model"
- depends on VIDEO_PVRUSB2 && EXPERIMENTAL
- select VIDEO_SAA711X
- select VIDEO_CS53L32A
- ---help---
-
- This option enables support for the OnAir Creator USB tuner
- device. This is a hybrid device, however currently only
- analog mode is supported.
-
- If you are in doubt, say Y.
-
-config VIDEO_PVRUSB2_ONAIR_USB2
- bool "pvrusb2 driver support for OnAir USB2 model"
- depends on VIDEO_PVRUSB2 && EXPERIMENTAL
- select VIDEO_SAA711X
- select VIDEO_CS53L32A
- ---help---
-
- This option enables support for the OnAir USB2 tuner device
- (also known as the Sasem tuner). This is a hybrid device,
- however currently only analog mode is supported.
-
- If you are in doubt, say Y.
-
config VIDEO_PVRUSB2_SYSFS
bool "pvrusb2 sysfs support (EXPERIMENTAL)"
default y
@@ -58,6 +35,25 @@ config VIDEO_PVRUSB2_SYSFS
Note: This feature is experimental and subject to change.
+config VIDEO_PVRUSB2_DVB
+ bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
+ default y
+ depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+ ---help---
+
+ This option enables a DVB interface for the pvrusb2 driver.
+ If your device does not support digital television, this
+ feature will have no affect on the driver's operation.
+
+ If you are in doubt, say Y.
+
config VIDEO_PVRUSB2_DEBUGIFC
bool "pvrusb2 debug interface"
depends on VIDEO_PVRUSB2_SYSFS
diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile
index 47284e558..4fda2de69 100644
--- a/linux/drivers/media/video/pvrusb2/Makefile
+++ b/linux/drivers/media/video/pvrusb2/Makefile
@@ -1,5 +1,6 @@
obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
@@ -9,6 +10,12 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
+ $(obj-pvrusb2-dvb-y) \
$(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 3ecf38d40..65babb878 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -76,7 +75,7 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt)
pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != 0) &&
+ ((sp = routing_schemes + sid) != NULL) &&
(hdw->input_val >= 0) &&
(hdw->input_val < sp->cnt)) {
route.input = sp->def[hdw->input_val];
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
index 536339b68..ac54eed37 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-context.c b/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
index b1b4f3a12..9631ade1e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -1,5 +1,4 @@
/*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -23,107 +22,245 @@
#include "pvrusb2-ioread.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-debug.h"
+#include <linux/wait.h>
#include <linux/kthread.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>
-#include <asm/semaphore.h>
#include "compat.h"
+static struct pvr2_context *pvr2_context_exist_first;
+static struct pvr2_context *pvr2_context_exist_last;
+static struct pvr2_context *pvr2_context_notify_first;
+static struct pvr2_context *pvr2_context_notify_last;
+static DEFINE_MUTEX(pvr2_context_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
+static int pvr2_context_cleanup_flag;
+static int pvr2_context_cleaned_flag;
+static struct task_struct *pvr2_context_thread_ptr;
+
+
+static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
+{
+ int signal_flag = 0;
+ mutex_lock(&pvr2_context_mutex);
+ if (fl) {
+ if (!mp->notify_flag) {
+ signal_flag = (pvr2_context_notify_first == NULL);
+ mp->notify_prev = pvr2_context_notify_last;
+ mp->notify_next = NULL;
+ pvr2_context_notify_last = mp;
+ if (mp->notify_prev) {
+ mp->notify_prev->notify_next = mp;
+ } else {
+ pvr2_context_notify_first = mp;
+ }
+ mp->notify_flag = !0;
+ }
+ } else {
+ if (mp->notify_flag) {
+ mp->notify_flag = 0;
+ if (mp->notify_next) {
+ mp->notify_next->notify_prev = mp->notify_prev;
+ } else {
+ pvr2_context_notify_last = mp->notify_prev;
+ }
+ if (mp->notify_prev) {
+ mp->notify_prev->notify_next = mp->notify_next;
+ } else {
+ pvr2_context_notify_first = mp->notify_next;
+ }
+ }
+ }
+ mutex_unlock(&pvr2_context_mutex);
+ if (signal_flag) wake_up(&pvr2_context_sync_data);
+}
+
static void pvr2_context_destroy(struct pvr2_context *mp)
{
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+ pvr2_context_set_notify(mp, 0);
+ mutex_lock(&pvr2_context_mutex);
+ if (mp->exist_next) {
+ mp->exist_next->exist_prev = mp->exist_prev;
+ } else {
+ pvr2_context_exist_last = mp->exist_prev;
+ }
+ if (mp->exist_prev) {
+ mp->exist_prev->exist_next = mp->exist_next;
+ } else {
+ pvr2_context_exist_first = mp->exist_next;
+ }
+ if (!pvr2_context_exist_first) {
+ /* Trigger wakeup on control thread in case it is waiting
+ for an exit condition. */
+ wake_up(&pvr2_context_sync_data);
+ }
+ mutex_unlock(&pvr2_context_mutex);
kfree(mp);
}
static void pvr2_context_notify(struct pvr2_context *mp)
{
- mp->notify_flag = !0;
- wake_up(&mp->wait_data);
+ pvr2_context_set_notify(mp,!0);
}
-static int pvr2_context_thread(void *_mp)
+static void pvr2_context_check(struct pvr2_context *mp)
{
- struct pvr2_channel *ch1,*ch2;
- struct pvr2_context *mp = _mp;
- pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread start)",mp);
-
- /* Finish hardware initialization */
- if (pvr2_hdw_initialize(mp->hdw,
- (void (*)(void *))pvr2_context_notify,mp)) {
- mp->video_stream.stream =
- pvr2_hdw_get_video_stream(mp->hdw);
- /* Trigger interface initialization. By doing this here
- initialization runs in our own safe and cozy thread
- context. */
- if (mp->setup_func) mp->setup_func(mp);
- } else {
+ struct pvr2_channel *ch1, *ch2;
+ pvr2_trace(PVR2_TRACE_CTXT,
+ "pvr2_context %p (notify)", mp);
+ if (!mp->initialized_flag && !mp->disconnect_flag) {
+ mp->initialized_flag = !0;
pvr2_trace(PVR2_TRACE_CTXT,
- "pvr2_context %p (thread skipping setup)",mp);
- /* Even though initialization did not succeed, we're still
- going to enter the wait loop anyway. We need to do this
- in order to await the expected disconnect (which we will
- detect in the normal course of operation). */
- }
-
- /* Now just issue callbacks whenever hardware state changes or if
- there is a disconnect. If there is a disconnect and there are
- no channels left, then there's no reason to stick around anymore
- so we'll self-destruct - tearing down the rest of this driver
- instance along the way. */
- pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread enter loop)",mp);
- while (!mp->disconnect_flag || mp->mc_first) {
- if (mp->notify_flag) {
- mp->notify_flag = 0;
+ "pvr2_context %p (initialize)", mp);
+ /* Finish hardware initialization */
+ if (pvr2_hdw_initialize(mp->hdw,
+ (void (*)(void *))pvr2_context_notify,
+ mp)) {
+ mp->video_stream.stream =
+ pvr2_hdw_get_video_stream(mp->hdw);
+ /* Trigger interface initialization. By doing this
+ here initialization runs in our own safe and
+ cozy thread context. */
+ if (mp->setup_func) mp->setup_func(mp);
+ } else {
pvr2_trace(PVR2_TRACE_CTXT,
- "pvr2_context %p (thread notify)",mp);
- for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
- ch2 = ch1->mc_next;
- if (ch1->check_func) ch1->check_func(ch1);
- }
+ "pvr2_context %p (thread skipping setup)",
+ mp);
+ /* Even though initialization did not succeed,
+ we're still going to continue anyway. We need
+ to do this in order to await the expected
+ disconnect (which we will detect in the normal
+ course of operation). */
}
- wait_event_interruptible(mp->wait_data, mp->notify_flag);
}
- pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread end)",mp);
- pvr2_context_destroy(mp);
+
+ for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+ ch2 = ch1->mc_next;
+ if (ch1->check_func) ch1->check_func(ch1);
+ }
+
+ if (mp->disconnect_flag && !mp->mc_first) {
+ /* Go away... */
+ pvr2_context_destroy(mp);
+ return;
+ }
+}
+
+
+static int pvr2_context_shutok(void)
+{
+ return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
+}
+
+
+static int pvr2_context_thread_func(void *foo)
+{
+ struct pvr2_context *mp;
+
+ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
+
+ do {
+ while ((mp = pvr2_context_notify_first) != NULL) {
+ pvr2_context_set_notify(mp, 0);
+ pvr2_context_check(mp);
+ }
+ wait_event_interruptible(
+ pvr2_context_sync_data,
+ ((pvr2_context_notify_first != NULL) ||
+ pvr2_context_shutok()));
+ } while (!pvr2_context_shutok());
+
+ pvr2_context_cleaned_flag = !0;
+ wake_up(&pvr2_context_cleanup_data);
+
+ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
+
+ wait_event_interruptible(
+ pvr2_context_sync_data,
+ kthread_should_stop());
+
+ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
+
return 0;
}
+int pvr2_context_global_init(void)
+{
+ pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
+ NULL,
+ "pvrusb2-context");
+ return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
+}
+
+
+void pvr2_context_global_done(void)
+{
+ pvr2_context_cleanup_flag = !0;
+ wake_up(&pvr2_context_sync_data);
+ wait_event_interruptible(
+ pvr2_context_cleanup_data,
+ pvr2_context_cleaned_flag);
+ kthread_stop(pvr2_context_thread_ptr);
+}
+
+
struct pvr2_context *pvr2_context_create(
struct usb_interface *intf,
const struct usb_device_id *devid,
void (*setup_func)(struct pvr2_context *))
{
- struct task_struct *thread;
struct pvr2_context *mp = NULL;
mp = kzalloc(sizeof(*mp),GFP_KERNEL);
if (!mp) goto done;
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
- init_waitqueue_head(&mp->wait_data);
mp->setup_func = setup_func;
mutex_init(&mp->mutex);
+ mutex_lock(&pvr2_context_mutex);
+ mp->exist_prev = pvr2_context_exist_last;
+ mp->exist_next = NULL;
+ pvr2_context_exist_last = mp;
+ if (mp->exist_prev) {
+ mp->exist_prev->exist_next = mp;
+ } else {
+ pvr2_context_exist_first = mp;
+ }
+ mutex_unlock(&pvr2_context_mutex);
mp->hdw = pvr2_hdw_create(intf,devid);
if (!mp->hdw) {
pvr2_context_destroy(mp);
mp = NULL;
goto done;
}
- thread = kthread_run(pvr2_context_thread, mp, "pvrusb2-context");
- if (!thread) {
- pvr2_context_destroy(mp);
- mp = NULL;
- goto done;
- }
+ pvr2_context_set_notify(mp, !0);
done:
return mp;
}
+static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
+{
+ unsigned int tmsk,mmsk;
+ struct pvr2_channel *cp;
+ struct pvr2_hdw *hdw = mp->hdw;
+ mmsk = pvr2_hdw_get_input_available(hdw);
+ tmsk = mmsk;
+ for (cp = mp->mc_first; cp; cp = cp->mc_next) {
+ if (!cp->input_mask) continue;
+ tmsk &= cp->input_mask;
+ }
+ pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
+ pvr2_hdw_commit_ctl(hdw);
+}
+
+
static void pvr2_context_enter(struct pvr2_context *mp)
{
mutex_lock(&mp->mutex);
@@ -179,7 +316,9 @@ void pvr2_channel_done(struct pvr2_channel *cp)
{
struct pvr2_context *mp = cp->mc_head;
pvr2_context_enter(mp);
+ cp->input_mask = 0;
pvr2_channel_disclaim_stream(cp);
+ pvr2_context_reset_input_limits(mp);
if (cp->mc_next) {
cp->mc_next->mc_prev = cp->mc_prev;
} else {
@@ -195,6 +334,57 @@ void pvr2_channel_done(struct pvr2_channel *cp)
}
+int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
+{
+ unsigned int tmsk,mmsk;
+ int ret = 0;
+ struct pvr2_channel *p2;
+ struct pvr2_hdw *hdw = cp->hdw;
+
+ mmsk = pvr2_hdw_get_input_available(hdw);
+ cmsk &= mmsk;
+ if (cmsk == cp->input_mask) {
+ /* No change; nothing to do */
+ return 0;
+ }
+
+ pvr2_context_enter(cp->mc_head);
+ do {
+ if (!cmsk) {
+ cp->input_mask = 0;
+ pvr2_context_reset_input_limits(cp->mc_head);
+ break;
+ }
+ tmsk = mmsk;
+ for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
+ if (p2 == cp) continue;
+ if (!p2->input_mask) continue;
+ tmsk &= p2->input_mask;
+ }
+ if (!(tmsk & cmsk)) {
+ ret = -EPERM;
+ break;
+ }
+ tmsk &= cmsk;
+ if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
+ /* Internal failure changing allowed list; probably
+ should not happen, but react if it does. */
+ break;
+ }
+ cp->input_mask = cmsk;
+ pvr2_hdw_commit_ctl(hdw);
+ } while (0);
+ pvr2_context_exit(cp->mc_head);
+ return ret;
+}
+
+
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
+{
+ return cp->input_mask;
+}
+
+
int pvr2_channel_claim_stream(struct pvr2_channel *cp,
struct pvr2_context_stream *sp)
{
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-context.h b/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
index 1df66ac81..c7cbc28a8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-context.h
@@ -1,5 +1,4 @@
/*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -44,6 +43,10 @@ struct pvr2_context_stream {
struct pvr2_context {
struct pvr2_channel *mc_first;
struct pvr2_channel *mc_last;
+ struct pvr2_context *exist_next;
+ struct pvr2_context *exist_prev;
+ struct pvr2_context *notify_next;
+ struct pvr2_context *notify_prev;
struct pvr2_hdw *hdw;
struct pvr2_context_stream video_stream;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
@@ -52,10 +55,9 @@ struct pvr2_context {
struct semaphore mutex;
#endif
int notify_flag;
+ int initialized_flag;
int disconnect_flag;
- wait_queue_head_t wait_data;
-
/* Called after pvr2_context initialization is complete */
void (*setup_func)(struct pvr2_context *);
@@ -67,6 +69,7 @@ struct pvr2_channel {
struct pvr2_channel *mc_prev;
struct pvr2_context_stream *stream;
struct pvr2_hdw *hdw;
+ unsigned int input_mask;
void (*check_func)(struct pvr2_channel *);
};
@@ -77,11 +80,15 @@ void pvr2_context_disconnect(struct pvr2_context *);
void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
int pvr2_channel_claim_stream(struct pvr2_channel *,
struct pvr2_context_stream *);
struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
struct pvr2_context_stream *);
+int pvr2_context_global_init(void);
+void pvr2_context_global_done(void);
#endif /* __PVRUSB2_CONTEXT_H */
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 32e43e9d1..5c8942e93 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -68,7 +67,7 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
int ret = 0;
if (!cptr) return -EINVAL;
LOCK_TAKE(cptr->hdw->big_lock); do {
- if (cptr->info->set_value != 0) {
+ if (cptr->info->set_value) {
if (cptr->info->type == pvr2_ctl_bitmask) {
mask &= cptr->info->def.type_bitmask.valid_bits;
} else if ((cptr->info->type == pvr2_ctl_int)||
@@ -269,7 +268,7 @@ unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
{
if (!cptr) return 0;
- return cptr->info->set_value != 0;
+ return cptr->info->set_value != NULL;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
index c1680053c..0371ae6e6 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index c64bd6078..2f051f797 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -85,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = {
.vid = CX25840_COMPOSITE2,
.aud = CX25840_AUDIO5,
},
- [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
+ [PVR2_CVAL_INPUT_RADIO] = {
+ /* line-in is used for radio and composite. A GPIO is
+ used to switch between the two choices. */
.vid = CX25840_COMPOSITE1,
.aud = CX25840_AUDIO_SERIAL,
},
@@ -122,7 +123,7 @@ static void set_input(struct pvr2_v4l_cx2584x *ctxt)
memset(&route,0,sizeof(route));
if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != 0) &&
+ ((sp = routing_schemes + sid) != NULL) &&
(hdw->input_val >= 0) &&
(hdw->input_val < sp->cnt)) {
vid_input = sp->def[hdw->input_val].vid;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
index 54b2844e7..66abf77f5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debug.h b/linux/drivers/media/video/pvrusb2/pvrusb2-debug.h
index 11537ddf8..be79249f8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debug.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debug.h
@@ -1,5 +1,4 @@
/*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -54,6 +53,7 @@ extern int pvrusb2_debug;
#define PVR2_TRACE_DATA_FLOW (1 << 25) /* Track data flow */
#define PVR2_TRACE_DEBUGIFC (1 << 26) /* Debug interface actions */
#define PVR2_TRACE_GPIO (1 << 27) /* GPIO state bit changes */
+#define PVR2_TRACE_DVB_FEED (1 << 28) /* DVB transport feed debug */
#endif /* __PVRUSB2_HDW_INTERNAL_H */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index b0687430f..ca892fb78 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -164,6 +163,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
int ccnt;
int ret;
u32 gpio_dir,gpio_in,gpio_out;
+ struct pvr2_stream_stats stats;
+ struct pvr2_stream *sp;
ret = pvr2_hdw_is_hsm(hdw);
ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
@@ -182,6 +183,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
pvr2_hdw_get_streaming(hdw) ? "on" : "off");
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+ sp = pvr2_hdw_get_video_stream(hdw);
+ if (sp) {
+ pvr2_stream_get_stats(sp, &stats, 0);
+ ccnt = scnprintf(
+ buf,acnt,
+ "Bytes streamed=%u"
+ " URBs: queued=%u idle=%u ready=%u"
+ " processed=%u failed=%u\n",
+ stats.bytes_processed,
+ stats.buffers_in_queue,
+ stats.buffers_in_idle,
+ stats.buffers_in_ready,
+ stats.buffers_processed,
+ stats.buffers_failed);
+ bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+ }
+
return bcnt;
}
@@ -220,6 +239,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
return pvr2_hdw_cmd_decoder_reset(hdw);
} else if (debugifc_match_keyword(wptr,wlen,"worker")) {
return pvr2_hdw_untrip(hdw);
+ } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
+ pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
+ NULL, !0);
+ return 0;
}
return -EINVAL;
} else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
index 990b02d35..e24ff59f8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 3434b0e6d..5d036e7e3 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2007 Mike Isely <isely@pobox.com>
*
@@ -32,7 +31,16 @@ pvr2_device_desc structures.
/* This is needed in order to pull in tuner type ids... */
#include <linux/i2c.h>
#include <media/tuner.h>
-
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-hdw-internal.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "s5h1411.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "tda8290.h"
+#include "tuner-simple.h"
+#endif
/*------------------------------------------------------------------------*/
@@ -49,7 +57,7 @@ static const char *pvr2_fw1_names_29xxx[] = {
};
static const struct pvr2_device_desc pvr2_device_29xxx = {
- .description = "WinTV PVR USB2 Model Category 29xxxx",
+ .description = "WinTV PVR USB2 Model Category 29xxx",
.shortname = "29xxx",
.client_modules.lst = pvr2_client_29xxx,
.client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
@@ -80,7 +88,7 @@ static const char *pvr2_fw1_names_24xxx[] = {
};
static const struct pvr2_device_desc pvr2_device_24xxx = {
- .description = "WinTV PVR USB2 Model Category 24xxxx",
+ .description = "WinTV PVR USB2 Model Category 24xxx",
.shortname = "24xxx",
.client_modules.lst = pvr2_client_24xxx,
.client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
@@ -116,6 +124,7 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
.flag_has_cx25840 = !0,
.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.flag_has_analogtuner = !0,
+ .flag_has_fmradio = !0,
.flag_has_composite = !0,
.flag_has_svideo = !0,
.signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
@@ -143,10 +152,41 @@ static const struct pvr2_device_desc pvr2_device_gotview_2d = {
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
/*------------------------------------------------------------------------*/
/* OnAir Creator */
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3303_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .clock_polarity_flip = 1,
+};
+
+static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
+{
+ adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
+ &adap->channel.hdw->i2c_adap);
+ if (adap->fe)
+ return 0;
+
+ return -EIO;
+}
+
+static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
+{
+ dvb_attach(simple_tuner_attach, adap->fe,
+ &adap->channel.hdw->i2c_adap, 0x61,
+ TUNER_LG_TDVS_H06XF);
+
+ return 0;
+}
+
+static struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+ .frontend_attach = pvr2_lgdt3303_attach,
+ .tuner_attach = pvr2_lgh06xf_attach,
+};
+#endif
+
static const char *pvr2_client_onair_creator[] = {
"saa7115",
"tuner",
@@ -162,18 +202,51 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
.flag_has_analogtuner = !0,
.flag_has_composite = !0,
.flag_has_svideo = !0,
+ .flag_digital_requires_cx23416 = !0,
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
.default_std_mask = V4L2_STD_NTSC_M,
-};
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_onair_creator_fe_props,
#endif
+};
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
/*------------------------------------------------------------------------*/
/* OnAir USB 2.0 */
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3302_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3302,
+};
+
+static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
+{
+ adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
+ &adap->channel.hdw->i2c_adap);
+ if (adap->fe)
+ return 0;
+
+ return -EIO;
+}
+
+static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
+{
+ dvb_attach(simple_tuner_attach, adap->fe,
+ &adap->channel.hdw->i2c_adap, 0x61,
+ TUNER_PHILIPS_FCV1236D);
+
+ return 0;
+}
+
+static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+ .frontend_attach = pvr2_lgdt3302_attach,
+ .tuner_attach = pvr2_fcv1236d_attach,
+};
+#endif
+
static const char *pvr2_client_onair_usb2[] = {
"saa7115",
"tuner",
@@ -189,17 +262,64 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
.flag_has_analogtuner = !0,
.flag_has_composite = !0,
.flag_has_svideo = !0,
+ .flag_digital_requires_cx23416 = !0,
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
.default_std_mask = V4L2_STD_NTSC_M,
-};
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_onair_usb2_fe_props,
#endif
+};
/*------------------------------------------------------------------------*/
/* Hauppauge PVR-USB2 Model 73xxx */
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct tda10048_config hauppauge_tda10048_config = {
+ .demod_address = 0x10 >> 1,
+ .output_mode = TDA10048_PARALLEL_OUTPUT,
+ .fwbulkwritelen = TDA10048_BULKWRITE_50,
+ .inversion = TDA10048_INVERSION_ON,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+ .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda18271_config hauppauge_tda18271_dvb_config = {
+ .gate = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
+{
+ adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
+ &adap->channel.hdw->i2c_adap);
+ if (adap->fe)
+ return 0;
+
+ return -EIO;
+}
+
+static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+ dvb_attach(tda829x_attach, adap->fe,
+ &adap->channel.hdw->i2c_adap, 0x42,
+ &tda829x_no_probe);
+ dvb_attach(tda18271_attach, adap->fe, 0x60,
+ &adap->channel.hdw->i2c_adap,
+ &hauppauge_tda18271_dvb_config);
+
+ return 0;
+}
+
+static struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+ .frontend_attach = pvr2_tda10048_attach,
+ .tuner_attach = pvr2_73xxx_tda18271_8295_attach,
+};
+#endif
+
static const char *pvr2_client_73xxx[] = {
"cx25840",
"tuner",
@@ -210,7 +330,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
};
static const struct pvr2_device_desc pvr2_device_73xxx = {
- .description = "WinTV PVR USB2 Model Category 73xxxx",
+ .description = "WinTV PVR USB2 Model Category 73xxx",
.shortname = "73xxx",
.client_modules.lst = pvr2_client_73xxx,
.client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
@@ -224,6 +344,9 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
.digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_73xxx_dvb_props,
+#endif
};
@@ -231,6 +354,80 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
/*------------------------------------------------------------------------*/
/* Hauppauge PVR-USB2 Model 75xxx */
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct s5h1409_config pvr2_s5h1409_config = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_PARALLEL_OUTPUT,
+ .gpio = S5H1409_GPIO_OFF,
+ .qam_if = 4000,
+ .inversion = S5H1409_INVERSION_ON,
+ .status_mode = S5H1409_DEMODLOCKING,
+};
+
+static struct s5h1411_config pvr2_s5h1411_config = {
+ .output_mode = S5H1411_PARALLEL_OUTPUT,
+ .gpio = S5H1411_GPIO_OFF,
+ .vsb_if = S5H1411_IF_44000,
+ .qam_if = S5H1411_IF_4000,
+ .inversion = S5H1411_INVERSION_ON,
+ .status_mode = S5H1411_DEMODLOCKING,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+ .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+ .if_lvl = 6, .rfagc_top = 0x37, },
+ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+ .if_lvl = 6, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+ .std_map = &hauppauge_tda18271_std_map,
+ .gate = TDA18271_GATE_ANALOG,
+};
+
+static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
+{
+ adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
+ &adap->channel.hdw->i2c_adap);
+ if (adap->fe)
+ return 0;
+
+ return -EIO;
+}
+
+static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
+{
+ adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
+ &adap->channel.hdw->i2c_adap);
+ if (adap->fe)
+ return 0;
+
+ return -EIO;
+}
+
+static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+ dvb_attach(tda829x_attach, adap->fe,
+ &adap->channel.hdw->i2c_adap, 0x42,
+ &tda829x_no_probe);
+ dvb_attach(tda18271_attach, adap->fe, 0x60,
+ &adap->channel.hdw->i2c_adap,
+ &hauppauge_tda18271_config);
+
+ return 0;
+}
+
+static struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+ .frontend_attach = pvr2_s5h1409_attach,
+ .tuner_attach = pvr2_tda18271_8295_attach,
+};
+
+static struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+ .frontend_attach = pvr2_s5h1411_attach,
+ .tuner_attach = pvr2_tda18271_8295_attach,
+};
+#endif
+
static const char *pvr2_client_75xxx[] = {
"cx25840",
"tuner",
@@ -240,9 +437,9 @@ static const char *pvr2_fw1_names_75xxx[] = {
"v4l-pvrusb2-73xxx-01.fw",
};
-static const struct pvr2_device_desc pvr2_device_75xxx = {
- .description = "WinTV PVR USB2 Model Category 75xxxx",
- .shortname = "75xxx",
+static const struct pvr2_device_desc pvr2_device_750xx = {
+ .description = "WinTV PVR USB2 Model Category 750xx",
+ .shortname = "750xx",
.client_modules.lst = pvr2_client_75xxx,
.client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
.fx2_firmware.lst = pvr2_fw1_names_75xxx,
@@ -256,6 +453,30 @@ static const struct pvr2_device_desc pvr2_device_75xxx = {
.digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
.default_std_mask = V4L2_STD_NTSC_M,
.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_750xx_dvb_props,
+#endif
+};
+
+static const struct pvr2_device_desc pvr2_device_751xx = {
+ .description = "WinTV PVR USB2 Model Category 751xx",
+ .shortname = "751xx",
+ .client_modules.lst = pvr2_client_75xxx,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+ .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+ .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+ .flag_has_cx25840 = !0,
+ .flag_has_hauppauge_rom = !0,
+ .flag_has_analogtuner = !0,
+ .flag_has_composite = !0,
+ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+ .default_std_mask = V4L2_STD_NTSC_M,
+ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ .dvb_props = &pvr2_751xx_dvb_props,
+#endif
};
@@ -271,20 +492,16 @@ struct usb_device_id pvr2_device_table[] = {
.driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
{ USB_DEVICE(0x1164, 0x0602),
.driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
{ USB_DEVICE(0x11ba, 0x1003),
.driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
-#endif
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
{ USB_DEVICE(0x11ba, 0x1001),
.driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
-#endif
{ USB_DEVICE(0x2040, 0x7300),
.driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
{ USB_DEVICE(0x2040, 0x7500),
- .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+ .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
{ USB_DEVICE(0x2040, 0x7501),
- .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
+ .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
{ }
};
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index fb5f5d17e..e23ce1d2e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -23,6 +22,9 @@
#include <linux/mod_devicetable.h>
#include <linux/videodev2.h>
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-dvb.h"
+#endif
/*
@@ -65,6 +67,11 @@ struct pvr2_device_desc {
was initialized from internal ROM. */
struct pvr2_string_table fx2_firmware;
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ /* callback functions to handle attachment of digital tuner & demod */
+ struct pvr2_dvb_props *dvb_props;
+
+#endif
/* Initial standard bits to use for this device, if not zero.
Anything set here is also implied as an available standard.
Note: This is ignored if overridden on the module load line via
@@ -96,21 +103,28 @@ struct pvr2_device_desc {
unsigned char digital_control_scheme;
/* If set, we don't bother trying to load cx23416 firmware. */
- int flag_skip_cx23416_firmware:1;
+ unsigned int flag_skip_cx23416_firmware:1;
+
+ /* If set, the encoder must be healthy in order for digital mode to
+ work (otherwise we assume that digital streaming will work even
+ if we fail to locate firmware for the encoder). If the device
+ doesn't support digital streaming then this flag has no
+ effect. */
+ unsigned int flag_digital_requires_cx23416:1;
/* Device has a hauppauge eeprom which we can interrogate. */
- int flag_has_hauppauge_rom:1;
+ unsigned int flag_has_hauppauge_rom:1;
/* Device does not require a powerup command to be issued. */
- int flag_no_powerup:1;
+ unsigned int flag_no_powerup:1;
/* Device has a cx25840 - this enables special additional logic to
handle it. */
- int flag_has_cx25840:1;
+ unsigned int flag_has_cx25840:1;
/* Device has a wm8775 - this enables special additional logic to
ensure that it is found. */
- int flag_has_wm8775:1;
+ unsigned int flag_has_wm8775:1;
/* Device has IR hardware that can be faked into looking like a
normal Hauppauge i2c IR receiver. This is currently very
@@ -120,15 +134,15 @@ struct pvr2_device_desc {
to virtualize the presence of the non-existant IR receiver chip and
implement the virtual receiver in terms of appropriate FX2
commands. */
- int flag_has_hauppauge_custom_ir:1;
+ unsigned int flag_has_hauppauge_custom_ir:1;
/* These bits define which kinds of sources the device can handle.
Note: Digital tuner presence is inferred by the
digital_control_scheme enumeration. */
- int flag_has_fmradio:1; /* Has FM radio receiver */
- int flag_has_analogtuner:1; /* Has analog tuner */
- int flag_has_composite:1; /* Has composite input */
- int flag_has_svideo:1; /* Has s-video input */
+ unsigned int flag_has_fmradio:1; /* Has FM radio receiver */
+ unsigned int flag_has_analogtuner:1; /* Has analog tuner */
+ unsigned int flag_has_composite:1; /* Has composite input */
+ unsigned int flag_has_svideo:1; /* Has s-video input */
};
extern struct usb_device_id pvr2_device_table[];
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c
new file mode 100644
index 000000000..a317347ad
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -0,0 +1,438 @@
+/*
+ * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
+ *
+ * Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kthread.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#include <linux/suspend.h>
+#else
+#include <linux/freezer.h>
+#endif
+#include "compat.h"
+#include "dvbdev.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
+{
+ int ret;
+ unsigned int count;
+ struct pvr2_buffer *bp;
+ struct pvr2_stream *stream;
+
+ pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started");
+ set_freezable();
+
+ stream = adap->channel.stream->stream;
+
+ for (;;) {
+ if (kthread_should_stop()) break;
+
+ /* Not sure about this... */
+ try_to_freeze();
+
+ bp = pvr2_stream_get_ready_buffer(stream);
+ if (bp != NULL) {
+ count = pvr2_buffer_get_count(bp);
+ if (count) {
+ dvb_dmx_swfilter(
+ &adap->demux,
+ adap->buffer_storage[
+ pvr2_buffer_get_id(bp)],
+ count);
+ } else {
+ ret = pvr2_buffer_get_status(bp);
+ if (ret < 0) break;
+ }
+ ret = pvr2_buffer_queue(bp);
+ if (ret < 0) break;
+
+ /* Since we know we did something to a buffer,
+ just go back and try again. No point in
+ blocking unless we really ran out of
+ buffers to process. */
+ continue;
+ }
+
+
+ /* Wait until more buffers become available or we're
+ told not to wait any longer. */
+ ret = wait_event_interruptible(
+ adap->buffer_wait_data,
+ (pvr2_stream_get_ready_count(stream) > 0) ||
+ kthread_should_stop());
+ if (ret < 0) break;
+ }
+
+ /* If we get here and ret is < 0, then an error has occurred.
+ Probably would be a good idea to communicate that to DVB core... */
+
+ pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped");
+
+ return 0;
+}
+
+static int pvr2_dvb_feed_thread(void *data)
+{
+ int stat = pvr2_dvb_feed_func(data);
+ /* from videobuf-dvb.c: */
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ return stat;
+}
+
+static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
+{
+ wake_up(&adap->buffer_wait_data);
+}
+
+static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
+{
+ unsigned int idx;
+ struct pvr2_stream *stream;
+
+ if (adap->thread) {
+ kthread_stop(adap->thread);
+ adap->thread = NULL;
+ }
+
+ if (adap->channel.stream) {
+ stream = adap->channel.stream->stream;
+ } else {
+ stream = NULL;
+ }
+ if (stream) {
+ pvr2_hdw_set_streaming(adap->channel.hdw, 0);
+ pvr2_stream_set_callback(stream, NULL, NULL);
+ pvr2_stream_kill(stream);
+ pvr2_stream_set_buffer_count(stream, 0);
+ pvr2_channel_claim_stream(&adap->channel, NULL);
+ }
+
+ if (adap->stream_run) {
+ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+ if (!(adap->buffer_storage[idx])) continue;
+ kfree(adap->buffer_storage[idx]);
+ adap->buffer_storage[idx] = NULL;
+ }
+ adap->stream_run = 0;
+ }
+}
+
+static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
+{
+ struct pvr2_context *pvr = adap->channel.mc_head;
+ unsigned int idx;
+ int ret;
+ struct pvr2_buffer *bp;
+ struct pvr2_stream *stream = NULL;
+
+ if (adap->stream_run) return -EIO;
+
+ ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
+ /* somebody else already has the stream */
+ if (ret < 0) return ret;
+
+ stream = adap->channel.stream->stream;
+
+ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+ adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!(adap->buffer_storage[idx])) return -ENOMEM;
+ }
+
+ pvr2_stream_set_callback(pvr->video_stream.stream,
+ (pvr2_stream_callback) pvr2_dvb_notify, adap);
+
+ ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
+ if (ret < 0) return ret;
+
+ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+ bp = pvr2_stream_get_buffer(stream, idx);
+ pvr2_buffer_set_buffer(bp,
+ adap->buffer_storage[idx],
+ PVR2_DVB_BUFFER_SIZE);
+ }
+
+ ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
+ if (ret < 0) return ret;
+
+ while ((bp = pvr2_stream_get_idle_buffer(stream)) != NULL) {
+ ret = pvr2_buffer_queue(bp);
+ if (ret < 0) return ret;
+ }
+
+ adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
+
+ if (IS_ERR(adap->thread)) {
+ ret = PTR_ERR(adap->thread);
+ adap->thread = NULL;
+ return ret;
+ }
+
+ adap->stream_run = !0;
+
+ return 0;
+}
+
+static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
+{
+ int ret = pvr2_dvb_stream_do_start(adap);
+ if (ret < 0) pvr2_dvb_stream_end(adap);
+ return ret;
+}
+
+static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+ struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
+ int ret = 0;
+
+ if (adap == NULL) return -ENODEV;
+
+ mutex_lock(&adap->lock);
+ do {
+ if (onoff) {
+ if (!adap->feedcount) {
+ pvr2_trace(PVR2_TRACE_DVB_FEED,
+ "start feeding demux");
+ ret = pvr2_dvb_stream_start(adap);
+ if (ret < 0) break;
+ }
+ (adap->feedcount)++;
+ } else if (adap->feedcount > 0) {
+ (adap->feedcount)--;
+ if (!adap->feedcount) {
+ pvr2_trace(PVR2_TRACE_DVB_FEED,
+ "stop feeding demux");
+ pvr2_dvb_stream_end(adap);
+ }
+ }
+ } while (0);
+ mutex_unlock(&adap->lock);
+
+ return ret;
+}
+
+static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid);
+ return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
+}
+
+static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid);
+ return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
+}
+
+static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+ struct pvr2_dvb_adapter *adap = fe->dvb->priv;
+ return pvr2_channel_limit_inputs(
+ &adap->channel,
+ (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
+}
+
+static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
+{
+ int ret;
+
+ ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
+ THIS_MODULE/*&hdw->usb_dev->owner*/,
+ &adap->channel.hdw->usb_dev->dev,
+ adapter_nr);
+ if (ret < 0) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "dvb_register_adapter failed: error %d", ret);
+ goto err;
+ }
+ adap->dvb_adap.priv = adap;
+
+ adap->demux.dmx.capabilities = DMX_TS_FILTERING |
+ DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING;
+ adap->demux.priv = adap;
+ adap->demux.filternum = 256;
+ adap->demux.feednum = 256;
+ adap->demux.start_feed = pvr2_dvb_start_feed;
+ adap->demux.stop_feed = pvr2_dvb_stop_feed;
+ adap->demux.write_to_decoder = NULL;
+
+ ret = dvb_dmx_init(&adap->demux);
+ if (ret < 0) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "dvb_dmx_init failed: error %d", ret);
+ goto err_dmx;
+ }
+
+ adap->dmxdev.filternum = adap->demux.filternum;
+ adap->dmxdev.demux = &adap->demux.dmx;
+ adap->dmxdev.capabilities = 0;
+
+ ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+ if (ret < 0) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "dvb_dmxdev_init failed: error %d", ret);
+ goto err_dmx_dev;
+ }
+
+ dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+
+ return 0;
+
+err_dmx_dev:
+ dvb_dmx_release(&adap->demux);
+err_dmx:
+ dvb_unregister_adapter(&adap->dvb_adap);
+err:
+ return ret;
+}
+
+static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
+{
+ pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices");
+ dvb_net_release(&adap->dvb_net);
+ adap->demux.dmx.close(&adap->demux.dmx);
+ dvb_dmxdev_release(&adap->dmxdev);
+ dvb_dmx_release(&adap->demux);
+ dvb_unregister_adapter(&adap->dvb_adap);
+ return 0;
+}
+
+static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
+{
+ struct pvr2_hdw *hdw = adap->channel.hdw;
+ struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+ int ret = 0;
+
+ if (dvb_props == NULL) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!");
+ return -EINVAL;
+ }
+
+ ret = pvr2_channel_limit_inputs(
+ &adap->channel,
+ (1 << PVR2_CVAL_INPUT_DTV));
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "failed to grab control of dtv input (code=%d)",
+ ret);
+ return ret;
+ }
+
+ if (dvb_props->frontend_attach == NULL) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "frontend_attach not defined!");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
+
+ if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "frontend registration failed!");
+ dvb_frontend_detach(adap->fe);
+ adap->fe = NULL;
+ ret = -ENODEV;
+ goto done;
+ }
+
+ if (dvb_props->tuner_attach)
+ dvb_props->tuner_attach(adap);
+
+ if (adap->fe->ops.analog_ops.standby)
+ adap->fe->ops.analog_ops.standby(adap->fe);
+
+ /* Ensure all frontends negotiate bus access */
+ adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
+
+ } else {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "no frontend was attached!");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ done:
+ pvr2_channel_limit_inputs(&adap->channel, 0);
+ return ret;
+}
+
+static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
+{
+ if (adap->fe != NULL) {
+ dvb_unregister_frontend(adap->fe);
+ dvb_frontend_detach(adap->fe);
+ }
+ return 0;
+}
+
+static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
+{
+ pvr2_dvb_stream_end(adap);
+ pvr2_dvb_frontend_exit(adap);
+ pvr2_dvb_adapter_exit(adap);
+ pvr2_channel_done(&adap->channel);
+ kfree(adap);
+}
+
+static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
+{
+ struct pvr2_dvb_adapter *adap;
+ adap = container_of(chp, struct pvr2_dvb_adapter, channel);
+ if (!adap->channel.mc_head->disconnect_flag) return;
+ pvr2_dvb_destroy(adap);
+}
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
+{
+ int ret = 0;
+ struct pvr2_dvb_adapter *adap;
+ if (!pvr->hdw->hdw_desc->dvb_props) {
+ /* Device lacks a digital interface so don't set up
+ the DVB side of the driver either. For now. */
+ return NULL;
+ }
+ adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+ if (!adap) return adap;
+ pvr2_channel_init(&adap->channel, pvr);
+ adap->channel.check_func = pvr2_dvb_internal_check;
+ init_waitqueue_head(&adap->buffer_wait_data);
+ mutex_init(&adap->lock);
+ ret = pvr2_dvb_adapter_init(adap);
+ if (ret < 0) goto fail1;
+ ret = pvr2_dvb_frontend_init(adap);
+ if (ret < 0) goto fail2;
+ return adap;
+
+fail2:
+ pvr2_dvb_adapter_exit(adap);
+fail1:
+ pvr2_channel_done(&adap->channel);
+ return NULL;
+}
+
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.h
new file mode 100644
index 000000000..c13ecfb13
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.h
@@ -0,0 +1,45 @@
+#ifndef __PVRUSB2_DVB_H__
+#define __PVRUSB2_DVB_H__
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+#include "pvrusb2-context.h"
+
+#define PVR2_DVB_BUFFER_COUNT 32
+#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_dvb_adapter {
+ struct pvr2_channel channel;
+
+ struct dvb_adapter dvb_adap;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+ struct dvb_net dvb_net;
+ struct dvb_frontend *fe;
+
+ int feedcount;
+ int max_feed_count;
+
+ struct task_struct *thread;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+ struct mutex lock;
+#else
+ struct semaphore lock;
+#endif
+
+ unsigned int stream_run:1;
+
+ wait_queue_head_t buffer_wait_data;
+ char *buffer_storage[PVR2_DVB_BUFFER_COUNT];
+};
+
+struct pvr2_dvb_props {
+ int (*frontend_attach) (struct pvr2_dvb_adapter *);
+ int (*tuner_attach) (struct pvr2_dvb_adapter *);
+};
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
+
+#endif /* __PVRUSB2_DVB_H__ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
index b831559bd..349618395 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
index 84242975d..cca3216f9 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index 70a2bc251..da5b5a7e9 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -300,11 +299,20 @@ static int pvr2_encoder_cmd(void *ctxt,
ret = -EBUSY;
}
if (ret) {
+ del_timer_sync(&hdw->encoder_run_timer);
hdw->state_encoder_ok = 0;
pvr2_trace(PVR2_TRACE_STBITS,
"State bit %s <-- %s",
"state_encoder_ok",
(hdw->state_encoder_ok ? "true" : "false"));
+ if (hdw->state_encoder_runok) {
+ hdw->state_encoder_runok = 0;
+ pvr2_trace(PVR2_TRACE_STBITS,
+ "State bit %s <-- %s",
+ "state_encoder_runok",
+ (hdw->state_encoder_runok ?
+ "true" : "false"));
+ }
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Giving up on command."
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.h
index 54caf2e3c..232fefbcd 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/linux/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
index a866c9492..b58369e7f 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
*
@@ -22,41 +21,41 @@
#ifndef _PVRUSB2_FX2_CMD_H_
#define _PVRUSB2_FX2_CMD_H_
-#define FX2CMD_MEM_WRITE_DWORD 0x01
-#define FX2CMD_MEM_READ_DWORD 0x02
+#define FX2CMD_MEM_WRITE_DWORD 0x01u
+#define FX2CMD_MEM_READ_DWORD 0x02u
-#define FX2CMD_MEM_READ_64BYTES 0x28
+#define FX2CMD_MEM_READ_64BYTES 0x28u
-#define FX2CMD_REG_WRITE 0x04
-#define FX2CMD_REG_READ 0x05
-#define FX2CMD_MEMSEL 0x06
+#define FX2CMD_REG_WRITE 0x04u
+#define FX2CMD_REG_READ 0x05u
+#define FX2CMD_MEMSEL 0x06u
-#define FX2CMD_I2C_WRITE 0x08
-#define FX2CMD_I2C_READ 0x09
+#define FX2CMD_I2C_WRITE 0x08u
+#define FX2CMD_I2C_READ 0x09u
-#define FX2CMD_GET_USB_SPEED 0x0b
+#define FX2CMD_GET_USB_SPEED 0x0bu
-#define FX2CMD_STREAMING_ON 0x36
-#define FX2CMD_STREAMING_OFF 0x37
+#define FX2CMD_STREAMING_ON 0x36u
+#define FX2CMD_STREAMING_OFF 0x37u
-#define FX2CMD_FWPOST1 0x52
+#define FX2CMD_FWPOST1 0x52u
-#define FX2CMD_POWER_OFF 0xdc
-#define FX2CMD_POWER_ON 0xde
+#define FX2CMD_POWER_OFF 0xdcu
+#define FX2CMD_POWER_ON 0xdeu
-#define FX2CMD_DEEP_RESET 0xdd
+#define FX2CMD_DEEP_RESET 0xddu
-#define FX2CMD_GET_EEPROM_ADDR 0xeb
-#define FX2CMD_GET_IR_CODE 0xec
+#define FX2CMD_GET_EEPROM_ADDR 0xebu
+#define FX2CMD_GET_IR_CODE 0xecu
-#define FX2CMD_HCW_DEMOD_RESETIN 0xf0
-#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1
-#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2
+#define FX2CMD_HCW_DEMOD_RESETIN 0xf0u
+#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1u
+#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2u
-#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0
-#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1
-#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2
-#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3
+#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0u
+#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
+#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2u
+#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3u
#endif /* _PVRUSB2_FX2_CMD_H_ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index 631973652..f75dd1613 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -254,6 +253,7 @@ struct pvr2_hdw {
int state_encoder_run; /* Encoder is running */
int state_encoder_config; /* Encoder is configured */
int state_encoder_waitok; /* Encoder pre-wait done */
+ int state_encoder_runok; /* Encoder has run for >= .25 sec */
int state_decoder_run; /* Decoder is running */
int state_usbstream_run; /* FX2 is streaming */
int state_decoder_quiescent; /* Decoder idle for > 50msec */
@@ -283,6 +283,9 @@ struct pvr2_hdw {
/* Timer for measuring encoder pre-wait time */
struct timer_list encoder_wait_timer;
+ /* Timer for measuring encoder minimum run time */
+ struct timer_list encoder_run_timer;
+
/* Place to block while waiting for state changes */
wait_queue_head_t state_wait_data;
@@ -348,8 +351,10 @@ struct pvr2_hdw {
int v4l_minor_number_vbi;
int v4l_minor_number_radio;
- /* Bit mask of PVR2_CVAL_INPUT choices which are valid */
+ /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
unsigned int input_avail_mask;
+ /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
+ unsigned int input_allowed_mask;
/* Location of eeprom or a negative number if none */
int eeprom_addr;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 77edc72a2..f78bc351f 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -25,7 +24,6 @@
#include <linux/firmware.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
-#include <asm/semaphore.h>
#include "pvrusb2.h"
#include "pvrusb2-std.h"
#include "pvrusb2-util.h"
@@ -42,6 +40,23 @@
#define TV_MIN_FREQ 55250000L
#define TV_MAX_FREQ 850000000L
+/* This defines a minimum interval that the decoder must remain quiet
+ before we are allowed to start it running. */
+#define TIME_MSEC_DECODER_WAIT 50
+
+/* This defines a minimum interval that the encoder must remain quiet
+ before we are allowed to configure it. I had this originally set to
+ 50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that
+ things work better when it's set to 100msec. */
+#define TIME_MSEC_ENCODER_WAIT 100
+
+/* This defines the minimum interval that the encoder must successfully run
+ before we consider that the encoder has run at least once since its
+ firmware has been loaded. This measurement is in important for cases
+ where we can't do something until we know that the encoder has been run
+ at least once. */
+#define TIME_MSEC_ENCODER_OK 250
+
static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
static DEFINE_MUTEX(pvr2_unit_mtx);
@@ -69,6 +84,16 @@ MODULE_PARM_DESC(video_std,"specify initial video standard");
module_param_array(tolerance, int, NULL, 0444);
MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
+/* US Broadcast channel 7 (175.25 MHz) */
+static int default_tv_freq = 175250000L;
+/* 104.3 MHz, a usable FM station for my area */
+static int default_radio_freq = 104300000L;
+
+module_param_named(tv_freq, default_tv_freq, int, 0444);
+MODULE_PARM_DESC(tv_freq, "specify initial television frequency");
+module_param_named(radio_freq, default_radio_freq, int, 0444);
+MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
+
#define PVR2_CTL_WRITE_ENDPOINT 0x01
#define PVR2_CTL_READ_ENDPOINT 0x81
@@ -218,6 +243,40 @@ static const char *pvr2_state_names[] = {
};
+struct pvr2_fx2cmd_descdef {
+ unsigned char id;
+ unsigned char *desc;
+};
+
+static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
+ {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
+ {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
+ {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
+ {FX2CMD_REG_WRITE, "write encoder register"},
+ {FX2CMD_REG_READ, "read encoder register"},
+ {FX2CMD_MEMSEL, "encoder memsel"},
+ {FX2CMD_I2C_WRITE, "i2c write"},
+ {FX2CMD_I2C_READ, "i2c read"},
+ {FX2CMD_GET_USB_SPEED, "get USB speed"},
+ {FX2CMD_STREAMING_ON, "stream on"},
+ {FX2CMD_STREAMING_OFF, "stream off"},
+ {FX2CMD_FWPOST1, "fwpost1"},
+ {FX2CMD_POWER_OFF, "power off"},
+ {FX2CMD_POWER_ON, "power on"},
+ {FX2CMD_DEEP_RESET, "deep reset"},
+ {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
+ {FX2CMD_GET_IR_CODE, "get IR code"},
+ {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
+ {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
+ {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
+ {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
+ {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
+ {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
+ {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
+};
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
static void pvr2_hdw_state_sched(struct pvr2_hdw *);
static int pvr2_hdw_state_eval(struct pvr2_hdw *);
static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
@@ -233,6 +292,8 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
static void pvr2_hdw_quiescent_timeout(unsigned long);
static void pvr2_hdw_encoder_wait_timeout(unsigned long);
+static void pvr2_hdw_encoder_run_timeout(unsigned long);
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
unsigned int timeout,int probe_fl,
void *write_data,unsigned int write_len,
@@ -371,30 +432,12 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
{
- return ((1 << v) & cptr->hdw->input_avail_mask) != 0;
+ return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
}
static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
{
- struct pvr2_hdw *hdw = cptr->hdw;
-
- if (hdw->input_val != v) {
- hdw->input_val = v;
- hdw->input_dirty = !0;
- }
-
- /* Handle side effects - if we switch to a mode that needs the RF
- tuner, then select the right frequency choice as well and mark
- it dirty. */
- if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
- hdw->freqSelector = 0;
- hdw->freqDirty = !0;
- } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
- (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
- hdw->freqSelector = 1;
- hdw->freqDirty = !0;
- }
- return 0;
+ return pvr2_hdw_set_input(cptr->hdw,v);
}
static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
@@ -991,7 +1034,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
/* Set the currently tuned frequency and account for all possible
driver-core side effects of this action. */
-void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
{
if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
if (hdw->freqSelector) {
@@ -1213,6 +1256,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
time we configure the encoder, then we'll fully configure it. */
hdw->enc_cur_valid = 0;
+ /* Encoder is about to be reset so note that as far as we're
+ concerned now, the encoder has never been run. */
+ del_timer_sync(&hdw->encoder_run_timer);
+ if (hdw->state_encoder_runok) {
+ hdw->state_encoder_runok = 0;
+ trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+ }
+
/* First prepare firmware loading */
ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
@@ -1230,19 +1281,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
- hdw->cmd_buffer[1] = 0;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
+ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
+ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"firmware2 upload prep failed, ret=%d",ret);
release_firmware(fw_entry);
- return ret;
+ goto done;
}
/* Now send firmware */
@@ -1255,7 +1301,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
" must be a multiple of %zu bytes",
fw_files[fwidx],sizeof(u32));
release_firmware(fw_entry);
- return -1;
+ ret = -EINVAL;
+ goto done;
}
fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
@@ -1263,7 +1310,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
release_firmware(fw_entry);
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"failed to allocate memory for firmware2 upload");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto done;
}
pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
@@ -1294,23 +1342,27 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"firmware2 upload transfer failure");
- return ret;
+ goto done;
}
/* Finish upload */
ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
- hdw->cmd_buffer[1] = 0;
- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
+ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"firmware2 upload post-proc failure");
}
+
+ done:
+ if (hdw->hdw_desc->signal_routing_scheme ==
+ PVR2_ROUTING_SCHEME_GOTVIEW) {
+ /* Ensure that GPIO 11 is set to output for GOTVIEW
+ hardware. */
+ pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+ }
return ret;
}
@@ -1382,11 +1434,13 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
}
+#if 0
const char *pvr2_hdw_get_state_name(unsigned int id)
{
if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL;
return pvr2_state_names[id];
}
+#endif /* 0 */
int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
@@ -1690,10 +1744,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
are, but I set them to something usable in the Chicago area just
to make driver testing a little easier. */
- /* US Broadcast channel 7 (175.25 MHz) */
- hdw->freqValTelevision = 175250000L;
- /* 104.3 MHz, a usable FM station for my area */
- hdw->freqValRadio = 104300000L;
+ hdw->freqValTelevision = default_tv_freq;
+ hdw->freqValRadio = default_radio_freq;
// Do not use pvr2_reset_ctl_endpoints() here. It is not
// thread-safe against the normal pvr2_send_request() mechanism.
@@ -1730,6 +1782,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
if (!pvr2_hdw_dev_ok(hdw)) return;
+ if (hdw->hdw_desc->signal_routing_scheme ==
+ PVR2_ROUTING_SCHEME_GOTVIEW) {
+ /* Ensure that GPIO 11 is set to output for GOTVIEW
+ hardware. */
+ pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+ }
+
pvr2_hdw_commit_setup(hdw);
hdw->vid_stream = pvr2_stream_create();
@@ -1831,10 +1890,19 @@ int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
void *callback_data)
{
LOCK_TAKE(hdw->big_lock); do {
+ if (hdw->flag_disconnected) {
+ /* Handle a race here: If we're already
+ disconnected by this point, then give up. If we
+ get past this then we'll remain connected for
+ the duration of initialization since the entire
+ initialization sequence is now protected by the
+ big_lock. */
+ break;
+ }
hdw->state_data = callback_data;
hdw->state_func = callback_func;
+ pvr2_hdw_setup(hdw);
} while (0); LOCK_GIVE(hdw->big_lock);
- pvr2_hdw_setup(hdw);
return hdw->flag_init_ok;
}
@@ -1868,6 +1936,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->encoder_wait_timer.data = (unsigned long)hdw;
hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
+ init_timer(&hdw->encoder_run_timer);
+ hdw->encoder_run_timer.data = (unsigned long)hdw;
+ hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
+
hdw->master_state = PVR2_STATE_DEAD;
init_waitqueue_head(&hdw->state_wait_data);
@@ -1885,6 +1957,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
hdw->input_avail_mask = m;
+ hdw->input_allowed_mask = hdw->input_avail_mask;
/* If not a hybrid device, pathway_state never changes. So
initialize it here to what it should forever be. */
@@ -2075,6 +2148,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
fail:
if (hdw) {
del_timer_sync(&hdw->quiescent_timer);
+ del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->workqueue) {
flush_workqueue(hdw->workqueue);
@@ -2137,6 +2211,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
hdw->workqueue = NULL;
}
del_timer_sync(&hdw->quiescent_timer);
+ del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->fw_buffer) {
kfree(hdw->fw_buffer);
@@ -2357,7 +2432,7 @@ static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw)
for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
- if (cptr->info->is_dirty == 0) continue;
+ if (!cptr->info->is_dirty) continue;
if (!cptr->info->is_dirty(cptr)) continue;
commit_flag = !0;
@@ -2419,7 +2494,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
}
}
- if (hdw->input_dirty &&
+ if (hdw->input_dirty && hdw->state_pathway_ok &&
(((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
hdw->pathway_state)) {
@@ -2484,6 +2559,20 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
hdw->active_stream_type = hdw->desired_stream_type;
}
+ if (hdw->hdw_desc->signal_routing_scheme ==
+ PVR2_ROUTING_SCHEME_GOTVIEW) {
+ u32 b;
+ /* Handle GOTVIEW audio switching */
+ pvr2_hdw_gpio_get_out(hdw,&b);
+ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ /* Set GPIO 11 */
+ pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
+ } else {
+ /* Clear GPIO 11 */
+ pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
+ }
+ }
+
/* Now execute i2c core update */
pvr2_i2c_core_sync(hdw);
@@ -2706,7 +2795,7 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw,
u16 address;
unsigned int pipe;
LOCK_TAKE(hdw->big_lock); do {
- if ((hdw->fw_buffer == 0) == !enable_flag) break;
+ if ((hdw->fw_buffer == NULL) == !enable_flag) break;
if (!enable_flag) {
pvr2_trace(PVR2_TRACE_FIRMWARE,
@@ -2775,7 +2864,7 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw,
/* Return true if we're in a mode for retrieval CPU firmware */
int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
{
- return hdw->fw_buffer != 0;
+ return hdw->fw_buffer != NULL;
}
@@ -3185,6 +3274,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
read_data,read_len);
}
+
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
+{
+ int ret;
+ unsigned int cnt = 1;
+ unsigned int args = 0;
+ LOCK_TAKE(hdw->ctl_lock);
+ hdw->cmd_buffer[0] = cmdcode & 0xffu;
+ args = (cmdcode >> 8) & 0xffu;
+ args = (args > 2) ? 2 : args;
+ if (args) {
+ cnt += args;
+ hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
+ if (args > 1) {
+ hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
+ }
+ }
+ if (pvrusb2_debug & PVR2_TRACE_INIT) {
+ unsigned int idx;
+ unsigned int ccnt,bcnt;
+ char tbuf[50];
+ cmdcode &= 0xffu;
+ bcnt = 0;
+ ccnt = scnprintf(tbuf+bcnt,
+ sizeof(tbuf)-bcnt,
+ "Sending FX2 command 0x%x",cmdcode);
+ bcnt += ccnt;
+ for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
+ if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
+ ccnt = scnprintf(tbuf+bcnt,
+ sizeof(tbuf)-bcnt,
+ " \"%s\"",
+ pvr2_fx2cmd_desc[idx].desc);
+ bcnt += ccnt;
+ break;
+ }
+ }
+ if (args) {
+ ccnt = scnprintf(tbuf+bcnt,
+ sizeof(tbuf)-bcnt,
+ " (%u",hdw->cmd_buffer[1]);
+ bcnt += ccnt;
+ if (args > 1) {
+ ccnt = scnprintf(tbuf+bcnt,
+ sizeof(tbuf)-bcnt,
+ ",%u",hdw->cmd_buffer[2]);
+ bcnt += ccnt;
+ }
+ ccnt = scnprintf(tbuf+bcnt,
+ sizeof(tbuf)-bcnt,
+ ")");
+ bcnt += ccnt;
+ }
+ pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
+ }
+ ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
+ LOCK_GIVE(hdw->ctl_lock);
+ return ret;
+}
+
+
int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
{
int ret;
@@ -3292,40 +3442,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
{
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
- hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
+ return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
}
-static int pvr2_hdw_cmd_power_ctrl(struct pvr2_hdw *hdw, int onoff)
-{
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- if (onoff) {
- pvr2_trace(PVR2_TRACE_INIT, "Requesting powerup");
- hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
- } else {
- pvr2_trace(PVR2_TRACE_INIT, "Requesting powerdown");
- hdw->cmd_buffer[0] = FX2CMD_POWER_OFF;
- }
- status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
-}
-
int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
{
- return pvr2_hdw_cmd_power_ctrl(hdw, 1);
+ return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
}
+
int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
{
- return pvr2_hdw_cmd_power_ctrl(hdw, 0);
+ return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
}
@@ -3352,55 +3481,29 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
{
- int status;
-
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,
- "Issuing fe demod wake command (%s)",
- (onoff ? "on" : "off"));
- hdw->flag_ok = !0;
- hdw->cmd_buffer[0] = FX2CMD_HCW_DEMOD_RESETIN;
- hdw->cmd_buffer[1] = onoff;
- status = pvr2_send_request(hdw, hdw->cmd_buffer, 2, NULL, 0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
-
- return status;
+ hdw->flag_ok = !0;
+ return pvr2_issue_simple_cmd(hdw,
+ FX2CMD_HCW_DEMOD_RESETIN |
+ (1 << 8) |
+ ((onoff ? 1 : 0) << 16));
}
static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
{
- int status;
-
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,
- "Issuing fe power command to CPLD (%s)",
- (onoff ? "on" : "off"));
- hdw->flag_ok = !0;
- hdw->cmd_buffer[0] =
- (onoff ? FX2CMD_ONAIR_DTV_POWER_ON :
- FX2CMD_ONAIR_DTV_POWER_OFF);
- status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
-
- return status;
+ hdw->flag_ok = !0;
+ return pvr2_issue_simple_cmd(hdw,(onoff ?
+ FX2CMD_ONAIR_DTV_POWER_ON :
+ FX2CMD_ONAIR_DTV_POWER_OFF));
}
static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
int onoff)
{
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,
- "Issuing onair digital setup command (%s)",
- (onoff ? "on" : "off"));
- hdw->cmd_buffer[0] =
- (onoff ? FX2CMD_ONAIR_DTV_STREAMING_ON :
- FX2CMD_ONAIR_DTV_STREAMING_OFF);
- status = pvr2_send_request(hdw, hdw->cmd_buffer, 1, NULL, 0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
+ return pvr2_issue_simple_cmd(hdw,(onoff ?
+ FX2CMD_ONAIR_DTV_STREAMING_ON :
+ FX2CMD_ONAIR_DTV_STREAMING_OFF));
}
@@ -3430,9 +3533,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
/* Supposedly we should always have the power on whether in
digital or analog mode. But for now do what appears to
work... */
- if (digitalFl) pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,!0);
- pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,digitalFl);
- if (!digitalFl) pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,0);
+ pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
break;
default: break;
}
@@ -3442,7 +3543,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
}
-void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
+static void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
{
/* change some GPIO data
*
@@ -3490,24 +3591,43 @@ static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
/* Stop / start video stream transport */
static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
{
- int status,cc;
- if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
- hdw->hdw_desc->digital_control_scheme ==
- PVR2_DIGITAL_SCHEME_HAUPPAUGE) {
- cc = (runFl ?
- FX2CMD_HCW_DTV_STREAMING_ON :
- FX2CMD_HCW_DTV_STREAMING_OFF);
- } else {
- cc = (runFl ?
- FX2CMD_STREAMING_ON :
- FX2CMD_STREAMING_OFF);
+ int ret;
+
+ /* If we're in analog mode, then just issue the usual analog
+ command. */
+ if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+ return pvr2_issue_simple_cmd(hdw,
+ (runFl ?
+ FX2CMD_STREAMING_ON :
+ FX2CMD_STREAMING_OFF));
+ /*Note: Not reached */
}
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = cc;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
+ if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
+ /* Whoops, we don't know what mode we're in... */
+ return -EINVAL;
+ }
+
+ /* To get here we have to be in digital mode. The mechanism here
+ is unfortunately different for different vendors. So we switch
+ on the device's digital scheme attribute in order to figure out
+ what to do. */
+ switch (hdw->hdw_desc->digital_control_scheme) {
+ case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+ return pvr2_issue_simple_cmd(hdw,
+ (runFl ?
+ FX2CMD_HCW_DTV_STREAMING_ON :
+ FX2CMD_HCW_DTV_STREAMING_OFF));
+ case PVR2_DIGITAL_SCHEME_ONAIR:
+ ret = pvr2_issue_simple_cmd(hdw,
+ (runFl ?
+ FX2CMD_STREAMING_ON :
+ FX2CMD_STREAMING_OFF));
+ if (ret) return ret;
+ return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
+ default:
+ return -EINVAL;
+ }
}
@@ -3538,7 +3658,12 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
if (hdw->state_encoder_config) return 0;
if (hdw->state_decoder_run) return 0;
if (hdw->state_usbstream_run) return 0;
- if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) return 0;
+ if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
+ if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
+ } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
+ return 0;
+ }
+
if (pvr2_upload_firmware2(hdw) < 0) {
hdw->flag_tripped = !0;
trace_stbit("flag_tripped",hdw->flag_tripped);
@@ -3598,7 +3723,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
the encoder. */
if (!hdw->state_encoder_waitok) {
hdw->encoder_wait_timer.expires =
- jiffies + (HZ*50/1000);
+ jiffies +
+ (HZ * TIME_MSEC_ENCODER_WAIT
+ / 1000);
add_timer(&hdw->encoder_wait_timer);
}
}
@@ -3615,23 +3742,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
}
+/* Return true if the encoder should not be running. */
+static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
+{
+ if (!hdw->state_encoder_ok) {
+ /* Encoder isn't healthy at the moment, so stop it. */
+ return !0;
+ }
+ if (!hdw->state_pathway_ok) {
+ /* Mode is not understood at the moment (i.e. it wants to
+ change), so encoder must be stopped. */
+ return !0;
+ }
+
+ switch (hdw->pathway_state) {
+ case PVR2_PATHWAY_ANALOG:
+ if (!hdw->state_decoder_run) {
+ /* We're in analog mode and the decoder is not
+ running; thus the encoder should be stopped as
+ well. */
+ return !0;
+ }
+ break;
+ case PVR2_PATHWAY_DIGITAL:
+ if (hdw->state_encoder_runok) {
+ /* This is a funny case. We're in digital mode so
+ really the encoder should be stopped. However
+ if it really is running, only kill it after
+ runok has been set. This gives a chance for the
+ onair quirk to function (encoder must run
+ briefly first, at least once, before onair
+ digital streaming can work). */
+ return !0;
+ }
+ break;
+ default:
+ /* Unknown mode; so encoder should be stopped. */
+ return !0;
+ }
+
+ /* If we get here, we haven't found a reason to stop the
+ encoder. */
+ return 0;
+}
+
+
+/* Return true if the encoder should be running. */
+static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
+{
+ if (!hdw->state_encoder_ok) {
+ /* Don't run the encoder if it isn't healthy... */
+ return 0;
+ }
+ if (!hdw->state_pathway_ok) {
+ /* Don't run the encoder if we don't (yet) know what mode
+ we need to be in... */
+ return 0;
+ }
+
+ switch (hdw->pathway_state) {
+ case PVR2_PATHWAY_ANALOG:
+ if (hdw->state_decoder_run) {
+ /* In analog mode, if the decoder is running, then
+ run the encoder. */
+ return !0;
+ }
+ break;
+ case PVR2_PATHWAY_DIGITAL:
+ if ((hdw->hdw_desc->digital_control_scheme ==
+ PVR2_DIGITAL_SCHEME_ONAIR) &&
+ !hdw->state_encoder_runok) {
+ /* This is a quirk. OnAir hardware won't stream
+ digital until the encoder has been run at least
+ once, for a minimal period of time (empiricially
+ measured to be 1/4 second). So if we're on
+ OnAir hardware and the encoder has never been
+ run at all, then start the encoder. Normal
+ state machine logic in the driver will
+ automatically handle the remaining bits. */
+ return !0;
+ }
+ break;
+ default:
+ /* For completeness (unknown mode; encoder won't run ever) */
+ break;
+ }
+ /* If we get here, then we haven't found any reason to run the
+ encoder, so don't run it. */
+ return 0;
+}
+
+
/* Evaluate whether or not state_encoder_run can change */
static int state_eval_encoder_run(struct pvr2_hdw *hdw)
{
if (hdw->state_encoder_run) {
+ if (!state_check_disable_encoder_run(hdw)) return 0;
if (hdw->state_encoder_ok) {
- if (hdw->state_decoder_run &&
- hdw->state_pathway_ok) return 0;
+ del_timer_sync(&hdw->encoder_run_timer);
if (pvr2_encoder_stop(hdw) < 0) return !0;
}
hdw->state_encoder_run = 0;
} else {
- if (!hdw->state_encoder_ok) return 0;
- if (!hdw->state_decoder_run) return 0;
- if (!hdw->state_pathway_ok) return 0;
- if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) return 0;
+ if (!state_check_enable_encoder_run(hdw)) return 0;
if (pvr2_encoder_start(hdw) < 0) return !0;
hdw->state_encoder_run = !0;
+ if (!hdw->state_encoder_runok) {
+ hdw->encoder_run_timer.expires =
+ jiffies + (HZ * TIME_MSEC_ENCODER_OK / 1000);
+ add_timer(&hdw->encoder_run_timer);
+ }
}
trace_stbit("state_encoder_run",hdw->state_encoder_run);
return !0;
@@ -3660,6 +3880,19 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
}
+/* Timeout function for encoder run timer. */
+static void pvr2_hdw_encoder_run_timeout(unsigned long data)
+{
+ struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+ if (!hdw->state_encoder_runok) {
+ hdw->state_encoder_runok = !0;
+ trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+ hdw->state_stale = !0;
+ queue_work(hdw->workqueue,&hdw->workpoll);
+ }
+}
+
+
/* Evaluate whether or not state_decoder_run can change */
static int state_eval_decoder_run(struct pvr2_hdw *hdw)
{
@@ -3691,7 +3924,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
but before we did the pending check. */
if (!hdw->state_decoder_quiescent) {
hdw->quiescent_timer.expires =
- jiffies + (HZ*50/1000);
+ jiffies +
+ (HZ * TIME_MSEC_DECODER_WAIT
+ / 1000);
add_timer(&hdw->quiescent_timer);
}
}
@@ -3723,14 +3958,19 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
{
if (hdw->state_usbstream_run) {
+ int fl = !0;
if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
- if (hdw->state_encoder_ok &&
- hdw->state_encoder_run &&
- hdw->state_pathway_ok) return 0;
- } else {
- if (hdw->state_pipeline_req &&
- !hdw->state_pipeline_pause &&
- hdw->state_pathway_ok) return 0;
+ fl = (hdw->state_encoder_ok &&
+ hdw->state_encoder_run);
+ } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+ (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+ fl = hdw->state_encoder_ok;
+ }
+ if (fl &&
+ hdw->state_pipeline_req &&
+ !hdw->state_pipeline_pause &&
+ hdw->state_pathway_ok) {
+ return 0;
}
pvr2_hdw_cmd_usbstream(hdw,0);
hdw->state_usbstream_run = 0;
@@ -3741,6 +3981,19 @@ static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
if (!hdw->state_encoder_ok ||
!hdw->state_encoder_run) return 0;
+ } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+ (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+ if (!hdw->state_encoder_ok) return 0;
+ if (hdw->state_encoder_run) return 0;
+ if (hdw->hdw_desc->digital_control_scheme ==
+ PVR2_DIGITAL_SCHEME_ONAIR) {
+ /* OnAir digital receivers won't stream
+ unless the analog encoder has run first.
+ Why? I have no idea. But don't even
+ try until we know the analog side is
+ known to have run. */
+ if (!hdw->state_encoder_runok) return 0;
+ }
}
if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
hdw->state_usbstream_run = !0;
@@ -3836,6 +4089,24 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
}
+static unsigned int print_input_mask(unsigned int msk,
+ char *buf,unsigned int acnt)
+{
+ unsigned int idx,ccnt;
+ unsigned int tcnt = 0;
+ for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
+ if (!((1 << idx) & msk)) continue;
+ ccnt = scnprintf(buf+tcnt,
+ acnt-tcnt,
+ "%s%s",
+ (tcnt ? ", " : ""),
+ control_values_input[idx]);
+ tcnt += ccnt;
+ }
+ return tcnt;
+}
+
+
static const char *pvr2_pathway_state_name(int id)
{
switch (id) {
@@ -3884,22 +4155,65 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
(hdw->state_encoder_ok ?
"" : " <encode:init>"),
(hdw->state_encoder_run ?
- " <encode:run>" : " <encode:stop>"),
+ (hdw->state_encoder_runok ?
+ " <encode:run>" :
+ " <encode:firstrun>") :
+ (hdw->state_encoder_runok ?
+ " <encode:stop>" :
+ " <encode:virgin>")),
(hdw->state_encoder_config ?
" <encode:configok>" :
(hdw->state_encoder_waitok ?
- "" : " <encode:wait>")),
+ "" : " <encode:waitok>")),
(hdw->state_usbstream_run ?
" <usb:run>" : " <usb:stop>"),
(hdw->state_pathway_ok ?
" <pathway:ok>" : ""));
- break;
case 3:
return scnprintf(
buf,acnt,
"state: %s",
pvr2_get_state_name(hdw->master_state));
- break;
+ case 4: {
+ unsigned int tcnt = 0;
+ unsigned int ccnt;
+
+ ccnt = scnprintf(buf,
+ acnt,
+ "Hardware supported inputs: ");
+ tcnt += ccnt;
+ tcnt += print_input_mask(hdw->input_avail_mask,
+ buf+tcnt,
+ acnt-tcnt);
+ if (hdw->input_avail_mask != hdw->input_allowed_mask) {
+ ccnt = scnprintf(buf+tcnt,
+ acnt-tcnt,
+ "; allowed inputs: ");
+ tcnt += ccnt;
+ tcnt += print_input_mask(hdw->input_allowed_mask,
+ buf+tcnt,
+ acnt-tcnt);
+ }
+ return tcnt;
+ }
+ case 5: {
+ struct pvr2_stream_stats stats;
+ if (!hdw->vid_stream) break;
+ pvr2_stream_get_stats(hdw->vid_stream,
+ &stats,
+ 0);
+ return scnprintf(
+ buf,acnt,
+ "Bytes streamed=%u"
+ " URBs: queued=%u idle=%u ready=%u"
+ " processed=%u failed=%u",
+ stats.bytes_processed,
+ stats.buffers_in_queue,
+ stats.buffers_in_idle,
+ stats.buffers_in_ready,
+ stats.buffers_processed,
+ stats.buffers_failed);
+ }
default: break;
}
return 0;
@@ -3963,7 +4277,9 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
st = PVR2_STATE_DEAD;
} else if (hdw->fw1_state != FW1_STATE_OK) {
st = PVR2_STATE_COLD;
- } else if (analog_mode && !hdw->state_encoder_ok) {
+ } else if ((analog_mode ||
+ hdw->hdw_desc->flag_digital_requires_cx23416) &&
+ !hdw->state_encoder_ok) {
st = PVR2_STATE_WARM;
} else if (hdw->flag_tripped ||
(analog_mode && hdw->flag_decoder_missed)) {
@@ -4009,6 +4325,7 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
queue_work(hdw->workqueue,&hdw->workpoll);
}
+#if 0
void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
struct pvr2_hdw_debug_info *ptr)
@@ -4050,6 +4367,7 @@ void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
} while(0); LOCK_GIVE(hdw->ctl_lock);
}
+#endif /* 0 */
int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
{
@@ -4116,6 +4434,74 @@ unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
}
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
+{
+ return hdw->input_allowed_mask;
+}
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
+{
+ if (hdw->input_val != v) {
+ hdw->input_val = v;
+ hdw->input_dirty = !0;
+ }
+
+ /* Handle side effects - if we switch to a mode that needs the RF
+ tuner, then select the right frequency choice as well and mark
+ it dirty. */
+ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ hdw->freqSelector = 0;
+ hdw->freqDirty = !0;
+ } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
+ (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
+ hdw->freqSelector = 1;
+ hdw->freqDirty = !0;
+ }
+ return 0;
+}
+
+
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
+ unsigned int change_mask,
+ unsigned int change_val)
+{
+ int ret = 0;
+ unsigned int nv,m,idx;
+ LOCK_TAKE(hdw->big_lock);
+ do {
+ nv = hdw->input_allowed_mask & ~change_mask;
+ nv |= (change_val & change_mask);
+ nv &= hdw->input_avail_mask;
+ if (!nv) {
+ /* No legal modes left; return error instead. */
+ ret = -EPERM;
+ break;
+ }
+ hdw->input_allowed_mask = nv;
+ if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
+ /* Current mode is still in the allowed mask, so
+ we're done. */
+ break;
+ }
+ /* Select and switch to a mode that is still in the allowed
+ mask */
+ if (!hdw->input_allowed_mask) {
+ /* Nothing legal; give up */
+ break;
+ }
+ m = hdw->input_allowed_mask;
+ for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+ if (!((1 << idx) & m)) continue;
+ pvr2_hdw_set_input(hdw,idx);
+ break;
+ }
+ } while (0);
+ LOCK_GIVE(hdw->big_lock);
+ return ret;
+}
+
+
/* Find I2C address of eeprom */
static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
{
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index e3e965546..4e60f6262 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -92,9 +91,6 @@ enum pvr2_v4l_type {
/* Translate configuration enum to a string label */
const char *pvr2_config_get_name(enum pvr2_config);
-/* Translate a master state enum to a string label */
-const char *pvr2_hdw_get_state_name(unsigned int);
-
struct pvr2_hdw;
/* Create and return a structure for interacting with the underlying
@@ -158,6 +154,19 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
* will be according to PVR_CVAL_INPUT_xxxx definitions. */
unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
+/* Return a bit mask of allowed input selections for this device. Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
+
+/* Change the set of allowed input selections for this device. Both
+ change_mask and change_valu are mask bits according to
+ PVR_CVAL_INPUT_xxxx definitions. The change_mask parameter indicate
+ which settings are being changed and the change_val parameter indicates
+ whether corresponding settings are being set or cleared. */
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
+ unsigned int change_mask,
+ unsigned int change_val);
+
/* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index 4b0ded374..25e611b2e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index 7ce929be8..d715c80ef 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index c838df616..7fa38683b 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index ddf357d1b..362ec49f5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index bd0807b90..6ef7a1c0e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-io.c b/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
index 7b3be67f5..bf7bd5906 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -100,6 +99,10 @@ struct pvr2_stream {
/* Tracking state for tolerating errors */
unsigned int fail_count;
unsigned int fail_tolerance;
+
+ unsigned int buffers_processed;
+ unsigned int buffers_failed;
+ unsigned int bytes_processed;
};
struct pvr2_buffer {
@@ -470,6 +473,8 @@ static void buffer_complete(struct urb *urb)
(urb->status == -ENOENT) ||
(urb->status == -ECONNRESET) ||
(urb->status == -ESHUTDOWN)) {
+ (sp->buffers_processed)++;
+ sp->bytes_processed += urb->actual_length;
bp->used_count = urb->actual_length;
if (sp->fail_count) {
pvr2_trace(PVR2_TRACE_TOLERANCE,
@@ -481,11 +486,13 @@ static void buffer_complete(struct urb *urb)
// We can tolerate this error, because we're below the
// threshold...
(sp->fail_count)++;
+ (sp->buffers_failed)++;
pvr2_trace(PVR2_TRACE_TOLERANCE,
"stream %p ignoring error %d"
" - fail count increased to %u",
sp,urb->status,sp->fail_count);
} else {
+ (sp->buffers_failed)++;
bp->status = urb->status;
}
spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -539,6 +546,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
} while(0); mutex_unlock(&sp->mutex);
}
+void pvr2_stream_get_stats(struct pvr2_stream *sp,
+ struct pvr2_stream_stats *stats,
+ int zero_counts)
+{
+ unsigned long irq_flags;
+ spin_lock_irqsave(&sp->list_lock,irq_flags);
+ if (stats) {
+ stats->buffers_in_queue = sp->q_count;
+ stats->buffers_in_idle = sp->i_count;
+ stats->buffers_in_ready = sp->r_count;
+ stats->buffers_processed = sp->buffers_processed;
+ stats->buffers_failed = sp->buffers_failed;
+ stats->bytes_processed = sp->bytes_processed;
+ }
+ if (zero_counts) {
+ sp->buffers_processed = 0;
+ sp->buffers_failed = 0;
+ sp->bytes_processed = 0;
+ }
+ spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
/* Query / set the nominal buffer count */
int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
{
@@ -603,7 +632,7 @@ void pvr2_stream_kill(struct pvr2_stream *sp)
struct pvr2_buffer *bp;
mutex_lock(&sp->mutex); do {
pvr2_stream_internal_flush(sp);
- while ((bp = pvr2_stream_get_ready_buffer(sp)) != 0) {
+ while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
pvr2_buffer_set_idle(bp);
}
if (sp->buffer_total_count != sp->buffer_target_count) {
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-io.h b/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
index b43e5f4cf..0a4b9a114 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -36,6 +35,15 @@ enum pvr2_buffer_state {
struct pvr2_stream;
struct pvr2_buffer;
+struct pvr2_stream_stats {
+ unsigned int buffers_in_queue;
+ unsigned int buffers_in_idle;
+ unsigned int buffers_in_ready;
+ unsigned int buffers_processed;
+ unsigned int buffers_failed;
+ unsigned int bytes_processed;
+};
+
/* Initialize / tear down stream structure */
struct pvr2_stream *pvr2_stream_create(void);
void pvr2_stream_destroy(struct pvr2_stream *);
@@ -45,6 +53,9 @@ void pvr2_stream_setup(struct pvr2_stream *,
void pvr2_stream_set_callback(struct pvr2_stream *,
pvr2_stream_callback func,
void *data);
+void pvr2_stream_get_stats(struct pvr2_stream *,
+ struct pvr2_stream_stats *,
+ int zero_counts);
/* Query / set the nominal buffer count */
int pvr2_stream_get_buffer_count(struct pvr2_stream *);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index aef12fecb..fb3ad639f 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -174,7 +173,7 @@ static int pvr2_ioread_start(struct pvr2_ioread *cp)
if (!(cp->stream)) return 0;
pvr2_trace(PVR2_TRACE_START_STOP,
"/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
- while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != 0) {
+ while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) {
stat = pvr2_buffer_queue(bp);
if (stat < 0) {
pvr2_trace(PVR2_TRACE_DATA_FLOW,
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
index fe397e987..f98dafac7 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ioread.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
index 59f8d7298..ff85b381c 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -61,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
{
/* Create association with v4l layer */
pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+ /* Create association with dvb layer */
+ pvr2_dvb_create(pvr);
+#endif
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_create(pvr,class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -125,6 +128,12 @@ static int __init pvr_init(void)
pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+ ret = pvr2_context_global_init();
+ if (ret != 0) {
+ pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
+ return ret;
+ }
+
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
class_ptr = pvr2_sysfs_class_create();
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@@ -136,6 +145,8 @@ static int __init pvr_init(void)
if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
pvrusb2_debug,pvrusb2_debug);
+ pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
+
return ret;
}
@@ -148,6 +159,10 @@ static void __exit pvr_exit(void)
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_class_destroy(class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+ pvr2_context_global_done();
+
+ pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
}
module_init(pvr_init);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-std.c b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c
index bd7a8de95..1e91401ba 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-std.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-std.h b/linux/drivers/media/video/pvrusb2/pvrusb2-std.h
index 07c399375..a35c53d0b 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-std.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-std.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index f672473dd..f6ace8abe 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
@@ -21,7 +20,6 @@
#include <linux/string.h>
#include <linux/slab.h>
-#include <asm/semaphore.h>
#include "pvrusb2-sysfs.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-debug.h"
@@ -73,6 +71,7 @@ struct pvr2_sysfs_ctl_item {
struct device_attribute attr_val;
struct device_attribute attr_custom;
struct pvr2_ctrl *cptr;
+ int ctl_id;
struct pvr2_sysfs *chptr;
struct pvr2_sysfs_ctl_item *item_next;
struct attribute *attr_gen[7];
@@ -85,38 +84,29 @@ struct pvr2_sysfs_class {
struct class class;
};
-static ssize_t show_name(int id,struct device *class_dev,char *buf)
+static ssize_t show_name(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
const char *name;
-
- 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;
-
- name = pvr2_ctrl_get_desc(cptr);
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);
-
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
+ name = pvr2_ctrl_get_desc(cip->cptr);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
+ cip->chptr, cip->ctl_id, name);
if (!name) return -EINVAL;
-
- return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+ return scnprintf(buf, PAGE_SIZE, "%s\n", name);
}
-static ssize_t show_type(int id,struct device *class_dev,char *buf)
+static ssize_t show_type(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
const char *name;
enum pvr2_ctl_type tp;
-
- 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;
-
- tp = pvr2_ctrl_get_type(cptr);
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
+ tp = pvr2_ctrl_get_type(cip->cptr);
switch (tp) {
case pvr2_ctl_int: name = "integer"; break;
case pvr2_ctl_enum: name = "enum"; break;
@@ -124,403 +114,178 @@ static ssize_t show_type(int id,struct device *class_dev,char *buf)
case pvr2_ctl_bool: name = "boolean"; break;
default: name = "?"; break;
}
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name);
-
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
+ cip->chptr, cip->ctl_id, name);
if (!name) return -EINVAL;
-
- return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+ return scnprintf(buf, PAGE_SIZE, "%s\n", name);
}
-static ssize_t show_min(int id,struct device *class_dev,char *buf)
+static ssize_t show_min(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
long val;
-
- 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;
- val = pvr2_ctrl_get_min(cptr);
-
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
-
- return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
+ val = pvr2_ctrl_get_min(cip->cptr);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
+ cip->chptr, cip->ctl_id, val);
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
}
-static ssize_t show_max(int id,struct device *class_dev,char *buf)
+static ssize_t show_max(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
long val;
-
- 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;
- val = pvr2_ctrl_get_max(cptr);
-
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
-
- return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
+ val = pvr2_ctrl_get_max(cip->cptr);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
+ cip->chptr, cip->ctl_id, val);
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
}
-static ssize_t show_val_norm(int id,struct device *class_dev,char *buf)
+static ssize_t show_val_norm(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
- int val,ret;
+ struct pvr2_sysfs_ctl_item *cip;
+ int val;
+ int ret;
unsigned int cnt = 0;
-
- 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;
-
- ret = pvr2_ctrl_get_value(cptr,&val);
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
+ ret = pvr2_ctrl_get_value(cip->cptr, &val);
if (ret < 0) return ret;
-
- ret = pvr2_ctrl_value_to_sym(cptr,~0,val,
- buf,PAGE_SIZE-1,&cnt);
-
+ ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
+ buf, PAGE_SIZE - 1, &cnt);
pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
- sfp,id,cnt,buf,val);
+ cip->chptr, cip->ctl_id, cnt, buf, val);
buf[cnt] = '\n';
return cnt+1;
}
-static ssize_t show_val_custom(int id,struct device *class_dev,char *buf)
+static ssize_t show_val_custom(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
- int val,ret;
+ struct pvr2_sysfs_ctl_item *cip;
+ int val;
+ int ret;
unsigned int cnt = 0;
-
- 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;
-
- ret = pvr2_ctrl_get_value(cptr,&val);
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
+ ret = pvr2_ctrl_get_value(cip->cptr, &val);
if (ret < 0) return ret;
-
- ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val,
- buf,PAGE_SIZE-1,&cnt);
-
+ ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
+ buf, PAGE_SIZE - 1, &cnt);
pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
- sfp,id,cnt,buf,val);
+ cip->chptr, cip->ctl_id, cnt, buf, val);
buf[cnt] = '\n';
return cnt+1;
}
-static ssize_t show_enum(int id,struct device *class_dev,char *buf)
+static ssize_t show_enum(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
long val;
- unsigned int bcnt,ccnt,ecnt;
-
- 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;
- ecnt = pvr2_ctrl_get_cnt(cptr);
+ unsigned int bcnt, ccnt, ecnt;
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
+ ecnt = pvr2_ctrl_get_cnt(cip->cptr);
bcnt = 0;
for (val = 0; val < ecnt; val++) {
- pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+ pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
+ PAGE_SIZE - bcnt, &ccnt);
if (!ccnt) continue;
bcnt += ccnt;
if (bcnt >= PAGE_SIZE) break;
buf[bcnt] = '\n';
bcnt++;
}
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
+ cip->chptr, cip->ctl_id);
return bcnt;
}
-static ssize_t show_bits(int id,struct device *class_dev,char *buf)
+static ssize_t show_bits(struct device *class_dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct pvr2_ctrl *cptr;
- struct pvr2_sysfs *sfp;
- int valid_bits,msk;
- unsigned int bcnt,ccnt;
-
- 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;
- valid_bits = pvr2_ctrl_get_mask(cptr);
+ struct pvr2_sysfs_ctl_item *cip;
+ int valid_bits, msk;
+ unsigned int bcnt, ccnt;
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
+ valid_bits = pvr2_ctrl_get_mask(cip->cptr);
bcnt = 0;
for (msk = 1; valid_bits; msk <<= 1) {
if (!(msk & valid_bits)) continue;
valid_bits &= ~msk;
- pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+ pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
+ PAGE_SIZE - bcnt, &ccnt);
bcnt += ccnt;
if (bcnt >= PAGE_SIZE) break;
buf[bcnt] = '\n';
bcnt++;
}
- pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);
+ pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
+ cip->chptr, cip->ctl_id);
return bcnt;
}
-static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
+static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
const char *buf,unsigned int count)
{
- struct pvr2_ctrl *cptr;
int ret;
int mask,val;
-
- cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
if (customfl) {
- ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val);
+ ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
+ &mask, &val);
} else {
- ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val);
+ ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
+ &mask, &val);
}
if (ret < 0) return ret;
- ret = pvr2_ctrl_set_mask_value(cptr,mask,val);
- pvr2_hdw_commit_ctl(sfp->channel.hdw);
+ ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
+ pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
return ret;
}
-static ssize_t store_val_norm(int id,struct device *class_dev,
- const char *buf,size_t count)
+static ssize_t store_val_norm(struct device *class_dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
- sfp,id,(int)count,buf);
- ret = store_val_any(id,0,sfp,buf,count);
+ cip->chptr, cip->ctl_id, (int)count, buf);
+ ret = store_val_any(cip, 0, buf, count);
if (!ret) ret = count;
return ret;
}
-static ssize_t store_val_custom(int id,struct device *class_dev,
- const char *buf,size_t count)
+static ssize_t store_val_custom(struct device *class_dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct pvr2_sysfs *sfp;
+ struct pvr2_sysfs_ctl_item *cip;
int ret;
- sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+ cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
- sfp,id,(int)count,buf);
- ret = store_val_any(id,1,sfp,buf,count);
+ cip->chptr, cip->ctl_id, (int)count, buf);
+ ret = store_val_any(cip, 1, buf, count);
if (!ret) ret = count;
return ret;
}
-/*
- Mike Isely <isely@pobox.com> 30-April-2005
-
- This next batch of horrible preprocessor hackery is needed because the
- 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
- id into the show / store functions themselves and pick the function based
- on the control id we're setting up. These macros try to ease the pain.
- Yuck.
-*/
-
-#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
-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 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) \
-CREATE_SHOW_INSTANCE(show_name,ctl_id) \
-CREATE_SHOW_INSTANCE(show_type,ctl_id) \
-CREATE_SHOW_INSTANCE(show_min,ctl_id) \
-CREATE_SHOW_INSTANCE(show_max,ctl_id) \
-CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
-CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
-CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
-CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
-CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
-CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
-
-CREATE_BATCH(0)
-CREATE_BATCH(1)
-CREATE_BATCH(2)
-CREATE_BATCH(3)
-CREATE_BATCH(4)
-CREATE_BATCH(5)
-CREATE_BATCH(6)
-CREATE_BATCH(7)
-CREATE_BATCH(8)
-CREATE_BATCH(9)
-CREATE_BATCH(10)
-CREATE_BATCH(11)
-CREATE_BATCH(12)
-CREATE_BATCH(13)
-CREATE_BATCH(14)
-CREATE_BATCH(15)
-CREATE_BATCH(16)
-CREATE_BATCH(17)
-CREATE_BATCH(18)
-CREATE_BATCH(19)
-CREATE_BATCH(20)
-CREATE_BATCH(21)
-CREATE_BATCH(22)
-CREATE_BATCH(23)
-CREATE_BATCH(24)
-CREATE_BATCH(25)
-CREATE_BATCH(26)
-CREATE_BATCH(27)
-CREATE_BATCH(28)
-CREATE_BATCH(29)
-CREATE_BATCH(30)
-CREATE_BATCH(31)
-CREATE_BATCH(32)
-CREATE_BATCH(33)
-CREATE_BATCH(34)
-CREATE_BATCH(35)
-CREATE_BATCH(36)
-CREATE_BATCH(37)
-CREATE_BATCH(38)
-CREATE_BATCH(39)
-CREATE_BATCH(40)
-CREATE_BATCH(41)
-CREATE_BATCH(42)
-CREATE_BATCH(43)
-CREATE_BATCH(44)
-CREATE_BATCH(45)
-CREATE_BATCH(46)
-CREATE_BATCH(47)
-CREATE_BATCH(48)
-CREATE_BATCH(49)
-CREATE_BATCH(50)
-CREATE_BATCH(51)
-CREATE_BATCH(52)
-CREATE_BATCH(53)
-CREATE_BATCH(54)
-CREATE_BATCH(55)
-CREATE_BATCH(56)
-CREATE_BATCH(57)
-CREATE_BATCH(58)
-CREATE_BATCH(59)
-
-struct pvr2_sysfs_func_set {
- 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 device *,
- struct device_attribute *attr, char *);
- ssize_t (*store_val_custom)(struct device *,
- struct device_attribute *attr,
- const char *,size_t);
-};
-
-#define INIT_BATCH(ctl_id) \
-[ctl_id] = { \
- .show_name = show_name_##ctl_id, \
- .show_type = show_type_##ctl_id, \
- .show_min = show_min_##ctl_id, \
- .show_max = show_max_##ctl_id, \
- .show_enum = show_enum_##ctl_id, \
- .show_bits = show_bits_##ctl_id, \
- .show_val_norm = show_val_norm_##ctl_id, \
- .store_val_norm = store_val_norm_##ctl_id, \
- .show_val_custom = show_val_custom_##ctl_id, \
- .store_val_custom = store_val_custom_##ctl_id, \
-} \
-
-static struct pvr2_sysfs_func_set funcs[] = {
- INIT_BATCH(0),
- INIT_BATCH(1),
- INIT_BATCH(2),
- INIT_BATCH(3),
- INIT_BATCH(4),
- INIT_BATCH(5),
- INIT_BATCH(6),
- INIT_BATCH(7),
- INIT_BATCH(8),
- INIT_BATCH(9),
- INIT_BATCH(10),
- INIT_BATCH(11),
- INIT_BATCH(12),
- INIT_BATCH(13),
- INIT_BATCH(14),
- INIT_BATCH(15),
- INIT_BATCH(16),
- INIT_BATCH(17),
- INIT_BATCH(18),
- INIT_BATCH(19),
- INIT_BATCH(20),
- INIT_BATCH(21),
- INIT_BATCH(22),
- INIT_BATCH(23),
- INIT_BATCH(24),
- INIT_BATCH(25),
- INIT_BATCH(26),
- INIT_BATCH(27),
- INIT_BATCH(28),
- INIT_BATCH(29),
- INIT_BATCH(30),
- INIT_BATCH(31),
- INIT_BATCH(32),
- INIT_BATCH(33),
- INIT_BATCH(34),
- INIT_BATCH(35),
- INIT_BATCH(36),
- INIT_BATCH(37),
- INIT_BATCH(38),
- INIT_BATCH(39),
- INIT_BATCH(40),
- INIT_BATCH(41),
- INIT_BATCH(42),
- INIT_BATCH(43),
- INIT_BATCH(44),
- INIT_BATCH(45),
- INIT_BATCH(46),
- INIT_BATCH(47),
- INIT_BATCH(48),
- INIT_BATCH(49),
- INIT_BATCH(50),
- INIT_BATCH(51),
- INIT_BATCH(52),
- INIT_BATCH(53),
- INIT_BATCH(54),
- INIT_BATCH(55),
- INIT_BATCH(56),
- INIT_BATCH(57),
- INIT_BATCH(58),
- INIT_BATCH(59),
-};
-
-
static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
{
struct pvr2_sysfs_ctl_item *cip;
- struct pvr2_sysfs_func_set *fp;
struct pvr2_ctrl *cptr;
unsigned int cnt,acnt;
int ret;
- if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
- return;
- }
-
- fp = funcs + ctl_id;
cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
if (!cptr) return;
@@ -529,6 +294,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
cip->cptr = cptr;
+ cip->ctl_id = ctl_id;
cip->chptr = sfp;
cip->item_next = NULL;
@@ -541,19 +307,19 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_name.attr.name = "name";
cip->attr_name.attr.mode = S_IRUGO;
- cip->attr_name.show = fp->show_name;
+ cip->attr_name.show = show_name;
cip->attr_type.attr.name = "type";
cip->attr_type.attr.mode = S_IRUGO;
- cip->attr_type.show = fp->show_type;
+ cip->attr_type.show = show_type;
cip->attr_min.attr.name = "min_val";
cip->attr_min.attr.mode = S_IRUGO;
- cip->attr_min.show = fp->show_min;
+ cip->attr_min.show = show_min;
cip->attr_max.attr.name = "max_val";
cip->attr_max.attr.mode = S_IRUGO;
- cip->attr_max.show = fp->show_max;
+ cip->attr_max.show = show_max;
cip->attr_val.attr.name = "cur_val";
cip->attr_val.attr.mode = S_IRUGO;
@@ -563,11 +329,11 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_enum.attr.name = "enum_val";
cip->attr_enum.attr.mode = S_IRUGO;
- cip->attr_enum.show = fp->show_enum;
+ cip->attr_enum.show = show_enum;
cip->attr_bits.attr.name = "bit_val";
cip->attr_bits.attr.mode = S_IRUGO;
- cip->attr_bits.show = fp->show_bits;
+ cip->attr_bits.show = show_bits;
if (pvr2_ctrl_is_writable(cptr)) {
cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
@@ -578,12 +344,12 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->attr_gen[acnt++] = &cip->attr_name.attr;
cip->attr_gen[acnt++] = &cip->attr_type.attr;
cip->attr_gen[acnt++] = &cip->attr_val.attr;
- cip->attr_val.show = fp->show_val_norm;
- cip->attr_val.store = fp->store_val_norm;
+ cip->attr_val.show = show_val_norm;
+ cip->attr_val.store = store_val_norm;
if (pvr2_ctrl_has_custom_symbols(cptr)) {
cip->attr_gen[acnt++] = &cip->attr_custom.attr;
- cip->attr_custom.show = fp->show_val_custom;
- cip->attr_custom.store = fp->store_val_custom;
+ cip->attr_custom.show = show_val_custom;
+ cip->attr_custom.store = store_val_custom;
}
switch (pvr2_ctrl_get_type(cptr)) {
case pvr2_ctl_enum:
@@ -610,8 +376,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
if (ret) {
- printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "sysfs_create_group error: %d",
+ ret);
return;
}
cip->created_ok = !0;
@@ -642,15 +409,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
sfp->debugifc = dip;
ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
dip->debugcmd_created_ok = !0;
}
ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
dip->debuginfo_created_ok = !0;
}
@@ -861,8 +630,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
class_dev->driver_data = sfp;
ret = device_register(class_dev);
if (ret) {
- printk(KERN_ERR "%s: device_register failed\n",
- __FUNCTION__);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_register failed");
kfree(class_dev);
return;
}
@@ -874,8 +643,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
ret = device_create_file(sfp->class_dev,
&sfp->attr_v4l_minor_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->v4l_minor_number_created_ok = !0;
}
@@ -887,8 +657,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
ret = device_create_file(sfp->class_dev,
&sfp->attr_v4l_radio_minor_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->v4l_radio_minor_number_created_ok = !0;
}
@@ -899,8 +670,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_unit_number.store = NULL;
ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->unit_number_created_ok = !0;
}
@@ -912,8 +684,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
ret = device_create_file(sfp->class_dev,
&sfp->attr_bus_info);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->bus_info_created_ok = !0;
}
@@ -925,8 +698,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
ret = device_create_file(sfp->class_dev,
&sfp->attr_hdw_name);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->hdw_name_created_ok = !0;
}
@@ -938,8 +712,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
ret = device_create_file(sfp->class_dev,
&sfp->attr_hdw_desc);
if (ret < 0) {
- printk(KERN_WARNING "%s: device_create_file error: %d\n",
- __FUNCTION__, ret);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "device_create_file error: %d",
+ ret);
} else {
sfp->hdw_desc_created_ok = !0;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
index ff9373b47..6d875bfe7 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
index c65dbe727..efec78516 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h
index 556f12aa9..ef4afaf37 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-util.h b/linux/drivers/media/video/pvrusb2/pvrusb2-util.h
index e53aee416..92b75544e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-util.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-util.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 38b0ff0f5..55cb4021a 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -58,7 +57,9 @@ struct pvr2_v4l2_fh {
struct pvr2_v4l2_fh *vprev;
wait_queue_head_t wait_data;
int fw_mode_flag;
- int prev_input_val;
+ /* Map contiguous ordinal value to input id */
+ unsigned char *input_map;
+ unsigned int input_cnt;
};
struct pvr2_v4l2 {
@@ -68,10 +69,6 @@ struct pvr2_v4l2 {
struct v4l2_prio_state prio;
- /* Map contiguous ordinal value to input id */
- unsigned char *input_map;
- unsigned int input_cnt;
-
/* streams - Note that these must be separately, individually,
* allocated pointers. This is because the v4l core is going to
* manage their deletion - separately, individually... */
@@ -271,11 +268,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
memset(&tmp,0,sizeof(tmp));
tmp.index = vi->index;
ret = 0;
- if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
+ if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
ret = -EINVAL;
break;
}
- val = vp->input_map[vi->index];
+ val = fh->input_map[vi->index];
switch (val) {
case PVR2_CVAL_INPUT_TV:
case PVR2_CVAL_INPUT_DTV:
@@ -323,8 +320,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
val = 0;
ret = pvr2_ctrl_get_value(cptr,&val);
vi->index = 0;
- for (idx = 0; idx < vp->input_cnt; idx++) {
- if (vp->input_map[idx] == val) {
+ for (idx = 0; idx < fh->input_cnt; idx++) {
+ if (fh->input_map[idx] == val) {
vi->index = idx;
break;
}
@@ -335,13 +332,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_INPUT:
{
struct v4l2_input *vi = (struct v4l2_input *)arg;
- if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
+ if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
ret = -ERANGE;
break;
}
ret = pvr2_ctrl_set_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
- vp->input_map[vi->index]);
+ fh->input_map[vi->index]);
break;
}
@@ -840,10 +837,6 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
pvr2_v4l2_dev_destroy(vp->dev_radio);
vp->dev_radio = NULL;
}
- if (vp->input_map) {
- kfree(vp->input_map);
- vp->input_map = NULL;
- }
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
pvr2_channel_done(&vp->channel);
@@ -901,20 +894,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
v4l2_prio_close(&vp->prio, &fhp->prio);
file->private_data = NULL;
- /* Restore the previous input selection, if it makes sense
- to do so. */
- if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
- struct pvr2_ctrl *cp;
- int pval;
- cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
- pvr2_ctrl_get_value(cp,&pval);
- /* Only restore if we're still selecting the radio */
- if (pval == PVR2_CVAL_INPUT_RADIO) {
- pvr2_ctrl_set_value(cp,fhp->prev_input_val);
- pvr2_hdw_commit_ctl(hdw);
- }
- }
-
if (fhp->vnext) {
fhp->vnext->vprev = fhp->vprev;
} else {
@@ -931,6 +910,10 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
pvr2_channel_done(&fhp->channel);
pvr2_trace(PVR2_TRACE_STRUCT,
"Destroying pvr_v4l2_fh id=%p",fhp);
+ if (fhp->input_map) {
+ kfree(fhp->input_map);
+ fhp->input_map = NULL;
+ }
kfree(fhp);
if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
pvr2_v4l2_destroy_no_lock(vp);
@@ -945,6 +928,9 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
struct pvr2_v4l2_fh *fhp;
struct pvr2_v4l2 *vp;
struct pvr2_hdw *hdw;
+ unsigned int input_mask = 0;
+ unsigned int input_cnt,idx;
+ int ret = 0;
dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
@@ -970,6 +956,50 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+ if (dip->v4l_type == VFL_TYPE_RADIO) {
+ /* Opening device as a radio, legal input selection subset
+ is just the radio. */
+ input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
+ } else {
+ /* Opening the main V4L device, legal input selection
+ subset includes all analog inputs. */
+ input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
+ (1 << PVR2_CVAL_INPUT_TV) |
+ (1 << PVR2_CVAL_INPUT_COMPOSITE) |
+ (1 << PVR2_CVAL_INPUT_SVIDEO));
+ }
+ ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
+ if (ret) {
+ pvr2_channel_done(&fhp->channel);
+ pvr2_trace(PVR2_TRACE_STRUCT,
+ "Destroying pvr_v4l2_fh id=%p (input mask error)",
+ fhp);
+
+ kfree(fhp);
+ return ret;
+ }
+
+ input_mask &= pvr2_hdw_get_input_available(hdw);
+ input_cnt = 0;
+ for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+ if (input_mask & (1 << idx)) input_cnt++;
+ }
+ fhp->input_cnt = input_cnt;
+ fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
+ if (!fhp->input_map) {
+ pvr2_channel_done(&fhp->channel);
+ pvr2_trace(PVR2_TRACE_STRUCT,
+ "Destroying pvr_v4l2_fh id=%p (input map failure)",
+ fhp);
+ kfree(fhp);
+ return -ENOMEM;
+ }
+ input_cnt = 0;
+ for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+ if (!(input_mask & (1 << idx))) continue;
+ fhp->input_map[input_cnt++] = idx;
+ }
+
fhp->vnext = NULL;
fhp->vprev = vp->vlast;
if (vp->vlast) {
@@ -980,18 +1010,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
vp->vlast = fhp;
fhp->vhead = vp;
- /* Opening the /dev/radioX device implies a mode switch.
- So execute that here. Note that you can get the
- IDENTICAL effect merely by opening the normal video
- device and setting the input appropriately. */
- if (dip->v4l_type == VFL_TYPE_RADIO) {
- struct pvr2_ctrl *cp;
- cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
- pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
- pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
- pvr2_hdw_commit_ctl(hdw);
- }
-
fhp->file = file;
file->private_data = fhp;
v4l2_prio_open(&vp->prio,&fhp->prio);
@@ -1226,8 +1244,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
{
struct pvr2_v4l2 *vp;
- struct pvr2_hdw *hdw;
- unsigned int input_mask,input_cnt,idx;
vp = kzalloc(sizeof(*vp),GFP_KERNEL);
if (!vp) return vp;
@@ -1236,26 +1252,12 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
vp->channel.check_func = pvr2_v4l2_internal_check;
- hdw = vp->channel.mc_head->hdw;
- input_mask = pvr2_hdw_get_input_available(hdw);
- input_cnt = 0;
- for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
- if (input_mask & (1 << idx)) input_cnt++;
- }
- vp->input_cnt = input_cnt;
- vp->input_map = kzalloc(input_cnt,GFP_KERNEL);
- if (!vp->input_map) goto fail;
- input_cnt = 0;
- for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
- if (!(input_mask & (1 << idx))) continue;
- vp->input_map[input_cnt++] = idx;
- }
-
/* register streams */
vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
if (!vp->dev_video) goto fail;
pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
- if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) {
+ if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
+ (1 << PVR2_CVAL_INPUT_RADIO)) {
vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
if (!vp->dev_radio) goto fail;
pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
@@ -1265,7 +1267,7 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
fail:
pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
pvr2_v4l2_destroy_no_lock(vp);
- return 0;
+ return NULL;
}
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
index 9a995e2d2..34c011a7b 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index 36ce6dc66..b1ff3803f 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
@@ -82,7 +81,7 @@ static void set_input(struct pvr2_v4l_decoder *ctxt)
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != 0) &&
+ ((sp = routing_schemes + sid) != NULL) &&
(hdw->input_val >= 0) &&
(hdw->input_val < sp->cnt)) {
route.input = sp->def[hdw->input_val];
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
index 2b917fda0..4ff5b892b 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index d578f2491..6cdcbf2fe 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
index 8aaeff4e1..807090961 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2.h b/linux/drivers/media/video/pvrusb2/pvrusb2.h
index 1a9a4baf1..240de9b35 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2.h
@@ -1,6 +1,5 @@
/*
*
- * $Id$
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
* Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c
index a54d4ddfa..8236b2b2d 100644
--- a/linux/drivers/media/video/pwc/pwc-if.c
+++ b/linux/drivers/media/video/pwc/pwc-if.c
@@ -489,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
int i;
unsigned long flags;
- PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
+ PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
spin_lock_irqsave(&pdev->ptrlock, flags);
pdev->full_frames = NULL;
@@ -511,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
pdev->fill_image = 0;
spin_unlock_irqrestore(&pdev->ptrlock, flags);
- PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
+ PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
}
@@ -929,7 +929,7 @@ static void pwc_iso_stop(struct pwc_device *pdev)
struct urb *urb;
urb = pdev->sbuf[i].urb;
- if (urb != 0) {
+ if (urb) {
PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
usb_kill_urb(urb);
}
@@ -945,7 +945,7 @@ static void pwc_iso_free(struct pwc_device *pdev)
struct urb *urb;
urb = pdev->sbuf[i].urb;
- if (urb != 0) {
+ if (urb) {
PWC_DEBUG_MEMORY("Freeing URB\n");
usb_free_urb(urb);
pdev->sbuf[i].urb = NULL;
@@ -1440,7 +1440,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long page, pos = 0;
int index;
- PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
+ PWC_DEBUG_MEMORY(">> %s\n", __func__);
pdev = vdev->priv;
size = vma->vm_end - vma->vm_start;
start = vma->vm_start;
@@ -1784,8 +1784,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
/* Allocate video_device structure */
pdev->vdev = video_device_alloc();
- if (pdev->vdev == 0)
- {
+ if (!pdev->vdev) {
PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
kfree(pdev);
return -ENOMEM;
diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c
index 32fbe1ae6..174288987 100644
--- a/linux/drivers/media/video/pwc/pwc-v4l.c
+++ b/linux/drivers/media/video/pwc/pwc-v4l.c
@@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
#ifdef CONFIG_USB_PWC_DEBUG
- if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+ if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
v4l_printk_ioctl(cmd);
+ printk("\n");
+ }
#endif
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c
index bef3c9c79..7cc8e9b19 100644
--- a/linux/drivers/media/video/pxa_camera.c
+++ b/linux/drivers/media/video/pxa_camera.c
@@ -49,6 +49,9 @@
#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */
#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */
+#define CICR1_COLOR_SP_VAL(x) (((x) << 3) & CICR1_COLOR_SP) /* color space */
+#define CICR1_RGB_BPP_VAL(x) (((x) << 7) & CICR1_RGB_BPP) /* bpp for rgb */
+#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */
#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
@@ -70,6 +73,19 @@ static DEFINE_MUTEX(camera_lock);
/*
* Structures
*/
+enum pxa_camera_active_dma {
+ DMA_Y = 0x1,
+ DMA_U = 0x2,
+ DMA_V = 0x4,
+};
+
+/* descriptor needed for the PXA DMA engine */
+struct pxa_cam_dma {
+ dma_addr_t sg_dma;
+ struct pxa_dma_desc *sg_cpu;
+ size_t sg_size;
+ int sglen;
+};
/* buffer for one video frame */
struct pxa_buffer {
@@ -78,16 +94,12 @@ struct pxa_buffer {
const struct soc_camera_data_format *fmt;
- /* our descriptor list needed for the PXA DMA engine */
- dma_addr_t sg_dma;
- struct pxa_dma_desc *sg_cpu;
- size_t sg_size;
+ /* our descriptor lists for Y, U and V channels */
+ struct pxa_cam_dma dmas[3];
+
int inwork;
-};
-struct pxa_framebuffer_queue {
- dma_addr_t sg_last_dma;
- struct pxa_dma_desc *sg_last_cpu;
+ enum pxa_camera_active_dma active_dma;
};
struct pxa_camera_dev {
@@ -100,7 +112,9 @@ struct pxa_camera_dev {
unsigned int irq;
void __iomem *base;
- unsigned int dma_chan_y;
+
+ int channels;
+ unsigned int dma_chans[3];
struct pxacamera_platform_data *pdata;
struct resource *res;
@@ -112,6 +126,7 @@ struct pxa_camera_dev {
spinlock_t lock;
struct pxa_buffer *active;
+ struct pxa_dma_desc *sg_tail[3];
};
static const char *pxa_cam_driver_description = "PXA_Camera";
@@ -125,10 +140,21 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
unsigned int *size)
{
struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icd->dev.parent);
+ struct pxa_camera_dev *pcdev = ici->priv;
dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
- *size = icd->width * icd->height * ((icd->current_fmt->depth + 7) >> 3);
+ /* planar capture requires Y, U and V buffers to be page aligned */
+ if (pcdev->channels == 3) {
+ *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
+ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
+ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
+ } else {
+ *size = icd->width * icd->height *
+ ((icd->current_fmt->depth + 7) >> 3);
+ }
if (0 == *count)
*count = 32;
@@ -145,10 +171,11 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
to_soc_camera_host(icd->dev.parent);
struct pxa_camera_dev *pcdev = ici->priv;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+ int i;
BUG_ON(in_interrupt());
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__,
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
&buf->vb, buf->vb.baddr, buf->vb.bsize);
/* This waits until this buffer is out of danger, i.e., until it is no
@@ -157,14 +184,62 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
videobuf_dma_unmap(vq, dma);
videobuf_dma_free(dma);
- if (buf->sg_cpu)
- dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu,
- buf->sg_dma);
- buf->sg_cpu = NULL;
+ for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
+ if (buf->dmas[i].sg_cpu)
+ dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+ buf->dmas[i].sg_cpu,
+ buf->dmas[i].sg_dma);
+ buf->dmas[i].sg_cpu = NULL;
+ }
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
+static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
+ struct pxa_buffer *buf,
+ struct videobuf_dmabuf *dma, int channel,
+ int sglen, int sg_start, int cibr,
+ unsigned int size)
+{
+ struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
+ int i;
+
+ if (pxa_dma->sg_cpu)
+ dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+ pxa_dma->sg_cpu, pxa_dma->sg_dma);
+
+ pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
+ pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+ &pxa_dma->sg_dma, GFP_KERNEL);
+ if (!pxa_dma->sg_cpu)
+ return -ENOMEM;
+
+ pxa_dma->sglen = sglen;
+
+ for (i = 0; i < sglen; i++) {
+ int sg_i = sg_start + i;
+ struct scatterlist *sg = dma->sglist;
+ unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len;
+
+ pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
+ pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]);
+
+ /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
+ xfer_len = (min(dma_len, size) + 7) & ~7;
+
+ pxa_dma->sg_cpu[i].dcmd =
+ DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
+ size -= dma_len;
+ pxa_dma->sg_cpu[i].ddadr =
+ pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
+ }
+
+ pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP;
+ pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN;
+
+ return 0;
+}
+
static int pxa_videobuf_prepare(struct videobuf_queue *vq,
struct videobuf_buffer *vb, enum v4l2_field field)
{
@@ -173,9 +248,11 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
to_soc_camera_host(icd->dev.parent);
struct pxa_camera_dev *pcdev = ici->priv;
struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
- int i, ret;
+ int ret;
+ int sglen_y, sglen_yu = 0, sglen_u = 0, sglen_v = 0;
+ int size_y, size_u = 0, size_v = 0;
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__,
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
/* Added list head initialization on alloc */
@@ -218,49 +295,64 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
if (ret)
goto fail;
- if (buf->sg_cpu)
- dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu,
- buf->sg_dma);
+ if (pcdev->channels == 3) {
+ /* FIXME the calculations should be more precise */
+ sglen_y = dma->sglen / 2;
+ sglen_u = sglen_v = dma->sglen / 4 + 1;
+ sglen_yu = sglen_y + sglen_u;
+ size_y = size / 2;
+ size_u = size_v = size / 4;
+ } else {
+ sglen_y = dma->sglen;
+ size_y = size;
+ }
+
+ /* init DMA for Y channel */
+ ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y,
+ 0, 0x28, size_y);
- buf->sg_size = (dma->sglen + 1) * sizeof(struct pxa_dma_desc);
- buf->sg_cpu = dma_alloc_coherent(pcdev->dev, buf->sg_size,
- &buf->sg_dma, GFP_KERNEL);
- if (!buf->sg_cpu) {
- ret = -ENOMEM;
+ if (ret) {
+ dev_err(pcdev->dev,
+ "DMA initialization for Y/RGB failed\n");
goto fail;
}
- dev_dbg(&icd->dev, "nents=%d size: %d sg=0x%p\n",
- dma->sglen, size, dma->sglist);
- for (i = 0; i < dma->sglen; i++) {
- struct scatterlist *sg = dma->sglist;
- unsigned int dma_len = sg_dma_len(&sg[i]), xfer_len;
-
- /* CIBR0 */
- buf->sg_cpu[i].dsadr = pcdev->res->start + 0x28;
- buf->sg_cpu[i].dtadr = sg_dma_address(&sg[i]);
- /* PXA270 Developer's Manual 27.4.4.1:
- * round up to 8 bytes */
- xfer_len = (min(dma_len, size) + 7) & ~7;
- if (xfer_len & 7)
- dev_err(&icd->dev, "Unaligned buffer: "
- "dma_len %u, size %u\n", dma_len, size);
- buf->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 |
- DCMD_INCTRGADDR | xfer_len;
- size -= dma_len;
- buf->sg_cpu[i].ddadr = buf->sg_dma + (i + 1) *
- sizeof(struct pxa_dma_desc);
+ if (pcdev->channels == 3) {
+ /* init DMA for U channel */
+ ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
+ sglen_y, 0x30, size_u);
+ if (ret) {
+ dev_err(pcdev->dev,
+ "DMA initialization for U failed\n");
+ goto fail_u;
+ }
+
+ /* init DMA for V channel */
+ ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v,
+ sglen_yu, 0x38, size_v);
+ if (ret) {
+ dev_err(pcdev->dev,
+ "DMA initialization for V failed\n");
+ goto fail_v;
+ }
}
- buf->sg_cpu[dma->sglen - 1].ddadr = DDADR_STOP;
- buf->sg_cpu[dma->sglen - 1].dcmd |= DCMD_ENDIRQEN;
vb->state = VIDEOBUF_PREPARED;
}
buf->inwork = 0;
+ buf->active_dma = DMA_Y;
+ if (pcdev->channels == 3)
+ buf->active_dma |= DMA_U | DMA_V;
return 0;
+fail_v:
+ dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+ buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
+fail_u:
+ dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+ buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
fail:
free_buffer(vq, buf);
out:
@@ -277,11 +369,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
struct pxa_camera_dev *pcdev = ici->priv;
struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
struct pxa_buffer *active;
- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
- int nents = dma->sglen;
unsigned long flags;
+ int i;
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__,
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
spin_lock_irqsave(&pcdev->lock, flags);
@@ -292,59 +383,63 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
if (!active) {
CIFR |= CIFR_RESET_F;
- DDADR(pcdev->dma_chan_y) = buf->sg_dma;
- DCSR(pcdev->dma_chan_y) = DCSR_RUN;
+
+ for (i = 0; i < pcdev->channels; i++) {
+ DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
+ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+ pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
+ }
+
pcdev->active = buf;
CICR0 |= CICR0_ENB;
} else {
- struct videobuf_dmabuf *active_dma =
- videobuf_to_dma(&active->vb);
- /* Stop DMA engine */
- DCSR(pcdev->dma_chan_y) = 0;
-
- /* Add the descriptors we just initialized to the currently
- * running chain
- */
- active->sg_cpu[active_dma->sglen - 1].ddadr = buf->sg_dma;
-
- /* Setup a dummy descriptor with the DMA engines current
- * state
- */
- /* CIBR0 */
- buf->sg_cpu[nents].dsadr = pcdev->res->start + 0x28;
- buf->sg_cpu[nents].dtadr = DTADR(pcdev->dma_chan_y);
- buf->sg_cpu[nents].dcmd = DCMD(pcdev->dma_chan_y);
-
- if (DDADR(pcdev->dma_chan_y) == DDADR_STOP) {
- /* The DMA engine is on the last descriptor, set the
- * next descriptors address to the descriptors
- * we just initialized
- */
- buf->sg_cpu[nents].ddadr = buf->sg_dma;
- } else {
- buf->sg_cpu[nents].ddadr = DDADR(pcdev->dma_chan_y);
- }
+ struct pxa_cam_dma *buf_dma;
+ struct pxa_cam_dma *act_dma;
+ int nents;
- /* The next descriptor is the dummy descriptor */
- DDADR(pcdev->dma_chan_y) = buf->sg_dma + nents *
- sizeof(struct pxa_dma_desc);
+ for (i = 0; i < pcdev->channels; i++) {
+ buf_dma = &buf->dmas[i];
+ act_dma = &active->dmas[i];
+ nents = buf_dma->sglen;
-#ifdef DEBUG
- if (CISR & CISR_IFO_0) {
- dev_warn(pcdev->dev, "FIFO overrun\n");
- DDADR(pcdev->dma_chan_y) = pcdev->active->sg_dma;
-
- CICR0 &= ~CICR0_ENB;
- CIFR |= CIFR_RESET_F;
- DCSR(pcdev->dma_chan_y) = DCSR_RUN;
- CICR0 |= CICR0_ENB;
- } else
-#endif
- DCSR(pcdev->dma_chan_y) = DCSR_RUN;
+ /* Stop DMA engine */
+ DCSR(pcdev->dma_chans[i]) = 0;
+
+ /* Add the descriptors we just initialized to
+ the currently running chain */
+ pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
+ pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
+
+ /* Setup a dummy descriptor with the DMA engines current
+ * state
+ */
+ buf_dma->sg_cpu[nents].dsadr =
+ pcdev->res->start + 0x28 + i*8; /* CIBRx */
+ buf_dma->sg_cpu[nents].dtadr =
+ DTADR(pcdev->dma_chans[i]);
+ buf_dma->sg_cpu[nents].dcmd =
+ DCMD(pcdev->dma_chans[i]);
+
+ if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) {
+ /* The DMA engine is on the last
+ descriptor, set the next descriptors
+ address to the descriptors we just
+ initialized */
+ buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma;
+ } else {
+ buf_dma->sg_cpu[nents].ddadr =
+ DDADR(pcdev->dma_chans[i]);
+ }
+
+ /* The next descriptor is the dummy descriptor */
+ DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents *
+ sizeof(struct pxa_dma_desc);
+
+ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+ }
}
spin_unlock_irqrestore(&pcdev->lock, flags);
-
}
static void pxa_videobuf_release(struct videobuf_queue *vq,
@@ -354,21 +449,21 @@ static void pxa_videobuf_release(struct videobuf_queue *vq,
#ifdef DEBUG
struct soc_camera_device *icd = vq->priv_data;
- dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__,
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
switch (vb->state) {
case VIDEOBUF_ACTIVE:
- dev_dbg(&icd->dev, "%s (active)\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s (active)\n", __func__);
break;
case VIDEOBUF_QUEUED:
- dev_dbg(&icd->dev, "%s (queued)\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s (queued)\n", __func__);
break;
case VIDEOBUF_PREPARED:
- dev_dbg(&icd->dev, "%s (prepared)\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
break;
default:
- dev_dbg(&icd->dev, "%s (unknown)\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
break;
}
#endif
@@ -376,18 +471,42 @@ static void pxa_videobuf_release(struct videobuf_queue *vq,
free_buffer(vq, buf);
}
-static void pxa_camera_dma_irq_y(int channel, void *data)
+static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
+ struct videobuf_buffer *vb,
+ struct pxa_buffer *buf)
+{
+ /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
+ list_del_init(&vb->queue);
+ vb->state = VIDEOBUF_DONE;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+ wake_up(&vb->done);
+
+ if (list_empty(&pcdev->capture)) {
+ pcdev->active = NULL;
+ DCSR(pcdev->dma_chans[0]) = 0;
+ DCSR(pcdev->dma_chans[1]) = 0;
+ DCSR(pcdev->dma_chans[2]) = 0;
+ CICR0 &= ~CICR0_ENB;
+ return;
+ }
+
+ pcdev->active = list_entry(pcdev->capture.next,
+ struct pxa_buffer, vb.queue);
+}
+
+static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+ enum pxa_camera_active_dma act_dma)
{
- struct pxa_camera_dev *pcdev = data;
struct pxa_buffer *buf;
unsigned long flags;
- unsigned int status;
+ u32 status, camera_status, overrun;
struct videobuf_buffer *vb;
spin_lock_irqsave(&pcdev->lock, flags);
- status = DCSR(pcdev->dma_chan_y);
- DCSR(pcdev->dma_chan_y) = status;
+ status = DCSR(channel);
+ DCSR(channel) = status | DCSR_ENDINTR;
if (status & DCSR_BUSERR) {
dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
@@ -405,33 +524,57 @@ static void pxa_camera_dma_irq_y(int channel, void *data)
goto out;
}
+ camera_status = CISR;
+ overrun = CISR_IFO_0;
+ if (pcdev->channels == 3)
+ overrun |= CISR_IFO_1 | CISR_IFO_2;
+ if (camera_status & overrun) {
+ dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status);
+ /* Stop the Capture Interface */
+ CICR0 &= ~CICR0_ENB;
+ /* Stop DMA */
+ DCSR(channel) = 0;
+ /* Reset the FIFOs */
+ CIFR |= CIFR_RESET_F;
+ /* Enable End-Of-Frame Interrupt */
+ CICR0 &= ~CICR0_EOFM;
+ /* Restart the Capture Interface */
+ CICR0 |= CICR0_ENB;
+ goto out;
+ }
+
vb = &pcdev->active->vb;
buf = container_of(vb, struct pxa_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__,
+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
- /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_DONE;
- do_gettimeofday(&vb->ts);
- vb->field_count++;
- wake_up(&vb->done);
-
- if (list_empty(&pcdev->capture)) {
- pcdev->active = NULL;
- DCSR(pcdev->dma_chan_y) = 0;
- CICR0 &= ~CICR0_ENB;
- goto out;
- }
-
- pcdev->active = list_entry(pcdev->capture.next, struct pxa_buffer,
- vb.queue);
+ buf->active_dma &= ~act_dma;
+ if (!buf->active_dma)
+ pxa_camera_wakeup(pcdev, vb, buf);
out:
spin_unlock_irqrestore(&pcdev->lock, flags);
}
+static void pxa_camera_dma_irq_y(int channel, void *data)
+{
+ struct pxa_camera_dev *pcdev = data;
+ pxa_camera_dma_irq(channel, pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(int channel, void *data)
+{
+ struct pxa_camera_dev *pcdev = data;
+ pxa_camera_dma_irq(channel, pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(int channel, void *data)
+{
+ struct pxa_camera_dev *pcdev = data;
+ pxa_camera_dma_irq(channel, pcdev, DMA_V);
+}
+
static struct videobuf_queue_ops pxa_videobuf_ops = {
.buf_setup = pxa_videobuf_setup,
.buf_prepare = pxa_videobuf_prepare,
@@ -466,18 +609,18 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
pcdev, pdata);
if (pdata && pdata->init) {
- dev_dbg(pcdev->dev, "%s: Init gpios\n", __FUNCTION__);
+ dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
pdata->init(pcdev->dev);
}
if (pdata && pdata->power) {
- dev_dbg(pcdev->dev, "%s: Power on camera\n", __FUNCTION__);
+ dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
pdata->power(pcdev->dev, 1);
}
if (pdata && pdata->reset) {
dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
- __FUNCTION__);
+ __func__);
pdata->reset(pcdev->dev, 1);
}
@@ -507,12 +650,12 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
if (board && board->reset) {
dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
- __FUNCTION__);
+ __func__);
board->reset(pcdev->dev, 0);
}
if (board && board->power) {
- dev_dbg(pcdev->dev, "%s: Power off camera\n", __FUNCTION__);
+ dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
board->power(pcdev->dev, 0);
}
}
@@ -524,8 +667,21 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status);
+ if (!status)
+ return IRQ_NONE;
+
CISR = status;
+ if (status & CISR_EOF) {
+ int i;
+ for (i = 0; i < pcdev->channels; i++) {
+ DDADR(pcdev->dma_chans[i]) =
+ pcdev->active->dmas[i].sg_dma;
+ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+ }
+ CICR0 |= CICR0_EOFM;
+ }
+
return IRQ_HANDLED;
}
@@ -571,8 +727,11 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd)
/* disable capture, disable interrupts */
CICR0 = 0x3ff;
+
/* Stop DMA engine */
- DCSR(pcdev->dma_chan_y) = 0;
+ DCSR(pcdev->dma_chans[0]) = 0;
+ DCSR(pcdev->dma_chans[1]) = 0;
+ DCSR(pcdev->dma_chans[2]) = 0;
icd->ops->release(icd);
@@ -625,7 +784,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
to_soc_camera_host(icd->dev.parent);
struct pxa_camera_dev *pcdev = ici->priv;
unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
- u32 cicr0, cicr4 = 0;
+ u32 cicr0, cicr1, cicr4 = 0;
int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
if (ret < 0)
@@ -637,6 +796,8 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
if (!common_flags)
return -EINVAL;
+ pcdev->channels = 1;
+
/* Make choises, based on platform preferences */
if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
(common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
@@ -702,7 +863,26 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
cicr0 = CICR0;
if (cicr0 & CICR0_ENB)
CICR0 = cicr0 & ~CICR0_ENB;
- CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
+
+ cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
+
+ switch (pixfmt) {
+ case V4L2_PIX_FMT_YUV422P:
+ pcdev->channels = 3;
+ cicr1 |= CICR1_YCBCR_F;
+ case V4L2_PIX_FMT_YUYV:
+ cicr1 |= CICR1_COLOR_SP_VAL(2);
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
+ CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
+ break;
+ }
+
+ CICR1 = cicr1;
CICR2 = 0;
CICR3 = CICR3_LPF_VAL(icd->height - 1) |
CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
@@ -905,16 +1085,36 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->dev = &pdev->dev;
/* request dma */
- pcdev->dma_chan_y = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
- pxa_camera_dma_irq_y, pcdev);
- if (pcdev->dma_chan_y < 0) {
+ pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_y, pcdev);
+ if (pcdev->dma_chans[0] < 0) {
dev_err(pcdev->dev, "Can't request DMA for Y\n");
err = -ENOMEM;
goto exit_iounmap;
}
- dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan_y);
+ dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+
+ pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_u, pcdev);
+ if (pcdev->dma_chans[1] < 0) {
+ dev_err(pcdev->dev, "Can't request DMA for U\n");
+ err = -ENOMEM;
+ goto exit_free_dma_y;
+ }
+ dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+
+ pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
+ pxa_camera_dma_irq_v, pcdev);
+ if (pcdev->dma_chans[0] < 0) {
+ dev_err(pcdev->dev, "Can't request DMA for V\n");
+ err = -ENOMEM;
+ goto exit_free_dma_u;
+ }
+ dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
- DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD;
+ DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
+ DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
+ DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
/* request irq */
err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
@@ -936,7 +1136,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
exit_free_irq:
free_irq(pcdev->irq, pcdev);
exit_free_dma:
- pxa_free_dma(pcdev->dma_chan_y);
+ pxa_free_dma(pcdev->dma_chans[2]);
+exit_free_dma_u:
+ pxa_free_dma(pcdev->dma_chans[1]);
+exit_free_dma_y:
+ pxa_free_dma(pcdev->dma_chans[0]);
exit_iounmap:
iounmap(base);
exit_release:
@@ -956,7 +1160,9 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev)
clk_put(pcdev->clk);
- pxa_free_dma(pcdev->dma_chan_y);
+ pxa_free_dma(pcdev->dma_chans[0]);
+ pxa_free_dma(pcdev->dma_chans[1]);
+ pxa_free_dma(pcdev->dma_chans[2]);
free_irq(pcdev->irq, pcdev);
soc_camera_host_unregister(&pxa_soc_camera_host);
diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c
index eb561ce6c..0692e4bef 100644
--- a/linux/drivers/media/video/saa7110.c
+++ b/linux/drivers/media/video/saa7110.c
@@ -489,7 +489,7 @@ saa7110_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
@@ -497,7 +497,7 @@ saa7110_detect_client (struct i2c_adapter *adapter,
strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
- if (decoder == 0) {
+ if (!decoder) {
kfree(client);
return -ENOMEM;
}
diff --git a/linux/drivers/media/video/saa7111.c b/linux/drivers/media/video/saa7111.c
index df44aed92..917fb2553 100644
--- a/linux/drivers/media/video/saa7111.c
+++ b/linux/drivers/media/video/saa7111.c
@@ -503,7 +503,7 @@ saa7111_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/saa7114.c b/linux/drivers/media/video/saa7114.c
index ebf42cf9e..158bd123c 100644
--- a/linux/drivers/media/video/saa7114.c
+++ b/linux/drivers/media/video/saa7114.c
@@ -842,7 +842,7 @@ saa7114_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c
index a5ae60c7b..fc4c17bbd 100644
--- a/linux/drivers/media/video/saa7115.c
+++ b/linux/drivers/media/video/saa7115.c
@@ -1461,19 +1461,25 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
/* ----------------------------------------------------------------------- */
-static int saa7115_probe(struct i2c_client *client)
+static int saa7115_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct saa711x_state *state;
int i;
char name[17];
- u8 chip_id;
+ char chip_id;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ int autodetect = !id || id->driver_data == 1;
+#endif
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
+#endif
for (i = 0; i < 0x0f; i++) {
saa711x_write(client, 0, i);
name[i] = (saa711x_read(client, 0) & 0x0f) + '0';
@@ -1482,8 +1488,7 @@ static int saa7115_probe(struct i2c_client *client)
}
name[i] = '\0';
- saa711x_write(client, 0, 5);
- chip_id = saa711x_read(client, 0) & 0x0f;
+ chip_id = name[5];
/* Check whether this chip is part of the saa711x series */
if (memcmp(name, "1f711", 5)) {
@@ -1492,8 +1497,16 @@ static int saa7115_probe(struct i2c_client *client)
return -ENODEV;
}
- snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id);
- v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, client->addr << 1, client->adapter->name);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ /* Safety check */
+ if (!autodetect && id->name[6] != chip_id) {
+ v4l_warn(client, "found saa711%c while %s was expected\n",
+ chip_id, id->name);
+ }
+#endif
+ snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
+ v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
+ client->addr << 1, client->adapter->name);
state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
i2c_set_clientdata(client, state);
@@ -1509,19 +1522,19 @@ static int saa7115_probe(struct i2c_client *client)
state->hue = 0;
state->sat = 64;
switch (chip_id) {
- case 1:
+ case '1':
state->ident = V4L2_IDENT_SAA7111;
break;
- case 3:
+ case '3':
state->ident = V4L2_IDENT_SAA7113;
break;
- case 4:
+ case '4':
state->ident = V4L2_IDENT_SAA7114;
break;
- case 5:
+ case '5':
state->ident = V4L2_IDENT_SAA7115;
break;
- case 8:
+ case '8':
state->ident = V4L2_IDENT_SAA7118;
break;
default:
@@ -1563,6 +1576,19 @@ static int saa7115_remove(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id saa7115_id[] = {
+ { "saa711x", 1 }, /* autodetect */
+ { "saa7111", 0 },
+ { "saa7113", 0 },
+ { "saa7114", 0 },
+ { "saa7115", 0 },
+ { "saa7118", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7115_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "saa7115",
.driverid = I2C_DRIVERID_SAA711X,
@@ -1572,6 +1598,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
#ifdef I2C_CLASS_TV_ANALOG
.legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = saa7115_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c
index ff2e70833..a73ae00af 100644
--- a/linux/drivers/media/video/saa7127.c
+++ b/linux/drivers/media/video/saa7127.c
@@ -679,7 +679,8 @@ static int saa7127_command(struct i2c_client *client,
/* ----------------------------------------------------------------------- */
-static int saa7127_probe(struct i2c_client *client)
+static int saa7127_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct saa7127_state *state;
struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
@@ -689,8 +690,10 @@ static int saa7127_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "saa7127");
+#endif
v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
client->addr << 1);
@@ -758,12 +761,23 @@ static int saa7127_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static struct i2c_device_id saa7127_id[] = {
+ { "saa7127", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7127_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "saa7127",
.driverid = I2C_DRIVERID_SAA7127,
.command = saa7127_command,
.probe = saa7127_probe,
.remove = saa7127_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = saa7127_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig
index e086f14d5..83f076abc 100644
--- a/linux/drivers/media/video/saa7134/Kconfig
+++ b/linux/drivers/media/video/saa7134/Kconfig
@@ -27,6 +27,7 @@ config VIDEO_SAA7134_ALSA
config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
+ depends on HOTPLUG # due to FW_LOADER
select VIDEOBUF_DVB
select FW_LOADER
select DVB_PLL if !DVB_FE_CUSTOMISE
@@ -35,9 +36,9 @@ config VIDEO_SAA7134_DVB
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
- select DVB_TDA827X if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
- select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
diff --git a/linux/drivers/media/video/saa7134/Makefile b/linux/drivers/media/video/saa7134/Makefile
index 9aff937ba..3dbaa19a6 100644
--- a/linux/drivers/media/video/saa7134/Makefile
+++ b/linux/drivers/media/video/saa7134/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c
index 121b50e88..58670f9ea 100644
--- a/linux/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c
@@ -969,10 +969,8 @@ static void snd_saa7134_free(struct snd_card * card)
if (chip->dev->dmasound.priv_data == NULL)
return;
- if (chip->irq >= 0) {
- synchronize_irq(chip->irq);
+ if (chip->irq >= 0)
free_irq(chip->irq, &chip->dev->dmasound);
- }
chip->dev->dmasound.priv_data = NULL;
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 3bee2d71c..49bf24e7b 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -30,6 +30,7 @@
#include "tuner-xc2028.h"
#include <media/v4l2-common.h>
#include <media/tveeprom.h>
+#include "tea5767.h"
/* commly used strings */
static char name_mute[] = "mute";
@@ -46,6 +47,9 @@ static char name_svideo[] = "S-Video";
/* ------------------------------------------------------------------ */
/* board config info */
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
@@ -1049,7 +1053,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_MANLI_MTV002] = {
/* Ognjen Nastic <ognjen@logosoft.ba> */
- .name = "Manli MuchTV M-TV002/Behold TV 403 FM",
+ .name = "Manli MuchTV M-TV002",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.radio_type = UNSET,
@@ -1076,7 +1080,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_MANLI_MTV001] = {
/* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
- .name = "Manli MuchTV M-TV001/Behold TV 401",
+ .name = "Manli MuchTV M-TV001",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.radio_type = UNSET,
@@ -2198,6 +2202,8 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_BEHOLD_409FM] = {
/* <http://tuner.beholder.ru>, Sergey <skiv@orel.ru> */
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 409 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -2205,6 +2211,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -3122,7 +3129,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_type = TUNER_PHILIPS_TD1316, /* untested */
.radio_type = TUNER_TEA5767, /* untested */
.tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
+ .radio_addr = 0x60,
.tda9887_conf = TDA9887_PRESENT,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
@@ -3615,12 +3622,15 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_401] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 401",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FQ1216ME,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3641,12 +3651,15 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_403] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 403",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FQ1216ME,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3663,12 +3676,15 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_403FM] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 403 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FQ1216ME,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3689,6 +3705,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_405] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 405",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3696,6 +3714,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3713,6 +3732,8 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_BEHOLD_405FM] = {
/* Sergey <skiv@orel.ru> */
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 405 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3720,6 +3741,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3740,6 +3762,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_407] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 407",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3747,7 +3771,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
- .gpiomask = 0xc0c000,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3767,6 +3791,8 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_407FM] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 407 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3774,7 +3800,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
- .gpiomask = 0xc0c000,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_svideo,
.vmux = 8,
@@ -3799,6 +3825,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_409] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 409",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3806,6 +3834,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -3822,6 +3851,8 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_BEHOLD_505FM] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 505 FM/RDS",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3829,6 +3860,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -3853,6 +3885,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_507_9FM] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -3860,6 +3894,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00008000,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -3880,6 +3915,8 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
+ /* Beholder Intl. Ltd. 2008 */
+ /*Dmitry Belimov <d.belimov@gmail.com> */
.name = "Beholder BeholdTV Columbus TVFM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_ALPS_TSBE5_PAL,
@@ -3887,23 +3924,28 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x000A8004,
.inputs = {{
.name = name_tv,
.vmux = 3,
.amux = TV,
.tv = 1,
- },{
+ .gpio = 0x000A8004,
+ }, {
.name = name_comp1,
.vmux = 1,
.amux = LINE1,
- },{
+ .gpio = 0x000A8000,
+ }, {
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
- }},
+ .gpio = 0x000A8000,
+ } },
.radio = {
.name = name_radio,
.amux = LINE2,
+ .gpio = 0x000A8000,
},
},
[SAA7134_BOARD_BEHOLD_607_9FM] = {
@@ -4251,6 +4293,36 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
} },
},
+ [SAA7134_BOARD_BEHOLD_H6] = {
+ /* Igor Kuznetsov <igk@igk.ru> */
+ .name = "Beholder BeholdTV H6",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ /* no DVB support for now */
+ /* .mpeg = SAA7134_MPEG_DVB, */
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5201,6 +5273,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x5ace,
.subdevice = 0x6193,
.driver_data = SAA7134_BOARD_BEHOLD_M6,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5ace,
+ .subdevice = 0x6191,
+ .driver_data = SAA7134_BOARD_BEHOLD_M6,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5250,6 +5328,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0xc900,
.driver_data = SAA7134_BOARD_VIDEOMATE_T750,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5ace,
+ .subdevice = 0x6290,
+ .driver_data = SAA7134_BOARD_BEHOLD_H6,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5574,7 +5658,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_CARDBUS:
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
case SAA7134_BOARD_AVERMEDIA_M115:
- case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
case SAA7134_BOARD_AVERMEDIA_A16D:
#if 1
/* power-down tuner chip */
@@ -5587,6 +5670,20 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
msleep(10);
break;
+ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+#if 1
+ /* power-down tuner chip */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
+#endif
+ msleep(10);
+ /* power-up tuner chip */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
+ msleep(10);
+ /* remote via GPIO */
+ dev->has_remote = SAA7134_REMOTE_GPIO;
+ break;
case SAA7134_BOARD_RTD_VFG7350:
/*
@@ -5632,20 +5729,87 @@ int saa7134_board_init1(struct saa7134_dev *dev)
return 0;
}
+static void saa7134_tuner_setup(struct saa7134_dev *dev)
+{
+ struct tuner_setup tun_setup;
+ unsigned int mode_mask = T_RADIO |
+ T_ANALOG_TV |
+ T_DIGITAL_TV;
+
+ memset(&tun_setup, 0, sizeof(tun_setup));
+ tun_setup.tuner_callback = saa7134_tuner_callback;
+
+ if (saa7134_boards[dev->board].radio_type != UNSET) {
+ tun_setup.type = saa7134_boards[dev->board].radio_type;
+ tun_setup.addr = saa7134_boards[dev->board].radio_addr;
+
+ tun_setup.mode_mask = T_RADIO;
+
+ saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+ mode_mask &= ~T_RADIO;
+ }
+
+ if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = dev->tuner_addr;
+ tun_setup.config = saa7134_boards[dev->board].tuner_config;
+ tun_setup.tuner_callback = saa7134_tuner_callback;
+
+ tun_setup.mode_mask = mode_mask;
+
+ saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+
+ if (dev->tda9887_conf) {
+ struct v4l2_priv_tun_config tda9887_cfg;
+
+ tda9887_cfg.tuner = TUNER_TDA9887;
+ tda9887_cfg.priv = &dev->tda9887_conf;
+
+ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
+ &tda9887_cfg);
+ }
+
+ if (dev->tuner_type == TUNER_XC2028) {
+ struct v4l2_priv_tun_config xc2028_cfg;
+ struct xc2028_ctrl ctl;
+
+ memset(&xc2028_cfg, 0, sizeof(ctl));
+ memset(&ctl, 0, sizeof(ctl));
+
+ ctl.fname = XC2028_DEFAULT_FIRMWARE;
+ ctl.max_len = 64;
+
+ switch (dev->board) {
+ case SAA7134_BOARD_AVERMEDIA_A16D:
+ ctl.demod = XC3028_FE_ZARLINK456;
+ break;
+ default:
+ ctl.demod = XC3028_FE_OREN538;
+ ctl.mts = 1;
+ }
+
+ xc2028_cfg.tuner = TUNER_XC2028;
+ xc2028_cfg.priv = &ctl;
+
+ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+ }
+}
+
/* stuff which needs working i2c */
int saa7134_board_init2(struct saa7134_dev *dev)
{
unsigned char buf;
int board;
- struct tuner_setup tun_setup;
- tun_setup.config = 0;
- tun_setup.tuner_callback = saa7134_tuner_callback;
+
+ dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+ dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
switch (dev->board) {
case SAA7134_BOARD_BMK_MPEX_NOTUNER:
case SAA7134_BOARD_BMK_MPEX_TUNER:
dev->i2c_client.addr = 0x60;
- board = (i2c_master_recv(&dev->i2c_client,&buf,0) < 0)
+ board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
? SAA7134_BOARD_BMK_MPEX_NOTUNER
: SAA7134_BOARD_BMK_MPEX_TUNER;
if (board == dev->board)
@@ -5655,21 +5819,9 @@ int saa7134_board_init2(struct saa7134_dev *dev)
saa7134_boards[dev->board].name);
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
- if (TUNER_ABSENT != dev->tuner_type) {
- tun_setup.mode_mask = T_RADIO |
- T_ANALOG_TV |
- T_DIGITAL_TV;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = ADDR_UNSET;
- tun_setup.tuner_callback = saa7134_tuner_callback;
-
- saa7134_i2c_call_clients(dev,
- TUNER_SET_TYPE_ADDR,
- &tun_setup);
- }
break;
case SAA7134_BOARD_MD7134:
- {
+ {
u8 subaddr;
u8 data[3];
int ret, tuner_t;
@@ -5722,30 +5874,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
- if (dev->tuner_type == TUNER_PHILIPS_FMD1216ME_MK3) {
- struct v4l2_priv_tun_config tda9887_cfg;
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &dev->tda9887_conf;
-
- dev->tda9887_conf = TDA9887_PRESENT |
- TDA9887_PORT1_ACTIVE |
- TDA9887_PORT2_ACTIVE;
-
- saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
- &tda9887_cfg);
- }
-
- tun_setup.mode_mask = T_RADIO |
- T_ANALOG_TV |
- T_DIGITAL_TV;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = ADDR_UNSET;
-
- saa7134_i2c_call_clients(dev,
- TUNER_SET_TYPE_ADDR, &tun_setup);
- }
break;
+ }
case SAA7134_BOARD_PHILIPS_EUROPA:
if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
/* Reconfigure board as Snake reference design */
@@ -5757,43 +5887,43 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+ {
+
/* The Philips EUROPA based hybrid boards have the tuner connected through
* the channel decoder. We have to make it transparent to find it
*/
- {
u8 data[] = { 0x07, 0x02};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
- tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = dev->tuner_addr;
-
- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
- }
break;
+ }
case SAA7134_BOARD_PHILIPS_TIGER:
case SAA7134_BOARD_PHILIPS_TIGER_S:
- {
+ {
u8 data[] = { 0x3c, 0x33, 0x60};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
- if(dev->autodetected && (dev->eedata[0x49] == 0x50)) {
+ if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
printk(KERN_INFO "%s: Reconfigured board as %s\n",
dev->name, saa7134_boards[dev->board].name);
}
- if(dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
- tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
- tun_setup.type = TUNER_PHILIPS_TDA8290;
- tun_setup.addr = 0x4b;
- tun_setup.config = 2;
+ if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
+ dev->tuner_type = TUNER_PHILIPS_TDA8290;
+
+ saa7134_tuner_setup(dev);
- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
data[2] = 0x68;
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ /* Tuner setup is handled before I2C transfer.
+ Due to that, there's no need to do it later
+ */
+ return 0;
}
i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
break;
+ }
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
hauppauge_eeprom(dev, dev->eedata+0x80);
/* break intentionally omitted */
@@ -5806,52 +5936,55 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_SUPER_007:
case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
case SAA7134_BOARD_CREATIX_CTX953:
+ {
/* this is a hybrid board, initialize to analog mode
* and configure firmware eeprom address
*/
- {
u8 data[] = { 0x3c, 0x33, 0x60};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
break;
+ }
case SAA7134_BOARD_FLYDVB_TRIO:
- {
+ {
u8 data[] = { 0x3c, 0x33, 0x62};
struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
break;
+ }
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+ {
/* initialize analog mode */
- {
u8 data[] = { 0x3c, 0x33, 0x6a};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
break;
+ }
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
case SAA7134_BOARD_CINERGY_HT_PCI:
+ {
/* initialize analog mode */
- {
u8 data[] = { 0x3c, 0x33, 0x68};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
- }
break;
+ }
case SAA7134_BOARD_KWORLD_ATSC110:
- {
- /* enable tuner */
- int i;
- static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 };
- dev->i2c_client.addr = 0x0a;
- for (i = 0; i < 5; i++)
- if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2))
- printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n",
- dev->name, i);
- }
+ {
+ /* enable tuner */
+ int i;
+ static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16,
+ 0x00, 0x14, 0x04, 0x17, 0x00 };
+ dev->i2c_client.addr = 0x0a;
+ for (i = 0; i < 5; i++)
+ if (2 != i2c_master_send(&dev->i2c_client,
+ &buffer[i*2], 2))
+ printk(KERN_WARNING
+ "%s: Unable to enable tuner(%i).\n",
+ dev->name, i);
break;
+ }
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
/* The T200 and the T200A share the same pci id. Consequently,
@@ -5875,32 +6008,23 @@ int saa7134_board_init2(struct saa7134_dev *dev)
break;
}
break;
- }
-
- if (dev->tuner_type == TUNER_XC2028) {
- struct v4l2_priv_tun_config xc2028_cfg;
- struct xc2028_ctrl ctl;
+ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+ {
+ struct v4l2_priv_tun_config tea5767_cfg;
+ struct tea5767_ctrl ctl;
- memset(&xc2028_cfg, 0, sizeof(ctl));
+ dev->i2c_client.addr = 0xC0;
+ /* set TEA5767(analog FM) defines */
memset(&ctl, 0, sizeof(ctl));
-
- ctl.fname = XC2028_DEFAULT_FIRMWARE;
- ctl.max_len = 64;
-
- switch (dev->board) {
- case SAA7134_BOARD_AVERMEDIA_A16D:
- ctl.demod = XC3028_FE_ZARLINK456;
- break;
- default:
- ctl.demod = XC3028_FE_OREN538;
- ctl.mts = 1;
- }
-
- xc2028_cfg.tuner = TUNER_XC2028;
- xc2028_cfg.priv = &ctl;
-
- saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+ ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+ tea5767_cfg.tuner = TUNER_TEA5767;
+ tea5767_cfg.priv = &ctl;
+ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
+ break;
}
+ } /* switch() */
+
+ saa7134_tuner_setup(dev);
return 0;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index 7296eeba0..9ed2997f7 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -960,7 +960,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
struct saa7134_dev *dev;
struct saa7134_mpeg_ops *mops;
int err;
- int mask;
if (saa7134_devcount == SAA7134_MAXBOARDS)
return -ENOMEM;
@@ -1161,11 +1160,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (TUNER_ABSENT != dev->tuner_type)
saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
- if (card(dev).gpiomask != 0) {
- mask = card(dev).gpiomask;
- saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask);
- saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0);
- }
return 0;
fail4:
diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c
index 165b4b850..a5a2d5905 100644
--- a/linux/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c
@@ -65,6 +65,8 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
#define dprintk(fmt, arg...) do { if (debug) \
printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
@@ -539,19 +541,23 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
return 0;
}
-static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf,
- struct tda827x_config *tuner_conf)
+static int configure_tda827x_fe(struct saa7134_dev *dev,
+ struct tda1004x_config *cdec_conf,
+ struct tda827x_config *tuner_conf)
{
dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
if (dev->dvb.frontend) {
if (cdec_conf->i2c_gate)
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
- if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address,
- &dev->i2c_adap, tuner_conf) == NULL) {
- wprintk("no tda827x tuner found at addr: %02x\n",
+ if (dvb_attach(tda827x_attach, dev->dvb.frontend,
+ cdec_conf->tuner_address,
+ &dev->i2c_adap, tuner_conf))
+ return 0;
+
+ wprintk("no tda827x tuner found at addr: %02x\n",
cdec_conf->tuner_address);
- }
}
+ return -EINVAL;
}
/* ------------------------------------------------------------------ */
@@ -852,6 +858,14 @@ static struct tda10086_config flydvbs = {
.demod_address = 0x0e,
.invert = 0,
.diseqc_tone = 0,
+ .xtal_freq = TDA10086_XTAL_16M,
+};
+
+static struct tda10086_config sd1878_4m = {
+ .demod_address = 0x0e,
+ .invert = 0,
+ .diseqc_tone = 0,
+ .xtal_freq = TDA10086_XTAL_4M,
};
/* ------------------------------------------------------------------
@@ -990,7 +1004,9 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_FLYDVBTDUO:
case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
- configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_PHILIPS_EUROPA:
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
@@ -1015,36 +1031,52 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_KWORLD_DVBT_210:
- configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2);
+ if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_PHILIPS_TIGER:
- configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &philips_tiger_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_PINNACLE_PCTV_310i:
- configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1);
+ if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config,
+ &tda827x_cfg_1) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
- configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1);
+ if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config,
+ &tda827x_cfg_1) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
- configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &asus_p7131_dual_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_FLYDVBT_LR301:
- configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_FLYDVB_TRIO:
- if(! use_frontend) { /* terrestrial */
- configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0);
+ if (!use_frontend) { /* terrestrial */
+ if (configure_tda827x_fe(dev, &lifeview_trio_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
} else { /* satellite */
dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
if (dev->dvb.frontend) {
if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
&dev->i2c_adap, 0) == NULL) {
wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+ goto dettach_frontend;
}
if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
0x08, 0, 0) == NULL) {
wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+ goto dettach_frontend;
}
}
}
@@ -1060,15 +1092,20 @@ static int dvb_init(struct saa7134_dev *dev)
&ads_duo_cfg) == NULL) {
wprintk("no tda827x tuner found at addr: %02x\n",
ads_tech_duo_config.tuner_address);
+ goto dettach_frontend;
}
}
break;
case SAA7134_BOARD_TEVION_DVBT_220RF:
- configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_MEDION_MD8800_QUADRO:
if (!use_frontend) { /* terrestrial */
- configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
} else { /* satellite */
dev->dvb.frontend = dvb_attach(tda10086_attach,
&flydvbs, &dev->i2c_adap);
@@ -1079,16 +1116,20 @@ static int dvb_init(struct saa7134_dev *dev)
struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
if (dvb_attach(tda826x_attach, dev->dvb.frontend,
- 0x60, &dev->i2c_adap, 0) == NULL)
+ 0x60, &dev->i2c_adap, 0) == NULL) {
wprintk("%s: Medion Quadro, no tda826x "
"found !\n", __func__);
+ goto dettach_frontend;
+ }
if (dev_id != 0x08) {
/* we need to open the i2c gate (we know it exists) */
fe->ops.i2c_gate_ctrl(fe, 1);
if (dvb_attach(isl6405_attach, fe,
- &dev->i2c_adap, 0x08, 0, 0) == NULL)
+ &dev->i2c_adap, 0x08, 0, 0) == NULL) {
wprintk("%s: Medion Quadro, no ISL6405 "
"found !\n", __func__);
+ goto dettach_frontend;
+ }
if (dev_id == 0x07) {
/* fire up the 2nd section of the LNB supply since
we can't do this from the other section */
@@ -1110,19 +1151,17 @@ static int dvb_init(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
+ if (dev->dvb.frontend)
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
NULL, DVB_PLL_TDHU2);
- }
break;
case SAA7134_BOARD_KWORLD_ATSC110:
dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
&dev->i2c_adap);
- if (dev->dvb.frontend) {
+ if (dev->dvb.frontend)
dvb_attach(simple_tuner_attach, dev->dvb.frontend,
&dev->i2c_adap, 0x61,
TUNER_PHILIPS_TUV1236D);
- }
break;
case SAA7134_BOARD_FLYDVBS_LR300:
dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
@@ -1131,10 +1170,12 @@ static int dvb_init(struct saa7134_dev *dev)
if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
wprintk("%s: No tda826x found!\n", __func__);
+ goto dettach_frontend;
}
if (dvb_attach(isl6421_attach, dev->dvb.frontend,
&dev->i2c_adap, 0x08, 0, 0) == NULL) {
wprintk("%s: No ISL6421 found!\n", __func__);
+ goto dettach_frontend;
}
}
break;
@@ -1161,43 +1202,65 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
- configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &cinergy_ht_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_CINERGY_HT_PCI:
- configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &cinergy_ht_pci_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_PHILIPS_TIGER_S:
- configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+ if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_ASUS_P7131_4871:
- configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2);
+ if (configure_tda827x_fe(dev, &asus_p7131_4871_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
- configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2);
+ if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_AVERMEDIA_SUPER_007:
- configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &avermedia_super_007_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
- configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42);
+ if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config,
+ &tda827x_cfg_2_sw42) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_PHILIPS_SNAKE:
dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
&dev->i2c_adap);
if (dev->dvb.frontend) {
if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
- &dev->i2c_adap, 0) == NULL)
+ &dev->i2c_adap, 0) == NULL) {
wprintk("%s: No tda826x found!\n", __func__);
+ goto dettach_frontend;
+ }
if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
- &dev->i2c_adap, 0, 0) == NULL)
+ &dev->i2c_adap, 0, 0) == NULL) {
wprintk("%s: No lnbp21 found!\n", __func__);
+ goto dettach_frontend;
+ }
}
break;
case SAA7134_BOARD_CREATIX_CTX953:
- configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
+ if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+ &tda827x_cfg_0) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
- configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+ if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+ &tda827x_cfg_2) < 0)
+ goto dettach_frontend;
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
#if 0
@@ -1211,20 +1274,24 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_MD7134_BRIDGE_2:
dev->dvb.frontend = dvb_attach(tda10086_attach,
- &flydvbs, &dev->i2c_adap);
+ &sd1878_4m, &dev->i2c_adap);
if (dev->dvb.frontend) {
struct dvb_frontend *fe;
if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
- &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL)
+ &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
wprintk("%s: MD7134 DVB-S, no SD1878 "
"found !\n", __func__);
+ goto dettach_frontend;
+ }
/* we need to open the i2c gate (we know it exists) */
fe = dev->dvb.frontend;
fe->ops.i2c_gate_ctrl(fe, 1);
if (dvb_attach(isl6405_attach, fe,
- &dev->i2c_adap, 0x08, 0, 0) == NULL)
+ &dev->i2c_adap, 0x08, 0, 0) == NULL) {
wprintk("%s: MD7134 DVB-S, no ISL6405 "
"found !\n", __func__);
+ goto dettach_frontend;
+ }
fe->ops.i2c_gate_ctrl(fe, 0);
dev->original_set_voltage = fe->ops.set_voltage;
fe->ops.set_voltage = md8800_set_voltage;
@@ -1251,10 +1318,7 @@ static int dvb_init(struct saa7134_dev *dev)
if (!fe) {
printk(KERN_ERR "%s/2: xc3028 attach failed\n",
dev->name);
- dvb_frontend_detach(dev->dvb.frontend);
- dvb_unregister_frontend(dev->dvb.frontend);
- dev->dvb.frontend = NULL;
- return -1;
+ goto dettach_frontend;
}
}
@@ -1264,7 +1328,8 @@ static int dvb_init(struct saa7134_dev *dev)
}
/* register everything else */
- ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
+ ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
+ adapter_nr);
/* this sequence is necessary to make the tda1004x load its firmware
* and to enter analog mode of hybrid boards
@@ -1278,6 +1343,13 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend);
}
return ret;
+
+dettach_frontend:
+ if (dev->dvb.frontend)
+ dvb_frontend_detach(dev->dvb.frontend);
+ dev->dvb.frontend = NULL;
+
+ return -1;
}
static int dvb_fini(struct saa7134_dev *dev)
@@ -1309,7 +1381,8 @@ static int dvb_fini(struct saa7134_dev *dev)
}
}
}
- videobuf_dvb_unregister(&dev->dvb);
+ if (dev->dvb.frontend)
+ videobuf_dvb_unregister(&dev->dvb);
return 0;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c
index b83e910c3..b8ecaa623 100644
--- a/linux/drivers/media/video/saa7134/saa7134-empress.c
+++ b/linux/drivers/media/video/saa7134/saa7134-empress.c
@@ -172,8 +172,7 @@ ts_mmap(struct file *file, struct vm_area_struct * vma)
static int empress_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = file->private_data;
strcpy(cap->driver, "saa7134");
strlcpy(cap->card, saa7134_boards[dev->board].name,
@@ -213,7 +212,7 @@ static int empress_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}
-static int empress_enum_fmt_cap(struct file *file, void *priv,
+static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
@@ -225,7 +224,7 @@ static int empress_enum_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int empress_g_fmt_cap(struct file *file, void *priv,
+static int empress_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -239,7 +238,7 @@ static int empress_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int empress_s_fmt_cap(struct file *file, void *priv,
+static int empress_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -363,9 +362,9 @@ static struct video_device saa7134_empress_template =
.minor = -1,
.vidioc_querycap = empress_querycap,
- .vidioc_enum_fmt_cap = empress_enum_fmt_cap,
- .vidioc_s_fmt_cap = empress_s_fmt_cap,
- .vidioc_g_fmt_cap = empress_g_fmt_cap,
+ .vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
.vidioc_reqbufs = empress_reqbufs,
.vidioc_querybuf = empress_querybuf,
.vidioc_qbuf = empress_qbuf,
@@ -419,7 +418,7 @@ static int empress_init(struct saa7134_dev *dev)
{
int err;
- dprintk("%s: %s\n",dev->name,__FUNCTION__);
+ dprintk("%s: %s\n",dev->name,__func__);
dev->empress_dev = video_device_alloc();
if (NULL == dev->empress_dev)
return -ENOMEM;
@@ -467,7 +466,7 @@ static int empress_init(struct saa7134_dev *dev)
static int empress_fini(struct saa7134_dev *dev)
{
- dprintk("%s: %s\n",dev->name,__FUNCTION__);
+ dprintk("%s: %s\n",dev->name,__func__);
if (NULL == dev->empress_dev)
return 0;
diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c
index fda6d44cd..c222313fc 100644
--- a/linux/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c
@@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status)
{
switch (status) {
case BUSY:
+ case TO_SCL:
+ case TO_ARB:
return true;
default:
return false;
@@ -327,8 +329,6 @@ static u32 functionality(struct i2c_adapter *adap)
static int attach_inform(struct i2c_client *client)
{
struct saa7134_dev *dev = client->adapter->algo_data;
- int tuner = dev->tuner_type;
- struct tuner_setup tun_setup;
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
@@ -357,46 +357,6 @@ static int attach_inform(struct i2c_client *client)
}
}
- if (!client->driver->command)
- return 0;
-
- if (saa7134_boards[dev->board].radio_type != UNSET) {
-
- tun_setup.type = saa7134_boards[dev->board].radio_type;
- tun_setup.addr = saa7134_boards[dev->board].radio_addr;
-
- if ((tun_setup.addr == ADDR_UNSET) || (tun_setup.addr == client->addr)) {
- tun_setup.mode_mask = T_RADIO;
-
- client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup);
- }
- }
-
- if (tuner != UNSET) {
- tun_setup.type = tuner;
- tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
- tun_setup.config = saa7134_boards[dev->board].tuner_config;
- tun_setup.tuner_callback = saa7134_tuner_callback;
-
- if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
-
- tun_setup.mode_mask = T_ANALOG_TV;
-
- client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup);
- }
-
- if (tuner == TUNER_TDA9887) {
- struct v4l2_priv_tun_config tda9887_cfg;
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &dev->tda9887_conf;
-
- client->driver->command(client, TUNER_SET_CONFIG,
- &tda9887_cfg);
- }
- }
-
-
return 0;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c
index 225f075e5..45c4c8125 100644
--- a/linux/drivers/media/video/saa7134/saa7134-input.c
+++ b/linux/drivers/media/video/saa7134/saa7134-input.c
@@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_MANLI_MTV001:
case SAA7134_BOARD_MANLI_MTV002:
+ ir_codes = ir_codes_manli;
+ mask_keycode = 0x001f00;
+ mask_keyup = 0x004000;
+ polling = 50; /* ms */
+ break;
case SAA7134_BOARD_BEHOLD_409FM:
case SAA7134_BOARD_BEHOLD_401:
case SAA7134_BOARD_BEHOLD_403:
@@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_505FM:
case SAA7134_BOARD_BEHOLD_507_9FM:
ir_codes = ir_codes_manli;
- mask_keycode = 0x001f00;
+ mask_keycode = 0x003f00;
+ mask_keyup = 0x004000;
+ polling = 50; /* ms */
+ break;
+ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+ ir_codes = ir_codes_behold_columbus;
+ mask_keycode = 0x003f00;
mask_keyup = 0x004000;
polling = 50; // ms
break;
@@ -530,6 +541,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
break;
case SAA7134_BOARD_BEHOLD_607_9FM:
case SAA7134_BOARD_BEHOLD_M6:
+ case SAA7134_BOARD_BEHOLD_H6:
snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
ir->get_key = get_key_beholdm6xx;
ir->ir_codes = ir_codes_behold;
diff --git a/linux/drivers/media/video/saa7134/saa7134-reg.h b/linux/drivers/media/video/saa7134/saa7134-reg.h
index 86f5eefdb..258792c17 100644
--- a/linux/drivers/media/video/saa7134/saa7134-reg.h
+++ b/linux/drivers/media/video/saa7134/saa7134-reg.h
@@ -353,6 +353,7 @@
/* I2S output */
#define SAA7134_I2S_AUDIO_OUTPUT 0x1c0
+#define SAA7134_I2S_AUDIO_CONTROL 0x591
/* test modes */
#define SAA7134_SPECIAL_MODE 0x1d0
diff --git a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
index 0d24ab598..89f64f927 100644
--- a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -928,13 +928,25 @@ void saa7134_enable_i2s(struct saa7134_dev *dev)
if (!card_is_empress(dev))
return;
- i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
- /* enable I2S audio output for the mpeg encoder */
- saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
- saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
- saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F);
- saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
+ switch (dev->board) {
+ case SAA7134_BOARD_BEHOLD_M6:
+ /* configure GPIO for out audio */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0E000000, 0x00000000);
+ /* Set I2S format */
+ saa_writeb(SAA7134_I2S_AUDIO_CONTROL, 0x00);
+ /* Start I2S */
+ saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x11);
+ break;
+ default:
+ i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
+
+ /* enable I2S audio output for the mpeg encoder */
+ saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
+ saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
+ saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F);
+ saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
+ }
}
int saa7134_tvaudio_rx2mode(u32 rx)
diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c
index 3b7774305..353679fef 100644
--- a/linux/drivers/media/video/saa7134/saa7134-video.c
+++ b/linux/drivers/media/video/saa7134/saa7134-video.c
@@ -1496,7 +1496,7 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */
-static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv,
+static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -1523,7 +1523,7 @@ static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv,
return 0;
}
-static int saa7134_g_fmt_cap(struct file *file, void *priv,
+static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -1539,7 +1539,7 @@ static int saa7134_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int saa7134_g_fmt_overlay(struct file *file, void *priv,
+static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -1553,7 +1553,7 @@ static int saa7134_g_fmt_overlay(struct file *file, void *priv,
return 0;
}
-static int saa7134_try_fmt_cap(struct file *file, void *priv,
+static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -1604,7 +1604,7 @@ static int saa7134_try_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int saa7134_try_fmt_overlay(struct file *file, void *priv,
+static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
@@ -1618,13 +1618,13 @@ static int saa7134_try_fmt_overlay(struct file *file, void *priv,
return verify_preview(dev, &f->fmt.win);
}
-static int saa7134_s_fmt_cap(struct file *file, void *priv,
+static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
int err;
- err = saa7134_try_fmt_cap(file, priv, f);
+ err = saa7134_try_fmt_vid_cap(file, priv, f);
if (0 != err)
return err;
@@ -1635,13 +1635,13 @@ static int saa7134_s_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int saa7134_s_fmt_overlay(struct file *file, void *priv,
+static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_fh *fh = priv;
struct saa7134_dev *dev = fh->dev;
int err;
- unsigned int flags;
+ unsigned long flags;
if (saa7134_no_overlay > 0) {
printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
@@ -2035,7 +2035,7 @@ static int saa7134_s_priority(struct file *file, void *f,
return v4l2_prio_change(&dev->prio, &fh->prio, prio);
}
-static int saa7134_enum_fmt_cap(struct file *file, void *priv,
+static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index >= FORMATS)
@@ -2049,7 +2049,7 @@ static int saa7134_enum_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int saa7134_enum_fmt_overlay(struct file *file, void *priv,
+static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (saa7134_no_overlay > 0) {
@@ -2068,7 +2068,7 @@ static int saa7134_enum_fmt_overlay(struct file *file, void *priv,
return 0;
}
-static int saa7134_enum_fmt_vbi(struct file *file, void *priv,
+static int saa7134_enum_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (0 != f->index)
@@ -2359,18 +2359,18 @@ struct video_device saa7134_video_template =
.fops = &video_fops,
.minor = -1,
.vidioc_querycap = saa7134_querycap,
- .vidioc_enum_fmt_cap = saa7134_enum_fmt_cap,
- .vidioc_g_fmt_cap = saa7134_g_fmt_cap,
- .vidioc_try_fmt_cap = saa7134_try_fmt_cap,
- .vidioc_s_fmt_cap = saa7134_s_fmt_cap,
- .vidioc_enum_fmt_overlay = saa7134_enum_fmt_overlay,
- .vidioc_g_fmt_overlay = saa7134_g_fmt_overlay,
- .vidioc_try_fmt_overlay = saa7134_try_fmt_overlay,
- .vidioc_s_fmt_overlay = saa7134_s_fmt_overlay,
- .vidioc_enum_fmt_vbi = saa7134_enum_fmt_vbi,
- .vidioc_g_fmt_vbi = saa7134_try_get_set_fmt_vbi,
- .vidioc_try_fmt_vbi = saa7134_try_get_set_fmt_vbi,
- .vidioc_s_fmt_vbi = saa7134_try_get_set_fmt_vbi,
+ .vidioc_enum_fmt_vid_cap = saa7134_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = saa7134_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = saa7134_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = saa7134_s_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_overlay = saa7134_enum_fmt_vid_overlay,
+ .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay,
+ .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay,
+ .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay,
+ .vidioc_enum_fmt_vbi_cap = saa7134_enum_fmt_vbi_cap,
+ .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
+ .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
+ .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
.vidioc_g_audio = saa7134_g_audio,
.vidioc_s_audio = saa7134_s_audio,
.vidioc_cropcap = saa7134_cropcap,
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index c8fb28d99..2aa30895f 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -270,6 +270,7 @@ struct saa7134_format {
#define SAA7134_BOARD_VIDEOMATE_T750 139
#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140
#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
+#define SAA7134_BOARD_BEHOLD_H6 142
#define SAA7134_MAXBOARDS 8
diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c
new file mode 100644
index 000000000..adcc7adc5
--- /dev/null
+++ b/linux/drivers/media/video/saa717x.c
@@ -0,0 +1,1547 @@
+/*
+ * saa717x - Philips SAA717xHL video decoder driver
+ *
+ * Based on the saa7115 driver
+ *
+ * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
+ * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
+ *
+ * Changes by T.Adachi (tadachi@tadachi-net.com)
+ * - support audio, video scaler etc, and checked the initialize sequence.
+ *
+ * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this is a reversed engineered driver based on captures from
+ * the I2C bus under Windows. This chip is very similar to the saa7134,
+ * though. Unfortunately, this driver is currently only working for NTSC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv.h>
+#include "compat.h"
+
+MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
+MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+module_param(debug, int, 0644);
+#else
+MODULE_PARM(debug, "i");
+#endif
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+static unsigned short normal_i2c[] = { 0x42 >> 1, I2C_CLIENT_END };
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+#endif
+
+I2C_CLIENT_INSMOD;
+#endif
+
+struct saa717x_state {
+ v4l2_std_id std;
+ int input;
+ int enable;
+ int radio;
+ int bright;
+ int contrast;
+ int hue;
+ int sat;
+ int playback;
+ int audio;
+ int tuner_audio_mode;
+ int audio_main_mute;
+ int audio_main_vol_r;
+ int audio_main_vol_l;
+ u16 audio_main_bass;
+ u16 audio_main_treble;
+ u16 audio_main_volume;
+ u16 audio_main_balance;
+ int audio_input;
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* for audio mode */
+#define TUNER_AUDIO_MONO 0 /* LL */
+#define TUNER_AUDIO_STEREO 1 /* LR */
+#define TUNER_AUDIO_LANG1 2 /* LL */
+#define TUNER_AUDIO_LANG2 3 /* RR */
+
+#define SAA717X_NTSC_WIDTH (704)
+#define SAA717X_NTSC_HEIGHT (480)
+
+/* ----------------------------------------------------------------------- */
+
+static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
+ unsigned char mm1[6];
+ struct i2c_msg msg;
+
+ msg.flags = 0;
+ msg.addr = client->addr;
+ mm1[0] = (reg >> 8) & 0xff;
+ mm1[1] = reg & 0xff;
+
+ if (fw_addr) {
+ mm1[4] = (value >> 16) & 0xff;
+ mm1[3] = (value >> 8) & 0xff;
+ mm1[2] = value & 0xff;
+ } else {
+ mm1[2] = value & 0xff;
+ }
+ msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
+ msg.buf = mm1;
+ v4l_dbg(2, debug, client, "wrote: reg 0x%03x=%08x\n", reg, value);
+ return i2c_transfer(adap, &msg, 1) == 1;
+}
+
+static void saa717x_write_regs(struct i2c_client *client, u32 *data)
+{
+ while (data[0] || data[1]) {
+ saa717x_write(client, data[0], data[1]);
+ data += 2;
+ }
+}
+
+static u32 saa717x_read(struct i2c_client *client, u32 reg)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
+ unsigned char mm1[2];
+ unsigned char mm2[4] = { 0, 0, 0, 0 };
+ struct i2c_msg msgs[2];
+ u32 value;
+
+ msgs[0].flags = 0;
+ msgs[1].flags = I2C_M_RD;
+ msgs[0].addr = msgs[1].addr = client->addr;
+ mm1[0] = (reg >> 8) & 0xff;
+ mm1[1] = reg & 0xff;
+ msgs[0].len = 2;
+ msgs[0].buf = mm1;
+ msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
+ msgs[1].buf = mm2;
+ i2c_transfer(adap, msgs, 2);
+
+ if (fw_addr)
+ value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+ else
+ value = mm2[0] & 0xff;
+
+ v4l_dbg(2, debug, client, "read: reg 0x%03x=0x%08x\n", reg, value);
+ return value;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static u32 reg_init_initialize[] =
+{
+ /* from linux driver */
+ 0x101, 0x008, /* Increment delay */
+
+ 0x103, 0x000, /* Analog input control 2 */
+ 0x104, 0x090, /* Analog input control 3 */
+ 0x105, 0x090, /* Analog input control 4 */
+ 0x106, 0x0eb, /* Horizontal sync start */
+ 0x107, 0x0e0, /* Horizontal sync stop */
+ 0x109, 0x055, /* Luminance control */
+
+ 0x10f, 0x02a, /* Chroma gain control */
+ 0x110, 0x000, /* Chroma control 2 */
+
+ 0x114, 0x045, /* analog/ADC */
+
+ 0x118, 0x040, /* RAW data gain */
+ 0x119, 0x080, /* RAW data offset */
+
+ 0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
+ 0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
+ 0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
+ 0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
+
+ 0x049, 0x000, /* VBI vertical input window start (H) TASK A */
+
+ 0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
+ 0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
+
+ 0x064, 0x080, /* Lumina brightness TASK A */
+ 0x065, 0x040, /* Luminance contrast TASK A */
+ 0x066, 0x040, /* Chroma saturation TASK A */
+ /* 067H: Reserved */
+ 0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
+ 0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
+ 0x06a, 0x000, /* VBI phase offset TASK A */
+
+ 0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
+ 0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
+
+ 0x072, 0x000, /* Vertical filter mode TASK A */
+
+ 0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
+ 0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
+ 0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
+ 0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
+
+ 0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
+
+ 0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
+ 0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
+
+ 0x0a4, 0x080, /* Lumina brightness TASK B */
+ 0x0a5, 0x040, /* Luminance contrast TASK B */
+ 0x0a6, 0x040, /* Chroma saturation TASK B */
+ /* 0A7H reserved */
+ 0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
+ 0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
+ 0x0aa, 0x000, /* VBI phase offset TASK B */
+
+ 0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
+ 0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
+
+ 0x0b2, 0x000, /* Vertical filter mode TASK B */
+
+ 0x00c, 0x000, /* Start point GREEN path */
+ 0x00d, 0x000, /* Start point BLUE path */
+ 0x00e, 0x000, /* Start point RED path */
+
+ 0x010, 0x010, /* GREEN path gamma curve --- */
+ 0x011, 0x020,
+ 0x012, 0x030,
+ 0x013, 0x040,
+ 0x014, 0x050,
+ 0x015, 0x060,
+ 0x016, 0x070,
+ 0x017, 0x080,
+ 0x018, 0x090,
+ 0x019, 0x0a0,
+ 0x01a, 0x0b0,
+ 0x01b, 0x0c0,
+ 0x01c, 0x0d0,
+ 0x01d, 0x0e0,
+ 0x01e, 0x0f0,
+ 0x01f, 0x0ff, /* --- GREEN path gamma curve */
+
+ 0x020, 0x010, /* BLUE path gamma curve --- */
+ 0x021, 0x020,
+ 0x022, 0x030,
+ 0x023, 0x040,
+ 0x024, 0x050,
+ 0x025, 0x060,
+ 0x026, 0x070,
+ 0x027, 0x080,
+ 0x028, 0x090,
+ 0x029, 0x0a0,
+ 0x02a, 0x0b0,
+ 0x02b, 0x0c0,
+ 0x02c, 0x0d0,
+ 0x02d, 0x0e0,
+ 0x02e, 0x0f0,
+ 0x02f, 0x0ff, /* --- BLUE path gamma curve */
+
+ 0x030, 0x010, /* RED path gamma curve --- */
+ 0x031, 0x020,
+ 0x032, 0x030,
+ 0x033, 0x040,
+ 0x034, 0x050,
+ 0x035, 0x060,
+ 0x036, 0x070,
+ 0x037, 0x080,
+ 0x038, 0x090,
+ 0x039, 0x0a0,
+ 0x03a, 0x0b0,
+ 0x03b, 0x0c0,
+ 0x03c, 0x0d0,
+ 0x03d, 0x0e0,
+ 0x03e, 0x0f0,
+ 0x03f, 0x0ff, /* --- RED path gamma curve */
+
+ 0x109, 0x085, /* Luminance control */
+
+ /**** from app start ****/
+ 0x584, 0x000, /* AGC gain control */
+ 0x585, 0x000, /* Program count */
+ 0x586, 0x003, /* Status reset */
+ 0x588, 0x0ff, /* Number of audio samples (L) */
+ 0x589, 0x00f, /* Number of audio samples (M) */
+ 0x58a, 0x000, /* Number of audio samples (H) */
+ 0x58b, 0x000, /* Audio select */
+ 0x58c, 0x010, /* Audio channel assign1 */
+ 0x58d, 0x032, /* Audio channel assign2 */
+ 0x58e, 0x054, /* Audio channel assign3 */
+ 0x58f, 0x023, /* Audio format */
+ 0x590, 0x000, /* SIF control */
+
+ 0x595, 0x000, /* ?? */
+ 0x596, 0x000, /* ?? */
+ 0x597, 0x000, /* ?? */
+
+ 0x464, 0x00, /* Digital input crossbar1 */
+
+ 0x46c, 0xbbbb10, /* Digital output selection1-3 */
+ 0x470, 0x101010, /* Digital output selection4-6 */
+
+ 0x478, 0x00, /* Sound feature control */
+
+ 0x474, 0x18, /* Softmute control */
+
+ 0x454, 0x0425b9, /* Sound Easy programming(reset) */
+ 0x454, 0x042539, /* Sound Easy programming(reset) */
+
+
+ /**** common setting( of DVD play, including scaler commands) ****/
+ 0x042, 0x003, /* Data path configuration for VBI (TASK A) */
+
+ 0x082, 0x003, /* Data path configuration for VBI (TASK B) */
+
+ 0x108, 0x0f8, /* Sync control */
+ 0x2a9, 0x0fd, /* ??? */
+ 0x102, 0x089, /* select video input "mode 9" */
+ 0x111, 0x000, /* Mode/delay control */
+
+ 0x10e, 0x00a, /* Chroma control 1 */
+
+ 0x594, 0x002, /* SIF, analog I/O select */
+
+ 0x454, 0x0425b9, /* Sound */
+ 0x454, 0x042539,
+
+ 0x111, 0x000,
+ 0x10e, 0x00a,
+ 0x464, 0x000,
+ 0x300, 0x000,
+ 0x301, 0x006,
+ 0x302, 0x000,
+ 0x303, 0x006,
+ 0x308, 0x040,
+ 0x309, 0x000,
+ 0x30a, 0x000,
+ 0x30b, 0x000,
+ 0x000, 0x002,
+ 0x001, 0x000,
+ 0x002, 0x000,
+ 0x003, 0x000,
+ 0x004, 0x033,
+ 0x040, 0x01d,
+ 0x041, 0x001,
+ 0x042, 0x004,
+ 0x043, 0x000,
+ 0x080, 0x01e,
+ 0x081, 0x001,
+ 0x082, 0x004,
+ 0x083, 0x000,
+ 0x190, 0x018,
+ 0x115, 0x000,
+ 0x116, 0x012,
+ 0x117, 0x018,
+ 0x04a, 0x011,
+ 0x08a, 0x011,
+ 0x04b, 0x000,
+ 0x08b, 0x000,
+ 0x048, 0x000,
+ 0x088, 0x000,
+ 0x04e, 0x012,
+ 0x08e, 0x012,
+ 0x058, 0x012,
+ 0x098, 0x012,
+ 0x059, 0x000,
+ 0x099, 0x000,
+ 0x05a, 0x003,
+ 0x09a, 0x003,
+ 0x05b, 0x001,
+ 0x09b, 0x001,
+ 0x054, 0x008,
+ 0x094, 0x008,
+ 0x055, 0x000,
+ 0x095, 0x000,
+ 0x056, 0x0c7,
+ 0x096, 0x0c7,
+ 0x057, 0x002,
+ 0x097, 0x002,
+ 0x0ff, 0x0ff,
+ 0x060, 0x001,
+ 0x0a0, 0x001,
+ 0x061, 0x000,
+ 0x0a1, 0x000,
+ 0x062, 0x000,
+ 0x0a2, 0x000,
+ 0x063, 0x000,
+ 0x0a3, 0x000,
+ 0x070, 0x000,
+ 0x0b0, 0x000,
+ 0x071, 0x004,
+ 0x0b1, 0x004,
+ 0x06c, 0x0e9,
+ 0x0ac, 0x0e9,
+ 0x06d, 0x003,
+ 0x0ad, 0x003,
+ 0x05c, 0x0d0,
+ 0x09c, 0x0d0,
+ 0x05d, 0x002,
+ 0x09d, 0x002,
+ 0x05e, 0x0f2,
+ 0x09e, 0x0f2,
+ 0x05f, 0x000,
+ 0x09f, 0x000,
+ 0x074, 0x000,
+ 0x0b4, 0x000,
+ 0x075, 0x000,
+ 0x0b5, 0x000,
+ 0x076, 0x000,
+ 0x0b6, 0x000,
+ 0x077, 0x000,
+ 0x0b7, 0x000,
+ 0x195, 0x008,
+ 0x0ff, 0x0ff,
+ 0x108, 0x0f8,
+ 0x111, 0x000,
+ 0x10e, 0x00a,
+ 0x2a9, 0x0fd,
+ 0x464, 0x001,
+ 0x454, 0x042135,
+ 0x598, 0x0e7,
+ 0x599, 0x07d,
+ 0x59a, 0x018,
+ 0x59c, 0x066,
+ 0x59d, 0x090,
+ 0x59e, 0x001,
+ 0x584, 0x000,
+ 0x585, 0x000,
+ 0x586, 0x003,
+ 0x588, 0x0ff,
+ 0x589, 0x00f,
+ 0x58a, 0x000,
+ 0x58b, 0x000,
+ 0x58c, 0x010,
+ 0x58d, 0x032,
+ 0x58e, 0x054,
+ 0x58f, 0x023,
+ 0x590, 0x000,
+ 0x595, 0x000,
+ 0x596, 0x000,
+ 0x597, 0x000,
+ 0x464, 0x000,
+ 0x46c, 0xbbbb10,
+ 0x470, 0x101010,
+
+
+ 0x478, 0x000,
+ 0x474, 0x018,
+ 0x454, 0x042135,
+ 0x598, 0x0e7,
+ 0x599, 0x07d,
+ 0x59a, 0x018,
+ 0x59c, 0x066,
+ 0x59d, 0x090,
+ 0x59e, 0x001,
+ 0x584, 0x000,
+ 0x585, 0x000,
+ 0x586, 0x003,
+ 0x588, 0x0ff,
+ 0x589, 0x00f,
+ 0x58a, 0x000,
+ 0x58b, 0x000,
+ 0x58c, 0x010,
+ 0x58d, 0x032,
+ 0x58e, 0x054,
+ 0x58f, 0x023,
+ 0x590, 0x000,
+ 0x595, 0x000,
+ 0x596, 0x000,
+ 0x597, 0x000,
+ 0x464, 0x000,
+ 0x46c, 0xbbbb10,
+ 0x470, 0x101010,
+
+ 0x478, 0x000,
+ 0x474, 0x018,
+ 0x454, 0x042135,
+ 0x598, 0x0e7,
+ 0x599, 0x07d,
+ 0x59a, 0x018,
+ 0x59c, 0x066,
+ 0x59d, 0x090,
+ 0x59e, 0x001,
+ 0x584, 0x000,
+ 0x585, 0x000,
+ 0x586, 0x003,
+ 0x588, 0x0ff,
+ 0x589, 0x00f,
+ 0x58a, 0x000,
+ 0x58b, 0x000,
+ 0x58c, 0x010,
+ 0x58d, 0x032,
+ 0x58e, 0x054,
+ 0x58f, 0x023,
+ 0x590, 0x000,
+ 0x595, 0x000,
+ 0x596, 0x000,
+ 0x597, 0x000,
+ 0x464, 0x000,
+ 0x46c, 0xbbbb10,
+ 0x470, 0x101010,
+ 0x478, 0x000,
+ 0x474, 0x018,
+ 0x454, 0x042135,
+ 0x193, 0x000,
+ 0x300, 0x000,
+ 0x301, 0x006,
+ 0x302, 0x000,
+ 0x303, 0x006,
+ 0x308, 0x040,
+ 0x309, 0x000,
+ 0x30a, 0x000,
+ 0x30b, 0x000,
+ 0x000, 0x002,
+ 0x001, 0x000,
+ 0x002, 0x000,
+ 0x003, 0x000,
+ 0x004, 0x033,
+ 0x040, 0x01d,
+ 0x041, 0x001,
+ 0x042, 0x004,
+ 0x043, 0x000,
+ 0x080, 0x01e,
+ 0x081, 0x001,
+ 0x082, 0x004,
+ 0x083, 0x000,
+ 0x190, 0x018,
+ 0x115, 0x000,
+ 0x116, 0x012,
+ 0x117, 0x018,
+ 0x04a, 0x011,
+ 0x08a, 0x011,
+ 0x04b, 0x000,
+ 0x08b, 0x000,
+ 0x048, 0x000,
+ 0x088, 0x000,
+ 0x04e, 0x012,
+ 0x08e, 0x012,
+ 0x058, 0x012,
+ 0x098, 0x012,
+ 0x059, 0x000,
+ 0x099, 0x000,
+ 0x05a, 0x003,
+ 0x09a, 0x003,
+ 0x05b, 0x001,
+ 0x09b, 0x001,
+ 0x054, 0x008,
+ 0x094, 0x008,
+ 0x055, 0x000,
+ 0x095, 0x000,
+ 0x056, 0x0c7,
+ 0x096, 0x0c7,
+ 0x057, 0x002,
+ 0x097, 0x002,
+ 0x060, 0x001,
+ 0x0a0, 0x001,
+ 0x061, 0x000,
+ 0x0a1, 0x000,
+ 0x062, 0x000,
+ 0x0a2, 0x000,
+ 0x063, 0x000,
+ 0x0a3, 0x000,
+ 0x070, 0x000,
+ 0x0b0, 0x000,
+ 0x071, 0x004,
+ 0x0b1, 0x004,
+ 0x06c, 0x0e9,
+ 0x0ac, 0x0e9,
+ 0x06d, 0x003,
+ 0x0ad, 0x003,
+ 0x05c, 0x0d0,
+ 0x09c, 0x0d0,
+ 0x05d, 0x002,
+ 0x09d, 0x002,
+ 0x05e, 0x0f2,
+ 0x09e, 0x0f2,
+ 0x05f, 0x000,
+ 0x09f, 0x000,
+ 0x074, 0x000,
+ 0x0b4, 0x000,
+ 0x075, 0x000,
+ 0x0b5, 0x000,
+ 0x076, 0x000,
+ 0x0b6, 0x000,
+ 0x077, 0x000,
+ 0x0b7, 0x000,
+ 0x195, 0x008,
+ 0x598, 0x0e7,
+ 0x599, 0x07d,
+ 0x59a, 0x018,
+ 0x59c, 0x066,
+ 0x59d, 0x090,
+ 0x59e, 0x001,
+ 0x584, 0x000,
+ 0x585, 0x000,
+ 0x586, 0x003,
+ 0x588, 0x0ff,
+ 0x589, 0x00f,
+ 0x58a, 0x000,
+ 0x58b, 0x000,
+ 0x58c, 0x010,
+ 0x58d, 0x032,
+ 0x58e, 0x054,
+ 0x58f, 0x023,
+ 0x590, 0x000,
+ 0x595, 0x000,
+ 0x596, 0x000,
+ 0x597, 0x000,
+ 0x464, 0x000,
+ 0x46c, 0xbbbb10,
+ 0x470, 0x101010,
+ 0x478, 0x000,
+ 0x474, 0x018,
+ 0x454, 0x042135,
+ 0x193, 0x0a6,
+ 0x108, 0x0f8,
+ 0x042, 0x003,
+ 0x082, 0x003,
+ 0x454, 0x0425b9,
+ 0x454, 0x042539,
+ 0x193, 0x000,
+ 0x193, 0x0a6,
+ 0x464, 0x000,
+
+ 0, 0
+};
+
+/* Tuner */
+static u32 reg_init_tuner_input[] = {
+ 0x108, 0x0f8, /* Sync control */
+ 0x111, 0x000, /* Mode/delay control */
+ 0x10e, 0x00a, /* Chroma control 1 */
+ 0, 0
+};
+
+/* Composite */
+static u32 reg_init_composite_input[] = {
+ 0x108, 0x0e8, /* Sync control */
+ 0x111, 0x000, /* Mode/delay control */
+ 0x10e, 0x04a, /* Chroma control 1 */
+ 0, 0
+};
+
+/* S-Video */
+static u32 reg_init_svideo_input[] = {
+ 0x108, 0x0e8, /* Sync control */
+ 0x111, 0x000, /* Mode/delay control */
+ 0x10e, 0x04a, /* Chroma control 1 */
+ 0, 0
+};
+
+static u32 reg_set_audio_template[4][2] =
+{
+ { /* for MONO
+ tadachi 6/29 DMA audio output select?
+ Register 0x46c
+ 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
+ 0: MAIN left, 1: MAIN right
+ 2: AUX1 left, 3: AUX1 right
+ 4: AUX2 left, 5: AUX2 right
+ 6: DPL left, 7: DPL right
+ 8: DPL center, 9: DPL surround
+ A: monitor output, B: digital sense */
+ 0xbbbb00,
+
+ /* tadachi 6/29 DAC and I2S output select?
+ Register 0x470
+ 7-4:DAC right ch. 3-0:DAC left ch.
+ I2S1 right,left I2S2 right,left */
+ 0x00,
+ },
+ { /* for STEREO */
+ 0xbbbb10, 0x101010,
+ },
+ { /* for LANG1 */
+ 0xbbbb00, 0x00,
+ },
+ { /* for LANG2/SAP */
+ 0xbbbb11, 0x111111,
+ }
+};
+
+
+/* Get detected audio flags (from saa7134 driver) */
+static void get_inf_dev_status(struct i2c_client *client,
+ int *dual_flag, int *stereo_flag)
+{
+ u32 reg_data3;
+
+ static char *stdres[0x20] = {
+ [0x00] = "no standard detected",
+ [0x01] = "B/G (in progress)",
+ [0x02] = "D/K (in progress)",
+ [0x03] = "M (in progress)",
+
+ [0x04] = "B/G A2",
+ [0x05] = "B/G NICAM",
+ [0x06] = "D/K A2 (1)",
+ [0x07] = "D/K A2 (2)",
+ [0x08] = "D/K A2 (3)",
+ [0x09] = "D/K NICAM",
+ [0x0a] = "L NICAM",
+ [0x0b] = "I NICAM",
+
+ [0x0c] = "M Korea",
+ [0x0d] = "M BTSC ",
+ [0x0e] = "M EIAJ",
+
+ [0x0f] = "FM radio / IF 10.7 / 50 deemp",
+ [0x10] = "FM radio / IF 10.7 / 75 deemp",
+ [0x11] = "FM radio / IF sel / 50 deemp",
+ [0x12] = "FM radio / IF sel / 75 deemp",
+
+ [0x13 ... 0x1e] = "unknown",
+ [0x1f] = "??? [in progress]",
+ };
+
+
+ *dual_flag = *stereo_flag = 0;
+
+ /* (demdec status: 0x528) */
+
+ /* read current status */
+ reg_data3 = saa717x_read(client, 0x0528);
+
+ v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
+ reg_data3, stdres[reg_data3 & 0x1f],
+ (reg_data3 & 0x000020) ? ",stereo" : "",
+ (reg_data3 & 0x000040) ? ",dual" : "");
+ v4l_dbg(1, debug, client, "detailed status: "
+ "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+ (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone " : "",
+ (reg_data3 & 0x000100) ? " A2/EIAJ dual " : "",
+ (reg_data3 & 0x000200) ? " A2/EIAJ stereo " : "",
+ (reg_data3 & 0x000400) ? " A2/EIAJ noise mute " : "",
+
+ (reg_data3 & 0x000800) ? " BTSC/FM radio pilot " : "",
+ (reg_data3 & 0x001000) ? " SAP carrier " : "",
+ (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
+ (reg_data3 & 0x004000) ? " SAP noise mute " : "",
+ (reg_data3 & 0x008000) ? " VDSP " : "",
+
+ (reg_data3 & 0x010000) ? " NICST " : "",
+ (reg_data3 & 0x020000) ? " NICDU " : "",
+ (reg_data3 & 0x040000) ? " NICAM muted " : "",
+ (reg_data3 & 0x080000) ? " NICAM reserve sound " : "",
+
+ (reg_data3 & 0x100000) ? " init done " : "");
+
+ if (reg_data3 & 0x000220) {
+ v4l_dbg(1, debug, client, "ST!!!\n");
+ *stereo_flag = 1;
+ }
+
+ if (reg_data3 & 0x000140) {
+ v4l_dbg(1, debug, client, "DUAL!!!\n");
+ *dual_flag = 1;
+ }
+}
+
+/* regs write to set audio mode */
+static void set_audio_mode(struct i2c_client *client, int audio_mode)
+{
+ v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
+ audio_mode);
+
+ saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
+ saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
+}
+
+/* write regs to video output level (bright,contrast,hue,sat) */
+static void set_video_output_level_regs(struct i2c_client *client,
+ struct saa717x_state *decoder)
+{
+ /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
+ saa717x_write(client, 0x10a, decoder->bright);
+
+ /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
+ 0h (luminance off) 40: i2c dump
+ c0h (-1.0 inverse chrominance)
+ 80h (-2.0 inverse chrominance) */
+ saa717x_write(client, 0x10b, decoder->contrast);
+
+ /* saturation? 7fh(max)-40h(ITU)-0h(color off)
+ c0h (-1.0 inverse chrominance)
+ 80h (-2.0 inverse chrominance) */
+ saa717x_write(client, 0x10c, decoder->sat);
+
+ /* color hue (phase) control
+ 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
+ saa717x_write(client, 0x10d, decoder->hue);
+}
+
+/* write regs to set audio volume, bass and treble */
+static int set_audio_regs(struct i2c_client *client,
+ struct saa717x_state *decoder)
+{
+ u8 mute = 0xac; /* -84 dB */
+ u32 val;
+ unsigned int work_l, work_r;
+
+ /* set SIF analog I/O select */
+ saa717x_write(client, 0x0594, decoder->audio_input);
+ v4l_dbg(1, debug, client, "set audio input %d\n",
+ decoder->audio_input);
+
+ /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
+ work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
+ work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
+ decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
+ decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
+
+ /* set main volume */
+ /* main volume L[7-0],R[7-0],0x00 24=24dB,-83dB, -84(mute) */
+ /* def:0dB->6dB(MPG600GR) */
+ /* if mute is on, set mute */
+ if (decoder->audio_main_mute) {
+ val = mute | (mute << 8);
+ } else {
+ val = (u8)decoder->audio_main_vol_l |
+ ((u8)decoder->audio_main_vol_r << 8);
+ }
+
+ saa717x_write(client, 0x480, val);
+
+ /* bass and treble; go to another function */
+ /* set bass and treble */
+ val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
+ saa717x_write(client, 0x488, val);
+ return 0;
+}
+
+/********** scaling staff ***********/
+static void set_h_prescale(struct i2c_client *client,
+ int task, int prescale)
+{
+ static const struct {
+ int xpsc;
+ int xacl;
+ int xc2_1;
+ int xdcg;
+ int vpfy;
+ } vals[] = {
+ /* XPSC XACL XC2_1 XDCG VPFY */
+ { 1, 0, 0, 0, 0 },
+ { 2, 2, 1, 2, 2 },
+ { 3, 4, 1, 3, 2 },
+ { 4, 8, 1, 4, 2 },
+ { 5, 8, 1, 4, 2 },
+ { 6, 8, 1, 4, 3 },
+ { 7, 8, 1, 4, 3 },
+ { 8, 15, 0, 4, 3 },
+ { 9, 15, 0, 4, 3 },
+ { 10, 16, 1, 5, 3 },
+ };
+ static const int count = ARRAY_SIZE(vals);
+ int i, task_shift;
+
+ task_shift = task * 0x40;
+ for (i = 0; i < count; i++)
+ if (vals[i].xpsc == prescale)
+ break;
+ if (i == count)
+ return;
+
+ /* horizonal prescaling */
+ saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
+ /* accumulation length */
+ saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
+ /* level control */
+ saa717x_write(client, 0x62 + task_shift,
+ (vals[i].xc2_1 << 3) | vals[i].xdcg);
+ /*FIR prefilter control */
+ saa717x_write(client, 0x63 + task_shift,
+ (vals[i].vpfy << 2) | vals[i].vpfy);
+}
+
+/********** scaling staff ***********/
+static void set_v_scale(struct i2c_client *client, int task, int yscale)
+{
+ int task_shift;
+
+ task_shift = task * 0x40;
+ /* Vertical scaling ratio (LOW) */
+ saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
+ /* Vertical scaling ratio (HI) */
+ saa717x_write(client, 0x71 + task_shift, yscale >> 8);
+}
+
+static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
+{
+ /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
+ return 0;
+}
+
+static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct saa717x_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if (ctrl->value < 0 || ctrl->value > 255) {
+ v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ state->bright = ctrl->value;
+ v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
+ saa717x_write(client, 0x10a, state->bright);
+ break;
+
+ case V4L2_CID_CONTRAST:
+ if (ctrl->value < 0 || ctrl->value > 127) {
+ v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ state->contrast = ctrl->value;
+ v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
+ saa717x_write(client, 0x10b, state->contrast);
+ break;
+
+ case V4L2_CID_SATURATION:
+ if (ctrl->value < 0 || ctrl->value > 127) {
+ v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ state->sat = ctrl->value;
+ v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
+ saa717x_write(client, 0x10c, state->sat);
+ break;
+
+ case V4L2_CID_HUE:
+ if (ctrl->value < -127 || ctrl->value > 127) {
+ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ state->hue = ctrl->value;
+ v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
+ saa717x_write(client, 0x10d, state->hue);
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ state->audio_main_mute = ctrl->value;
+ set_audio_regs(client, state);
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ state->audio_main_volume = ctrl->value;
+ set_audio_regs(client, state);
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ state->audio_main_balance = ctrl->value;
+ set_audio_regs(client, state);
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ state->audio_main_treble = ctrl->value;
+ set_audio_regs(client, state);
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ state->audio_main_bass = ctrl->value;
+ set_audio_regs(client, state);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct saa717x_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = state->bright;
+ break;
+
+ case V4L2_CID_CONTRAST:
+ ctrl->value = state->contrast;
+ break;
+
+ case V4L2_CID_SATURATION:
+ ctrl->value = state->sat;
+ break;
+
+ case V4L2_CID_HUE:
+ ctrl->value = state->hue;
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = state->audio_main_mute;
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = state->audio_main_volume;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ ctrl->value = state->audio_main_balance;
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ ctrl->value = state->audio_main_treble;
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ ctrl->value = state->audio_main_bass;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct v4l2_queryctrl saa717x_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535 / 100,
+ .default_value = 58880,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535 / 100,
+ .default_value = 32768,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BASS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Bass",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535 / 100,
+ .default_value = 32768,
+ }, {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Treble",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535 / 100,
+ .default_value = 32768,
+ },
+};
+
+static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
+{
+ int is_tuner = inp & 0x80; /* tuner input flag */
+
+ inp &= 0x7f;
+
+ v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
+ /* inputs from 0-9 are available*/
+ /* saa717x have mode0-mode9 but mode5 is reserved. */
+ if (inp < 0 || inp > 9 || inp == 5)
+ return -EINVAL;
+
+ if (decoder->input != inp) {
+ int input_line = inp;
+
+ decoder->input = input_line;
+ v4l_dbg(1, debug, client, "now setting %s input %d\n",
+ input_line >= 6 ? "S-Video" : "Composite",
+ input_line);
+
+ /* select mode */
+ saa717x_write(client, 0x102,
+ (saa717x_read(client, 0x102) & 0xf0) |
+ input_line);
+
+ /* bypass chrominance trap for modes 6..9 */
+ saa717x_write(client, 0x109,
+ (saa717x_read(client, 0x109) & 0x7f) |
+ (input_line < 6 ? 0x0 : 0x80));
+
+ /* change audio_mode */
+ if (is_tuner) {
+ /* tuner */
+ set_audio_mode(client, decoder->tuner_audio_mode);
+ } else {
+ /* Force to STEREO mode if Composite or
+ * S-Video were chosen */
+ set_audio_mode(client, TUNER_AUDIO_STEREO);
+ }
+ /* change initialize procedure (Composite/S-Video) */
+ if (is_tuner)
+ saa717x_write_regs(client, reg_init_tuner_input);
+ else if (input_line >= 6)
+ saa717x_write_regs(client, reg_init_svideo_input);
+ else
+ saa717x_write_regs(client, reg_init_composite_input);
+ }
+
+ return 0;
+}
+
+static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+ struct saa717x_state *decoder = i2c_get_clientdata(client);
+
+ v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
+
+ switch (cmd) {
+ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
+
+ case VIDIOC_G_CTRL:
+ return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
+
+ case VIDIOC_S_CTRL:
+ return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
+
+ case VIDIOC_QUERYCTRL: {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
+ if (qc->id && qc->id == saa717x_qctrl[i].id) {
+ memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_G_REGISTER: {
+ struct v4l2_register *reg = arg;
+
+ if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ reg->val = saa717x_read(client, reg->reg);
+ break;
+ }
+
+ case VIDIOC_DBG_S_REGISTER: {
+ struct v4l2_register *reg = arg;
+ u16 addr = reg->reg & 0xffff;
+ u8 val = reg->val & 0xff;
+
+ if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ saa717x_write(client, addr, val);
+ break;
+ }
+#endif
+
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *fmt = (struct v4l2_format *)arg;
+ struct v4l2_pix_format *pix;
+ int prescale, h_scale, v_scale;
+
+ pix = &fmt->fmt.pix;
+ v4l_dbg(1, debug, client, "decoder set size\n");
+
+ /* FIXME need better bounds checking here */
+ if (pix->width < 1 || pix->width > 1440)
+ return -EINVAL;
+ if (pix->height < 1 || pix->height > 960)
+ return -EINVAL;
+
+ /* scaling setting */
+ /* NTSC and interlace only */
+ prescale = SAA717X_NTSC_WIDTH / pix->width;
+ if (prescale == 0)
+ prescale = 1;
+ h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
+ /* interlace */
+ v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
+
+ /* Horizontal prescaling etc */
+ set_h_prescale(client, 0, prescale);
+ set_h_prescale(client, 1, prescale);
+
+ /* Horizontal scaling increment */
+ /* TASK A */
+ saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
+ saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
+ /* TASK B */
+ saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
+ saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
+
+ /* Vertical prescaling etc */
+ set_v_scale(client, 0, v_scale);
+ set_v_scale(client, 1, v_scale);
+
+ /* set video output size */
+ /* video number of pixels at output */
+ /* TASK A */
+ saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
+ saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
+ /* TASK B */
+ saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
+ saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
+
+ /* video number of lines at output */
+ /* TASK A */
+ saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
+ saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
+ /* TASK B */
+ saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
+ saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
+ break;
+ }
+
+ case AUDC_SET_RADIO:
+ decoder->radio = 1;
+ break;
+
+ case VIDIOC_S_STD: {
+ v4l2_std_id std = *(v4l2_std_id *) arg;
+
+ v4l_dbg(1, debug, client, "decoder set norm ");
+ v4l_dbg(1, debug, client, "(not yet implementd)\n");
+
+ decoder->radio = 0;
+ decoder->std = std;
+ break;
+ }
+
+ case VIDIOC_INT_G_AUDIO_ROUTING: {
+ struct v4l2_routing *route = arg;
+
+ route->input = decoder->audio_input;
+ route->output = 0;
+ break;
+ }
+
+ case VIDIOC_INT_S_AUDIO_ROUTING: {
+ struct v4l2_routing *route = arg;
+
+ if (route->input < 3) { /* FIXME! --tadachi */
+ decoder->audio_input = route->input;
+ v4l_dbg(1, debug, client,
+ "set decoder audio input to %d\n",
+ decoder->audio_input);
+ set_audio_regs(client, decoder);
+ break;
+ }
+ return -ERANGE;
+ }
+
+ case VIDIOC_INT_S_VIDEO_ROUTING: {
+ struct v4l2_routing *route = arg;
+ int inp = route->input;
+
+ return saa717x_set_video_input(client, decoder, inp);
+ }
+
+ case VIDIOC_STREAMON: {
+ v4l_dbg(1, debug, client, "decoder enable output\n");
+ decoder->enable = 1;
+ saa717x_write(client, 0x193, 0xa6);
+ break;
+ }
+
+ case VIDIOC_STREAMOFF: {
+ v4l_dbg(1, debug, client, "decoder disable output\n");
+ decoder->enable = 0;
+ saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
+ break;
+ }
+
+ /* change audio mode */
+ case VIDIOC_S_TUNER: {
+ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+ int audio_mode;
+ char *mes[4] = {
+ "MONO", "STEREO", "LANG1", "LANG2/SAP"
+ };
+
+ audio_mode = V4L2_TUNER_MODE_STEREO;
+
+ switch (vt->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ audio_mode = TUNER_AUDIO_MONO;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ audio_mode = TUNER_AUDIO_STEREO;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ audio_mode = TUNER_AUDIO_LANG2;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ audio_mode = TUNER_AUDIO_LANG1;
+ break;
+ }
+
+ v4l_dbg(1, debug, client, "change audio mode to %s\n",
+ mes[audio_mode]);
+ decoder->tuner_audio_mode = audio_mode;
+ /* The registers are not changed here. */
+ /* See DECODER_ENABLE_OUTPUT section. */
+ set_audio_mode(client, decoder->tuner_audio_mode);
+ break;
+ }
+
+ case VIDIOC_G_TUNER: {
+ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+ int dual_f, stereo_f;
+
+ if (decoder->radio)
+ break;
+ get_inf_dev_status(client, &dual_f, &stereo_f);
+
+ v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
+ stereo_f, dual_f);
+
+ /* mono */
+ if ((dual_f == 0) && (stereo_f == 0)) {
+ vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+ v4l_dbg(1, debug, client, "DETECT==MONO\n");
+ }
+
+ /* stereo */
+ if (stereo_f == 1) {
+ if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
+ vt->audmode == V4L2_TUNER_MODE_LANG1) {
+ vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
+ } else {
+ vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+ v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
+ }
+ }
+
+ /* dual */
+ if (dual_f == 1) {
+ if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
+ vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
+ v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
+ } else {
+ vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
+ v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
+ }
+ }
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ /* not yet implemented */
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+
+/* i2c implementation */
+
+/* ----------------------------------------------------------------------- */
+static int saa717x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct saa717x_state *decoder;
+ u8 id = 0;
+ char *p = "";
+
+ /* Check if the adapter supports the needed features */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+ snprintf(client->name, sizeof(client->name) - 1, "saa717x");
+#endif
+ if (saa717x_write(client, 0x5a4, 0xfe) &&
+ saa717x_write(client, 0x5a5, 0x0f) &&
+ saa717x_write(client, 0x5a6, 0x00) &&
+ saa717x_write(client, 0x5a7, 0x01))
+ id = saa717x_read(client, 0x5a0);
+ if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
+ v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
+ return -ENODEV;
+ }
+ if (id == 0xc2)
+ p = "saa7173";
+ else if (id == 0x32)
+ p = "saa7174A";
+ else if (id == 0x6c)
+ p = "saa7174HL";
+ else
+ p = "saa7171";
+ v4l_info(client, "%s found @ 0x%x (%s)\n", p,
+ client->addr << 1, client->adapter->name);
+
+ decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
+ i2c_set_clientdata(client, decoder);
+
+ if (decoder == NULL)
+ return -ENOMEM;
+ decoder->std = V4L2_STD_NTSC;
+ decoder->input = -1;
+ decoder->enable = 1;
+
+ /* tune these parameters */
+ decoder->bright = 0x80;
+ decoder->contrast = 0x44;
+ decoder->sat = 0x40;
+ decoder->hue = 0x00;
+
+ /* FIXME!! */
+ decoder->playback = 0; /* initially capture mode used */
+ decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
+
+ decoder->audio_input = 2; /* FIXME!! */
+
+ decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
+ /* set volume, bass and treble */
+ decoder->audio_main_vol_l = 6;
+ decoder->audio_main_vol_r = 6;
+ decoder->audio_main_bass = 0;
+ decoder->audio_main_treble = 0;
+ decoder->audio_main_mute = 0;
+ decoder->audio_main_balance = 32768;
+ /* normalize (24 to -40 (not -84) -> 65535 to 0) */
+ decoder->audio_main_volume =
+ (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
+
+ v4l_dbg(1, debug, client, "writing init values\n");
+
+ /* FIXME!! */
+ saa717x_write_regs(client, reg_init_initialize);
+ set_video_output_level_regs(client, decoder);
+ /* set bass,treble to 0db 20041101 K.Ohta */
+ decoder->audio_main_bass = 0;
+ decoder->audio_main_treble = 0;
+ set_audio_regs(client, decoder);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2*HZ);
+ return 0;
+}
+
+static int saa717x_remove(struct i2c_client *client)
+{
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id saa717x_id[] = {
+ { "saa717x", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa717x_id);
+
+#endif
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa717x",
+ .driverid = I2C_DRIVERID_SAA717X,
+ .command = saa717x_command,
+ .probe = saa717x_probe,
+ .remove = saa717x_remove,
+#ifdef I2C_CLASS_TV_ANALOG
+ .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = saa717x_id,
+#endif
+};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+EXPORT_NO_SYMBOLS;
+#endif
diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c
index 2ac144d9a..7a6c9c1fb 100644
--- a/linux/drivers/media/video/saa7185.c
+++ b/linux/drivers/media/video/saa7185.c
@@ -404,7 +404,7 @@ saa7185_detect_client (struct i2c_adapter *adapter,
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
client->adapter = adapter;
diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c
index 1bc4b3a3f..c82bfddde 100644
--- a/linux/drivers/media/video/se401.c
+++ b/linux/drivers/media/video/se401.c
@@ -304,10 +304,10 @@ static void se401_button_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto exit;
}
@@ -319,7 +319,7 @@ exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ __func__, status);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
diff --git a/linux/drivers/media/video/sn9c102/sn9c102.h b/linux/drivers/media/video/sn9c102/sn9c102.h
index e845e2dea..c6e41428d 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102.h
+++ b/linux/drivers/media/video/sn9c102/sn9c102.h
@@ -183,7 +183,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __func__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -198,7 +198,7 @@ do { \
pr_info("sn9c102: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("sn9c102: [%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __func__, __LINE__ , ## args); \
} \
} while (0)
#else
@@ -209,7 +209,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
__LINE__ , ## args)
#undef PDBGG
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c
index b1a7e36d2..6747c4d7c 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c
@@ -34,7 +34,7 @@
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/page-flags.h>
-#include <linux/byteorder/generic.h>
+#include <asm/byteorder.h>
#include <asm/page.h>
#include <asm/uaccess.h>
diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c
index 1e9215788..208ed5278 100644
--- a/linux/drivers/media/video/soc_camera.c
+++ b/linux/drivers/media/video/soc_camera.c
@@ -44,7 +44,7 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
return NULL;
}
-static int soc_camera_try_fmt_cap(struct file *file, void *priv,
+static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct soc_camera_file *icf = file->private_data;
@@ -137,15 +137,13 @@ static int soc_camera_reqbufs(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
- dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory);
+ dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory);
ret = videobuf_reqbufs(&icf->vb_vidq, p);
if (ret < 0)
return ret;
return ici->ops->reqbufs(icf, p);
-
- return ret;
}
static int soc_camera_querybuf(struct file *file, void *priv,
@@ -344,7 +342,7 @@ static struct file_operations soc_camera_fops = {
};
-static int soc_camera_s_fmt_cap(struct file *file, void *priv,
+static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct soc_camera_file *icf = file->private_data;
@@ -364,7 +362,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
/* buswidth may be further adjusted by the ici */
icd->buswidth = data_fmt->depth;
- ret = soc_camera_try_fmt_cap(file, icf, f);
+ ret = soc_camera_try_fmt_vid_cap(file, icf, f);
if (ret < 0)
return ret;
@@ -391,7 +389,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
}
-static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
+static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct soc_camera_file *icf = file->private_data;
@@ -410,7 +408,7 @@ static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int soc_camera_g_fmt_cap(struct file *file, void *priv,
+static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct soc_camera_file *icf = file->private_data;
@@ -453,7 +451,7 @@ static int soc_camera_streamon(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
- dev_dbg(&icd->dev, "%s\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s\n", __func__);
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -472,7 +470,7 @@ static int soc_camera_streamoff(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
- dev_dbg(&icd->dev, "%s\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s\n", __func__);
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -937,15 +935,15 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev->minor = -1;
vdev->tvnorms = V4L2_STD_UNKNOWN,
vdev->vidioc_querycap = soc_camera_querycap;
- vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap;
- vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap;
- vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap;
+ vdev->vidioc_g_fmt_vid_cap = soc_camera_g_fmt_vid_cap;
+ vdev->vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap;
+ vdev->vidioc_s_fmt_vid_cap = soc_camera_s_fmt_vid_cap;
vdev->vidioc_enum_input = soc_camera_enum_input;
vdev->vidioc_g_input = soc_camera_g_input;
vdev->vidioc_s_input = soc_camera_s_input;
vdev->vidioc_s_std = soc_camera_s_std;
vdev->vidioc_reqbufs = soc_camera_reqbufs;
- vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap;
+ vdev->vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap;
vdev->vidioc_querybuf = soc_camera_querybuf;
vdev->vidioc_qbuf = soc_camera_qbuf;
vdev->vidioc_dqbuf = soc_camera_dqbuf;
@@ -985,7 +983,7 @@ void soc_camera_video_stop(struct soc_camera_device *icd)
{
struct video_device *vdev = icd->vdev;
- dev_dbg(&icd->dev, "%s\n", __FUNCTION__);
+ dev_dbg(&icd->dev, "%s\n", __func__);
if (!icd->dev.parent || !vdev)
return;
diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c
index 015f6a53f..28abeec05 100644
--- a/linux/drivers/media/video/stk-webcam.c
+++ b/linux/drivers/media/video/stk-webcam.c
@@ -30,6 +30,7 @@
#include <linux/kref.h>
#include <linux/usb.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include "compat.h"
#include <linux/videodev2.h>
@@ -246,6 +247,8 @@ static int stk_initialise(struct stk_camera *dev)
return -1;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+
/* sysfs functions */
/*FIXME cleanup this */
@@ -351,6 +354,10 @@ static void stk_remove_sysfs_files(struct video_device *vdev)
video_device_remove_file(vdev, &dev_attr_vflip);
}
+#else
+#define stk_create_sysfs_files(a)
+#define stk_remove_sysfs_files(a)
+#endif
/* *********************************************** */
/*
@@ -975,7 +982,7 @@ static int stk_vidioc_s_ctrl(struct file *filp,
}
-static int stk_vidioc_enum_fmt_cap(struct file *filp,
+static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_fmtdesc *fmtd)
{
fmtd->flags = 0;
@@ -1019,7 +1026,7 @@ static struct stk_size {
{ .w = 176, .h = 144, .m = MODE_QCIF, },
};
-static int stk_vidioc_g_fmt_cap(struct file *filp,
+static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_format *f)
{
struct v4l2_pix_format *pix_format = &f->fmt.pix;
@@ -1048,7 +1055,7 @@ static int stk_vidioc_g_fmt_cap(struct file *filp,
return 0;
}
-static int stk_vidioc_try_fmt_cap(struct file *filp,
+static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_format *fmtd)
{
int i;
@@ -1101,7 +1108,7 @@ static int stk_setup_format(struct stk_camera *dev)
&& i < ARRAY_SIZE(stk_sizes))
i++;
if (i == ARRAY_SIZE(stk_sizes)) {
- STK_ERROR("Something is broken in %s\n", __FUNCTION__);
+ STK_ERROR("Something is broken in %s\n", __func__);
return -EFAULT;
}
/* This registers controls some timings, not sure of what. */
@@ -1125,7 +1132,7 @@ static int stk_setup_format(struct stk_camera *dev)
return stk_sensor_configure(dev);
}
-static int stk_vidioc_s_fmt_cap(struct file *filp,
+static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_format *fmtd)
{
int ret;
@@ -1139,7 +1146,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
return -EBUSY;
if (dev->owner && dev->owner != filp)
return -EBUSY;
- ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd);
+ ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
if (ret)
return ret;
dev->owner = filp;
@@ -1336,10 +1343,10 @@ static struct video_device stk_v4l_data = {
.release = stk_v4l_dev_release,
.vidioc_querycap = stk_vidioc_querycap,
- .vidioc_enum_fmt_cap = stk_vidioc_enum_fmt_cap,
- .vidioc_try_fmt_cap = stk_vidioc_try_fmt_cap,
- .vidioc_s_fmt_cap = stk_vidioc_s_fmt_cap,
- .vidioc_g_fmt_cap = stk_vidioc_g_fmt_cap,
+ .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,
.vidioc_enum_input = stk_vidioc_enum_input,
.vidioc_s_input = stk_vidioc_s_input,
.vidioc_g_input = stk_vidioc_g_input,
diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c
index dfbb63b93..8bc396533 100644
--- a/linux/drivers/media/video/stv680.c
+++ b/linux/drivers/media/video/stv680.c
@@ -86,7 +86,7 @@ static unsigned int debug;
#define PDEBUG(level, fmt, args...) \
do { \
if (debug >= level) \
- info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \
+ info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
} while (0)
diff --git a/linux/drivers/media/video/tcm825x.c b/linux/drivers/media/video/tcm825x.c
index fb895f668..08c7888e5 100644
--- a/linux/drivers/media/video/tcm825x.c
+++ b/linux/drivers/media/video/tcm825x.c
@@ -523,6 +523,9 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s,
if (val < 0)
return val;
+ if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
+ val ^= sensor->platform_data->is_upside_down();
+
vc->value = val;
return 0;
}
@@ -556,6 +559,9 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s,
if (lvc == NULL)
return -EINVAL;
+ if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
+ val ^= sensor->platform_data->is_upside_down();
+
val = val << lvc->start_bit;
if (tcm825x_write_reg_mask(client, lvc->reg, val))
return -EIO;
@@ -840,7 +846,8 @@ static struct v4l2_int_device tcm825x_int_device = {
},
};
-static int tcm825x_probe(struct i2c_client *client)
+static int tcm825x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct tcm825x_sensor *sensor = &tcm825x;
int rval;
@@ -884,12 +891,23 @@ static int __exit tcm825x_remove(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id tcm825x_id[] = {
+ { "tcm825x", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tcm825x_id);
+#endif
+
static struct i2c_driver tcm825x_i2c_driver = {
.driver = {
.name = TCM825X_NAME,
},
.probe = tcm825x_probe,
.remove = __exit_p(tcm825x_remove),
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = tcm825x_id,
+#endif
};
static struct tcm825x_sensor tcm825x = {
@@ -906,7 +924,7 @@ static int __init tcm825x_init(void)
rval = i2c_add_driver(&tcm825x_i2c_driver);
if (rval)
printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
- __FUNCTION__);
+ __func__);
return rval;
}
diff --git a/linux/drivers/media/video/tcm825x.h b/linux/drivers/media/video/tcm825x.h
index 966765b66..770ebacfa 100644
--- a/linux/drivers/media/video/tcm825x.h
+++ b/linux/drivers/media/video/tcm825x.h
@@ -182,6 +182,7 @@ struct tcm825x_platform_data {
int (*needs_reset)(struct v4l2_int_device *s, void *buf,
struct v4l2_pix_format *fmt);
int (*ifparm)(struct v4l2_ifparm *p);
+ int (*is_upside_down)(void);
};
/* Array of image sizes supported by TCM825X. These must be ordered from
diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c
index 8218f466d..c41e50ba6 100644
--- a/linux/drivers/media/video/tda9840.c
+++ b/linux/drivers/media/video/tda9840.c
@@ -37,10 +37,10 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __func__, __LINE__); printk(args); } } while (0)
#else
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
#endif
#define SWITCH 0x00
@@ -181,7 +181,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
/* allocate memory for client structure */
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (0 == client) {
+ if (!client) {
printk("not enough kernel memory\n");
return -ENOMEM;
}
diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c
index 003fe1edb..16f369195 100644
--- a/linux/drivers/media/video/tea6415c.c
+++ b/linux/drivers/media/video/tea6415c.c
@@ -39,10 +39,10 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __func__, __LINE__); printk(args); } } while (0)
#else
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
#endif
#define TEA6415C_NUM_INPUTS 8
@@ -73,7 +73,7 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
/* allocate memory for client structure */
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (0 == client) {
+ if (!client) {
return -ENOMEM;
}
diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c
index 261675012..7a8fec9cf 100644
--- a/linux/drivers/media/video/tea6420.c
+++ b/linux/drivers/media/video/tea6420.c
@@ -39,10 +39,10 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __func__, __LINE__); printk(args); } } while (0)
#else
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
#endif
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
@@ -110,7 +110,7 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
/* allocate memory for client structure */
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (0 == client) {
+ if (!client) {
return -ENOMEM;
}
diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c
index 29e1f8a7b..9f96e200c 100644
--- a/linux/drivers/media/video/tlv320aic23b.c
+++ b/linux/drivers/media/video/tlv320aic23b.c
@@ -133,7 +133,8 @@ static int tlv320aic23b_command(struct i2c_client *client,
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int tlv320aic23b_probe(struct i2c_client *client)
+static int tlv320aic23b_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tlv320aic23b_state *state;
@@ -174,15 +175,25 @@ static int tlv320aic23b_remove(struct i2c_client *client)
}
/* ----------------------------------------------------------------------- */
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
EXPORT_NO_SYMBOLS;
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id tlv320aic23b_id[] = {
+ { "tlv320aic23b", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "tlv320aic23b",
.driverid = I2C_DRIVERID_TLV320AIC23B,
.command = tlv320aic23b_command,
.probe = tlv320aic23b_probe,
.remove = tlv320aic23b_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = tlv320aic23b_id,
+#endif
};
diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c
index 38a90afb6..e0228b865 100644
--- a/linux/drivers/media/video/tuner-core.c
+++ b/linux/drivers/media/video/tuner-core.c
@@ -41,6 +41,46 @@
#define PREFIX t->i2c->driver->driver.name
#endif
+/** This macro allows us to probe dynamically, avoiding static links */
+#ifdef CONFIG_MEDIA_ATTACH
+#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
+ int __r = -EINVAL; \
+ typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+ if (__a) { \
+ __r = (int) __a(ARGS); \
+ symbol_put(FUNCTION); \
+ } else { \
+ printk(KERN_ERR "TUNER: Unable to find " \
+ "symbol "#FUNCTION"()\n"); \
+ } \
+ __r; \
+})
+
+static void tuner_detach(struct dvb_frontend *fe)
+{
+ if (fe->ops.tuner_ops.release) {
+ fe->ops.tuner_ops.release(fe);
+ symbol_put_addr(fe->ops.tuner_ops.release);
+ }
+ if (fe->ops.analog_ops.release) {
+ fe->ops.analog_ops.release(fe);
+ symbol_put_addr(fe->ops.analog_ops.release);
+ }
+}
+#else
+#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
+ FUNCTION(ARGS); \
+})
+
+static void tuner_detach(struct dvb_frontend *fe)
+{
+ if (fe->ops.tuner_ops.release)
+ fe->ops.tuner_ops.release(fe);
+ if (fe->ops.analog_ops.release)
+ fe->ops.analog_ops.release(fe);
+}
+#endif
+
struct tuner {
/* device */
struct dvb_frontend fe;
@@ -60,11 +100,12 @@ struct tuner {
unsigned int type; /* chip type id */
unsigned int config;
int (*tuner_callback) (void *dev, int command, int arg);
+ const char *name;
};
/* standard i2c insmod options */
static unsigned short normal_i2c[] = {
-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
0x10,
#endif
0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
@@ -168,22 +209,6 @@ static void fe_set_params(struct dvb_frontend *fe,
fe_tuner_ops->set_analog_params(fe, params);
}
-static void fe_release(struct dvb_frontend *fe)
-{
- if (fe->ops.tuner_ops.release)
- fe->ops.tuner_ops.release(fe);
-
- /* DO NOT kfree(fe->analog_demod_priv)
- *
- * If we are in this function, analog_demod_priv contains a pointer
- * to struct tuner *t. This will be kfree'd in tuner_detach().
- *
- * Otherwise, fe->ops.analog_demod_ops->release will
- * handle the cleanup for analog demodulator modules.
- */
- fe->analog_demod_priv = NULL;
-}
-
static void fe_standby(struct dvb_frontend *fe)
{
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
@@ -220,7 +245,6 @@ static void tuner_status(struct dvb_frontend *fe);
static struct analog_demod_ops tuner_core_ops = {
.set_params = fe_set_params,
.standby = fe_standby,
- .release = fe_release,
.has_signal = fe_has_signal,
.set_config = fe_set_config,
.tuner_status = tuner_status
@@ -336,25 +360,16 @@ static void tuner_i2c_address_check(struct tuner *t)
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);
+ t->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, t->i2c->name);
+ t->i2c->adapter->name, t->i2c->addr, t->type, t->name);
tuner_warn("====================== WARNING! ======================\n");
}
-static void attach_tda829x(struct tuner *t)
-{
- struct tda829x_config cfg = {
- .lna_cfg = t->config,
- .tuner_callback = t->tuner_callback,
- };
- tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
-}
-
static struct xc5000_config xc5000_cfg;
static void set_type(struct i2c_client *c, unsigned int type,
@@ -385,32 +400,36 @@ static void set_type(struct i2c_client *c, unsigned int type,
}
/* discard private data, in case set_type() was previously called */
- if (analog_ops->release)
- analog_ops->release(&t->fe);
+ tuner_detach(&t->fe);
+ t->fe.analog_demod_priv = NULL;
switch (t->type) {
case TUNER_MT2032:
- microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+ if (!dvb_attach(microtune_attach,
+ &t->fe, t->i2c->adapter, t->i2c->addr))
+ goto attach_failed;
break;
case TUNER_PHILIPS_TDA8290:
{
- attach_tda829x(t);
+ struct tda829x_config cfg = {
+ .lna_cfg = t->config,
+ .tuner_callback = t->tuner_callback,
+ };
+ if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
+ t->i2c->addr, &cfg))
+ goto attach_failed;
break;
}
case TUNER_TEA5767:
- if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
+ if (!dvb_attach(tea5767_attach, &t->fe,
+ t->i2c->adapter, t->i2c->addr))
+ goto attach_failed;
t->mode_mask = T_RADIO;
break;
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;
- }
+ if (!dvb_attach(tea5761_attach, &t->fe,
+ t->i2c->adapter, t->i2c->addr))
+ goto attach_failed;
t->mode_mask = T_RADIO;
break;
case TUNER_PHILIPS_FMD1216ME_MK3:
@@ -423,25 +442,19 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[2] = 0x86;
buffer[3] = 0x54;
i2c_master_send(c, buffer, 4);
- if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
- t->type) == NULL) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
+ if (!dvb_attach(simple_tuner_attach, &t->fe,
+ t->i2c->adapter, t->i2c->addr, t->type))
+ goto attach_failed;
break;
case TUNER_PHILIPS_TD1316:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
buffer[2] = 0x86;
buffer[3] = 0xa4;
- i2c_master_send(c,buffer,4);
- if (simple_tuner_attach(&t->fe, t->i2c->adapter,
- t->i2c->addr, t->type) == NULL) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
+ i2c_master_send(c, buffer, 4);
+ if (!dvb_attach(simple_tuner_attach, &t->fe,
+ t->i2c->adapter, t->i2c->addr, t->type))
+ goto attach_failed;
break;
case TUNER_XC2028:
{
@@ -450,62 +463,67 @@ static void set_type(struct i2c_client *c, unsigned int type,
.i2c_addr = t->i2c->addr,
.callback = t->tuner_callback,
};
- if (!xc2028_attach(&t->fe, &cfg)) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
+ if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
+ goto attach_failed;
break;
}
case TUNER_TDA9887:
- tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+ if (!dvb_attach(tda9887_attach,
+ &t->fe, t->i2c->adapter, t->i2c->addr))
+ goto attach_failed;
break;
case TUNER_XC5000:
+ {
+ struct dvb_tuner_ops *xc_tuner_ops;
+
xc5000_cfg.i2c_address = t->i2c->addr;
xc5000_cfg.if_khz = 5380;
- xc5000_cfg.priv = c->adapter->algo_data;
xc5000_cfg.tuner_callback = t->tuner_callback;
- if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
- {
- struct dvb_tuner_ops *xc_tuner_ops;
+ if (!dvb_attach(xc5000_attach,
+ &t->fe, t->i2c->adapter, &xc5000_cfg,
+ c->adapter->algo_data))
+ goto attach_failed;
+
xc_tuner_ops = &t->fe.ops.tuner_ops;
- if(xc_tuner_ops->init != NULL)
+ if (xc_tuner_ops->init)
xc_tuner_ops->init(&t->fe);
- }
break;
+ }
default:
- if (simple_tuner_attach(&t->fe, t->i2c->adapter,
- t->i2c->addr, t->type) == NULL) {
- t->type = TUNER_ABSENT;
- t->mode_mask = T_UNINITIALIZED;
- return;
- }
+ if (!dvb_attach(simple_tuner_attach, &t->fe,
+ t->i2c->adapter, t->i2c->addr, t->type))
+ goto attach_failed;
+
break;
}
if ((NULL == analog_ops->set_params) &&
(fe_tuner_ops->set_analog_params)) {
- strlcpy(t->i2c->name, fe_tuner_ops->info.name,
- sizeof(t->i2c->name));
+
+ t->name = fe_tuner_ops->info.name;
t->fe.analog_demod_priv = t;
memcpy(analog_ops, &tuner_core_ops,
sizeof(struct analog_demod_ops));
+
} else {
- strlcpy(t->i2c->name, analog_ops->info.name,
- sizeof(t->i2c->name));
+ t->name = analog_ops->info.name;
}
- tuner_dbg("type set to %s\n", t->i2c->name);
+ tuner_dbg("type set to %s\n", t->name);
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
- set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
+ /* xc2028/3028 and xc5000 requires a firmware to be set-up later
+ trying to set a frequency here will just fail
+ FIXME: better to move set_freq to the tuner code. This is needed
+ on analog tuners for PLL to properly work
+ */
+ if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000)
+ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
+ t->radio_freq : t->tv_freq);
+
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
c->adapter->name, c->driver->name, c->addr << 1, type,
@@ -516,6 +534,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
t->mode_mask);
#endif
tuner_i2c_address_check(t);
+ return;
+
+attach_failed:
+ tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+
+ return;
}
/*
@@ -530,14 +556,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
{
struct tuner *t = i2c_get_clientdata(c);
- tuner_dbg("set addr for type %i\n", t->type);
-
if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
(t->mode_mask & tun_setup->mode_mask))) ||
(tun_setup->addr == c->addr)) {
set_type(c, tun_setup->type, tun_setup->mode_mask,
tun_setup->config, tun_setup->tuner_callback);
- }
+ } else
+ tuner_dbg("set addr discarded for type %i, mask %x. "
+ "Asked to change tuner at addr 0x%02x, with mask %x\n",
+ t->type, t->mode_mask,
+ tun_setup->addr, tun_setup->mode_mask);
}
static inline int check_mode(struct tuner *t, char *cmd)
@@ -546,7 +574,7 @@ static inline int check_mode(struct tuner *t, char *cmd)
#if 0
tuner_dbg("Cmd %s rejected for mode %i\n", cmd,t->mode);
#endif
- return EINVAL;
+ return -EINVAL;
}
switch (t->mode) {
@@ -683,8 +711,8 @@ static void tuner_status(struct dvb_frontend *fe)
{
struct tuner *t = fe->analog_demod_priv;
unsigned long freq, freq_fraction;
- struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
- struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+ struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
+ struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
const char *p;
switch (t->mode) {
@@ -740,11 +768,11 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
t->mode = mode;
- if (check_mode(t, cmd) == EINVAL) {
+ if (check_mode(t, cmd) == -EINVAL) {
t->mode = T_STANDBY;
if (analog_ops->standby)
analog_ops->standby(&t->fe);
- return EINVAL;
+ return -EINVAL;
}
return 0;
}
@@ -774,8 +802,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
- if (tuner_debug>1)
+ if (tuner_debug > 1) {
v4l_i2c_print_ioctl(client,cmd);
+ printk("\n");
+ }
switch (cmd) {
/* --- configuration --- */
@@ -790,23 +820,23 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
case AUDC_SET_RADIO:
if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
- == EINVAL)
+ == -EINVAL)
return 0;
if (t->radio_freq)
set_freq(client, t->radio_freq);
break;
case TUNER_SET_STANDBY:
- if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL)
return 0;
t->mode = T_STANDBY;
if (analog_ops->standby)
analog_ops->standby(&t->fe);
break;
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_ALLOW_V4L1
case VIDIOCSAUDIO:
- if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+ if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
/* Should be implemented, since bttv calls it */
@@ -824,10 +854,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
};
struct video_channel *vc = arg;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
- if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL)
+ if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL)
return 0;
if (vc->norm < ARRAY_SIZE(map))
@@ -841,9 +871,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
unsigned long *v = arg;
- if (check_mode(t, "VIDIOCSFREQ") == EINVAL)
+ if (check_mode(t, "VIDIOCSFREQ") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
set_freq(client, *v);
@@ -853,9 +883,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_tuner *vt = arg;
- if (check_mode(t, "VIDIOCGTUNER") == EINVAL)
+ if (check_mode(t, "VIDIOCGTUNER") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
if (V4L2_TUNER_RADIO == t->mode) {
@@ -897,9 +927,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_audio *va = arg;
- if (check_mode(t, "VIDIOCGAUDIO") == EINVAL)
+ if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL)
return 0;
- if (check_v4l2(t) == EINVAL)
+ if (check_v4l2(t) == -EINVAL)
return 0;
if (V4L2_TUNER_RADIO == t->mode) {
@@ -939,7 +969,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
v4l2_std_id *id = arg;
if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
- == EINVAL)
+ == -EINVAL)
return 0;
switch_v4l2();
@@ -955,7 +985,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_frequency *f = arg;
if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
- == EINVAL)
+ == -EINVAL)
return 0;
switch_v4l2();
set_freq(client,f->frequency);
@@ -966,7 +996,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_frequency *f = arg;
- if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL)
+ if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL)
return 0;
switch_v4l2();
f->type = t->mode;
@@ -987,7 +1017,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tuner = arg;
- if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL)
+ if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL)
return 0;
switch_v4l2();
@@ -1034,7 +1064,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tuner = arg;
- if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL)
+ if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL)
return 0;
switch_v4l2();
@@ -1117,7 +1147,8 @@ static void tuner_lookup(struct i2c_adapter *adap,
/* During client attach, set_type is called by adapter's attach_inform callback.
set_type must then be completed by tuner_probe.
*/
-static int tuner_probe(struct i2c_client *client)
+static int tuner_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tuner *t;
struct tuner *radio;
@@ -1127,7 +1158,7 @@ static int tuner_probe(struct i2c_client *client)
if (NULL == t)
return -ENOMEM;
t->i2c = client;
- strlcpy(client->name, "(tuner unset)", sizeof(client->name));
+ t->name = "(tuner unset)";
i2c_set_clientdata(client, t);
t->type = UNSET;
t->audmode = V4L2_TUNER_MODE_STEREO;
@@ -1155,8 +1186,9 @@ static int tuner_probe(struct i2c_client *client)
if (!no_autodetect) {
switch (client->addr) {
case 0x10:
- if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
- != EINVAL) {
+ if (tuner_symbol_probe(tea5761_autodetection,
+ t->i2c->adapter,
+ t->i2c->addr) >= 0) {
t->type = TUNER_TEA5761;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
@@ -1168,15 +1200,15 @@ static int tuner_probe(struct i2c_client *client)
goto register_client;
}
- break;
+ return -ENODEV;
case 0x42:
case 0x43:
case 0x4a:
case 0x4b:
/* If chip is not tda8290, don't register.
since it can be tda9887*/
- if (tda829x_probe(t->i2c->adapter,
- t->i2c->addr) == 0) {
+ if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
+ t->i2c->addr) >= 0) {
tuner_dbg("tda829x detected\n");
} else {
/* Default is being tda9887 */
@@ -1188,8 +1220,9 @@ static int tuner_probe(struct i2c_client *client)
}
break;
case 0x60:
- if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr)
- != EINVAL) {
+ if (tuner_symbol_probe(tea5767_autodetection,
+ t->i2c->adapter, t->i2c->addr)
+ >= 0) {
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
@@ -1281,10 +1314,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap)
static int tuner_remove(struct i2c_client *client)
{
struct tuner *t = i2c_get_clientdata(client);
- struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
- if (analog_ops->release)
- analog_ops->release(&t->fe);
+ tuner_detach(&t->fe);
+ t->fe.analog_demod_priv = NULL;
list_del(&t->list);
kfree(t);
@@ -1293,6 +1325,17 @@ static int tuner_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+/* This driver supports many devices and the idea is to let the driver
+ detect which device is present. So rather than listing all supported
+ devices here, we pretend to support a single, fake device type. */
+static const struct i2c_device_id tuner_id[] = {
+ { "tuner", }, /* autodetect */
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tuner_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "tuner",
.driverid = I2C_DRIVERID_TUNER,
@@ -1302,6 +1345,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.suspend = tuner_suspend,
.resume = tuner_resume,
.legacy_probe = tuner_legacy_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = tuner_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c
index 9ebe13fd7..830dbe8db 100644
--- a/linux/drivers/media/video/tvaudio.c
+++ b/linux/drivers/media/video/tvaudio.c
@@ -1478,7 +1478,7 @@ static struct CHIPDESC chiplist[] = {
/* ---------------------------------------------------------------------- */
/* i2c registration */
-static int chip_probe(struct i2c_client *client)
+static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct CHIPSTATE *chip;
struct CHIPDESC *desc;
@@ -1522,7 +1522,12 @@ static int chip_probe(struct i2c_client *client)
}
/* fill required data structures */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
strcpy(client->name, desc->name);
+#else
+ if (!id)
+ strlcpy(client->name, desc->name, I2C_NAME_SIZE);
+#endif
chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
@@ -1858,6 +1863,17 @@ static int chip_legacy_probe(struct i2c_adapter *adap)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+/* This driver supports many devices and the idea is to let the driver
+ detect which device is present. So rather than listing all supported
+ devices here, we pretend to support a single, fake device type. */
+static const struct i2c_device_id chip_id[] = {
+ { "tvaudio", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, chip_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "tvaudio",
.driverid = I2C_DRIVERID_TVAUDIO,
@@ -1865,6 +1881,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.probe = chip_probe,
.remove = chip_remove,
.legacy_probe = chip_legacy_probe,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = chip_id,
+#endif
};
/*
diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c
index 81a85035f..e38bda67a 100644
--- a/linux/drivers/media/video/tveeprom.c
+++ b/linux/drivers/media/video/tveeprom.c
@@ -323,10 +323,12 @@ audioIC[] =
{AUDIO_CHIP_INTERNAL, "CX25843"},
{AUDIO_CHIP_INTERNAL, "CX23418"},
{AUDIO_CHIP_INTERNAL, "CX23885"},
- /* 40-42 */
+ /* 40-44 */
{AUDIO_CHIP_INTERNAL, "CX23888"},
{AUDIO_CHIP_INTERNAL, "SAA7131"},
{AUDIO_CHIP_INTERNAL, "CX23887"},
+ {AUDIO_CHIP_INTERNAL, "SAA7164"},
+ {AUDIO_CHIP_INTERNAL, "AU8522"},
};
/* This list is supplied by Hauppauge. Thanks! */
@@ -345,8 +347,10 @@ static const char *decoderIC[] = {
"CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
/* 30-34 */
"CX25843", "CX23418", "NEC61153", "CX23885", "CX23888",
- /* 35-37 */
- "SAA7131", "CX25837", "CX23887"
+ /* 35-39 */
+ "SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A",
+ /* 40-42 */
+ "SAA7164", "CX23885B", "AU8522"
};
static int hasRadioTuner(int tunerType)
diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c
index e6907db8b..7dc6623cc 100644
--- a/linux/drivers/media/video/tvp5150.c
+++ b/linux/drivers/media/video/tvp5150.c
@@ -1175,12 +1175,12 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
return 0;
c = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (c == 0)
+ if (!c)
return -ENOMEM;
memcpy(c, &client_template, sizeof(struct i2c_client));
core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL);
- if (core == 0) {
+ if (!core) {
kfree(c);
return -ENOMEM;
}
diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c
index 92fc10901..c59944d72 100644
--- a/linux/drivers/media/video/upd64031a.c
+++ b/linux/drivers/media/video/upd64031a.c
@@ -209,7 +209,8 @@ static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg)
/* i2c implementation */
-static int upd64031a_probe(struct i2c_client *client)
+static int upd64031a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct upd64031a_state *state;
int i;
@@ -240,15 +241,25 @@ static int upd64031a_remove(struct i2c_client *client)
}
/* ----------------------------------------------------------------------- */
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
EXPORT_NO_SYMBOLS;
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id upd64031a_id[] = {
+ { "upd64031a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, upd64031a_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "upd64031a",
.driverid = I2C_DRIVERID_UPD64031A,
.command = upd64031a_command,
.probe = upd64031a_probe,
.remove = upd64031a_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = upd64031a_id,
+#endif
};
diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c
index 5d441538f..3dcc5a293 100644
--- a/linux/drivers/media/video/upd64083.c
+++ b/linux/drivers/media/video/upd64083.c
@@ -186,7 +186,8 @@ static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg)
/* i2c implementation */
-static int upd64083_probe(struct i2c_client *client)
+static int upd64083_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct upd64083_state *state;
int i;
@@ -217,15 +218,25 @@ static int upd64083_remove(struct i2c_client *client)
}
/* ----------------------------------------------------------------------- */
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
EXPORT_NO_SYMBOLS;
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id upd64083_id[] = {
+ { "upd64083", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, upd64083_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "upd64083",
.driverid = I2C_DRIVERID_UPD64083,
.command = upd64083_command,
.probe = upd64083_probe,
.remove = upd64083_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = upd64083_id,
+#endif
};
diff --git a/linux/drivers/media/video/usbvideo/ibmcam.c b/linux/drivers/media/video/usbvideo/ibmcam.c
index 1261593cf..1afbcc147 100644
--- a/linux/drivers/media/video/usbvideo/ibmcam.c
+++ b/linux/drivers/media/video/usbvideo/ibmcam.c
@@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
return scan_Continue;
}
+/*
+ * ibmcam_model3_parse_lines()
+ *
+ * | Even lines | Odd Lines |
+ * -----------------------------------|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |............|.....................|
+ * |YYY........Y|UYVYUYVY.........UYVY|
+ * |------------+---------------------|
+ *
+ * There is one (U, V) chroma pair for every four luma (Y) values. This
+ * function reads a pair of lines at a time and obtains missing chroma values
+ * from adjacent pixels.
+ */
static enum ParseState ibmcam_model3_parse_lines(
struct uvd *uvd,
struct usbvideo_frame *frame,
@@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines(
const int ccm = 128; /* Color correction median - see below */
int i, u, v, rw, data_w=0, data_h=0, color_corr;
static unsigned char lineBuffer[640*3];
+ int line;
color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
@@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines(
return scan_NextFrame;
}
- /* Make sure there's enough data for the entire line */
- len = 3 * data_w; /* <y-data> <uv-data> */
+ /* Make sure that lineBuffer can store two lines of data */
+ len = 3 * data_w; /* <y-data> <uyvy-data> */
assert(len <= sizeof(lineBuffer));
- /* Make sure there's enough data for the entire line */
+ /* Make sure there's enough data for two lines */
if (RingQueue_GetLength(&uvd->dp) < len)
return scan_Out;
- /* Suck one line out of the ring queue */
+ /* Suck two lines of data out of the ring queue */
RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
data = lineBuffer;
@@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines(
rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
- for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
- int y, rv, gv, bv; /* RGB components */
+ /* Iterate over two lines. */
+ for (line = 0; line < 2; line++) {
+ for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+ int y;
+ int rv, gv, bv; /* RGB components */
- if (i < data_w) {
- y = data[i]; /* Luminosity is the first line */
+ if (i >= data_w) {
+ RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
+ continue;
+ }
+
+ /* first line is YYY...Y; second is UYVY...UYVY */
+ y = data[(line == 0) ? i : (i*2 + 1)];
/* Apply static color correction */
- u = color[i*2] + hue_corr;
- v = color[i*2 + 1] + hue2_corr;
+ u = color[(i/2)*4] + hue_corr;
+ v = color[(i/2)*4 + 2] + hue2_corr;
/* Apply color correction */
if (color_corr != 0) {
@@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines(
u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
}
- } else
- y = 0, u = v = 128;
- YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
- RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
+
+ YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+ RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* No deinterlacing */
+ }
+
+ /* Check for the end of requested data */
+ if (rw == 0)
+ break;
+
+ /* Prepare for the second line */
+ rw--;
+ data = lineBuffer + data_w;
}
- frame->deinterlace = Deinterlace_FillEvenLines;
+ frame->deinterlace = Deinterlace_None;
/*
* Account for number of bytes that we wrote into output V4L frame.
diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c
index 67f46c77f..7e2f04fb4 100644
--- a/linux/drivers/media/video/usbvideo/konicawc.c
+++ b/linux/drivers/media/video/usbvideo/konicawc.c
@@ -64,7 +64,7 @@ static struct usbvideo *cams;
static int debug;
#define DEBUG(n, format, arg...) \
if (n <= debug) { \
- printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+ printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
}
#else
#define DEBUG(n, arg...)
diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
index c6673bd58..a4f1185c0 100644
--- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -51,7 +51,7 @@
static int debug;
#define DEBUG(n, format, arg...) \
if (n <= debug) { \
- printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+ printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
}
#else
#define DEBUG(n, arg...)
@@ -227,7 +227,7 @@ static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
return ret;
}
-static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
+static int qcm_stv_setw(struct usb_device *dev, u16 reg, __le16 val)
{
int ret;
diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c
index e9b305a77..f1aafd97d 100644
--- a/linux/drivers/media/video/usbvideo/usbvideo.c
+++ b/linux/drivers/media/video/usbvideo/usbvideo.c
@@ -525,11 +525,11 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
static int num_pass;
if (uvd == NULL) {
- err("%s: uvd == NULL", __FUNCTION__);
+ err("%s: uvd == NULL", __func__);
return;
}
if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
- err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
+ err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
return;
}
@@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump);
static int usbvideo_ClientIncModCount(struct uvd *uvd)
{
if (uvd == NULL) {
- err("%s: uvd == NULL", __FUNCTION__);
+ err("%s: uvd == NULL", __func__);
return -EINVAL;
}
if (uvd->handle == NULL) {
- err("%s: uvd->handle == NULL", __FUNCTION__);
+ err("%s: uvd->handle == NULL", __func__);
return -EINVAL;
}
if (!try_module_get(uvd->handle->md_module)) {
- err("%s: try_module_get() == 0", __FUNCTION__);
+ err("%s: try_module_get() == 0", __func__);
return -ENODEV;
}
return 0;
@@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd)
static void usbvideo_ClientDecModCount(struct uvd *uvd)
{
if (uvd == NULL) {
- err("%s: uvd == NULL", __FUNCTION__);
+ err("%s: uvd == NULL", __func__);
return;
}
if (uvd->handle == NULL) {
- err("%s: uvd->handle == NULL", __FUNCTION__);
+ err("%s: uvd->handle == NULL", __func__);
return;
}
if (uvd->handle->md_module == NULL) {
- err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
+ err("%s: uvd->handle->md_module == NULL", __func__);
return;
}
module_put(uvd->handle->md_module);
@@ -675,13 +675,13 @@ int usbvideo_register(
/* Check parameters for sanity */
if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
- err("%s: Illegal call", __FUNCTION__);
+ err("%s: Illegal call", __func__);
return -EINVAL;
}
/* Check registration callback - must be set! */
if (cbTbl->probe == NULL) {
- err("%s: probe() is required!", __FUNCTION__);
+ err("%s: probe() is required!", __func__);
return -EINVAL;
}
@@ -692,7 +692,7 @@ int usbvideo_register(
return -ENOMEM;
}
dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
- __FUNCTION__, cams, base_size, num_cams);
+ __func__, cams, base_size, num_cams);
/* Copy callbacks, apply defaults for those that are not set */
memmove(&cams->cb, cbTbl, sizeof(cams->cb));
@@ -721,7 +721,7 @@ int usbvideo_register(
up->user_data = kmalloc(up->user_size, GFP_KERNEL);
if (up->user_data == NULL) {
err("%s: Failed to allocate user_data (%d. bytes)",
- __FUNCTION__, up->user_size);
+ __func__, up->user_size);
while (i) {
up = &cams->cam[--i];
kfree(up->user_data);
@@ -730,7 +730,7 @@ int usbvideo_register(
return -ENOMEM;
}
dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
- __FUNCTION__, i, up->user_data, up->user_size);
+ __func__, i, up->user_data, up->user_size);
}
}
@@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams)
int i;
if (pCams == NULL) {
- err("%s: pCams == NULL", __FUNCTION__);
+ err("%s: pCams == NULL", __func__);
return;
}
cams = *pCams;
if (cams == NULL) {
- err("%s: cams == NULL", __FUNCTION__);
+ err("%s: cams == NULL", __func__);
return;
}
- dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
+ dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
usb_deregister(&cams->usbdrv);
- dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
+ dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
for (i=0; i < cams->num_cameras; i++) {
struct uvd *up = &cams->cam[i];
int warning = 0;
@@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams)
}
if (warning) {
err("%s: Warning: user_data=$%p user_size=%d.",
- __FUNCTION__, up->user_data, up->user_size);
+ __func__, up->user_data, up->user_size);
} else {
dbg("%s: Freeing %d. $%p->user_data=$%p",
- __FUNCTION__, i, up, up->user_data);
+ __func__, i, up, up->user_data);
kfree(up->user_data);
}
}
/* Whole array was allocated in one chunk */
dbg("%s: Freed %d uvd structures",
- __FUNCTION__, cams->num_cameras);
+ __func__, cams->num_cameras);
kfree(cams);
*pCams = NULL;
}
@@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
int i;
if (uvd == NULL) {
- err("%s($%p): Illegal call.", __FUNCTION__, intf);
+ err("%s($%p): Illegal call.", __func__, intf);
return;
}
@@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
usbvideo_ClientIncModCount(uvd);
if (uvd->debug > 0)
- info("%s(%p.)", __FUNCTION__, intf);
+ info("%s(%p.)", __func__, intf);
mutex_lock(&uvd->lock);
uvd->remove_pending = 1; /* Now all ISO data will be ignored */
@@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
video_unregister_device(&uvd->vdev);
if (uvd->debug > 0)
- info("%s: Video unregistered.", __FUNCTION__);
+ info("%s: Video unregistered.", __func__);
if (uvd->user)
- info("%s: In use, disconnect pending.", __FUNCTION__);
+ info("%s: In use, disconnect pending.", __func__);
else
usbvideo_CameraRelease(uvd);
mutex_unlock(&uvd->lock);
@@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
static void usbvideo_CameraRelease(struct uvd *uvd)
{
if (uvd == NULL) {
- err("%s: Illegal call", __FUNCTION__);
+ err("%s: Illegal call", __func__);
return;
}
@@ -1013,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
char tmp1[20], tmp2[20]; /* Buffers for printing */
if (uvd == NULL) {
- err("%s: Illegal call.", __FUNCTION__);
+ err("%s: Illegal call.", __func__);
return -EINVAL;
}
if (uvd->video_endp == 0) {
- info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
+ info("%s: No video endpoint specified; data pump disabled.", __func__);
}
if (uvd->paletteBits == 0) {
- err("%s: No palettes specified!", __FUNCTION__);
+ err("%s: No palettes specified!", __func__);
return -EINVAL;
}
if (uvd->defaultPalette == 0) {
- info("%s: No default palette!", __FUNCTION__);
+ info("%s: No default palette!", __func__);
}
uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
@@ -1034,7 +1034,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
if (uvd->debug > 0) {
info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
- __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+ __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
}
if (uvd->dev == NULL) {
err("%s: uvd->dev == NULL", __func__);
@@ -1042,11 +1042,11 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
}
uvd->vdev.dev = &uvd->dev->dev;
if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
- err("%s: video_register_device failed", __FUNCTION__);
+ err("%s: video_register_device failed", __func__);
return -EPIPE;
}
if (uvd->debug > 1) {
- info("%s: video_register_device() successful", __FUNCTION__);
+ info("%s: video_register_device() successful", __func__);
}
info("%s on /dev/video%d: canvas=%s videosize=%s",
@@ -1113,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
int i, errCode = 0;
if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, dev);
+ info("%s($%p)", __func__, dev);
if (0 < usbvideo_ClientIncModCount(uvd))
return -ENODEV;
mutex_lock(&uvd->lock);
if (uvd->user) {
- err("%s: Someone tried to open an already opened device!", __FUNCTION__);
+ err("%s: Someone tried to open an already opened device!", __func__);
errCode = -EBUSY;
} else {
/* Clear statistics */
@@ -1136,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
if ((uvd->fbuf == NULL) ||
(!RingQueue_IsAllocated(&uvd->dp))) {
- err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
+ err("%s: Failed to allocate fbuf or dp", __func__);
errCode = -ENOMEM;
} else {
/* Allocate all buffers */
@@ -1180,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
if (errCode == 0) {
if (VALID_CALLBACK(uvd, setupOnOpen)) {
if (uvd->debug > 1)
- info("%s: setupOnOpen callback", __FUNCTION__);
+ info("%s: setupOnOpen callback", __func__);
errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
if (errCode < 0) {
err("%s: setupOnOpen callback failed (%d.).",
- __FUNCTION__, errCode);
+ __func__, errCode);
} else if (uvd->debug > 1) {
- info("%s: setupOnOpen callback successful", __FUNCTION__);
+ info("%s: setupOnOpen callback successful", __func__);
}
}
if (errCode == 0) {
uvd->settingsAdjusted = 0;
if (uvd->debug > 1)
- info("%s: Open succeeded.", __FUNCTION__);
+ info("%s: Open succeeded.", __func__);
uvd->user++;
file->private_data = uvd;
}
@@ -1202,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
if (errCode != 0)
usbvideo_ClientDecModCount(uvd);
if (uvd->debug > 0)
- info("%s: Returning %d.", __FUNCTION__, errCode);
+ info("%s: Returning %d.", __func__, errCode);
return errCode;
}
@@ -1225,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
int i;
if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, dev);
+ info("%s($%p)", __func__, dev);
mutex_lock(&uvd->lock);
GET_CALLBACK(uvd, stopDataPump)(uvd);
@@ -1252,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
usbvideo_ClientDecModCount(uvd);
if (uvd->debug > 1)
- info("%s: Completed.", __FUNCTION__);
+ info("%s: Completed.", __func__);
file->private_data = NULL;
return 0;
}
@@ -1506,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
return -EFAULT;
if (uvd->debug >= 1)
- info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
+ info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
mutex_lock(&uvd->lock);
@@ -1553,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
*/
if (frmx == -1) {
if (uvd->defaultPalette == 0) {
- err("%s: No default palette; don't know what to do!", __FUNCTION__);
+ err("%s: No default palette; don't know what to do!", __func__);
count = -EFAULT;
goto read_done;
}
@@ -1625,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
frame->seqRead_Index += count;
if (uvd->debug >= 1) {
err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
- __FUNCTION__, count, frame->seqRead_Index);
+ __func__, count, frame->seqRead_Index);
}
/* Finally check if the frame is done with and "release" it */
@@ -1636,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
/* Mark it as available to be used again. */
uvd->frame[frmx].frameState = FrameState_Unused;
if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
- err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
+ err("%s: usbvideo_NewFrame failed.", __func__);
}
}
read_done:
@@ -1747,10 +1747,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
int i, errFlag;
if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, uvd);
+ info("%s($%p)", __func__, uvd);
if (!CAMERA_IS_OPERATIONAL(uvd)) {
- err("%s: Camera is not operational", __FUNCTION__);
+ err("%s: Camera is not operational", __func__);
return -EFAULT;
}
uvd->curframe = -1;
@@ -1758,14 +1758,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
/* Alternate interface 1 is is the biggest frame size */
i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
if (i < 0) {
- err("%s: usb_set_interface error", __FUNCTION__);
+ err("%s: usb_set_interface error", __func__);
uvd->last_error = i;
return -EBUSY;
}
if (VALID_CALLBACK(uvd, videoStart))
GET_CALLBACK(uvd, videoStart)(uvd);
else
- err("%s: videoStart not set", __FUNCTION__);
+ err("%s: videoStart not set", __func__);
/* We double buffer the Iso lists */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
@@ -1790,12 +1790,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
if (errFlag)
- err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
+ err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
}
uvd->streaming = 1;
if (uvd->debug > 1)
- info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
+ info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
return 0;
}
@@ -1817,14 +1817,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
return;
if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, uvd);
+ info("%s($%p)", __func__, uvd);
/* Unschedule all of the iso td's */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
usb_kill_urb(uvd->sbuf[i].urb);
}
if (uvd->debug > 1)
- info("%s: streaming=0", __FUNCTION__);
+ info("%s: streaming=0", __func__);
uvd->streaming = 0;
if (!uvd->remove_pending) {
@@ -1832,12 +1832,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
if (VALID_CALLBACK(uvd, videoStop))
GET_CALLBACK(uvd, videoStop)(uvd);
else
- err("%s: videoStop not set", __FUNCTION__);
+ err("%s: videoStop not set", __func__);
/* Set packet size to 0 */
j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
if (j < 0) {
- err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
+ err("%s: usb_set_interface() error %d.", __func__, j);
uvd->last_error = j;
}
}
@@ -1961,12 +1961,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
struct usbvideo_frame *frame = &uvd->frame[frameNum];
if (uvd->debug >= 2)
- info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
+ info("%s($%p,%d.)", __func__, uvd, frameNum);
switch (frame->frameState) {
case FrameState_Unused:
if (uvd->debug >= 2)
- info("%s: FrameState_Unused", __FUNCTION__);
+ info("%s: FrameState_Unused", __func__);
return -EINVAL;
case FrameState_Ready:
case FrameState_Grabbing:
@@ -1976,7 +1976,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
redo:
if (!CAMERA_IS_OPERATIONAL(uvd)) {
if (uvd->debug >= 2)
- info("%s: Camera is not operational (1)", __FUNCTION__);
+ info("%s: Camera is not operational (1)", __func__);
return -EIO;
}
ntries = 0;
@@ -1985,24 +1985,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
signalPending = signal_pending(current);
if (!CAMERA_IS_OPERATIONAL(uvd)) {
if (uvd->debug >= 2)
- info("%s: Camera is not operational (2)", __FUNCTION__);
+ info("%s: Camera is not operational (2)", __func__);
return -EIO;
}
assert(uvd->fbuf != NULL);
if (signalPending) {
if (uvd->debug >= 2)
- info("%s: Signal=$%08x", __FUNCTION__, signalPending);
+ info("%s: Signal=$%08x", __func__, signalPending);
if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
usbvideo_TestPattern(uvd, 1, 0);
uvd->curframe = -1;
uvd->stats.frame_num++;
if (uvd->debug >= 2)
- info("%s: Forced test pattern screen", __FUNCTION__);
+ info("%s: Forced test pattern screen", __func__);
return 0;
} else {
/* Standard answer: Interrupted! */
if (uvd->debug >= 2)
- info("%s: Interrupted!", __FUNCTION__);
+ info("%s: Interrupted!", __func__);
return -EINTR;
}
} else {
@@ -2012,17 +2012,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
else if (VALID_CALLBACK(uvd, processData))
GET_CALLBACK(uvd, processData)(uvd, frame);
else
- err("%s: processData not set", __FUNCTION__);
+ err("%s: processData not set", __func__);
}
} while (frame->frameState == FrameState_Grabbing);
if (uvd->debug >= 2) {
info("%s: Grabbing done; state=%d. (%lu. bytes)",
- __FUNCTION__, frame->frameState, frame->seqRead_Length);
+ __func__, frame->frameState, frame->seqRead_Length);
}
if (frame->frameState == FrameState_Error) {
int ret = usbvideo_NewFrame(uvd, frameNum);
if (ret < 0) {
- err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
+ err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
return ret;
}
goto redo;
@@ -2054,7 +2054,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
}
frame->frameState = FrameState_Done_Hold;
if (uvd->debug >= 2)
- info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
+ info("%s: Entered FrameState_Done_Hold state.", __func__);
return 0;
case FrameState_Done_Hold:
@@ -2065,12 +2065,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
* it will be released back into the wild to roam freely.
*/
if (uvd->debug >= 2)
- info("%s: FrameState_Done_Hold state.", __FUNCTION__);
+ info("%s: FrameState_Done_Hold state.", __func__);
return 0;
}
/* Catch-all for other cases. We shall not be here. */
- err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
+ err("%s: Invalid state %d.", __func__, frame->frameState);
frame->frameState = FrameState_Unused;
return 0;
}
@@ -2166,7 +2166,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
const int ccm = 128; /* Color correction median - see below */
if ((uvd == NULL) || (frame == NULL)) {
- err("%s: Illegal call.", __FUNCTION__);
+ err("%s: Illegal call.", __func__);
return;
}
adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c
index 984f4b756..049f588ae 100644
--- a/linux/drivers/media/video/usbvideo/vicam.c
+++ b/linux/drivers/media/video/usbvideo/vicam.c
@@ -50,7 +50,7 @@
// #define VICAM_DEBUG
#ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
+#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
#else
#define DBG(fmn,args...) do {} while(0)
@@ -72,12 +72,6 @@
#define VICAM_HEADER_SIZE 64
-#define clamp( x, l, h ) max_t( __typeof__( x ), \
- ( l ), \
- min_t( __typeof__( x ), \
- ( h ), \
- ( x ) ) )
-
/* Not sure what all the bytes in these char
* arrays do, but they're necessary to make
* the camera work.
diff --git a/linux/drivers/media/video/usbvision/Makefile b/linux/drivers/media/video/usbvision/Makefile
index 9ac92a80c..338718750 100644
--- a/linux/drivers/media/video/usbvision/Makefile
+++ b/linux/drivers/media/video/usbvision/Makefile
@@ -3,3 +3,4 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c
index 96155fd92..55b3f5e60 100644
--- a/linux/drivers/media/video/usbvision/usbvision-video.c
+++ b/linux/drivers/media/video/usbvision/usbvision-video.c
@@ -1031,7 +1031,7 @@ static int vidioc_streamoff(struct file *file,
return 0;
}
-static int vidioc_enum_fmt_cap (struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_fmtdesc *vfd)
{
if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
@@ -1045,7 +1045,7 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *vf)
{
struct video_device *dev = video_devdata(file);
@@ -1063,7 +1063,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_try_fmt_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *vf)
{
struct video_device *dev = video_devdata(file);
@@ -1093,7 +1093,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *vf)
{
struct video_device *dev = video_devdata(file);
@@ -1101,7 +1101,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
(struct usb_usbvision *) video_get_drvdata(dev);
int ret;
- if( 0 != (ret=vidioc_try_fmt_cap (file, priv, vf)) ) {
+ if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) {
return ret;
}
@@ -1501,10 +1501,10 @@ static struct video_device usbvision_video_template = {
#endif
.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_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index 34079657e..b721aca4e 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -711,13 +711,14 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
/* Helper function for I2C legacy drivers */
int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
- const char *name, int (*probe)(struct i2c_client *))
+ const char *name,
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *))
{
struct i2c_client *client;
int err;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ if (!client)
return -ENOMEM;
client->addr = address;
@@ -728,7 +729,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver
#endif
strlcpy(client->name, name, sizeof(client->name));
- err = probe(client);
+ err = probe(client, NULL);
if (err == 0) {
i2c_attach_client(client);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c
index 5220023c2..16c32c68c 100644
--- a/linux/drivers/media/video/videobuf-core.c
+++ b/linux/drivers/media/video/videobuf-core.c
@@ -95,13 +95,17 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
return CALL(q, iolock, q, vb, fbuf);
}
-/* --------------------------------------------------------------------- */
-
-static int videobuf_mmap_setup_default(struct videobuf_queue *q,
- struct videobuf_buffer *vb)
+void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
{
- return 0;
+ if (q->int_ops->vmalloc)
+ return q->int_ops->vmalloc(buf);
+ else
+ return NULL;
}
+EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
+
+/* --------------------------------------------------------------------- */
void videobuf_queue_core_init(struct videobuf_queue *q,
@@ -124,15 +128,15 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
q->priv_data = priv;
q->int_ops = int_ops;
- if (!q->int_ops->mmap_setup)
- q->int_ops->mmap_setup = videobuf_mmap_setup_default;
-
/* 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);
+ /* Lock is mandatory for queue_cancel to work */
+ BUG_ON(!irqlock);
+
/* Having implementations for abstract methods are mandatory */
BUG_ON(!q->int_ops);
@@ -190,8 +194,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
wake_up_interruptible_sync(&q->wait);
/* remove queued buffers from list */
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
@@ -201,8 +204,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
wake_up_all(&q->bufs[i]->done);
}
}
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
/* free all buffers + clear queue */
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -304,6 +306,8 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
rc = CALL(q, mmap_free, q);
+ q->is_mmapped = 0;
+
if (rc < 0)
return rc;
@@ -328,7 +332,7 @@ int videobuf_mmap_free(struct videobuf_queue *q)
}
/* Locking: Caller holds q->vb_lock */
-static int __videobuf_mmap_setup(struct videobuf_queue *q,
+int __videobuf_mmap_setup(struct videobuf_queue *q,
unsigned int bcount, unsigned int bsize,
enum v4l2_memory memory)
{
@@ -355,9 +359,6 @@ static int __videobuf_mmap_setup(struct videobuf_queue *q,
switch (memory) {
case V4L2_MEMORY_MMAP:
q->bufs[i]->boff = bsize * i;
- err = q->int_ops->mmap_setup(q, q->bufs[i]);
- if (err)
- break;
break;
case V4L2_MEMORY_USERPTR:
case V4L2_MEMORY_OVERLAY:
@@ -559,11 +560,9 @@ int videobuf_qbuf(struct videobuf_queue *q,
list_add_tail(&buf->stream, &q->stream);
if (q->streaming) {
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
q->ops->buf_queue(q, buf);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
}
dprintk(1, "qbuf: succeded\n");
retval = 0;
@@ -700,13 +699,11 @@ int videobuf_streamon(struct videobuf_queue *q)
if (q->streaming)
goto done;
q->streaming = 1;
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
list_for_each_entry(buf, &q->stream, stream)
if (buf->state == VIDEOBUF_PREPARED)
q->ops->buf_queue(q, buf);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
wake_up_interruptible_sync(&q->wait);
done:
@@ -762,11 +759,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
goto done;
/* start capture & wait */
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
q->ops->buf_queue(q, q->read_buf);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
retval = videobuf_waiton(q->read_buf, 0, 0);
if (0 == retval) {
CALL(q, sync, q, q->read_buf);
@@ -827,12 +822,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
q->read_buf = NULL;
goto done;
}
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
q->ops->buf_queue(q, q->read_buf);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
+
q->read_off = 0;
}
@@ -898,12 +892,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
return err;
list_add_tail(&q->bufs[i]->stream, &q->stream);
}
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
for (i = 0; i < count; i++)
q->ops->buf_queue(q, q->bufs[i]);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
q->reading = 1;
return 0;
}
@@ -912,7 +904,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
{
int i;
-
videobuf_queue_cancel(q);
__videobuf_mmap_free(q);
INIT_LIST_HEAD(&q->stream);
@@ -967,7 +958,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
- dprintk(2, "%s\n", __FUNCTION__);
+ dprintk(2, "%s\n", __func__);
mutex_lock(&q->vb_lock);
retval = -EBUSY;
if (q->streaming)
@@ -1016,11 +1007,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
if (q->read_off == q->read_buf->size) {
list_add_tail(&q->read_buf->stream,
&q->stream);
- if (q->irqlock)
- spin_lock_irqsave(q->irqlock, flags);
+ spin_lock_irqsave(q->irqlock, flags);
q->ops->buf_queue(q, q->read_buf);
- if (q->irqlock)
- spin_unlock_irqrestore(q->irqlock, flags);
+ spin_unlock_irqrestore(q->irqlock, flags);
q->read_buf = NULL;
}
if (retval < 0)
@@ -1080,6 +1069,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q,
mutex_lock(&q->vb_lock);
retval = CALL(q, mmap_mapper, q, vma);
+ q->is_mmapped = 1;
mutex_unlock(&q->vb_lock);
return retval;
@@ -1140,6 +1130,7 @@ EXPORT_SYMBOL_GPL(videobuf_read_stream);
EXPORT_SYMBOL_GPL(videobuf_read_one);
EXPORT_SYMBOL_GPL(videobuf_poll_stream);
+EXPORT_SYMBOL_GPL(__videobuf_mmap_setup);
EXPORT_SYMBOL_GPL(videobuf_mmap_setup);
EXPORT_SYMBOL_GPL(videobuf_mmap_free);
EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
diff --git a/linux/drivers/media/video/videobuf-dma-sg.c b/linux/drivers/media/video/videobuf-dma-sg.c
index 06a219e0d..7d459ed6b 100644
--- a/linux/drivers/media/video/videobuf-dma-sg.c
+++ b/linux/drivers/media/video/videobuf-dma-sg.c
@@ -163,9 +163,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
data,size,dma->nr_pages);
- dma->varea = (void *) data;
-
-
err = get_user_pages(current,current->mm,
data & PAGE_MASK, dma->nr_pages,
rw == READ, 1, /* force */
@@ -253,7 +250,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
dma->nr_pages, dma->direction);
if (0 == dma->sglen) {
printk(KERN_WARNING
- "%s: videobuf_map_sg failed\n",__FUNCTION__);
+ "%s: videobuf_map_sg failed\n",__func__);
kfree(dma->sglist);
dma->sglist = NULL;
dma->sglen = 0;
@@ -305,7 +302,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
vfree(dma->vmalloc);
dma->vmalloc = NULL;
- dma->varea = NULL;
if (dma->bus_addr) {
dma->bus_addr = 0;
@@ -476,12 +472,22 @@ static void *__videobuf_alloc(size_t size)
videobuf_dma_init(&mem->dma);
dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
- __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
mem,(long)sizeof(*mem));
return vb;
}
+static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf)
+{
+ struct videobuf_dma_sg_memory *mem = buf->priv;
+ BUG_ON(!mem);
+
+ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ return mem->dma.vmalloc;
+}
+
static int __videobuf_iolock (struct videobuf_queue* q,
struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf)
@@ -727,6 +733,7 @@ static struct videobuf_qtype_ops sg_ops = {
.mmap_mapper = __videobuf_mmap_mapper,
.video_copy_to_user = __videobuf_copy_to_user,
.copy_stream = __videobuf_copy_stream,
+ .vmalloc = __videobuf_to_vmalloc,
};
void *videobuf_sg_alloc(size_t size)
diff --git a/linux/drivers/media/video/videobuf-dvb.c b/linux/drivers/media/video/videobuf-dvb.c
index 8966a53db..9a821371a 100644
--- a/linux/drivers/media/video/videobuf-dvb.c
+++ b/linux/drivers/media/video/videobuf-dvb.c
@@ -21,13 +21,14 @@
#include <linux/fs.h>
#include <linux/kthread.h>
#include <linux/file.h>
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#include <linux/suspend.h>
#else
#include <linux/freezer.h>
#endif
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-core.h>
#include <media/videobuf-dvb.h>
#include "compat.h"
@@ -51,7 +52,7 @@ static int videobuf_dvb_thread(void *data)
struct videobuf_buffer *buf;
unsigned long flags;
int err;
- struct videobuf_dmabuf *dma;
+ void *outp;
dprintk("dvb thread started\n");
set_freezable();
@@ -72,9 +73,10 @@ static int videobuf_dvb_thread(void *data)
try_to_freeze();
/* feed buffer data to demux */
- dma=videobuf_to_dma(buf);
+ outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf);
+
if (buf->state == VIDEOBUF_DONE)
- dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
+ dvb_dmx_swfilter(&dvb->demux, outp,
buf->size);
/* requeue buffer */
@@ -144,14 +146,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
int videobuf_dvb_register(struct videobuf_dvb *dvb,
struct module *module,
void *adapter_priv,
- struct device *device)
+ struct device *device,
+ short *adapter_nr)
{
int result;
mutex_init(&dvb->lock);
/* register adapter */
- result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
+ result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
+ adapter_nr);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
dvb->name, result);
diff --git a/linux/drivers/media/video/videobuf-vmalloc.c b/linux/drivers/media/video/videobuf-vmalloc.c
index 3bc7308af..6f487b348 100644
--- a/linux/drivers/media/video/videobuf-vmalloc.c
+++ b/linux/drivers/media/video/videobuf-vmalloc.c
@@ -58,20 +58,26 @@ videobuf_vm_open(struct vm_area_struct *vma)
map->count++;
}
-static void
-videobuf_vm_close(struct vm_area_struct *vma)
+static void videobuf_vm_close(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
struct videobuf_queue *q = map->q;
int i;
- dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
- map->count,vma->vm_start,vma->vm_end);
+ dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
+ map->count, vma->vm_start, vma->vm_end);
map->count--;
if (0 == map->count) {
- dprintk(1,"munmap %p q=%p\n",map,q);
+ struct videobuf_vmalloc_memory *mem;
+
+ dprintk(1, "munmap %p q=%p\n", map, q);
mutex_lock(&q->vb_lock);
+
+ /* We need first to cancel streams, before unmapping */
+ if (q->streaming)
+ videobuf_queue_cancel(q);
+
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
@@ -79,12 +85,35 @@ videobuf_vm_close(struct vm_area_struct *vma)
if (q->bufs[i]->map != map)
continue;
+ mem = q->bufs[i]->priv;
+ if (mem) {
+ /* This callback is called only if kernel has
+ allocated memory and this memory is mmapped.
+ In this case, memory should be freed,
+ in order to do memory unmap.
+ */
+
+ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+ /* vfree is not atomic - can't be
+ called with IRQ's disabled
+ */
+ dprintk(1, "%s: buf[%d] freeing (%p)\n",
+ __func__, i, mem->vmalloc);
+
+ vfree(mem->vmalloc);
+ mem->vmalloc = NULL;
+ }
+
q->bufs[i]->map = NULL;
q->bufs[i]->baddr = 0;
}
- mutex_unlock(&q->vb_lock);
+
kfree(map);
+
+ mutex_unlock(&q->vb_lock);
}
+
return;
}
@@ -115,7 +144,7 @@ static void *__videobuf_alloc(size_t size)
mem->magic=MAGIC_VMAL_MEM;
dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
- __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
mem,(long)sizeof(*mem));
return vb;
@@ -125,53 +154,77 @@ static int __videobuf_iolock (struct videobuf_queue* q,
struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf)
{
+ struct videobuf_vmalloc_memory *mem = vb->priv;
int pages;
- struct videobuf_vmalloc_memory *mem=vb->priv;
BUG_ON(!mem);
- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
- pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+ switch (vb->memory) {
+ case V4L2_MEMORY_MMAP:
+ dprintk(1, "%s memory method MMAP\n", __func__);
- /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
- if ((vb->memory != V4L2_MEMORY_MMAP) &&
- (vb->memory != V4L2_MEMORY_USERPTR) ) {
- printk(KERN_ERR "Method currently unsupported.\n");
- return -EINVAL;
- }
+ /* All handling should be done by __videobuf_mmap_mapper() */
+ if (!mem->vmalloc) {
+ printk(KERN_ERR "memory is not alloced/mmapped.\n");
+ return -EINVAL;
+ }
+ break;
+ case V4L2_MEMORY_USERPTR:
+ pages = PAGE_ALIGN(vb->size);
- /* FIXME: should be tested with kernel mmap mem */
- mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
- if (NULL == mem->vmalloc) {
- printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
- return -ENOMEM;
- }
+ dprintk(1, "%s memory method USERPTR\n", __func__);
- dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
- (unsigned long)mem->vmalloc,
- pages << PAGE_SHIFT);
+#if 1 /* keep */
+ if (vb->baddr) {
+ printk(KERN_ERR "USERPTR is currently not supported\n");
+ return -EINVAL;
+ }
+#endif
- return 0;
-}
+ /* The only USERPTR currently supported is the one needed for
+ read() method.
+ */
-static int __videobuf_mmap_setup(struct videobuf_queue *q,
- struct videobuf_buffer *vb)
-{
- int retval = 0;
- BUG_ON(vb->memory != V4L2_MEMORY_MMAP);
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- /* bsize == size since the buffer needs to be large enough to
- * hold an entire frame, not the case in the read case for
- * example*/
- vb->size = vb->bsize;
- retval = __videobuf_iolock(q, vb, NULL);
- if (!retval) {
- /* Don't IOLOCK later */
- vb->state = VIDEOBUF_IDLE;
+ mem->vmalloc = vmalloc_user(pages);
+ if (!mem->vmalloc) {
+ printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+ return -ENOMEM;
+ }
+ dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+ mem->vmalloc, pages);
+
+#if 0 /* keep */
+ int rc;
+ /* Kernel userptr is used also by read() method. In this case,
+ there's no need to remap, since data will be copied to user
+ */
+ if (!vb->baddr)
+ return 0;
+
+ /* FIXME: to properly support USERPTR, remap should occur.
+ The code bellow won't work, since mem->vma = NULL
+ */
+ /* Try to remap memory */
+ rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
+ if (rc < 0) {
+ printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
+ return -ENOMEM;
}
+#endif
+
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ default:
+ dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
+
+ /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+ printk(KERN_ERR "Memory method currently unsupported.\n");
+ return -EINVAL;
}
- return retval;
+
+ return 0;
}
static int __videobuf_sync(struct videobuf_queue *q,
@@ -184,6 +237,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
{
unsigned int i;
+ dprintk(1, "%s\n", __func__);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (q->bufs[i]) {
if (q->bufs[i]->map)
@@ -200,10 +254,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct videobuf_vmalloc_memory *mem;
struct videobuf_mapping *map;
unsigned int first;
- int retval;
+ int retval, pages;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+ dprintk(1, "%s\n", __func__);
+ if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
return -EINVAL;
/* look for first buffer to map */
@@ -223,39 +278,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
}
/* create mapping + update buffer list */
- map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
if (NULL == map)
return -ENOMEM;
+ q->bufs[first]->map = map;
map->start = vma->vm_start;
map->end = vma->vm_end;
map->q = q;
q->bufs[first]->baddr = vma->vm_start;
- vma->vm_ops = &videobuf_vm_ops;
- vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
- vma->vm_private_data = map;
+ mem = q->bufs[first]->priv;
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
- mem=q->bufs[first]->priv;
- BUG_ON (!mem);
- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+ pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
+ mem->vmalloc = vmalloc_user(pages);
+ if (!mem->vmalloc) {
+ printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
+ goto error;
+ }
+ dprintk(1, "vmalloc is at addr %p (%d pages)\n",
+ mem->vmalloc, pages);
/* Try to remap memory */
- retval=remap_vmalloc_range(vma, mem->vmalloc,0);
- if (retval<0) {
- dprintk(1, "mmap: failed to remap_vmalloc_range\n");
- return -EINVAL;
+ retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
+ if (retval < 0) {
+ printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
+ vfree(mem->vmalloc);
+ goto error;
}
+ vma->vm_ops = &videobuf_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_private_data = map;
+
dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
- map,q,vma->vm_start,vma->vm_end,
+ map, q, vma->vm_start, vma->vm_end,
(long int) q->bufs[first]->bsize,
- vma->vm_pgoff,first);
+ vma->vm_pgoff, first);
videobuf_vm_open(vma);
- return (0);
+ return 0;
+
+error:
+ mem = NULL;
+ kfree(map);
+ return -ENOMEM;
}
static int __videobuf_copy_to_user ( struct videobuf_queue *q,
@@ -313,11 +384,11 @@ static struct videobuf_qtype_ops qops = {
.alloc = __videobuf_alloc,
.iolock = __videobuf_iolock,
.sync = __videobuf_sync,
- .mmap_setup = __videobuf_mmap_setup,
.mmap_free = __videobuf_mmap_free,
.mmap_mapper = __videobuf_mmap_mapper,
.video_copy_to_user = __videobuf_copy_to_user,
.copy_stream = __videobuf_copy_stream,
+ .vmalloc = videobuf_to_vmalloc,
};
void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
@@ -347,13 +418,24 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
void videobuf_vmalloc_free (struct videobuf_buffer *buf)
{
- struct videobuf_vmalloc_memory *mem=buf->priv;
- BUG_ON (!mem);
+ struct videobuf_vmalloc_memory *mem = buf->priv;
- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
+ /* mmapped memory can't be freed here, otherwise mmapped region
+ would be released, while still needed. In this case, the memory
+ release should happen inside videobuf_vm_close().
+ So, it should free memory only if the memory were allocated for
+ read() operation.
+ */
+ if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
+ return;
+
+ if (!mem)
+ return;
+
+ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
vfree(mem->vmalloc);
- mem->vmalloc=NULL;
+ mem->vmalloc = NULL;
return;
}
diff --git a/linux/drivers/media/video/videocodec.c b/linux/drivers/media/video/videocodec.c
index b30b6b2a9..cf24956f3 100644
--- a/linux/drivers/media/video/videocodec.c
+++ b/linux/drivers/media/video/videocodec.c
@@ -39,6 +39,7 @@
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#endif
@@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec)
}
#ifdef CONFIG_PROC_FS
-/* ============ */
-/* procfs stuff */
-/* ============ */
-
-static char *videocodec_buf = NULL;
-static int videocodec_bufsize;
-
-static int
-videocodec_build_table (void)
+static int proc_videocodecs_show(struct seq_file *m, void *v)
{
struct codec_list *h = codeclist_top;
struct attached_list *a;
- int i = 0, size;
-
- // sum up amount of slaves plus their attached masters
- while (h) {
- i += h->attached + 1;
- h = h->next;
- }
-#define LINESIZE 100
- size = LINESIZE * (i + 1);
- dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
- size);
-
- kfree(videocodec_buf);
- videocodec_buf = kmalloc(size, GFP_KERNEL);
-
- if (!videocodec_buf)
- return 0;
-
- i = 0;
- i += scnprintf(videocodec_buf + i, size - 1,
- "<S>lave or attached <M>aster name type flags magic ");
- i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
+ seq_printf(m, "<S>lave or attached <M>aster name type flags magic ");
+ seq_printf(m, "(connected as)\n");
h = codeclist_top;
while (h) {
- if (i > (size - LINESIZE))
- break; // security check
- i += scnprintf(videocodec_buf + i, size -i -1,
- "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+ seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
h->codec->name, h->codec->type,
h->codec->flags, h->codec->magic);
a = h->list;
while (a) {
- if (i > (size - LINESIZE))
- break; // security check
- i += scnprintf(videocodec_buf + i, size -i -1,
- "M %32s %04x %08lx %08lx (%s)\n",
+ seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
a->codec->master_data->name,
a->codec->master_data->type,
a->codec->master_data->flags,
@@ -380,54 +347,21 @@ videocodec_build_table (void)
h = h->next;
}
- return i;
+ return 0;
}
-//The definition:
-//typedef int (read_proc_t)(char *page, char **start, off_t off,
-// int count, int *eof, void *data);
-
-static int
-videocodec_info (char *buffer,
- char **buffer_location,
- off_t offset,
- int buffer_length,
- int *eof,
- void *data)
+static int proc_videocodecs_open(struct inode *inode, struct file *file)
{
- int size;
-
- dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n",
- offset, buffer_length, videocodec_bufsize);
-
- if (offset == 0) {
- videocodec_bufsize = videocodec_build_table();
- }
- if ((offset < 0) || (offset >= videocodec_bufsize)) {
- dprintk(4,
- "videocodec_info: call delivers no result, return 0\n");
- *eof = 1;
- return 0;
- }
-
- if (buffer_length < (videocodec_bufsize - offset)) {
- dprintk(4, "videocodec_info: %ld needed, %d got\n",
- videocodec_bufsize - offset, buffer_length);
- size = buffer_length;
- } else {
- dprintk(4, "videocodec_info: last reading of %ld bytes\n",
- videocodec_bufsize - offset);
- size = videocodec_bufsize - offset;
- *eof = 1;
- }
-
- memcpy(buffer, videocodec_buf + offset, size);
- /* doesn't work... */
- /* copy_to_user(buffer, videocodec_buf+offset, size); */
- /* *buffer_location = videocodec_buf+offset; */
-
- return size;
+ return single_open(file, proc_videocodecs_show, NULL);
}
+
+static const struct file_operations videocodecs_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = proc_videocodecs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif
/* ===================== */
@@ -444,16 +378,8 @@ videocodec_init (void)
VIDEOCODEC_VERSION);
#ifdef CONFIG_PROC_FS
- videocodec_buf = NULL;
- videocodec_bufsize = 0;
-
- videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL);
- if (videocodec_proc_entry) {
- videocodec_proc_entry->read_proc = videocodec_info;
- videocodec_proc_entry->write_proc = NULL;
- videocodec_proc_entry->data = NULL;
- videocodec_proc_entry->owner = THIS_MODULE;
- } else {
+ videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
+ if (!videocodec_proc_entry) {
dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
}
#endif
@@ -465,7 +391,6 @@ videocodec_exit (void)
{
#ifdef CONFIG_PROC_FS
remove_proc_entry("videocodecs", NULL);
- kfree(videocodec_buf);
#endif
}
diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c
index 43cdb1de5..d7059944b 100644
--- a/linux/drivers/media/video/videodev.c
+++ b/linux/drivers/media/video/videodev.c
@@ -18,14 +18,14 @@
#define dbgarg(cmd, fmt, arg...) \
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
- printk (KERN_DEBUG "%s: ", vfd->name); \
+ printk(KERN_DEBUG "%s: ", vfd->name); \
v4l_printk_ioctl(cmd); \
- printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
+ printk(" " fmt, ## arg); \
}
#define dbgarg2(fmt, arg...) \
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
- printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
#include <linux/module.h>
#include <linux/types.h>
@@ -335,6 +335,7 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
[_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT",
+ [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
#endif
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -382,38 +383,45 @@ static const char *v4l2_int_ioctls[] = {
external ioctl messages as well as internal V4L ioctl */
void v4l_printk_ioctl(unsigned int cmd)
{
- char *dir;
+ char *dir, *type;
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "*ERR*"; break;
- }
switch (_IOC_TYPE(cmd)) {
case 'd':
- printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
- (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
- v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
- break;
+ if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
+ type = "v4l2_int";
+ break;
+ }
+ printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
+ return;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case 'v':
- printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
- (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
- break;
+ if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
+ type = "v4l1";
+ break;
+ }
+ printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
+ return;
#endif
case 'V':
- printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
- (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
- break;
-
+ if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
+ type = "v4l2";
+ break;
+ }
+ printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
+ return;
default:
- printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
- _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+ type = "unknown";
+ }
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "*ERR*"; break;
}
+ printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
+ type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
}
EXPORT_SYMBOL(v4l_printk_ioctl);
@@ -762,35 +770,35 @@ static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
{
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (vfd->vidioc_try_fmt_cap)
+ if (vfd->vidioc_try_fmt_vid_cap)
return (0);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (vfd->vidioc_try_fmt_overlay)
+ if (vfd->vidioc_try_fmt_vid_overlay)
return (0);
break;
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (vfd->vidioc_try_fmt_vbi)
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ if (vfd->vidioc_try_fmt_vid_out)
return (0);
break;
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (vfd->vidioc_try_fmt_vbi_output)
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ if (vfd->vidioc_try_fmt_vid_out_overlay)
return (0);
break;
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (vfd->vidioc_try_fmt_vbi_capture)
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (vfd->vidioc_try_fmt_vbi_cap)
return (0);
break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (vfd->vidioc_try_fmt_video_output)
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ if (vfd->vidioc_try_fmt_vbi_out)
return (0);
break;
- case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (vfd->vidioc_try_fmt_vbi_output)
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ if (vfd->vidioc_try_fmt_sliced_vbi_cap)
return (0);
break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (vfd->vidioc_try_fmt_output_overlay)
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ if (vfd->vidioc_try_fmt_sliced_vbi_out)
return (0);
break;
case V4L2_BUF_TYPE_PRIVATE:
@@ -811,6 +819,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
v4l_print_ioctl(vfd->name, cmd);
+ printk("\n");
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -906,46 +915,37 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (vfd->vidioc_enum_fmt_cap)
- ret=vfd->vidioc_enum_fmt_cap(file, fh, f);
+ if (vfd->vidioc_enum_fmt_vid_cap)
+ ret = vfd->vidioc_enum_fmt_vid_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (vfd->vidioc_enum_fmt_overlay)
- ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);
+ if (vfd->vidioc_enum_fmt_vid_overlay)
+ ret = vfd->vidioc_enum_fmt_vid_overlay(file,
+ fh, f);
break;
+#if 1 /* keep */
+ /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
+ * according to the spec. The bttv and saa7134 drivers support
+ * it though, so just warn that this is deprecated and will be
+ * removed in the near future. */
case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (vfd->vidioc_enum_fmt_vbi)
- ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (vfd->vidioc_enum_fmt_vbi_output)
- ret=vfd->vidioc_enum_fmt_vbi_output(file,
- fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (vfd->vidioc_enum_fmt_vbi_capture)
- ret=vfd->vidioc_enum_fmt_vbi_capture(file,
- fh, f);
+ if (vfd->vidioc_enum_fmt_vbi_cap) {
+ printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
+ ret = vfd->vidioc_enum_fmt_vbi_cap(file, fh, f);
+ }
break;
+#endif
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (vfd->vidioc_enum_fmt_video_output)
- ret=vfd->vidioc_enum_fmt_video_output(file,
- fh, f);
- break;
- case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (vfd->vidioc_enum_fmt_vbi_output)
- ret=vfd->vidioc_enum_fmt_vbi_output(file,
- fh, f);
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (vfd->vidioc_enum_fmt_output_overlay)
- ret=vfd->vidioc_enum_fmt_output_overlay(file, fh, f);
+ if (vfd->vidioc_enum_fmt_vid_out)
+ ret = vfd->vidioc_enum_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
if (vfd->vidioc_enum_fmt_type_private)
- ret=vfd->vidioc_enum_fmt_type_private(file,
+ ret = vfd->vidioc_enum_fmt_type_private(file,
fh, f);
break;
+ default:
+ break;
}
if (!ret)
dbgarg (cmd, "index=%d, type=%d, flags=%d, "
@@ -961,54 +961,54 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- enum v4l2_buf_type type=f->type;
- memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
- f->type=type;
+ memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data));
/* FIXME: Should be one dump per type */
- dbgarg (cmd, "type=%s\n", prt_names(type,
- v4l2_type_names));
+ dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
- switch (type) {
+ switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (vfd->vidioc_g_fmt_cap)
- ret=vfd->vidioc_g_fmt_cap(file, fh, f);
+ if (vfd->vidioc_g_fmt_vid_cap)
+ ret = vfd->vidioc_g_fmt_vid_cap(file, fh, f);
if (!ret)
v4l_print_pix_fmt(vfd,&f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (vfd->vidioc_g_fmt_overlay)
- ret=vfd->vidioc_g_fmt_overlay(file, fh, f);
- break;
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (vfd->vidioc_g_fmt_vbi)
- ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (vfd->vidioc_g_fmt_vbi_output)
- ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (vfd->vidioc_g_fmt_vbi_capture)
- ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
+ if (vfd->vidioc_g_fmt_vid_overlay)
+ ret = vfd->vidioc_g_fmt_vid_overlay(file,
+ fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (vfd->vidioc_g_fmt_video_output)
- ret=vfd->vidioc_g_fmt_video_output(file,
- fh, f);
+ if (vfd->vidioc_g_fmt_vid_out)
+ ret = vfd->vidioc_g_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (vfd->vidioc_g_fmt_output_overlay)
- ret=vfd->vidioc_g_fmt_output_overlay(file, fh, f);
+ if (vfd->vidioc_g_fmt_vid_out_overlay)
+ ret = vfd->vidioc_g_fmt_vid_out_overlay(file,
+ fh, f);
+ break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (vfd->vidioc_g_fmt_vbi_cap)
+ ret = vfd->vidioc_g_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (vfd->vidioc_g_fmt_vbi_output)
- ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
+ if (vfd->vidioc_g_fmt_vbi_out)
+ ret = vfd->vidioc_g_fmt_vbi_out(file, fh, f);
+ break;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ if (vfd->vidioc_g_fmt_sliced_vbi_cap)
+ ret = vfd->vidioc_g_fmt_sliced_vbi_cap(file,
+ fh, f);
+ break;
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ if (vfd->vidioc_g_fmt_sliced_vbi_out)
+ ret = vfd->vidioc_g_fmt_sliced_vbi_out(file,
+ fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
if (vfd->vidioc_g_fmt_type_private)
- ret=vfd->vidioc_g_fmt_type_private(file,
+ ret = vfd->vidioc_g_fmt_type_private(file,
fh, f);
break;
}
@@ -1026,42 +1026,44 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
v4l_print_pix_fmt(vfd,&f->fmt.pix);
- if (vfd->vidioc_s_fmt_cap)
- ret=vfd->vidioc_s_fmt_cap(file, fh, f);
+ if (vfd->vidioc_s_fmt_vid_cap)
+ ret = vfd->vidioc_s_fmt_vid_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (vfd->vidioc_s_fmt_overlay)
- ret=vfd->vidioc_s_fmt_overlay(file, fh, f);
- break;
- case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (vfd->vidioc_s_fmt_vbi)
- ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (vfd->vidioc_s_fmt_vbi_output)
- ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
- break;
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (vfd->vidioc_s_fmt_vbi_capture)
- ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
+ if (vfd->vidioc_s_fmt_vid_overlay)
+ ret = vfd->vidioc_s_fmt_vid_overlay(file,
+ fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (vfd->vidioc_s_fmt_video_output)
- ret=vfd->vidioc_s_fmt_video_output(file,
- fh, f);
+ if (vfd->vidioc_s_fmt_vid_out)
+ ret = vfd->vidioc_s_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (vfd->vidioc_s_fmt_output_overlay)
- ret=vfd->vidioc_s_fmt_output_overlay(file, fh, f);
+ if (vfd->vidioc_s_fmt_vid_out_overlay)
+ ret = vfd->vidioc_s_fmt_vid_out_overlay(file,
+ fh, f);
+ break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (vfd->vidioc_s_fmt_vbi_cap)
+ ret = vfd->vidioc_s_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (vfd->vidioc_s_fmt_vbi_output)
- ret=vfd->vidioc_s_fmt_vbi_output(file,
- fh, f);
+ if (vfd->vidioc_s_fmt_vbi_out)
+ ret = vfd->vidioc_s_fmt_vbi_out(file, fh, f);
+ break;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ if (vfd->vidioc_s_fmt_sliced_vbi_cap)
+ ret = vfd->vidioc_s_fmt_sliced_vbi_cap(file,
+ fh, f);
+ break;
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ if (vfd->vidioc_s_fmt_sliced_vbi_out)
+ ret = vfd->vidioc_s_fmt_sliced_vbi_out(file,
+ fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
if (vfd->vidioc_s_fmt_type_private)
- ret=vfd->vidioc_s_fmt_type_private(file,
+ ret = vfd->vidioc_s_fmt_type_private(file,
fh, f);
break;
}
@@ -1076,46 +1078,46 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
v4l2_type_names));
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (vfd->vidioc_try_fmt_cap)
- ret=vfd->vidioc_try_fmt_cap(file, fh, f);
+ if (vfd->vidioc_try_fmt_vid_cap)
+ ret = vfd->vidioc_try_fmt_vid_cap(file, fh, f);
if (!ret)
v4l_print_pix_fmt(vfd,&f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (vfd->vidioc_try_fmt_overlay)
- ret=vfd->vidioc_try_fmt_overlay(file, fh, f);
+ if (vfd->vidioc_try_fmt_vid_overlay)
+ ret = vfd->vidioc_try_fmt_vid_overlay(file,
+ fh, f);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ if (vfd->vidioc_try_fmt_vid_out)
+ ret = vfd->vidioc_try_fmt_vid_out(file, fh, f);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ if (vfd->vidioc_try_fmt_vid_out_overlay)
+ ret = vfd->vidioc_try_fmt_vid_out_overlay(file,
+ fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (vfd->vidioc_try_fmt_vbi)
- ret=vfd->vidioc_try_fmt_vbi(file, fh, f);
+ if (vfd->vidioc_try_fmt_vbi_cap)
+ ret = vfd->vidioc_try_fmt_vbi_cap(file, fh, f);
break;
- case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (vfd->vidioc_try_fmt_vbi_output)
- ret=vfd->vidioc_try_fmt_vbi_output(file,
- fh, f);
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ if (vfd->vidioc_try_fmt_vbi_out)
+ ret = vfd->vidioc_try_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (vfd->vidioc_try_fmt_vbi_capture)
- ret=vfd->vidioc_try_fmt_vbi_capture(file,
- fh, f);
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (vfd->vidioc_try_fmt_video_output)
- ret=vfd->vidioc_try_fmt_video_output(file,
+ if (vfd->vidioc_try_fmt_sliced_vbi_cap)
+ ret = vfd->vidioc_try_fmt_sliced_vbi_cap(file,
fh, f);
break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (vfd->vidioc_try_fmt_output_overlay)
- ret=vfd->vidioc_try_fmt_output_overlay(file, fh, f);
- break;
- case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (vfd->vidioc_try_fmt_vbi_output)
- ret=vfd->vidioc_try_fmt_vbi_output(file,
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ if (vfd->vidioc_try_fmt_sliced_vbi_out)
+ ret = vfd->vidioc_try_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
if (vfd->vidioc_try_fmt_type_private)
- ret=vfd->vidioc_try_fmt_type_private(file,
+ ret = vfd->vidioc_try_fmt_type_private(file,
fh, f);
break;
}
@@ -1342,11 +1344,15 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
{
v4l2_std_id *id = arg;
- *id = vfd->current_norm;
-
- dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id);
+ ret = 0;
+ /* Calls the specific handler */
+ if (vfd->vidioc_g_std)
+ ret = vfd->vidioc_g_std(file, fh, id);
+ else
+ *id = vfd->current_norm;
- ret=0;
+ if (!ret)
+ dbgarg(cmd, "value=%08Lx\n", (long long unsigned)*id);
break;
}
case VIDIOC_S_STD:
@@ -1429,6 +1435,25 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
/* ------ output switching ---------- */
+ case VIDIOC_ENUMOUTPUT:
+ {
+ struct v4l2_output *p = arg;
+ int i = p->index;
+
+ if (!vfd->vidioc_enum_output)
+ break;
+ memset(p, 0, sizeof(*p));
+ p->index = i;
+
+ ret = vfd->vidioc_enum_output(file, fh, p);
+ if (!ret)
+ dbgarg(cmd, "index=%d, name=%s, type=%d, "
+ "audioset=%d, "
+ "modulator=%d, std=%08Lx\n",
+ p->index, p->name, p->type, p->audioset,
+ p->modulator, (unsigned long long)p->std);
+ break;
+ }
case VIDIOC_G_OUTPUT:
{
unsigned int *i = arg;
@@ -1821,16 +1846,17 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_G_FREQUENCY:
{
- struct v4l2_frequency *p=arg;
+ struct v4l2_frequency *p = arg;
+
if (!vfd->vidioc_g_frequency)
break;
- memset(p,0,sizeof(*p));
+ memset(p->reserved, 0, sizeof(p->reserved));
- ret=vfd->vidioc_g_frequency(file, fh, p);
+ ret = vfd->vidioc_g_frequency(file, fh, p);
if (!ret)
- dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
- p->tuner,p->type,p->frequency);
+ dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
+ p->tuner, p->type, p->frequency);
break;
}
case VIDIOC_S_FREQUENCY:
@@ -1890,12 +1916,31 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
break;
}
+ default:
+ {
+ if (!vfd->vidioc_default)
+ break;
+ ret = vfd->vidioc_default(file, fh, cmd, arg);
+ break;
+ }
+ case VIDIOC_S_HW_FREQ_SEEK:
+ {
+ struct v4l2_hw_freq_seek *p = arg;
+ if (!vfd->vidioc_s_hw_freq_seek)
+ break;
+ dbgarg(cmd,
+ "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
+ p->tuner, p->type, p->seek_upward, p->wrap_around);
+ ret = vfd->vidioc_s_hw_freq_seek(file, fh, p);
+ break;
+ }
} /* switch */
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret<0) {
- printk ("%s: err:\n", vfd->name);
+ printk("%s: err: on ", vfd->name);
v4l_print_ioctl(vfd->name, cmd);
+ printk("\n");
}
}
@@ -2056,7 +2101,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
break;
default:
printk(KERN_ERR "%s called with unknown type: %d\n",
- __FUNCTION__, type);
+ __func__, type);
return -1;
}
@@ -2105,7 +2150,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
ret = device_register(&vfd->class_dev);
if (ret < 0) {
printk(KERN_ERR "%s: device_register failed\n",
- __FUNCTION__);
+ __func__);
goto fail_minor;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c
index ef7752aa8..bf15e2eb2 100644
--- a/linux/drivers/media/video/vino.c
+++ b/linux/drivers/media/video/vino.c
@@ -13,7 +13,7 @@
/*
* TODO:
* - remove "mark pages reserved-hacks" from memory allocation code
- * and implement nopage()
+ * and implement fault()
* - check decimation, calculating and reporting image size when
* using decimation
* - implement read(), user mode buffers and overlay (?)
diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c
index 6464c69f3..028040dd8 100644
--- a/linux/drivers/media/video/vivi.c
+++ b/linux/drivers/media/video/vivi.c
@@ -439,7 +439,7 @@ static void vivi_sleep(struct vivi_fh *fh)
int timeout;
DECLARE_WAITQUEUE(wait, current);
- dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
+ dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
(unsigned long)dma_q);
add_wait_queue(&dma_q->wq, &wait);
@@ -514,7 +514,7 @@ static int vivi_start_thread(struct vivi_fh *fh)
dma_q->frame = 0;
dma_q->ini_jiffies = jiffies;
- dprintk(dev, 1, "%s\n", __FUNCTION__);
+ dprintk(dev, 1, "%s\n", __func__);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
@@ -541,7 +541,7 @@ static int vivi_start_thread(struct vivi_fh *fh)
/* Wakes thread */
wake_up_interruptible(&dma_q->wq);
- dprintk(dev, 1, "returning from %s\n", __FUNCTION__);
+ dprintk(dev, 1, "returning from %s\n", __func__);
return 0;
}
@@ -549,7 +549,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
{
struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
- dprintk(dev, 1, "%s\n", __FUNCTION__);
+ dprintk(dev, 1, "%s\n", __func__);
/* shutdown control thread */
if (dma_q->kthread) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
@@ -586,7 +586,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
while (*size * *count > vid_limit * 1024 * 1024)
(*count)--;
- dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__,
+ dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
*count, *size);
return 0;
@@ -597,13 +597,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
struct vivi_fh *fh = vq->priv_data;
struct vivi_dev *dev = fh->dev;
- dprintk(dev, 1, "%s, state: %i\n", __FUNCTION__, buf->vb.state);
+ dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
if (in_interrupt())
BUG();
videobuf_vmalloc_free(&buf->vb);
- dprintk(dev, 1, "free_buffer: freed");
+ dprintk(dev, 1, "free_buffer: freed\n");
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
@@ -618,7 +618,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
int rc;
- dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field);
+ dprintk(dev, 1, "%s, field=%d\n", __func__, field);
BUG_ON(NULL == fh->fmt);
@@ -659,7 +659,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
struct vivi_dev *dev = fh->dev;
struct vivi_dmaqueue *vidq = &dev->vidq;
- dprintk(dev, 1, "%s\n", __FUNCTION__);
+ dprintk(dev, 1, "%s\n", __func__);
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->vb.queue, &vidq->active);
@@ -672,7 +672,7 @@ static void buffer_release(struct videobuf_queue *vq,
struct vivi_fh *fh = vq->priv_data;
struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
- dprintk(dev, 1, "%s\n", __FUNCTION__);
+ dprintk(dev, 1, "%s\n", __func__);
free_buffer(vq, buf);
}
@@ -699,7 +699,7 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_cap(struct file *file, void *priv,
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index > 0)
@@ -710,7 +710,7 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct vivi_fh *fh = priv;
@@ -727,7 +727,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
return (0);
}
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct vivi_fh *fh = priv;
@@ -775,20 +775,20 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
}
/*FIXME: This seems to be generic enough to be at videodev2 */
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct vivi_fh *fh = priv;
struct videobuf_queue *q = &fh->vb_vidq;
- int ret = vidioc_try_fmt_cap(file, fh, f);
+ int ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
return (ret);
mutex_lock(&q->vb_lock);
if (videobuf_queue_is_busy(&fh->vb_vidq)) {
- dprintk(fh->dev, 1, "%s queue busy\n", __FUNCTION__);
+ dprintk(fh->dev, 1, "%s queue busy\n", __func__);
ret = -EBUSY;
goto out;
}
@@ -958,7 +958,7 @@ static int vivi_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct vivi_dev *dev;
- struct vivi_fh *fh;
+ struct vivi_fh *fh = NULL;
int i;
int retval = 0;
@@ -1044,7 +1044,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
struct vivi_dev *dev = fh->dev;
struct videobuf_queue *q = &fh->vb_vidq;
- dprintk(dev, 1, "%s\n", __FUNCTION__);
+ dprintk(dev, 1, "%s\n", __func__);
if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
return POLLERR;
@@ -1123,7 +1123,7 @@ static const struct file_operations vivi_fops = {
.poll = vivi_poll,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
- .compat_ioctl = v4l_compat_ioctl32,
+ .compat_ioctl = v4l_compat_ioctl32,
#endif
.mmap = vivi_mmap,
.llseek = no_llseek,
@@ -1137,10 +1137,10 @@ static struct video_device vivi_template = {
.release = video_device_release,
.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_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c
index 922aa8d74..25a69c7f5 100644
--- a/linux/drivers/media/video/vp27smpx.c
+++ b/linux/drivers/media/video/vp27smpx.c
@@ -135,7 +135,8 @@ static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg)
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int vp27smpx_probe(struct i2c_client *client)
+static int vp27smpx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct vp27smpx_state *state;
@@ -143,8 +144,9 @@ static int vp27smpx_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
snprintf(client->name, sizeof(client->name) - 1, "vp27smpx");
-
+#endif
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
@@ -167,6 +169,14 @@ static int vp27smpx_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id vp27smpx_id[] = {
+ { "vp27smpx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, vp27smpx_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "vp27smpx",
.driverid = I2C_DRIVERID_VP27SMPX,
@@ -176,6 +186,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
#ifndef I2C_CLASS_TV_ANALOG
.legacy_id = I2C_HW_B_CX2341X,
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = vp27smpx_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/w9966.c b/linux/drivers/media/video/w9966.c
index 595e32a87..9b77f268c 100644
--- a/linux/drivers/media/video/w9966.c
+++ b/linux/drivers/media/video/w9966.c
@@ -65,7 +65,7 @@
/*#define DEBUG*/ /* Undef me for production */
#ifdef DEBUG
-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a)
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
#else
#define DPRINTF(x...)
#endif
diff --git a/linux/drivers/media/video/w9968cf.h b/linux/drivers/media/video/w9968cf.h
index c2e609bac..8e1742cb7 100644
--- a/linux/drivers/media/video/w9968cf.h
+++ b/linux/drivers/media/video/w9968cf.h
@@ -304,7 +304,7 @@ struct w9968cf_device {
dev_warn(&cam->dev, fmt "\n", ## args); \
else if ((level) >= 5) \
dev_info(&cam->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __func__, __LINE__ , ## args); \
} \
}
/* For generic kernel (not device specific) messages */
@@ -315,7 +315,7 @@ struct w9968cf_device {
if ((level) >= 1 && (level) <= 4) \
pr_info("w9968cf: " fmt "\n", ## args); \
else if ((level) >= 5) \
- pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \
+ pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__, \
__LINE__ , ## args); \
} \
}
@@ -327,7 +327,7 @@ struct w9968cf_device {
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
+dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c
index f2010b8a7..d448dcf6e 100644
--- a/linux/drivers/media/video/wm8739.c
+++ b/linux/drivers/media/video/wm8739.c
@@ -279,7 +279,8 @@ static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg)
/* i2c implementation */
-static int wm8739_probe(struct i2c_client *client)
+static int wm8739_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8739_state *state;
@@ -330,6 +331,14 @@ static int wm8739_remove(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id wm8739_id[] = {
+ { "wm8739", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8739_id);
+#endif
+
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "wm8739",
.driverid = I2C_DRIVERID_WM8739,
@@ -339,6 +348,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
#ifndef I2C_CLASS_TV_ANALOG
.legacy_id = I2C_HW_B_CX2341X,
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = wm8739_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c
index b0030789b..81a08d674 100644
--- a/linux/drivers/media/video/wm8775.c
+++ b/linux/drivers/media/video/wm8775.c
@@ -167,7 +167,8 @@ static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg)
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int wm8775_probe(struct i2c_client *client)
+static int wm8775_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8775_state *state;
@@ -223,12 +224,23 @@ static int wm8775_remove(struct i2c_client *client)
return 0;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id wm8775_id[] = {
+ { "wm8775", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8775_id);
+
+#endif
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "wm8775",
.driverid = I2C_DRIVERID_WM8775,
.command = wm8775_command,
.probe = wm8775_probe,
.remove = wm8775_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = wm8775_id,
+#endif
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
diff --git a/linux/drivers/media/video/zc0301/zc0301.h b/linux/drivers/media/video/zc0301/zc0301.h
index 6a944c658..d0e258176 100644
--- a/linux/drivers/media/video/zc0301/zc0301.h
+++ b/linux/drivers/media/video/zc0301/zc0301.h
@@ -167,7 +167,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
- __FILE__, __FUNCTION__, __LINE__ , ## args); \
+ __FILE__, __func__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -177,7 +177,7 @@ do { \
pr_info("zc0301: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
- __FUNCTION__, __LINE__ , ## args); \
+ __func__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -193,7 +193,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
__LINE__ , ## args)
#undef PDBGG
diff --git a/linux/drivers/media/video/zc0301/zc0301_core.c b/linux/drivers/media/video/zc0301/zc0301_core.c
index 261964c6a..e167fa560 100644
--- a/linux/drivers/media/video/zc0301/zc0301_core.c
+++ b/linux/drivers/media/video/zc0301/zc0301_core.c
@@ -38,7 +38,7 @@
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/page-flags.h>
-#include <linux/byteorder/generic.h>
+#include <asm/byteorder.h>
#include <asm/page.h>
#include <asm/uaccess.h>
diff --git a/linux/drivers/media/video/zoran.h b/linux/drivers/media/video/zoran.h
index 848dbcf25..baa5f423d 100644
--- a/linux/drivers/media/video/zoran.h
+++ b/linux/drivers/media/video/zoran.h
@@ -243,10 +243,8 @@ struct zoran_format {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
int palette;
#endif
-#ifdef CONFIG_VIDEO_V4L2
__u32 fourcc;
int colorspace;
-#endif
int depth;
__u32 flags;
__u32 vfespfr;
@@ -271,20 +269,6 @@ struct zoran_v4l_settings {
const struct zoran_format *format; /* capture format */
};
-/* whoops, this one is undeclared if !v4l2 */
-#ifndef CONFIG_VIDEO_V4L2
-struct v4l2_jpegcompression {
- int quality;
- int APPn;
- int APP_len;
- char APP_data[60];
- int COM_len;
- char COM_data[60];
- __u32 jpeg_markers;
- __u8 reserved[116];
-};
-#endif
-
/* jpg-capture/-playback settings */
struct zoran_jpg_settings {
int decimation; /* this bit is used to set everything to default */
@@ -301,7 +285,7 @@ struct zoran_mapping {
struct zoran_jpg_buffer {
struct zoran_mapping *map;
- u32 *frag_tab; /* addresses of frag table */
+ __le32 *frag_tab; /* addresses of frag table */
u32 frag_tab_bus; /* same value cached to save time in ISR */
enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */
struct zoran_sync bs; /* DONE: info to return to application */
@@ -470,7 +454,7 @@ struct zoran {
unsigned long jpg_queued_num; /* count of frames queued since grab/play started */
/* zr36057's code buffer table */
- u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+ __le32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
/* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
int jpg_pend[BUZ_MAX_FRAME];
diff --git a/linux/drivers/media/video/zoran_device.c b/linux/drivers/media/video/zoran_device.c
index 575f5447c..b0a014d09 100644
--- a/linux/drivers/media/video/zoran_device.c
+++ b/linux/drivers/media/video/zoran_device.c
@@ -31,7 +31,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
-#include <linux/byteorder/generic.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
@@ -48,6 +47,7 @@
#include <linux/delay.h>
#include <linux/wait.h>
+#include <asm/byteorder.h>
#include <asm/io.h>
#include "videocodec.h"
@@ -1321,7 +1321,7 @@ error_handler (struct zoran *zr,
if (i) {
/* Rotate stat_comm entries to make current entry first */
int j;
- u32 bus_addr[BUZ_NUM_STAT_COM];
+ __le32 bus_addr[BUZ_NUM_STAT_COM];
/* Here we are copying the stat_com array, which
* is already in little endian format, so
diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c
index ceb5c1778..fdec02d98 100644
--- a/linux/drivers/media/video/zoran_driver.c
+++ b/linux/drivers/media/video/zoran_driver.c
@@ -52,7 +52,6 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <linux/byteorder/generic.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
@@ -74,6 +73,7 @@
#include <media/v4l2-common.h>
#include "videocodec.h"
+#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
@@ -88,7 +88,6 @@
#include "zoran_device.h"
#include "zoran_card.h"
-#ifdef CONFIG_VIDEO_V4L2
/* we declare some card type definitions here, they mean
* the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
#define ZORAN_V4L2_VID_FLAGS ( \
@@ -97,19 +96,15 @@
V4L2_CAP_VIDEO_OUTPUT |\
V4L2_CAP_VIDEO_OVERLAY \
)
-#endif
#include <asm/byteorder.h>
-#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
+#if defined(CONFIG_VIDEO_V4L1_COMPAT)
#define ZFMT(pal, fcc, cs) \
.palette = (pal), .fourcc = (fcc), .colorspace = (cs)
-#elif defined(CONFIG_VIDEO_V4L2)
-#define ZFMT(pal, fcc, cs) \
- .fourcc = (fcc), .colorspace = (cs)
#else
#define ZFMT(pal, fcc, cs) \
- .palette = (pal)
+ .fourcc = (fcc), .colorspace = (cs)
#endif
const struct zoran_format zoran_formats[] = {
@@ -219,7 +214,6 @@ static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */
module_param(lock_norm, int, 0644);
MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
-#ifdef CONFIG_VIDEO_V4L2
/* small helper function for calculating buffersizes for v4l2
* we calculate the nearest higher power-of-two, which
* will be the recommended buffersize */
@@ -242,7 +236,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
return 8192;
return result;
}
-#endif
/* forward references */
static void v4l_fbuffer_free(struct file *file);
@@ -353,7 +346,7 @@ v4l_fbuffer_alloc (struct file *file)
/* Use kmalloc */
mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
- if (mem == 0) {
+ if (!mem) {
dprintk(1,
KERN_ERR
"%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",
@@ -569,7 +562,7 @@ jpg_fbuffer_alloc (struct file *file)
jpg_fbuffer_free(file);
return -ENOBUFS;
}
- fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;
+ fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
fh->jpg_buffers.buffer[i].frag_tab_bus =
virt_to_bus((void *) mem);
@@ -1241,7 +1234,7 @@ zoran_close_end_session (struct file *file)
/* v4l capture */
if (fh->v4l_buffers.active != ZORAN_FREE) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -1776,7 +1769,6 @@ setup_overlay (struct file *file,
return wait_grab_pending(zr);
}
-#ifdef CONFIG_VIDEO_V4L2
/* get the status of a buffer in the clients buffer queue */
static int
zoran_v4l2_buffer_status (struct file *file,
@@ -1882,7 +1874,6 @@ zoran_v4l2_buffer_status (struct file *file,
return 0;
}
-#endif
static int
zoran_set_norm (struct zoran *zr,
@@ -2691,8 +2682,6 @@ zoran_do_ioctl (struct inode *inode,
}
break;
-#ifdef CONFIG_VIDEO_V4L2
-
/* The new video4linux2 capture interface - much nicer than video4linux1, since
* it allows for integrating the JPEG capturing calls inside standard v4l2
*/
@@ -3514,7 +3503,7 @@ zoran_do_ioctl (struct inode *inode,
/* unload capture */
if (zr->v4l_memgrab_active) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -4264,7 +4253,6 @@ zoran_do_ioctl (struct inode *inode,
return 0;
}
break;
-#endif
default:
dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
@@ -4314,7 +4302,7 @@ zoran_poll (struct file *file,
dprintk(3,
KERN_DEBUG
"%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
- ZR_DEVNAME(zr), __FUNCTION__,
+ ZR_DEVNAME(zr), __func__,
"FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
"UPMD"[zr->v4l_buffers.buffer[frame].state],
zr->v4l_pend_tail, zr->v4l_pend_head);
@@ -4336,7 +4324,7 @@ zoran_poll (struct file *file,
dprintk(3,
KERN_DEBUG
"%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
- ZR_DEVNAME(zr), __FUNCTION__,
+ ZR_DEVNAME(zr), __func__,
"FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
"UPMD"[zr->jpg_buffers.buffer[frame].state],
zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
@@ -4454,7 +4442,7 @@ zoran_vm_close (struct vm_area_struct *vma)
mutex_lock(&zr->resource_lock);
if (fh->v4l_buffers.active != ZORAN_FREE) {
- long flags;
+ unsigned long flags;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
@@ -4585,7 +4573,7 @@ zoran_mmap (struct file *file,
if (todo > fraglen)
todo = fraglen;
pos =
- le32_to_cpu((unsigned long) fh->jpg_buffers.
+ le32_to_cpu(fh->jpg_buffers.
buffer[i].frag_tab[2 * j]);
/* should just be pos on i386 */
page = virt_to_phys(bus_to_virt(pos))
@@ -4724,9 +4712,7 @@ static const struct file_operations zoran_fops = {
struct video_device zoran_template __devinitdata = {
.name = ZORAN_NAME,
.type = ZORAN_VID_TYPE,
-#ifdef CONFIG_VIDEO_V4L2
.type2 = ZORAN_V4L2_VID_FLAGS,
-#endif
.fops = &zoran_fops,
.release = &zoran_vdev_release,
.minor = -1
diff --git a/linux/drivers/media/video/zoran_procfs.c b/linux/drivers/media/video/zoran_procfs.c
index 5aa285bdc..d7bc097da 100644
--- a/linux/drivers/media/video/zoran_procfs.c
+++ b/linux/drivers/media/video/zoran_procfs.c
@@ -189,6 +189,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
}
static const struct file_operations zoran_operations = {
+ .owner = THIS_MODULE,
.open = zoran_open,
.read = seq_read,
.write = zoran_write,
@@ -204,10 +205,8 @@ zoran_proc_init (struct zoran *zr)
char name[8];
snprintf(name, 7, "zoran%d", zr->id);
- if ((zr->zoran_proc = create_proc_entry(name, 0, NULL))) {
- zr->zoran_proc->data = zr;
- zr->zoran_proc->owner = THIS_MODULE;
- zr->zoran_proc->proc_fops = &zoran_operations;
+ zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
+ if (zr->zoran_proc != NULL) {
dprintk(2,
KERN_INFO
"%s: procfs entry /proc/%s allocated. data=%p\n",
diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c
index 0afd1c9c1..2e7cf6f26 100644
--- a/linux/drivers/media/video/zr364xx.c
+++ b/linux/drivers/media/video/zr364xx.c
@@ -395,7 +395,7 @@ static int read_frame(struct zr364xx_camera *cam, int framenum)
}
-static ssize_t zr364xx_read(struct file *file, char *buf, size_t cnt,
+static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt,
loff_t * ppos)
{
unsigned long count = cnt;
@@ -526,7 +526,7 @@ static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
return 0;
}
-static int zr364xx_vidioc_enum_fmt_cap(struct file *file,
+static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
void *priv, struct v4l2_fmtdesc *f)
{
if (f->index > 0)
@@ -542,7 +542,7 @@ static int zr364xx_vidioc_enum_fmt_cap(struct file *file,
return 0;
}
-static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct video_device *vdev = video_devdata(file);
@@ -569,7 +569,7 @@ static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct video_device *vdev = video_devdata(file);
@@ -594,7 +594,7 @@ static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,
return 0;
}
-static int zr364xx_vidioc_s_fmt_cap(struct file *file, void *priv,
+static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct video_device *vdev = video_devdata(file);
@@ -775,10 +775,10 @@ static struct video_device zr364xx_template = {
.minor = -1,
.vidioc_querycap = zr364xx_vidioc_querycap,
- .vidioc_enum_fmt_cap = zr364xx_vidioc_enum_fmt_cap,
- .vidioc_try_fmt_cap = zr364xx_vidioc_try_fmt_cap,
- .vidioc_s_fmt_cap = zr364xx_vidioc_s_fmt_cap,
- .vidioc_g_fmt_cap = zr364xx_vidioc_g_fmt_cap,
+ .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
.vidioc_enum_input = zr364xx_vidioc_enum_input,
.vidioc_g_input = zr364xx_vidioc_g_input,
.vidioc_s_input = zr364xx_vidioc_s_input,
diff --git a/linux/include/asm-arm/arch-pxa/pxa-regs.h b/linux/include/asm-arm/arch-pxa/pxa-regs.h
index b65a3a789..a288ae8c7 100644
--- a/linux/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/linux/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1129,6 +1129,11 @@
#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */
+#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
+#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
+#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
+#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
+#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */
/*
* General Purpose I/O
@@ -1200,12 +1205,6 @@
/* Interrupt Controller */
-#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
-#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
-#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
-#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
-#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */
-
#define _GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3)
#define _GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3)
#define _GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3)
@@ -1237,342 +1236,6 @@
#endif
-
-/* GPIO alternate function assignments */
-
-#define GPIO1_RST 1 /* reset */
-#define GPIO6_MMCCLK 6 /* MMC Clock */
-#define GPIO7_48MHz 7 /* 48 MHz clock output */
-#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */
-#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */
-#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */
-#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */
-#define GPIO12_32KHz 12 /* 32 kHz out */
-#define GPIO12_CIF_DD7 12 /* Capture Interface D7 (PXA27x) */
-#define GPIO13_MBGNT 13 /* memory controller grant */
-#define GPIO14_MBREQ 14 /* alternate bus master request */
-#define GPIO15_nCS_1 15 /* chip select 1 */
-#define GPIO16_PWM0 16 /* PWM0 output */
-#define GPIO17_PWM1 17 /* PWM1 output */
-#define GPIO17_CIF_DD6 17 /* Capture Interface D6 (PXA27x) */
-#define GPIO18_RDY 18 /* Ext. Bus Ready */
-#define GPIO19_DREQ1 19 /* External DMA Request */
-#define GPIO20_DREQ0 20 /* External DMA Request */
-#define GPIO23_SCLK 23 /* SSP clock */
-#define GPIO23_CIF_MCLK 23 /* Capture Interface MCLK (PXA27x) */
-#define GPIO24_SFRM 24 /* SSP Frame */
-#define GPIO24_CIF_FV 24 /* Capture Interface FV (PXA27x) */
-#define GPIO25_STXD 25 /* SSP transmit */
-#define GPIO25_CIF_LV 25 /* Capture Interface LV (PXA27x) */
-#define GPIO26_SRXD 26 /* SSP receive */
-#define GPIO26_CIF_PCLK 26 /* Capture Interface PCLK (PXA27x) */
-#define GPIO27_SEXTCLK 27 /* SSP ext_clk */
-#define GPIO27_CIF_DD0 27 /* Capture Interface D0 (PXA27x) */
-#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */
-#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */
-#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */
-#define GPIO31_SYNC 31 /* AC97/I2S sync */
-#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */
-#define GPIO32_SYSCLK 32 /* I2S System Clock */
-#define GPIO32_MMCCLK 32 /* MMC Clock (PXA270) */
-#define GPIO33_nCS_5 33 /* chip select 5 */
-#define GPIO34_FFRXD 34 /* FFUART receive */
-#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */
-#define GPIO35_FFCTS 35 /* FFUART Clear to send */
-#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */
-#define GPIO37_FFDSR 37 /* FFUART data set ready */
-#define GPIO38_FFRI 38 /* FFUART Ring Indicator */
-#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */
-#define GPIO39_FFTXD 39 /* FFUART transmit data */
-#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */
-#define GPIO41_FFRTS 41 /* FFUART request to send */
-#define GPIO42_BTRXD 42 /* BTUART receive data */
-#define GPIO42_HWRXD 42 /* HWUART receive data */
-#define GPIO42_CIF_MCLK 42 /* Capture interface MCLK (PXA27x) */
-#define GPIO43_BTTXD 43 /* BTUART transmit data */
-#define GPIO43_HWTXD 43 /* HWUART transmit data */
-#define GPIO43_CIF_FV 43 /* Capture interface FV (PXA27x) */
-#define GPIO44_BTCTS 44 /* BTUART clear to send */
-#define GPIO44_HWCTS 44 /* HWUART clear to send */
-#define GPIO44_CIF_LV 44 /* Capture interface LV (PXA27x) */
-#define GPIO45_BTRTS 45 /* BTUART request to send */
-#define GPIO45_HWRTS 45 /* HWUART request to send */
-#define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */
-#define GPIO45_CIF_PCLK 45 /* Capture interface PCLK (PXA27x) */
-#define GPIO46_ICPRXD 46 /* ICP receive data */
-#define GPIO46_STRXD 46 /* STD_UART receive data */
-#define GPIO47_ICPTXD 47 /* ICP transmit data */
-#define GPIO47_STTXD 47 /* STD_UART transmit data */
-#define GPIO47_CIF_DD0 47 /* Capture interface D0 (PXA27x) */
-#define GPIO48_nPOE 48 /* Output Enable for Card Space */
-#define GPIO48_CIF_DD5 48 /* Capture interface D5 (PXA27x) */
-#define GPIO49_nPWE 49 /* Write Enable for Card Space */
-#define GPIO50_nPIOR 50 /* I/O Read for Card Space */
-#define GPIO50_CIF_DD3 50 /* Capture interface D3 (PXA27x) */
-#define GPIO51_nPIOW 51 /* I/O Write for Card Space */
-#define GPIO51_CIF_DD2 51 /* Capture interface D2 (PXA27x) */
-#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */
-#define GPIO52_CIF_DD4 52 /* Capture interface D4 (PXA27x) */
-#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */
-#define GPIO53_MMCCLK 53 /* MMC Clock */
-#define GPIO53_CIF_MCLK 53 /* Capture interface MCLK (PXA27x) */
-#define GPIO54_MMCCLK 54 /* MMC Clock */
-#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */
-#define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */
-#define GPIO54_CIF_PCLK 54 /* Capture interface PCLK (PXA27x) */
-#define GPIO55_nPREG 55 /* Card Address bit 26 */
-#define GPIO55_CIF_DD1 55 /* Capture interface D1 (PXA27x) */
-#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */
-#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */
-#define GPIO58_LDD_0 58 /* LCD data pin 0 */
-#define GPIO59_LDD_1 59 /* LCD data pin 1 */
-#define GPIO60_LDD_2 60 /* LCD data pin 2 */
-#define GPIO61_LDD_3 61 /* LCD data pin 3 */
-#define GPIO62_LDD_4 62 /* LCD data pin 4 */
-#define GPIO63_LDD_5 63 /* LCD data pin 5 */
-#define GPIO64_LDD_6 64 /* LCD data pin 6 */
-#define GPIO65_LDD_7 65 /* LCD data pin 7 */
-#define GPIO66_LDD_8 66 /* LCD data pin 8 */
-#define GPIO66_MBREQ 66 /* alternate bus master req */
-#define GPIO67_LDD_9 67 /* LCD data pin 9 */
-#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */
-#define GPIO68_LDD_10 68 /* LCD data pin 10 */
-#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */
-#define GPIO69_LDD_11 69 /* LCD data pin 11 */
-#define GPIO69_MMCCLK 69 /* MMC_CLK */
-#define GPIO70_LDD_12 70 /* LCD data pin 12 */
-#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */
-#define GPIO71_LDD_13 71 /* LCD data pin 13 */
-#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */
-#define GPIO72_LDD_14 72 /* LCD data pin 14 */
-#define GPIO72_32kHz 72 /* 32 kHz clock */
-#define GPIO73_LDD_15 73 /* LCD data pin 15 */
-#define GPIO73_MBGNT 73 /* Memory controller grant */
-#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */
-#define GPIO75_LCD_LCLK 75 /* LCD line clock */
-#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */
-#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */
-#define GPIO78_nCS_2 78 /* chip select 2 */
-#define GPIO79_nCS_3 79 /* chip select 3 */
-#define GPIO80_nCS_4 80 /* chip select 4 */
-#define GPIO81_NSCLK 81 /* NSSP clock */
-#define GPIO81_CIF_DD0 81 /* Capture Interface D0 (PXA27x) */
-#define GPIO82_NSFRM 82 /* NSSP Frame */
-#define GPIO82_CIF_DD5 82 /* Capture Interface D5 (PXA27x) */
-#define GPIO83_NSTXD 83 /* NSSP transmit */
-#define GPIO83_CIF_DD4 83 /* Capture Interface D4 (PXA27x) */
-#define GPIO84_NSRXD 84 /* NSSP receive */
-#define GPIO84_CIF_FV 84 /* Capture Interface FV (PXA27x) */
-#define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */
-#define GPIO85_CIF_LV 85 /* Capture Interface LV (PXA27x) */
-#define GPIO90_CIF_DD4 90 /* Capture Interface DD4 (PXA27x) */
-#define GPIO91_CIF_DD5 91 /* Capture Interface DD5 (PXA27x) */
-#define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */
-#define GPIO93_CIF_DD6 93 /* Capture interface D6 (PXA27x) */
-#define GPIO94_CIF_DD5 94 /* Capture interface D5 (PXA27x) */
-#define GPIO95_CIF_DD4 95 /* Capture interface D4 (PXA27x) */
-#define GPIO98_CIF_DD0 98 /* Capture interface D0 (PXA27x) */
-#define GPIO103_CIF_DD3 103 /* Capture interface D3 (PXA27x) */
-#define GPIO104_CIF_DD2 104 /* Capture interface D2 (PXA27x) */
-#define GPIO105_CIF_DD1 105 /* Capture interface D1 (PXA27x) */
-#define GPIO106_CIF_DD9 106 /* Capture interface D9 (PXA27x) */
-#define GPIO107_CIF_DD8 107 /* Capture interface D8 (PXA27x) */
-#define GPIO108_CIF_DD7 108 /* Capture interface D7 (PXA27x) */
-#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */
-#define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */
-#define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */
-#define GPIO110_MMCCS0 110 /* MMC Chip Select 0 (PXA27x) */
-#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */
-#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */
-#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */
-#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */
-#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */
-#define GPIO114_CIF_DD1 114 /* Capture interface D1 (PXA27x) */
-#define GPIO115_CIF_DD3 115 /* Capture interface D3 (PXA27x) */
-#define GPIO116_CIF_DD2 116 /* Capture interface D2 (PXA27x) */
-
-/* GPIO alternate function mode & direction */
-
-#define GPIO_IN 0x000
-#define GPIO_OUT 0x080
-#define GPIO_ALT_FN_1_IN 0x100
-#define GPIO_ALT_FN_1_OUT 0x180
-#define GPIO_ALT_FN_2_IN 0x200
-#define GPIO_ALT_FN_2_OUT 0x280
-#define GPIO_ALT_FN_3_IN 0x300
-#define GPIO_ALT_FN_3_OUT 0x380
-#define GPIO_MD_MASK_NR 0x07f
-#define GPIO_MD_MASK_DIR 0x080
-#define GPIO_MD_MASK_FN 0x300
-#define GPIO_DFLT_LOW 0x400
-#define GPIO_DFLT_HIGH 0x800
-
-#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN)
-#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT)
-#define GPIO7_48MHz_MD ( 7 | GPIO_ALT_FN_1_OUT)
-#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT)
-#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT)
-#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT)
-#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT)
-#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT)
-#define GPIO12_CIF_DD7_MD (12 | GPIO_ALT_FN_2_IN)
-#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT)
-#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN)
-#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT)
-#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT)
-#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT)
-#define GPIO17_CIF_DD6_MD (17 | GPIO_ALT_FN_2_IN)
-#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
-#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
-#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
-#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT)
-#define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT)
-#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT)
-#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
-#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT)
-#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
-#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN)
-#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN)
-#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN)
-#define GPIO27_CIF_DD0_MD (27 | GPIO_ALT_FN_3_IN)
-#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN)
-#define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN)
-#define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT)
-#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
-#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
-#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
-#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
-#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT)
-#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT)
-#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN)
-#define GPIO32_SYSCLK_I2S_MD (32 | GPIO_ALT_FN_1_OUT)
-#define GPIO32_MMCCLK_MD ( 32 | GPIO_ALT_FN_2_OUT)
-#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT)
-#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN)
-#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT)
-#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN)
-#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
-#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
-#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
-#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
-#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
-#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT)
-#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT)
-#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN)
-#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT)
-#define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN)
-#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT)
-#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT)
-#define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT)
-#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN)
-#define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN)
-#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT)
-#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT)
-#define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT)
-#define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT)
-#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN)
-#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN)
-#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN)
-#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT)
-#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT)
-#define GPIO47_CIF_DD0_MD (47 | GPIO_ALT_FN_1_IN)
-#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
-#define GPIO48_CIF_DD5_MD (48 | GPIO_ALT_FN_1_IN)
-#define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT)
-#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
-#define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN)
-#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT)
-#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT)
-#define GPIO50_CIF_DD3_MD (50 | GPIO_ALT_FN_1_IN)
-#define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN)
-#define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT)
-#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
-#define GPIO51_CIF_DD2_MD (51 | GPIO_ALT_FN_1_IN)
-#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
-#define GPIO52_CIF_DD4_MD (52 | GPIO_ALT_FN_1_IN)
-#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
-#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
-#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT)
-#define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT)
-#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN)
-#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT)
-#define GPIO55_CIF_DD1_MD (55 | GPIO_ALT_FN_1_IN)
-#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN)
-#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN)
-#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT)
-#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT)
-#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT)
-#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT)
-#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT)
-#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT)
-#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT)
-#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT)
-#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT)
-#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN)
-#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT)
-#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT)
-#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT)
-#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT)
-#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT)
-#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT)
-#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT)
-#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT)
-#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT)
-#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT)
-#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT)
-#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT)
-#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT)
-#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT)
-#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT)
-#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT)
-#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT)
-#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT)
-#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT)
-#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT)
-#define GPIO79_pSKTSEL_MD (79 | GPIO_ALT_FN_1_OUT)
-#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
-#define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT)
-#define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN)
-#define GPIO81_CIF_DD0_MD (81 | GPIO_ALT_FN_2_IN)
-#define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT)
-#define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN)
-#define GPIO82_CIF_DD5_MD (82 | GPIO_ALT_FN_3_IN)
-#define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT)
-#define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN)
-#define GPIO83_CIF_DD4_MD (83 | GPIO_ALT_FN_3_IN)
-#define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT)
-#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
-#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_OUT)
-#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
-#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_OUT)
-#define GPIO90_CIF_DD4_MD (90 | GPIO_ALT_FN_3_IN)
-#define GPIO91_CIF_DD5_MD (91 | GPIO_ALT_FN_3_IN)
-#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
-#define GPIO93_CIF_DD6_MD (93 | GPIO_ALT_FN_2_IN)
-#define GPIO94_CIF_DD5_MD (94 | GPIO_ALT_FN_2_IN)
-#define GPIO95_CIF_DD4_MD (95 | GPIO_ALT_FN_2_IN)
-#define GPIO98_CIF_DD0_MD (98 | GPIO_ALT_FN_2_IN)
-#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT)
-#define GPIO103_CIF_DD3_MD (103 | GPIO_ALT_FN_1_IN)
-#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT)
-#define GPIO104_CIF_DD2_MD (104 | GPIO_ALT_FN_1_IN)
-#define GPIO105_CIF_DD1_MD (105 | GPIO_ALT_FN_1_IN)
-#define GPIO106_CIF_DD9_MD (106 | GPIO_ALT_FN_1_IN)
-#define GPIO107_CIF_DD8_MD (107 | GPIO_ALT_FN_1_IN)
-#define GPIO108_CIF_DD7_MD (108 | GPIO_ALT_FN_1_IN)
-#define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT)
-#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT)
-#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT)
-#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT)
-#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
-#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT)
-#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_IN)
-#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN)
-
/*
* Power Manager
*/
@@ -1743,265 +1406,8 @@
#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
-
-/*
- * LCD
- */
-
-#define LCCR0 __REG(0x44000000) /* LCD Controller Control Register 0 */
-#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
-#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
-#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
-#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */
-#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
-#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
-#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
-#define LIIDR __REG(0x4400003C) /* LCD Controller Interrupt ID Register */
-#define TMEDRGBR __REG(0x44000040) /* TMED RGB Seed Register */
-#define TMEDCR __REG(0x44000044) /* TMED Control Register */
-
-#define LCCR3_1BPP (0 << 24)
-#define LCCR3_2BPP (1 << 24)
-#define LCCR3_4BPP (2 << 24)
-#define LCCR3_8BPP (3 << 24)
-#define LCCR3_16BPP (4 << 24)
-
-#define LCCR3_PDFOR_0 (0 << 30)
-#define LCCR3_PDFOR_1 (1 << 30)
-#define LCCR3_PDFOR_2 (2 << 30)
-#define LCCR3_PDFOR_3 (3 << 30)
-
-#define LCCR4_PAL_FOR_0 (0 << 15)
-#define LCCR4_PAL_FOR_1 (1 << 15)
-#define LCCR4_PAL_FOR_2 (2 << 15)
-#define LCCR4_PAL_FOR_MASK (3 << 15)
-
-#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
-#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
-#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
-#define LDCMD0 __REG(0x4400020C) /* DMA Channel 0 Command Register */
-#define FDADR1 __REG(0x44000210) /* DMA Channel 1 Frame Descriptor Address Register */
-#define FSADR1 __REG(0x44000214) /* DMA Channel 1 Frame Source Address Register */
-#define FIDR1 __REG(0x44000218) /* DMA Channel 1 Frame ID Register */
-#define LDCMD1 __REG(0x4400021C) /* DMA Channel 1 Command Register */
-
-#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
-#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
-#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
-#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */
-#define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display */
- /* Select */
-#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */
-#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */
-
-#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
-#define LCCR0_SFM (1 << 4) /* Start of frame mask */
-#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
-#define LCCR0_EFM (1 << 6) /* End of Frame mask */
-#define LCCR0_PAS (1 << 7) /* Passive/Active display Select */
-#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */
-#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */
-#define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome */
- /* display mode) */
-#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */
- /* display */
-#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */
- /* display */
-#define LCCR0_DIS (1 << 10) /* LCD Disable */
-#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
-#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
-#define LCCR0_PDD_S 12
-#define LCCR0_BM (1 << 20) /* Branch mask */
-#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
-#define LCCR0_LCDT (1 << 22) /* LCD panel type */
-#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */
-#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */
-#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */
-#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */
-
-#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
-#define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \
- (((Pixel) - 1) << FShft (LCCR1_PPL))
-
-#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
-#define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \
- /* pulse Width [1..64 Tpix] */ \
- (((Tpix) - 1) << FShft (LCCR1_HSW))
-
-#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */
- /* count - 1 [Tpix] */
-#define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \
- /* [1..256 Tpix] */ \
- (((Tpix) - 1) << FShft (LCCR1_ELW))
-
-#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
- /* Wait count - 1 [Tpix] */
-#define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \
- /* [1..256 Tpix] */ \
- (((Tpix) - 1) << FShft (LCCR1_BLW))
-
-#if 0
-#define LCCR3_PCD (0xff) /* Pixel clock divisor */
-#define LCCR3_ACB (0xff << 8) /* AC Bias pin frequency */
-#define LCCR3_ACB_S 8
-#endif
-
-#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
-#define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \
- (((Line) - 1) << FShft (LCCR2_LPP))
-
-#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */
- /* Width - 1 [Tln] (L_FCLK) */
-#define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \
- /* Width [1..64 Tln] */ \
- (((Tln) - 1) << FShft (LCCR2_VSW))
-
-#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
- /* count [Tln] */
-#define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \
- /* [0..255 Tln] */ \
- ((Tln) << FShft (LCCR2_EFW))
-
-#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
- /* Wait count [Tln] */
-#define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \
- /* [0..255 Tln] */ \
- ((Tln) << FShft (LCCR2_BFW))
-
-#if 0 /* keep */
-#define LCCR3_PCD (0xff) /* Pixel clock divisor */
-#define LCCR3_ACB (0xff << 8) /* AC Bias pin frequency */
-#define LCCR3_ACB_S 8
-#endif
-
-#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
-#define LCCR3_API_S 16
-#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
-#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
-#define LCCR3_PCP (1 << 22) /* Pixel Clock Polarity (L_PCLK) */
-#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */
-#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */
-
-#define LCCR3_OEP (1 << 23) /* Output Enable Polarity (L_BIAS, */
- /* active display mode) */
-#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */
-#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */
-
-#if 0 /* keep */
-#define LCCR3_BPP (7 << 24) /* bits per pixel */
-#define LCCR3_BPP_S 24
-#endif
-#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
-
-
-#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
-#define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \
- (((Div) << FShft (LCCR3_PCD)))
-
-
-#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
-#define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \
- (((Bpp) << FShft (LCCR3_BPP)))
-
-#define LCCR3_ACB Fld (8, 8) /* AC Bias */
-#define LCCR3_Acb(Acb) /* BAC Bias */ \
- (((Acb) << FShft (LCCR3_ACB)))
-
-#define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */
- /* pulse active High */
-#define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */
-
-#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */
- /* active High */
-#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */
- /* active Low */
-
-#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-#define LCSR_SOF (1 << 1) /* Start of frame */
-#define LCSR_BER (1 << 2) /* Bus error */
-#define LCSR_ABC (1 << 3) /* AC Bias count */
-#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-#define LCSR_OU (1 << 6) /* output FIFO underrun */
-#define LCSR_QD (1 << 7) /* quick disable */
-#define LCSR_EOF (1 << 8) /* end of frame */
-#define LCSR_BS (1 << 9) /* branch status */
-#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-
-#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-
-#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-#define LCSR_SOF (1 << 1) /* Start of frame */
-#define LCSR_BER (1 << 2) /* Bus error */
-#define LCSR_ABC (1 << 3) /* AC Bias count */
-#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-#define LCSR_OU (1 << 6) /* output FIFO underrun */
-#define LCSR_QD (1 << 7) /* quick disable */
-#define LCSR_EOF (1 << 8) /* end of frame */
-#define LCSR_BS (1 << 9) /* branch status */
-#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-
-#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-
#ifdef CONFIG_PXA27x
-/*
- * Keypad
- */
-#define KPC __REG(0x41500000) /* Keypad Interface Control register */
-#define KPDK __REG(0x41500008) /* Keypad Interface Direct Key register */
-#define KPREC __REG(0x41500010) /* Keypad Interface Rotary Encoder register */
-#define KPMK __REG(0x41500018) /* Keypad Interface Matrix Key register */
-#define KPAS __REG(0x41500020) /* Keypad Interface Automatic Scan register */
-#define KPASMKP0 __REG(0x41500028) /* Keypad Interface Automatic Scan Multiple Key Presser register 0 */
-#define KPASMKP1 __REG(0x41500030) /* Keypad Interface Automatic Scan Multiple Key Presser register 1 */
-#define KPASMKP2 __REG(0x41500038) /* Keypad Interface Automatic Scan Multiple Key Presser register 2 */
-#define KPASMKP3 __REG(0x41500040) /* Keypad Interface Automatic Scan Multiple Key Presser register 3 */
-#define KPKDI __REG(0x41500048) /* Keypad Interface Key Debounce Interval register */
-
-#define KPC_AS (0x1 << 30) /* Automatic Scan bit */
-#define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */
-#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
-#define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */
-#define KPC_MS7 (0x1 << 20) /* Matrix scan line 7 */
-#define KPC_MS6 (0x1 << 19) /* Matrix scan line 6 */
-#define KPC_MS5 (0x1 << 18) /* Matrix scan line 5 */
-#define KPC_MS4 (0x1 << 17) /* Matrix scan line 4 */
-#define KPC_MS3 (0x1 << 16) /* Matrix scan line 3 */
-#define KPC_MS2 (0x1 << 15) /* Matrix scan line 2 */
-#define KPC_MS1 (0x1 << 14) /* Matrix scan line 1 */
-#define KPC_MS0 (0x1 << 13) /* Matrix scan line 0 */
-#define KPC_MS_ALL (KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 | KPC_MS4 | KPC_MS5 | KPC_MS6 | KPC_MS7)
-#define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */
-#define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */
-#define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */
-#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
-#define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */
-#define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */
-#define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */
-#define KPC_DE (0x1 << 1) /* Direct Keypad Enable */
-#define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */
-
-#define KPDK_DKP (0x1 << 31)
-#define KPDK_DK7 (0x1 << 7)
-#define KPDK_DK6 (0x1 << 6)
-#define KPDK_DK5 (0x1 << 5)
-#define KPDK_DK4 (0x1 << 4)
-#define KPDK_DK3 (0x1 << 3)
-#define KPDK_DK2 (0x1 << 2)
-#define KPDK_DK1 (0x1 << 1)
-#define KPDK_DK0 (0x1 << 0)
-
-#define KPREC_OF1 (0x1 << 31)
-#define kPREC_UF1 (0x1 << 30)
-#define KPREC_OF0 (0x1 << 15)
-#define KPREC_UF0 (0x1 << 14)
-
-#define KPMK_MKP (0x1 << 31)
-#define KPAS_SO (0x1 << 31)
-#define KPASMKPx_SO (0x1 << 31)
-
/* Camera Interface */
#define CICR0 __REG(0x50000000)
#define CICR1 __REG(0x50000004)
@@ -2033,7 +1439,7 @@
#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */
#define CICR1_TBIT (1 << 31) /* Transparency bit */
-#define CICR1_RGBT_CONV (0x3 << 30) /* RGBT conversion mask */
+#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */
#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */
#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */
#define CICR1_RGB_F (1 << 11) /* RGB format */
diff --git a/linux/include/linux/i2c-id.h b/linux/include/linux/i2c-id.h
index b979112f7..580acc939 100644
--- a/linux/include/linux/i2c-id.h
+++ b/linux/include/linux/i2c-id.h
@@ -79,12 +79,9 @@
#define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */
#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
#define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */
-#define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */
-#define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */
#define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */
#define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */
#define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */
-#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */
@@ -125,6 +122,7 @@
#define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */
#define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */
#define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */
+#define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */
diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h
index 1760c4205..c6cffb912 100644
--- a/linux/include/linux/videodev2.h
+++ b/linux/include/linux/videodev2.h
@@ -246,6 +246,7 @@ struct v4l2_capability
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
+#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
@@ -865,9 +866,9 @@ struct v4l2_querymenu
#define V4L2_CID_HFLIP (V4L2_CID_BASE+20)
#define V4L2_CID_VFLIP (V4L2_CID_BASE+21)
-/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
-#define V4L2_CID_HCENTER_DEPRECATED (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER_DEPRECATED (V4L2_CID_BASE+23)
+/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
+#define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24)
enum v4l2_power_line_frequency {
@@ -1156,6 +1157,14 @@ struct v4l2_frequency
__u32 reserved[8];
};
+struct v4l2_hw_freq_seek {
+ __u32 tuner;
+ enum v4l2_tuner_type type;
+ __u32 seek_upward;
+ __u32 wrap_around;
+ __u32 reserved[8];
+};
+
/*
* A U D I O
*/
@@ -1441,6 +1450,7 @@ struct v4l2_chip_ident {
#define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident)
#endif
+#define VIDIOC_S_HW_FREQ_SEEK _IOW ('V', 82, struct v4l2_hw_freq_seek)
#ifdef __OLD_VIDIOC_
/* for compatibility, will go away some day */
diff --git a/linux/include/media/cx25840.h b/linux/include/media/cx25840.h
index cd599ad29..db431d513 100644
--- a/linux/include/media/cx25840.h
+++ b/linux/include/media/cx25840.h
@@ -32,12 +32,16 @@ enum cx25840_video_input {
CX25840_COMPOSITE7,
CX25840_COMPOSITE8,
- /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+ /* S-Video inputs consist of one luma input (In1-In8) ORed with one
chroma input (In5-In8) */
CX25840_SVIDEO_LUMA1 = 0x10,
CX25840_SVIDEO_LUMA2 = 0x20,
CX25840_SVIDEO_LUMA3 = 0x30,
CX25840_SVIDEO_LUMA4 = 0x40,
+ CX25840_SVIDEO_LUMA5 = 0x50,
+ CX25840_SVIDEO_LUMA6 = 0x60,
+ CX25840_SVIDEO_LUMA7 = 0x70,
+ CX25840_SVIDEO_LUMA8 = 0x80,
CX25840_SVIDEO_CHROMA4 = 0x400,
CX25840_SVIDEO_CHROMA5 = 0x500,
CX25840_SVIDEO_CHROMA6 = 0x600,
diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h
index 75a348286..bfee8be5d 100644
--- a/linux/include/media/ir-common.h
+++ b/linux/include/media/ir-common.h
@@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h
index 0ea0bd85c..2a5277427 100644
--- a/linux/include/media/v4l2-chip-ident.h
+++ b/linux/include/media/v4l2-chip-ident.h
@@ -64,6 +64,7 @@ enum {
/* Conexant MPEG encoder/decoders: reserved range 410-420 */
V4L2_IDENT_CX23415 = 415,
V4L2_IDENT_CX23416 = 416,
+ V4L2_IDENT_CX23418 = 418,
/* module vp27smpx: just ident 2700 */
V4L2_IDENT_VP27SMPX = 2700,
diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h
index 72ed0ddb2..47cc48ea9 100644
--- a/linux/include/media/v4l2-common.h
+++ b/linux/include/media/v4l2-common.h
@@ -113,9 +113,11 @@ int v4l2_chip_match_host(u32 id_type, u32 chip_id);
struct i2c_driver;
struct i2c_adapter;
struct i2c_client;
+struct i2c_device_id;
int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
- const char *name, int (*probe)(struct i2c_client *));
+ const char *name,
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *));
/* ------------------------------------------------------------------------- */
diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h
index fac381990..484090509 100644
--- a/linux/include/media/v4l2-dev.h
+++ b/linux/include/media/v4l2-dev.h
@@ -46,7 +46,6 @@
#define VFL_TYPE_VTX 3
/* Video standard functions */
-extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
extern char *v4l2_norm_to_name(v4l2_std_id id);
extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name);
@@ -135,74 +134,76 @@ struct video_device
enum v4l2_priority p);
/* VIDIOC_ENUM_FMT handlers */
- int (*vidioc_enum_fmt_cap) (struct file *file, void *fh,
+ int (*vidioc_enum_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_overlay) (struct file *file, void *fh,
+ int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_vbi) (struct file *file, void *fh,
+ int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh,
struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh,
- struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh,
- struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_output_overlay) (struct file *file, void *fh,
- struct v4l2_fmtdesc *f);
- int (*vidioc_enum_fmt_vbi_output) (struct file *file, void *fh,
+#if 1 /* keep */
+ /* deprecated, will be removed in 2.6.28 */
+ int (*vidioc_enum_fmt_vbi_cap) (struct file *file, void *fh,
struct v4l2_fmtdesc *f);
+#endif
int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
struct v4l2_fmtdesc *f);
/* VIDIOC_G_FMT handlers */
- int (*vidioc_g_fmt_cap) (struct file *file, void *fh,
+ int (*vidioc_g_fmt_vid_cap) (struct file *file, void *fh,
+ struct v4l2_format *f);
+ int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_overlay) (struct file *file, void *fh,
+ int (*vidioc_g_fmt_vid_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_vbi) (struct file *file, void *fh,
+ int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh,
+ int (*vidioc_g_fmt_vbi_cap) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh,
+ int (*vidioc_g_fmt_vbi_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_video_output)(struct file *file, void *fh,
+ int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_g_fmt_output_overlay) (struct file *file, void *fh,
+ int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
/* VIDIOC_S_FMT handlers */
- int (*vidioc_s_fmt_cap) (struct file *file, void *fh,
+ int (*vidioc_s_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_format *f);
-
- int (*vidioc_s_fmt_overlay) (struct file *file, void *fh,
+ int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
+ struct v4l2_format *f);
+ int (*vidioc_s_fmt_vid_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_s_fmt_vbi) (struct file *file, void *fh,
+ int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh,
+ int (*vidioc_s_fmt_vbi_cap) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh,
+ int (*vidioc_s_fmt_vbi_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_s_fmt_video_output)(struct file *file, void *fh,
+ int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_s_fmt_output_overlay) (struct file *file, void *fh,
+ int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
/* VIDIOC_TRY_FMT handlers */
- int (*vidioc_try_fmt_cap) (struct file *file, void *fh,
+ int (*vidioc_try_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_overlay) (struct file *file, void *fh,
+ int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_vbi) (struct file *file, void *fh,
+ int (*vidioc_try_fmt_vid_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh,
+ int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh,
+ int (*vidioc_try_fmt_vbi_cap) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_video_output)(struct file *file, void *fh,
+ int (*vidioc_try_fmt_vbi_out) (struct file *file, void *fh,
struct v4l2_format *f);
- int (*vidioc_try_fmt_output_overlay)(struct file *file, void *fh,
+ int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
+ struct v4l2_format *f);
+ int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
@@ -229,8 +230,9 @@ struct video_device
int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
/* Standard handling
- G_STD and ENUMSTD are handled by videodev.c
+ ENUMSTD is handled by videodev.c
*/
+ int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
@@ -241,7 +243,7 @@ struct video_device
int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i);
/* Output handling */
- int (*vidioc_enumoutput) (struct file *file, void *fh,
+ int (*vidioc_enum_output) (struct file *file, void *fh,
struct v4l2_output *a);
int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i);
int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i);
@@ -323,6 +325,8 @@ struct video_device
/* Log status ioctl */
int (*vidioc_log_status) (struct file *file, void *fh);
+ int (*vidioc_s_hw_freq_seek) (struct file *file, void *fh,
+ struct v4l2_hw_freq_seek *a);
/* Debugging ioctls */
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -334,6 +338,10 @@ struct video_device
int (*vidioc_g_chip_ident) (struct file *file, void *fh,
struct v4l2_chip_ident *chip);
+ /* For other private ioctls */
+ int (*vidioc_default) (struct file *file, void *fh,
+ int cmd, void *arg);
+
#if 0 /* old, obsolete interface */
int (*open)(struct video_device *, int mode);
void (*close)(struct video_device *);
diff --git a/linux/include/media/v4l2-i2c-drv-legacy.h b/linux/include/media/v4l2-i2c-drv-legacy.h
index 10c3231f0..e95e2a072 100644
--- a/linux/include/media/v4l2-i2c-drv-legacy.h
+++ b/linux/include/media/v4l2-i2c-drv-legacy.h
@@ -25,7 +25,7 @@ struct v4l2_i2c_driver_data {
const char * const name;
int driverid;
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
- int (*probe)(struct i2c_client *client);
+ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *client);
int (*suspend)(struct i2c_client *client, pm_message_t state);
int (*resume)(struct i2c_client *client);
@@ -35,6 +35,9 @@ struct v4l2_i2c_driver_data {
#else
int legacy_id;
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ const struct i2c_device_id *id_table;
+#endif
};
static struct v4l2_i2c_driver_data v4l2_i2c_data;
@@ -167,6 +170,12 @@ static struct i2c_driver v4l2_i2c_driver = {
.resume = v4l2_i2c_drv_resume_helper,
};
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+static int compat_legacy_probe(struct i2c_client *client)
+{
+ return v4l2_i2c_data.probe(client, NULL);
+}
+#endif
static int __init v4l2_i2c_drv_init(void)
{
@@ -198,8 +207,15 @@ static int __init v4l2_i2c_drv_init(void)
v4l2_i2c_driver.driver.name = v4l2_i2c_data.name;
v4l2_i2c_driver.id = v4l2_i2c_data.driverid;
v4l2_i2c_driver.command = v4l2_i2c_data.command;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
v4l2_i2c_driver.probe = v4l2_i2c_data.probe;
+#else
+ v4l2_i2c_driver.probe = compat_legacy_probe;
+#endif
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table;
+#endif
err = i2c_add_driver(&v4l2_i2c_driver);
if (err)
i2c_del_driver(&v4l2_i2c_driver_legacy);
diff --git a/linux/include/media/v4l2-i2c-drv.h b/linux/include/media/v4l2-i2c-drv.h
index 8b5d74912..73d713f07 100644
--- a/linux/include/media/v4l2-i2c-drv.h
+++ b/linux/include/media/v4l2-i2c-drv.h
@@ -30,7 +30,7 @@ struct v4l2_i2c_driver_data {
const char * const name;
int driverid;
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
- int (*probe)(struct i2c_client *client);
+ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *client);
int (*suspend)(struct i2c_client *client, pm_message_t state);
int (*resume)(struct i2c_client *client);
@@ -40,11 +40,20 @@ struct v4l2_i2c_driver_data {
#else
int legacy_id;
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ const struct i2c_device_id *id_table;
+#endif
};
static struct v4l2_i2c_driver_data v4l2_i2c_data;
static struct i2c_driver v4l2_i2c_driver;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+static int compat_legacy_probe(struct i2c_client *client)
+{
+ return v4l2_i2c_data.probe(client, NULL);
+}
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
/* Bus-based I2C implementation for kernels >= 2.6.22 */
@@ -54,10 +63,17 @@ static int __init v4l2_i2c_drv_init(void)
v4l2_i2c_driver.driver.name = v4l2_i2c_data.name;
v4l2_i2c_driver.id = v4l2_i2c_data.driverid;
v4l2_i2c_driver.command = v4l2_i2c_data.command;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
v4l2_i2c_driver.probe = v4l2_i2c_data.probe;
+#else
+ v4l2_i2c_driver.probe = compat_legacy_probe;
+#endif
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
v4l2_i2c_driver.suspend = v4l2_i2c_data.suspend;
v4l2_i2c_driver.resume = v4l2_i2c_data.resume;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table;
+#endif
return i2c_add_driver(&v4l2_i2c_driver);
}
diff --git a/linux/include/media/videobuf-core.h b/linux/include/media/videobuf-core.h
index 18b0ba615..a2f55ff24 100644
--- a/linux/include/media/videobuf-core.h
+++ b/linux/include/media/videobuf-core.h
@@ -13,6 +13,9 @@
* the Free Software Foundation; either version 2
*/
+#ifndef _VIDEOBUF_CORE_H
+#define _VIDEOBUF_CORE_H
+
#include <linux/poll.h>
#ifdef CONFIG_VIDEO_V4L1_COMPAT
#include <linux/videodev.h>
@@ -123,7 +126,8 @@ struct videobuf_queue_ops {
struct videobuf_qtype_ops {
u32 magic;
- void* (*alloc) (size_t size);
+ void *(*alloc) (size_t size);
+ void *(*vmalloc) (struct videobuf_buffer *buf);
int (*iolock) (struct videobuf_queue* q,
struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf);
@@ -144,8 +148,6 @@ struct videobuf_qtype_ops {
int vbihack,
int nonblocking);
int (*mmap_free) (struct videobuf_queue *q);
- int (*mmap_setup) (struct videobuf_queue *q,
- struct videobuf_buffer *vb);
int (*mmap_mapper) (struct videobuf_queue *q,
struct vm_area_struct *vma);
};
@@ -172,6 +174,7 @@ struct videobuf_queue {
unsigned int streaming:1;
unsigned int reading:1;
+ unsigned int is_mmapped:1;
/* capture via mmap() + ioctl(QBUF/DQBUF) */
struct list_head stream;
@@ -190,6 +193,10 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
void *videobuf_alloc(struct videobuf_queue* q);
+/* Used on videobuf-dvb */
+void *videobuf_queue_to_vmalloc (struct videobuf_queue* q,
+ struct videobuf_buffer *buf);
+
void videobuf_queue_core_init(struct videobuf_queue *q,
struct videobuf_queue_ops *ops,
struct device *dev,
@@ -234,14 +241,11 @@ unsigned int videobuf_poll_stream(struct file *file,
int videobuf_mmap_setup(struct videobuf_queue *q,
unsigned int bcount, unsigned int bsize,
enum v4l2_memory memory);
+int __videobuf_mmap_setup(struct videobuf_queue *q,
+ unsigned int bcount, unsigned int bsize,
+ enum v4l2_memory memory);
int videobuf_mmap_free(struct videobuf_queue *q);
int videobuf_mmap_mapper(struct videobuf_queue *q,
struct vm_area_struct *vma);
-/* --------------------------------------------------------------------- */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+#endif
diff --git a/linux/include/media/videobuf-dma-sg.h b/linux/include/media/videobuf-dma-sg.h
index b6ab08045..be8da269e 100644
--- a/linux/include/media/videobuf-dma-sg.h
+++ b/linux/include/media/videobuf-dma-sg.h
@@ -68,9 +68,6 @@ struct videobuf_dmabuf {
/* for kernel buffers */
void *vmalloc;
- /* Stores the userspace pointer to vmalloc area */
- void *varea;
-
/* for overlay buffers (pci-pci dma) */
dma_addr_t bus_addr;
diff --git a/linux/include/media/videobuf-dvb.h b/linux/include/media/videobuf-dvb.h
index 92545a0a2..14438bc98 100644
--- a/linux/include/media/videobuf-dvb.h
+++ b/linux/include/media/videobuf-dvb.h
@@ -35,7 +35,8 @@ struct videobuf_dvb {
int videobuf_dvb_register(struct videobuf_dvb *dvb,
struct module *module,
void *adapter_priv,
- struct device *device);
+ struct device *device,
+ short *adapter_nr);
void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
/*
diff --git a/linux/include/media/videobuf-vmalloc.h b/linux/include/media/videobuf-vmalloc.h
index ec63ab0fa..aed39460c 100644
--- a/linux/include/media/videobuf-vmalloc.h
+++ b/linux/include/media/videobuf-vmalloc.h
@@ -12,6 +12,8 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2
*/
+#ifndef _VIDEOBUF_VMALLOC_H
+#define _VIDEOBUF_VMALLOC_H
#include <media/videobuf-core.h>
@@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
void *videobuf_to_vmalloc (struct videobuf_buffer *buf);
void videobuf_vmalloc_free (struct videobuf_buffer *buf);
+
+#endif
diff --git a/mailimport b/mailimport
index 7b233932e..76364aeea 100755
--- a/mailimport
+++ b/mailimport
@@ -112,6 +112,11 @@ apply_patch () {
make whitespace
hg qrefresh
else
+ echo "WILL commit with this comment:"
+ cat $TMP2| grep -v "^#"
+ echo "Press <break> within 3 seconds if this is wrong."
+ sleep 3
+
patch -s -t -p1 -l -N -d $pdir -i $next
if [ "$?" != "0" ]; then
echo "*** ERROR at: patch -s -t -p1 -l -N -d $pdir -i $next"
diff --git a/v4l/compat.h b/v4l/compat.h
index 257143a6b..c480af095 100644
--- a/v4l/compat.h
+++ b/v4l/compat.h
@@ -14,6 +14,13 @@
#include <linux/i2c-dev.h>
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+#ifdef CONFIG_PROC_FS
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#endif
+#endif
+
/* To allow alsa code to work */
#ifdef NEED_SOUND_DRIVER_H
#include <sound/driver.h>
@@ -517,9 +524,66 @@ do { \
.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+#define get_unaligned_be16(a) \
+ be16_to_cpu(get_unaligned((unsigned short *)(a)))
+#define put_unaligned_be16(r, a) \
+ put_unaligned(cpu_to_be16(r), ((unsigned short *)(a)))
+#define get_unaligned_le16(a) \
+ le16_to_cpu(get_unaligned((unsigned short *)(a)))
+#define put_unaligned_le16(r, a) \
+ put_unaligned(cpu_to_le16(r), ((unsigned short *)(a)))
+#define get_unaligned_be32(a) \
+ be32_to_cpu(get_unaligned((u32 *)(a)))
+#define put_unaligned_be32(r, a) \
+ put_unaligned(cpu_to_be32(r), ((u32 *)(a)))
+#define get_unaligned_le32(a) \
+ le32_to_cpu(get_unaligned((u32 *)(a)))
+#define put_unaligned_le32(r, a) \
+ put_unaligned(cpu_to_le32(r), ((u32 *)(a)))
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+#ifdef CONFIG_PROC_FS
+static inline struct proc_dir_entry *proc_create(const char *a,
+ mode_t b, struct proc_dir_entry *c, const struct file_operations *d)
+{
+ struct proc_dir_entry *e;
+
+ e = create_proc_entry(a, b, c);
+ if (e) {
+ e->owner = THIS_MODULE;
+ e->proc_fops = d;
+
+ }
+ return e;
+}
+
+static inline struct proc_dir_entry *proc_create_data(const char *a,
+ mode_t b, struct proc_dir_entry *c, const struct file_operations *d,
+ void *f)
+{
+ struct proc_dir_entry *e;
+
+ e = create_proc_entry(a, b, c);
+ if (e) {
+ e->owner = THIS_MODULE;
+ e->proc_fops = d;
+ e->data = f;
+ }
+ return e;
+}
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+#define div64_u64(a,b) div64_64(a,b)
+
+#define clamp( x, l, h ) max_t( __typeof__( x ), \
+ ( l ), \
+ min_t( __typeof__( x ), \
+ ( h ), \
+ ( x ) ) )
+
+#endif
+
#endif
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/v4l/obsolete.txt b/v4l/obsolete.txt
index 384224df8..e720a48b8 100644
--- a/v4l/obsolete.txt
+++ b/v4l/obsolete.txt
@@ -3,3 +3,21 @@ video/video-buf
# This file were replaced by videobuf-dvb
video/video-buf-dvb
+
+# Those drivers were moved to common/tuners
+dvb/frontends/mt2060
+dvb/frontends/mt2131
+dvb/frontends/mt2266
+dvb/frontends/qt1010
+dvb/frontends/tda18271
+dvb/frontends/tda827x
+dvb/frontends/xc5000
+video/mt20xx
+video/tda8290
+video/tda9887
+video/tea5761
+video/tea5767
+video/tuner-simple
+video/tuner-types
+video/tuner-xc2028
+
diff --git a/v4l/scripts/au0828.pl b/v4l/scripts/au0828.pl
new file mode 100755
index 000000000..822a54afb
--- /dev/null
+++ b/v4l/scripts/au0828.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+use strict;
+
+my $new_entry = -1;
+my $nr = 0;
+my ($id,$subvendor,$subdevice);
+my %data;
+
+while (<>) {
+ # defines in header file
+ if (/#define\s+(AU08[\d]._BOARD_\w+)\s+(\d+)/) {
+ $data{$1}->{nr} = $2;
+ next;
+ }
+ # au0828_boards
+ if (/\[(AU0828_BOARD_\w+)\]/) {
+ $id = $1;
+ $data{$id}->{id} = $id;
+ $data{$id}->{type} = "(au0828)";
+# $data{$id}->{nr} = $nr++;
+ };
+
+ next unless defined($id);
+
+ if (/USB_DEVICE.*0x([0-9a-fA-F]*).*0x([0-9a-fA-F]*)/ ) {
+ $subvendor=$1;
+ $subdevice=$2;
+ }
+
+ if (/.*driver_info.*(AU08[\d]._BOARD_\w+)/ ) {
+ push @{$data{$1}->{subid}}, "$subvendor:$subdevice";
+ }
+
+ if (!defined($data{$id}) || !defined($data{$id}->{name})) {
+ $data{$id}->{name} = $1 if (/\.name\s*=\s*\"([^\"]+)\"/);
+ }
+
+ # au0828_USB_tbl
+
+
+}
+
+foreach my $item (sort { $data{$a}->{nr} <=> $data{$b}->{nr} } keys %data) {
+ printf("%3d -> %-40s %-15s", $data{$item}->{nr}, $data{$item}->{name},$data{$item}->{type});
+ printf(" [%s]",join(",",@{$data{$item}->{subid}}))
+ if defined($data{$item}->{subid});
+ print "\n";
+}
diff --git a/v4l/scripts/cardlist b/v4l/scripts/cardlist
index 3e5213975..7c903539c 100755
--- a/v4l/scripts/cardlist
+++ b/v4l/scripts/cardlist
@@ -6,10 +6,10 @@ scripts/bttv.pl ../linux/drivers/media/video/bt8xx/bttv.h ../linux/drivers/medi
scripts/cx88.pl ../linux/drivers/media/video/cx88/cx88.h ../linux/drivers/media/video/cx88/cx88-cards.c \
| perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.cx88
-scripts/em28xx.pl ../linux/drivers/media/video/em28xx/em28xx-cards.c \
+scripts/em28xx.pl ../linux/drivers/media/video/em28xx/em28xx-cards.c ../linux/drivers/media/video/em28xx/em28xx.h \
| perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.em28xx
-scripts/tuner.pl ../linux/include/media/tuner.h ../linux/drivers/media/video/tuner-types.c \
+scripts/tuner.pl ../linux/include/media/tuner.h ../linux/drivers/media/common/tuners/tuner-types.c \
| perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.tuner
scripts/saa7134.pl ../linux/drivers/media/video/saa7134/saa7134.h ../linux/drivers/media/video/saa7134/saa7134-cards.c \
@@ -20,3 +20,6 @@ scripts/usbvision.pl ../linux/drivers/media/video/usbvision/usbvision-cards.h ..
scripts/cx23885.pl ../linux/drivers/media/video/cx23885/cx23885.h ../linux/drivers/media/video/cx23885/cx23885-cards.c \
| perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.cx23885
+
+scripts/au0828.pl ../linux/drivers/media/video/au0828/au0828-cards.h ../linux/drivers/media/video/au0828/au0828-cards.c \
+ | perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.au0828
diff --git a/v4l/scripts/checkpatch.pl b/v4l/scripts/checkpatch.pl
index 12774e762..511935699 100755
--- a/v4l/scripts/checkpatch.pl
+++ b/v4l/scripts/checkpatch.pl
@@ -9,7 +9,7 @@ use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.14';
+my $V = '0.16';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -18,6 +18,7 @@ my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
my $tst_type = 0;
+my $tst_only;
my $emacs = 0;
my $terse = 0;
my $file = 0;
@@ -44,6 +45,7 @@ GetOptions(
'debug=s' => \%debug,
'test-type!' => \$tst_type,
+ 'test-only=s' => \$tst_only,
) or exit;
my $exit = 0;
@@ -105,8 +107,7 @@ our $Sparse = qr{
__iomem|
__must_check|
__init_refok|
- __kprobes|
- fastcall
+ __kprobes
}x;
our $Attribute = qr{
const|
@@ -158,7 +159,10 @@ sub build_types {
\b
(?:const\s+)?
(?:unsigned\s+)?
- $all
+ (?:
+ $all|
+ (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)
+ )
(?:\s+$Sparse|\s+const)*
\b
}x;
@@ -261,17 +265,7 @@ sub expand_tabs {
return $res;
}
sub copy_spacing {
- my ($str) = @_;
-
- my $res = '';
- for my $c (split(//, $str)) {
- if ($c eq "\t") {
- $res .= $c;
- } else {
- $res .= ' ';
- }
- }
-
+ (my $res = shift) =~ tr/\t/ /c;
return $res;
}
@@ -288,53 +282,76 @@ sub line_stats {
return (length($line), length($white));
}
+my $sanitise_quote = '';
+
+sub sanitise_line_reset {
+ my ($in_comment) = @_;
+
+ if ($in_comment) {
+ $sanitise_quote = '*/';
+ } else {
+ $sanitise_quote = '';
+ }
+}
sub sanitise_line {
my ($line) = @_;
my $res = '';
my $l = '';
- my $quote = '';
my $qlen = 0;
+ my $off = 0;
+ my $c;
- foreach my $c (split(//, $line)) {
- # The second backslash of a pair is not a "quote".
- if ($l eq "\\" && $c eq "\\") {
- $c = 'X';
- }
- if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
- if ($quote eq '') {
- $quote = $c;
- $res .= $c;
- $l = $c;
- $qlen = 0;
- next;
- } elsif ($quote eq $c) {
- $quote = '';
- }
+ # Always copy over the diff marker.
+ $res = substr($line, 0, 1);
+
+ for ($off = 1; $off < length($line); $off++) {
+ $c = substr($line, $off, 1);
+
+ # Comments we are wacking completly including the begin
+ # and end, all to $;.
+ if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
+ $sanitise_quote = '*/';
+
+ substr($res, $off, 2, "$;$;");
+ $off++;
+ next;
}
- if ($quote eq "'" && $qlen > 1) {
- $quote = '';
+ if (substr($line, $off, 2) eq $sanitise_quote) {
+ $sanitise_quote = '';
+ substr($res, $off, 2, "$;$;");
+ $off++;
+ next;
}
- if ($quote && $c ne "\t") {
- $res .= "X";
- $qlen++;
- } else {
- $res .= $c;
+
+ # A \ in a string means ignore the next character.
+ if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
+ $c eq "\\") {
+ substr($res, $off, 2, 'XX');
+ $off++;
+ next;
}
+ # Regular quotes.
+ if ($c eq "'" || $c eq '"') {
+ if ($sanitise_quote eq '') {
+ $sanitise_quote = $c;
- $l = $c;
- }
+ substr($res, $off, 1, $c);
+ next;
+ } elsif ($sanitise_quote eq $c) {
+ $sanitise_quote = '';
+ }
+ }
- # Clear out the comments.
- while ($res =~ m@(/\*.*?\*/)@g) {
- substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
- }
- if ($res =~ m@(/\*.*)@) {
- substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
- }
- if ($res =~ m@^.(.*\*/)@) {
- substr($res, $-[1], $+[1] - $-[1]) = $; x ($+[1] - $-[1]);
+ #print "SQ:$sanitise_quote\n";
+ if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
+ substr($res, $off, 1, $;);
+ } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
+ substr($res, $off, 1, 'X');
+ } else {
+ substr($res, $off, 1, $c);
+ }
}
# The pathname on a #include may be surrounded by '<' and '>'.
@@ -357,17 +374,19 @@ sub ctx_statement_block {
my $blk = '';
my $soff = $off;
my $coff = $off - 1;
+ my $coff_set = 0;
my $loff = 0;
my $type = '';
my $level = 0;
+ my $p;
my $c;
my $len = 0;
my $remainder;
while (1) {
- #warn "CSB: blk<$blk>\n";
+ #warn "CSB: blk<$blk> remain<$remain>\n";
# If we are about to drop off the end, pull in more
# context.
if ($off >= $len) {
@@ -386,10 +405,11 @@ sub ctx_statement_block {
last;
}
}
+ $p = $c;
$c = substr($blk, $off, 1);
$remainder = substr($blk, $off);
- #warn "CSB: c<$c> type<$type> level<$level>\n";
+ #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
# Statement ends at the ';' or a close '}' at the
# outermost level.
if ($level == 0 && $c eq ';') {
@@ -397,9 +417,14 @@ sub ctx_statement_block {
}
# An else is really a conditional as long as its not else if
- if ($level == 0 && $remainder =~ /(\s+else)(?:\s|{)/ &&
- $remainder !~ /\s+else\s+if\b/) {
- $coff = $off + length($1);
+ if ($level == 0 && $coff_set == 0 &&
+ (!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
+ $remainder =~ /^(else)(?:\s|{)/ &&
+ $remainder !~ /^else\s+if\b/) {
+ $coff = $off + length($1) - 1;
+ $coff_set = 1;
+ #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
+ #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
}
if (($type eq '' || $type eq '(') && $c eq '(') {
@@ -412,6 +437,8 @@ sub ctx_statement_block {
if ($level == 0 && $coff < $soff) {
$coff = $off;
+ $coff_set = 1;
+ #warn "CSB: mark coff<$coff>\n";
}
}
if (($type eq '' || $type eq '{') && $c eq '{') {
@@ -439,27 +466,79 @@ sub ctx_statement_block {
#warn "STATEMENT<$statement>\n";
#warn "CONDITION<$condition>\n";
- #print "off<$off> loff<$loff>\n";
+ #print "coff<$coff> soff<$off> loff<$loff>\n";
return ($statement, $condition,
$line, $remain + 1, $off - $loff + 1, $level);
}
+sub statement_lines {
+ my ($stmt) = @_;
+
+ # Strip the diff line prefixes and rip blank lines at start and end.
+ $stmt =~ s/(^|\n)./$1/g;
+ $stmt =~ s/^\s*//;
+ $stmt =~ s/\s*$//;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+
+ return $#stmt_lines + 2;
+}
+
+sub statement_rawlines {
+ my ($stmt) = @_;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+
+ return $#stmt_lines + 2;
+}
+
+sub statement_block_size {
+ my ($stmt) = @_;
+
+ $stmt =~ s/(^|\n)./$1/g;
+ $stmt =~ s/^\s*{//;
+ $stmt =~ s/}\s*$//;
+ $stmt =~ s/^\s*//;
+ $stmt =~ s/\s*$//;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+ my @stmt_statements = ($stmt =~ /;/g);
+
+ my $stmt_lines = $#stmt_lines + 2;
+ my $stmt_statements = $#stmt_statements + 1;
+
+ if ($stmt_lines > $stmt_statements) {
+ return $stmt_lines;
+ } else {
+ return $stmt_statements;
+ }
+}
+
sub ctx_statement_full {
my ($linenr, $remain, $off) = @_;
my ($statement, $condition, $level);
my (@chunks);
+ # Grab the first conditional/block pair.
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
- #print "F: c<$condition> s<$statement>\n";
+ #print "F: c<$condition> s<$statement> remain<$remain>\n";
+ push(@chunks, [ $condition, $statement ]);
+ if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
+ return ($level, $linenr, @chunks);
+ }
+
+ # Pull in the following conditional/block pairs and see if they
+ # could continue the statement.
for (;;) {
- push(@chunks, [ $condition, $statement ]);
- last if (!($remain > 0 && $condition =~ /^.\s*(?:if|else|do)/));
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
- #print "C: c<$condition> s<$statement>\n";
+ #print "C: c<$condition> s<$statement> remain<$remain>\n";
+ last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
+ #print "C: push\n";
+ push(@chunks, [ $condition, $statement ]);
}
return ($level, $linenr, @chunks);
@@ -593,13 +672,13 @@ sub cat_vet {
}
my $av_preprocessor = 0;
-my $av_paren = 0;
+my $av_pending;
my @av_paren_type;
sub annotate_reset {
$av_preprocessor = 0;
- $av_paren = 0;
- @av_paren_type = ();
+ $av_pending = '_';
+ @av_paren_type = ('E');
}
sub annotate_values {
@@ -611,12 +690,14 @@ sub annotate_values {
print "$stream\n" if ($dbg_values > 1);
while (length($cur)) {
- print " <$type> " if ($dbg_values > 1);
+ @av_paren_type = ('E') if ($#av_paren_type < 0);
+ print " <" . join('', @av_paren_type) .
+ "> <$type> " if ($dbg_values > 1);
if ($cur =~ /^(\s+)/o) {
print "WS($1)\n" if ($dbg_values > 1);
if ($1 =~ /\n/ && $av_preprocessor) {
+ $type = pop(@av_paren_type);
$av_preprocessor = 0;
- $type = 'N';
}
} elsif ($cur =~ /^($Type)/) {
@@ -626,11 +707,33 @@ sub annotate_values {
} elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
print "DEFINE($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
- $av_paren_type[$av_paren] = 'N';
+ $av_pending = 'N';
- } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if|else|elif|endif))/o) {
- print "PRE($1)\n" if ($dbg_values > 1);
+ } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if))/o) {
+ print "PRE_START($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
+
+ push(@av_paren_type, $type);
+ push(@av_paren_type, $type);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(#\s*(?:else|elif))/o) {
+ print "PRE_RESTART($1)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+
+ push(@av_paren_type, $av_paren_type[$#av_paren_type]);
+
+ $type = 'N';
+
+ } elsif ($cur =~ /^(#\s*(?:endif))/o) {
+ print "PRE_END($1)\n" if ($dbg_values > 1);
+
+ $av_preprocessor = 1;
+
+ # Assume all arms of the conditional end as this
+ # one does, and continue as if the #endif was not here.
+ pop(@av_paren_type);
+ push(@av_paren_type, $type);
$type = 'N';
} elsif ($cur =~ /^(\\\n)/o) {
@@ -639,13 +742,13 @@ sub annotate_values {
} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
print "SIZEOF($1)\n" if ($dbg_values > 1);
if (defined $2) {
- $av_paren_type[$av_paren] = 'V';
+ $av_pending = 'V';
}
$type = 'N';
} elsif ($cur =~ /^(if|while|typeof|__typeof__|for)\b/o) {
print "COND($1)\n" if ($dbg_values > 1);
- $av_paren_type[$av_paren] = 'N';
+ $av_pending = 'N';
$type = 'N';
} elsif ($cur =~/^(return|case|else)/o) {
@@ -654,14 +757,14 @@ sub annotate_values {
} elsif ($cur =~ /^(\()/o) {
print "PAREN('$1')\n" if ($dbg_values > 1);
- $av_paren++;
+ push(@av_paren_type, $av_pending);
+ $av_pending = '_';
$type = 'N';
} elsif ($cur =~ /^(\))/o) {
- $av_paren-- if ($av_paren > 0);
- if (defined $av_paren_type[$av_paren]) {
- $type = $av_paren_type[$av_paren];
- undef $av_paren_type[$av_paren];
+ my $new_type = pop(@av_paren_type);
+ if ($new_type ne '_') {
+ $type = $new_type;
print "PAREN('$1') -> $type\n"
if ($dbg_values > 1);
} else {
@@ -670,7 +773,7 @@ sub annotate_values {
} elsif ($cur =~ /^($Ident)\(/o) {
print "FUNC($1)\n" if ($dbg_values > 1);
- $av_paren_type[$av_paren] = 'V';
+ $av_pending = 'V';
} elsif ($cur =~ /^($Ident|$Constant)/o) {
print "IDENT($1)\n" if ($dbg_values > 1);
@@ -680,11 +783,11 @@ sub annotate_values {
print "ASSIGN($1)\n" if ($dbg_values > 1);
$type = 'N';
- } elsif ($cur =~/^(;)/) {
+ } elsif ($cur =~/^(;|{|})/) {
print "END($1)\n" if ($dbg_values > 1);
$type = 'E';
- } elsif ($cur =~ /^(;|{|}|\?|:|\[)/o) {
+ } elsif ($cur =~ /^(;|\?|:|\[)/o) {
print "CLOSE($1)\n" if ($dbg_values > 1);
$type = 'N';
@@ -724,28 +827,34 @@ sub possible {
my $prefix = '';
sub report {
+ if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
+ return 0;
+ }
my $line = $prefix . $_[0];
$line = (split('\n', $line))[0] . "\n" if ($terse);
push(our @report, $line);
+
+ return 1;
}
sub report_dump {
our @report;
}
sub ERROR {
- report("ERROR: $_[0]\n");
- our $clean = 0;
- our $cnt_error++;
+ if (report("ERROR: $_[0]\n")) {
+ our $clean = 0;
+ our $cnt_error++;
+ }
}
sub WARN {
- report("WARNING: $_[0]\n");
- our $clean = 0;
- our $cnt_warn++;
+ if (report("WARNING: $_[0]\n")) {
+ our $clean = 0;
+ our $cnt_warn++;
+ }
}
sub CHK {
- if ($check) {
- report("CHECK: $_[0]\n");
+ if ($check && report("CHECK: $_[0]\n")) {
our $clean = 0;
our $cnt_chk++;
}
@@ -787,30 +896,76 @@ sub process {
my $prev_values = 'E';
# suppression flags
- my $suppress_ifbraces = 0;
+ my %suppress_ifbraces;
# Pre-scan the patch sanitizing the lines.
# Pre-scan the patch looking for any __setup documentation.
#
my @setup_docs = ();
my $setup_docs = 0;
+
+ sanitise_line_reset();
my $line;
foreach my $rawline (@rawlines) {
- # Standardise the strings and chars within the input to
- # simplify matching.
- $line = sanitise_line($rawline);
- push(@lines, $line);
-
- ##print "==>$rawline\n";
- ##print "-->$line\n";
+ $linenr++;
+ $line = $rawline;
- if ($line=~/^\+\+\+\s+(\S+)/) {
+ if ($rawline=~/^\+\+\+\s+(\S+)/) {
$setup_docs = 0;
if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
$setup_docs = 1;
}
- next;
+ #next;
+ }
+ if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ $realline=$1-1;
+ if (defined $2) {
+ $realcnt=$3+1;
+ } else {
+ $realcnt=1+1;
+ }
+
+ # Guestimate if this is a continuing comment. Run
+ # the context looking for a comment "edge". If this
+ # edge is a close comment then we must be in a comment
+ # at context start.
+ my $edge;
+ for (my $ln = $linenr; $ln < ($linenr + $realcnt); $ln++) {
+ next if ($line =~ /^-/);
+ ($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
+ last if (defined $edge);
+ }
+ if (defined $edge && $edge eq '*/') {
+ $in_comment = 1;
+ }
+
+ # Guestimate if this is a continuing comment. If this
+ # is the start of a diff block and this line starts
+ # ' *' then it is very likely a comment.
+ if (!defined $edge &&
+ $rawlines[$linenr] =~ m@^.\s* \*(?:\s|$)@)
+ {
+ $in_comment = 1;
+ }
+
+ ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
+ sanitise_line_reset($in_comment);
+
+ } elsif ($realcnt) {
+ # Standardise the strings and chars within the input to
+ # simplify matching.
+ $line = sanitise_line($rawline);
}
+ push(@lines, $line);
+
+ if ($realcnt > 1) {
+ $realcnt-- if ($line =~ /^(?:\+| |$)/);
+ } else {
+ $realcnt = 0;
+ }
+
+ #print "==>$rawline\n";
+ #print "-->$line\n";
if ($setup_docs && $line =~ /^\+/) {
push(@setup_docs, $line);
@@ -819,23 +974,17 @@ sub process {
$prefix = '';
+ $realcnt = 0;
+ $linenr = 0;
foreach my $line (@lines) {
$linenr++;
my $rawline = $rawlines[$linenr - 1];
-#extract the filename as it passes
- if ($line=~/^\+\+\+\s+(\S+)/) {
- $realfile=$1;
- $realfile =~ s@^[^/]*/@@;
- $in_comment = 0;
- next;
- }
#extract the line range in the file after the patch is applied
if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$is_patch = 1;
$first_line = $linenr + 1;
- $in_comment = 0;
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
@@ -845,50 +994,16 @@ sub process {
annotate_reset();
$prev_values = 'E';
- $suppress_ifbraces = $linenr - 1;
+ %suppress_ifbraces = ();
next;
- }
# track the line number as we move through the hunk, note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too.
- if ($line =~ /^( |\+|$)/) {
+ } elsif ($line =~ /^( |\+|$)/) {
$realline++;
$realcnt-- if ($realcnt != 0);
- # Guestimate if this is a continuing comment. Run
- # the context looking for a comment "edge". If this
- # edge is a close comment then we must be in a comment
- # at context start.
- if ($linenr == $first_line) {
- my $edge;
- for (my $ln = $first_line; $ln < ($linenr + $realcnt); $ln++) {
- ($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
- last if (defined $edge);
- }
- if (defined $edge && $edge eq '*/') {
- $in_comment = 1;
- }
- }
-
- # Guestimate if this is a continuing comment. If this
- # is the start of a diff block and this line starts
- # ' *' then it is very likely a comment.
- if ($linenr == $first_line and $rawline =~ m@^.\s* \*(?:\s|$)@) {
- $in_comment = 1;
- }
-
- # Find the last comment edge on _this_ line.
- $comment_edge = 0;
- while (($rawline =~ m@(/\*|\*/)@g)) {
- if ($1 eq '/*') {
- $in_comment = 1;
- } else {
- $in_comment = 0;
- }
- $comment_edge = 1;
- }
-
# Measure the line length and indent.
($length, $indent) = line_stats($rawline);
@@ -897,23 +1012,36 @@ sub process {
($previndent, $stashindent) = ($stashindent, $indent);
($prevrawline, $stashrawline) = ($stashrawline, $rawline);
- #warn "ic<$in_comment> ce<$comment_edge> line<$line>\n";
+ #warn "line<$line>\n";
} elsif ($realcnt == 1) {
$realcnt--;
}
#make up the handle for any error we report on this line
+ $prefix = "$filename:$realline: " if ($emacs && $file);
+ $prefix = "$filename:$linenr: " if ($emacs && !$file);
+
$here = "#$linenr: " if (!$file);
$here = "#$realline: " if ($file);
+
+ # extract the filename as it passes
+ if ($line=~/^\+\+\+\s+(\S+)/) {
+ $realfile = $1;
+ $realfile =~ s@^[^/]*/@@;
+
+ if ($realfile =~ m@include/asm/@) {
+ ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
+ }
+ next;
+ }
+
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
my $hereline = "$here\n$rawline\n";
my $herecurr = "$here\n$rawline\n";
my $hereprev = "$here\n$prevrawline\n$rawline\n";
- $prefix = "$filename:$realline: " if ($emacs && $file);
- $prefix = "$filename:$linenr: " if ($emacs && !$file);
$cnt_lines++ if ($realcnt != 0);
#check the patch for a signoff:
@@ -925,7 +1053,7 @@ sub process {
$herecurr);
}
if ($line =~ /^\s*signed-off-by:\S/i) {
- WARN("need space after Signed-off-by:\n" .
+ WARN("space required after Signed-off-by:\n" .
$herecurr);
}
}
@@ -988,52 +1116,50 @@ sub process {
}
# check for RCS/CVS revision markers
- if ($rawline =~ /\$(Revision|Log|Id)(?:\$|)/) {
+ if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
}
-# The rest of our checks refer specifically to C style
-# only apply those _outside_ comments. Only skip
-# lines in the middle of comments.
- next if (!$comment_edge && $in_comment);
-
# Check for potential 'bare' types
if ($realcnt) {
+ my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
+ $s =~ s/\n./ /g;
+ $s =~ s/{.*$//;
+
# Ignore goto labels.
- if ($line =~ /$Ident:\*$/) {
+ if ($s =~ /$Ident:\*$/) {
# Ignore functions being called
- } elsif ($line =~ /^.\s*$Ident\s*\(/) {
+ } elsif ($s =~ /^.\s*$Ident\s*\(/) {
# definitions in global scope can only start with types
- } elsif ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
- possible($1, $line);
+ } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
+ possible($1, $s);
# declarations always start with types
- } elsif ($prev_values eq 'E' && $line =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) {
- possible($1);
+ } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) {
+ possible($1, $s);
}
# any (foo ... *) is a pointer cast, and foo is a type
- while ($line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
- possible($1, $line);
+ while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
+ possible($1, $s);
}
# Check for any sort of function declaration.
# int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *);
- if ($prev_values eq 'E' && $line =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
+ if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
my ($name_len) = length($1);
- my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, $name_len);
- my $ctx = join("\n", @ctx);
- $ctx =~ s/\n.//;
- substr($ctx, 0, $name_len + 1) = '';
+ my $ctx = $s;
+ substr($ctx, 0, $name_len + 1, '');
$ctx =~ s/\)[^\)]*$//;
+
for my $arg (split(/\s*,\s*/, $ctx)) {
if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/ || $arg =~ /^($Ident)$/) {
- possible($1, $line);
+ possible($1, $s);
}
}
}
@@ -1068,27 +1194,33 @@ sub process {
# if/while/etc brace do not go on next line, unless defining a do while loop,
# or if that brace on the next line is for something else
- if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
+ if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
+ my $pre_ctx = "$1$2";
+
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
my $ctx_ln = $linenr + $#ctx + 1;
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
+ ##warn "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+
# Skip over any removed lines in the context following statement.
- while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
+ while (defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^-/) {
$ctx_ln++;
- $ctx_cnt--;
}
- ##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
+ ##warn "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
- if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
- ERROR("That open brace { should be on the previous line\n" .
+ if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+ ERROR("that open brace { should be on the previous line\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]");
}
- if ($level == 0 && $ctx =~ /\)\s*\;\s*$/ && defined $lines[$ctx_ln - 1]) {
+ if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
+ $ctx =~ /\)\s*\;\s*$/ &&
+ defined $lines[$ctx_ln - 1])
+ {
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
if ($nindent > $indent) {
- WARN("Trailing semicolon indicates no statements, indent implies otherwise\n" .
+ WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]");
}
}
@@ -1100,8 +1232,8 @@ sub process {
$curr_values = $prev_values . $curr_values;
if ($dbg_values) {
my $outline = $opline; $outline =~ s/\t/ /g;
- warn "--> .$outline\n";
- warn "--> $curr_values\n";
+ print "$linenr > .$outline\n";
+ print "$linenr > $curr_values\n";
}
$prev_values = substr($curr_values, -1);
@@ -1117,7 +1249,7 @@ sub process {
# check for initialisation to aggregates open brace on the next line
if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
$line =~ /^.\s*{/) {
- ERROR("That open brace { should be on the previous line\n" . $hereprev);
+ ERROR("that open brace { should be on the previous line\n" . $hereprev);
}
#
@@ -1148,7 +1280,9 @@ sub process {
if (($prevline !~ /^}/) &&
($prevline !~ /^\+}/) &&
($prevline !~ /^ }/) &&
- ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=)/)) {
+ ($prevline !~ /^.DECLARE_$Ident\(\Q$name\E\)/) &&
+ ($prevline !~ /^.LIST_HEAD\(\Q$name\E\)/) &&
+ ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)/)) {
WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
}
}
@@ -1240,22 +1374,31 @@ sub process {
# check for spaces between functions and their parentheses.
while ($line =~ /($Ident)\s+\(/g) {
my $name = $1;
- my $ctx = substr($line, 0, $-[1]);
+ my $ctx_before = substr($line, 0, $-[1]);
+ my $ctx = "$ctx_before$name";
# Ignore those directives where spaces _are_ permitted.
- if ($name =~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright|case|__asm__)$/) {
+ if ($name =~ /^(?:
+ if|for|while|switch|return|case|
+ volatile|__volatile__|
+ __attribute__|format|__extension__|
+ asm|__asm__)$/x)
+ {
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open
# parenthesis it is simply not a parameter group.
- } elsif ($ctx =~ /^.\#\s*define\s*$/) {
+ } elsif ($ctx_before =~ /^.\#\s*define\s*$/) {
+
+ # cpp #elif statement condition may start with a (
+ } elsif ($ctx =~ /^.\#\s*elif\s*$/) {
# If this whole things ends with a type its most
# likely a typedef for a function.
- } elsif ("$ctx$name" =~ /$Type$/) {
+ } elsif ($ctx =~ /$Type$/) {
} else {
- WARN("no space between function name and open parenthesis '('\n" . $herecurr);
+ WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr);
}
}
# Check operator spacing.
@@ -1266,7 +1409,7 @@ sub process {
=>|->|<<|>>|<|>|=|!|~|
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
}x;
- my @elements = split(/($;+|$ops|;)/, $opline);
+ my @elements = split(/($ops|;)/, $opline);
my $off = 0;
my $blank = copy_spacing($opline);
@@ -1274,12 +1417,21 @@ sub process {
for (my $n = 0; $n < $#elements; $n += 2) {
$off += length($elements[$n]);
+ # Pick up the preceeding and succeeding characters.
+ my $ca = substr($opline, 0, $off);
+ my $cc = '';
+ if (length($opline) >= ($off + length($elements[$n + 1]))) {
+ $cc = substr($opline, $off + length($elements[$n + 1]));
+ }
+ my $cb = "$ca$;$cc";
+
my $a = '';
$a = 'V' if ($elements[$n] ne '');
$a = 'W' if ($elements[$n] =~ /\s$/);
+ $a = 'C' if ($elements[$n] =~ /$;$/);
$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
$a = 'O' if ($elements[$n] eq '');
- $a = 'E' if ($elements[$n] eq '' && $n == 0);
+ $a = 'E' if ($ca =~ /^\s*$/);
my $op = $elements[$n + 1];
@@ -1287,6 +1439,7 @@ sub process {
if (defined $elements[$n + 2]) {
$c = 'V' if ($elements[$n + 2] ne '');
$c = 'W' if ($elements[$n + 2] =~ /^\s/);
+ $c = 'C' if ($elements[$n + 2] =~ /^$;/);
$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
$c = 'O' if ($elements[$n + 2] eq '');
$c = 'E' if ($elements[$n + 2] =~ /\s*\\$/);
@@ -1294,14 +1447,6 @@ sub process {
$c = 'E';
}
- # Pick up the preceeding and succeeding characters.
- my $ca = substr($opline, 0, $off);
- my $cc = '';
- if (length($opline) >= ($off + length($elements[$n + 1]))) {
- $cc = substr($opline, $off + length($elements[$n + 1]));
- }
- my $cb = "$ca$;$cc";
-
my $ctx = "${a}x${c}";
my $at = "(ctx:$ctx)";
@@ -1330,14 +1475,14 @@ sub process {
if ($op_type ne 'V' &&
$ca =~ /\s$/ && $cc =~ /^\s*,/) {
- # Ignore comments
- } elsif ($op =~ /^$;+$/) {
+# # Ignore comments
+# } elsif ($op =~ /^$;+$/) {
# ; should have either the end of line or a space or \ after it
} elsif ($op eq ';') {
- if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
- $cc !~ /^;/) {
- ERROR("need space after that '$op' $at\n" . $hereptr);
+ if ($ctx !~ /.x[WEBC]/ &&
+ $cc !~ /^\\/ && $cc !~ /^;/) {
+ ERROR("space required after that '$op' $at\n" . $hereptr);
}
# // is a comment
@@ -1346,13 +1491,13 @@ sub process {
# -> should have no spaces
} elsif ($op eq '->') {
if ($ctx =~ /Wx.|.xW/) {
- ERROR("no spaces around that '$op' $at\n" . $hereptr);
+ ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
}
# , must have a space on the right.
} elsif ($op eq ',') {
- if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
- ERROR("need space after that '$op' $at\n" . $hereptr);
+ if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
+ ERROR("space required after that '$op' $at\n" . $hereptr);
}
# '*' as part of a type definition -- reported already.
@@ -1364,21 +1509,26 @@ sub process {
# unary operator, or a cast
} elsif ($op eq '!' || $op eq '~' ||
($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
- if ($ctx !~ /[WEB]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
- ERROR("need space before that '$op' $at\n" . $hereptr);
+ if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
+ ERROR("space required before that '$op' $at\n" . $hereptr);
}
if ($ctx =~ /.xW/) {
- ERROR("no space after that '$op' $at\n" . $hereptr);
+ ERROR("space prohibited after that '$op' $at\n" . $hereptr);
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq '++' or $op eq '--') {
- if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
- ERROR("need space one side of that '$op' $at\n" . $hereptr);
+ if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
+ ERROR("space required one side of that '$op' $at\n" . $hereptr);
}
- if ($ctx =~ /WxB/ || ($ctx =~ /Wx./ && $cc =~ /^;/)) {
- ERROR("no space before that '$op' $at\n" . $hereptr);
+ if ($ctx =~ /Wx[BE]/ ||
+ ($ctx =~ /Wx./ && $cc =~ /^;/)) {
+ ERROR("space prohibited before that '$op' $at\n" . $hereptr);
}
+ if ($ctx =~ /ExW/) {
+ ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ }
+
# << and >> may either have or not have spaces both sides
} elsif ($op eq '<<' or $op eq '>>' or
@@ -1387,17 +1537,17 @@ sub process {
$op eq '*' or $op eq '/' or
$op eq '%')
{
- if ($ctx !~ /VxV|WxW|VxE|WxE|VxO/) {
+ if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
ERROR("need consistent spacing around '$op' $at\n" .
$hereptr);
}
# All the others need spaces both sides.
- } elsif ($ctx !~ /[EW]x[WE]/) {
+ } elsif ($ctx !~ /[EWC]x[CWE]/) {
# Ignore email addresses <foo@bar>
if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
!($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
- ERROR("need spaces around that '$op' $at\n" . $hereptr);
+ ERROR("spaces required around that '$op' $at\n" . $hereptr);
}
}
$off += length($elements[$n + 1]);
@@ -1427,31 +1577,31 @@ sub process {
#need space before brace following if, while, etc
if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
$line =~ /do{/) {
- ERROR("need a space before the open brace '{'\n" . $herecurr);
+ ERROR("space required before the open brace '{'\n" . $herecurr);
}
# closing brace should have a space following it when it has anything
# on the line
if ($line =~ /}(?!(?:,|;|\)))\S/) {
- ERROR("need a space after that close brace '}'\n" . $herecurr);
+ ERROR("space required after that close brace '}'\n" . $herecurr);
}
# check spacing on square brackets
if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
- ERROR("no space after that open square bracket '['\n" . $herecurr);
+ ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
}
if ($line =~ /\s\]/) {
- ERROR("no space before that close square bracket ']'\n" . $herecurr);
+ ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
}
# check spacing on paretheses
if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
$line !~ /for\s*\(\s+;/) {
- ERROR("no space after that open parenthesis '('\n" . $herecurr);
+ ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
}
if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
$line !~ /for\s*\(.*;\s+\)/) {
- ERROR("no space before that close parenthesis ')'\n" . $herecurr);
+ ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
}
#goto labels aren't indented, allow a single space however
@@ -1462,7 +1612,7 @@ sub process {
# Need a space before open parenthesis after if, while etc
if ($line=~/\b(if|while|for|switch)\(/) {
- ERROR("need a space before the open parenthesis '('\n" . $herecurr);
+ ERROR("space required before the open parenthesis '('\n" . $herecurr);
}
# Check for illegal assignment in if conditional.
@@ -1475,10 +1625,12 @@ sub process {
# Find out what is on the end of the line after the
# conditional.
- substr($s, 0, length($c)) = '';
+ substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
$s =~ s/$;//g; # Remove any comments
- if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/) {
+ if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ &&
+ $c !~ /^.\#\s*if/)
+ {
ERROR("trailing statements should be on next line\n" . $herecurr);
}
}
@@ -1520,7 +1672,7 @@ sub process {
# Find out what is on the end of the line after the
# conditional.
- substr($s, 0, length($c)) = '';
+ substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
if ($s =~ /^\s*;/) {
@@ -1544,14 +1696,14 @@ sub process {
if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
my $checkfile = "$root/include/linux/$1.h";
if (-f $checkfile && $1 ne 'irq.h') {
- CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
+ WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
$herecurr);
}
}
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
-# in a known goot container
+# in a known good container
if ($prevline =~ /\#define.*\\/ &&
$prevline !~/(?:do\s+{|\(\{|\{)/ &&
$line !~ /(?:do\s+{|\(\{|\{)/ &&
@@ -1599,84 +1751,103 @@ sub process {
# check for redundant bracing round if etc
if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
my ($level, $endln, @chunks) =
- ctx_statement_full($linenr, $realcnt, 0);
+ ctx_statement_full($linenr, $realcnt, 1);
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
- if ($#chunks > 1 && $level == 0) {
+ #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
+ if ($#chunks > 0 && $level == 0) {
my $allowed = 0;
my $seen = 0;
+ my $herectx = $here . "\n";
+ my $ln = $linenr - 1;
for my $chunk (@chunks) {
my ($cond, $block) = @{$chunk};
- substr($block, 0, length($cond)) = '';
+ # If the condition carries leading newlines, then count those as offsets.
+ my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
+ my $offset = statement_rawlines($whitespace) - 1;
- $seen++ if ($block =~ /^\s*{/);
+ #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
- $block =~ s/(^|\n)./$1/g;
- $block =~ s/^\s*{//;
- $block =~ s/}\s*$//;
- $block =~ s/^\s*//;
- $block =~ s/\s*$//;
+ # We have looked at and allowed this specific line.
+ $suppress_ifbraces{$ln + $offset} = 1;
- my @lines = ($block =~ /\n/g);
- my @statements = ($block =~ /;/g);
+ $herectx .= "$rawlines[$ln + $offset]\n[...]\n";
+ $ln += statement_rawlines($block) - 1;
- #print "cond<$cond> block<$block> lines<" . scalar(@lines) . "> statements<" . scalar(@statements) . "> seen<$seen> allowed<$allowed>\n";
- if (scalar(@lines) != 0) {
+ substr($block, 0, length($cond), '');
+
+ $seen++ if ($block =~ /^\s*{/);
+
+ #print "cond<$cond> block<$block> allowed<$allowed>\n";
+ if (statement_lines($cond) > 1) {
+ #print "APW: ALLOWED: cond<$cond>\n";
$allowed = 1;
}
if ($block =~/\b(?:if|for|while)\b/) {
+ #print "APW: ALLOWED: block<$block>\n";
$allowed = 1;
}
- if (scalar(@statements) > 1) {
+ if (statement_block_size($block) > 1) {
+ #print "APW: ALLOWED: lines block<$block>\n";
$allowed = 1;
}
}
if ($seen && !$allowed) {
- WARN("braces {} are not necessary for any arm of this statement\n" . $herecurr);
- $suppress_ifbraces = $endln;
+ WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
}
}
}
- if ($linenr > $suppress_ifbraces &&
+ if (!defined $suppress_ifbraces{$linenr - 1} &&
$line =~ /\b(if|while|for|else)\b/) {
- # Locate the end of the opening statement.
- my @control = ctx_statement($linenr, $realcnt, 0);
- my $nr = $linenr + (scalar(@control) - 1);
- my $cnt = $realcnt - (scalar(@control) - 1);
-
- my $off = $realcnt - $cnt;
- #print "$off: line<$line>end<" . $lines[$nr - 1] . ">\n";
-
- # If this is is a braced statement group check it
- if ($lines[$nr - 1] =~ /{\s*$/) {
- my ($lvl, @block) = ctx_block_level($nr, $cnt);
-
- my $stmt = join("\n", @block);
- # Drop the diff line leader.
- $stmt =~ s/\n./\n/g;
- # Drop the code outside the block.
- $stmt =~ s/(^[^{]*){\s*//;
- my $before = $1;
- $stmt =~ s/\s*}([^}]*$)//;
- my $after = $1;
-
- #print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n";
- #print "before<$before> stmt<$stmt> after<$after>\n\n";
-
- # Count the newlines, if there is only one
- # then the block should not have {}'s.
- my @lines = ($stmt =~ /\n/g);
- my @statements = ($stmt =~ /;/g);
- #print "lines<" . scalar(@lines) . ">\n";
- #print "statements<" . scalar(@statements) . ">\n";
- if ($lvl == 0 && scalar(@lines) == 0 &&
- scalar(@statements) < 2 &&
- $stmt !~ /{/ && $stmt !~ /\bif\b/ &&
- $before !~ /}/ && $after !~ /{/) {
- my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n";
- shift(@block);
- WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
+ my $allowed = 0;
+
+ # Check the pre-context.
+ if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
+ #print "APW: ALLOWED: pre<$1>\n";
+ $allowed = 1;
+ }
+
+ my ($level, $endln, @chunks) =
+ ctx_statement_full($linenr, $realcnt, $-[0]);
+
+ # Check the condition.
+ my ($cond, $block) = @{$chunks[0]};
+ #print "CHECKING<$linenr> cond<$cond> block<$block>\n";
+ if (defined $cond) {
+ substr($block, 0, length($cond), '');
+ }
+ if (statement_lines($cond) > 1) {
+ #print "APW: ALLOWED: cond<$cond>\n";
+ $allowed = 1;
+ }
+ if ($block =~/\b(?:if|for|while)\b/) {
+ #print "APW: ALLOWED: block<$block>\n";
+ $allowed = 1;
+ }
+ if (statement_block_size($block) > 1) {
+ #print "APW: ALLOWED: lines block<$block>\n";
+ $allowed = 1;
+ }
+ # Check the post-context.
+ if (defined $chunks[1]) {
+ my ($cond, $block) = @{$chunks[1]};
+ if (defined $cond) {
+ substr($block, 0, length($cond), '');
}
+ if ($block =~ /^\s*\{/) {
+ #print "APW: ALLOWED: chunk-1 block<$block>\n";
+ $allowed = 1;
+ }
+ }
+ if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
+ my $herectx = $here . "\n";;
+ my $end = $linenr + statement_rawlines($block) - 1;
+
+ for (my $ln = $linenr - 1; $ln < $end; $ln++) {
+ $herectx .= $rawlines[$ln] . "\n";;
+ }
+
+ WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
}
}
@@ -1784,6 +1955,28 @@ sub process {
if ($line =~ /__FUNCTION__/) {
WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
}
+
+# check for semaphores used as mutexes
+ if ($line =~ /\b(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
+ WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
+ }
+# check for semaphores used as mutexes
+ if ($line =~ /\binit_MUTEX_LOCKED\s*\(/) {
+ WARN("consider using a completion\n" . $herecurr);
+ }
+# recommend strict_strto* over simple_strto*
+ if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
+ WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+ }
+
+# use of NR_CPUS is usually wrong
+# ignore definitions of NR_CPUS and usage to define arrays as likely right
+ if ($line =~ /\bNR_CPUS\b/ &&
+ $line !~ /^.#\s*define\s+NR_CPUS\s+/ &&
+ $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/)
+ {
+ WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
+ }
}
# If we have no input at all, then there is nothing to report on
@@ -1828,15 +2021,6 @@ sub process {
print "are false positives report them to the maintainer, see\n";
print "CHECKPATCH in MAINTAINERS.\n";
}
- print <<EOL if ($file == 1 && $quiet == 0);
-
-WARNING: Using --file mode. Please do not send patches to linux-kernel
-that change whole existing files if you did not significantly change most
-of the the file for other reasons anyways or just wrote the file newly
-from scratch. Pure code style patches have a significant cost in a
-quickly changing code base like Linux because they cause rejects
-with other changes.
-EOL
return $clean;
}
diff --git a/v4l/scripts/hghead.pl b/v4l/scripts/hghead.pl
index 9a6389311..1eb7355c4 100755
--- a/v4l/scripts/hghead.pl
+++ b/v4l/scripts/hghead.pl
@@ -25,7 +25,7 @@ my $fromname="";
open IN, "<$in";
while ($line = <IN>) {
- if ($line =~ m/Index.*/) {
+ if ($line =~ m/^\s*Index.*/) {
last;
}
if ($line =~ m/^diff .*/) {
diff --git a/v4l/versions.txt b/v4l/versions.txt
index cb12bb229..54be82237 100644
--- a/v4l/versions.txt
+++ b/v4l/versions.txt
@@ -121,11 +121,14 @@ VIDEO_WM8739
VIDEO_VP27SMPX
VIDEO_CX25840
VIDEO_SAA711X
+VIDEO_SAA717X
VIDEO_SAA7127
VIDEO_UPD64031A
VIDEO_UPD64083
VIDEO_IVTV
+VIDEO_CX18
VIDEO_EM28XX
+VIDEO_AU0828
DVB
DVB_CORE
DVB_AV7110
@@ -200,6 +203,9 @@ DVB_TUNER_MT2060
DVB_TUNER_MT2131
DVB_TDA827X
DVB_TDA18271
+DVB_AU8522
+DVB_TDA10048
+DVB_S5H1411
VIDEO_SAA7146
VIDEO_SAA7146_VV
VIDEO_TUNER
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile
index 34fc9a103..cc0547c32 100644
--- a/v4l2-apps/util/Makefile
+++ b/v4l2-apps/util/Makefile
@@ -1,8 +1,13 @@
# Makefile for linuxtv.org v4l2-apps/util
-CPPFLAGS += -I../../linux/include
+CPPFLAGS += -I../../linux/include -D_GNU_SOURCE
+LDFLAGS += -lm
-binaries = v4l2-ctl v4l2-dbg
+binaries = v4l2-ctl v4l2-dbg ivtv-ctl cx18-ctl
+
+ifeq ($(prefix),)
+prefix = /usr
+endif
.PHONY: all clean install qv4l2
@@ -22,6 +27,8 @@ v4l2-dbg: v4l2-dbg.o v4l2-driverids.o v4l2-chipids.o
$(CXX) $^ -o $@
install:
+ mkdir -p $(prefix)/bin
+ cp $(binaries) $(prefix)/bin
include ../Make.rules
diff --git a/v4l2-apps/util/cx18-ctl.c b/v4l2-apps/util/cx18-ctl.c
new file mode 100644
index 000000000..755b9437f
--- /dev/null
+++ b/v4l2-apps/util/cx18-ctl.c
@@ -0,0 +1,496 @@
+/*
+ Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo dot com>
+
+ Cleanup and VBI and audio in/out options:
+ Copyright (C) 2004 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 <unistd.h>
+#include <features.h> /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <math.h>
+#include <linux/types.h>
+#include <sys/klog.h>
+
+#include <linux/videodev2.h>
+
+/* copied from cx18-driver.h */
+#define CX18_DBGFLG_WARN (1 << 0)
+#define CX18_DBGFLG_INFO (1 << 1)
+#define CX18_DBGFLG_API (1 << 2)
+#define CX18_DBGFLG_DMA (1 << 3)
+#define CX18_DBGFLG_IOCTL (1 << 4)
+#define CX18_DBGFLG_FILE (1 << 5)
+#define CX18_DBGFLG_I2C (1 << 6)
+#define CX18_DBGFLG_IRQ (1 << 7)
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_HIGHVOL (1 << 8)
+
+/* Internals copied from media/v4l2-common.h */
+struct v4l2_routing {
+ __u32 input;
+ __u32 output;
+};
+#define VIDIOC_INT_S_AUDIO_ROUTING _IOW('d', 109, struct v4l2_routing)
+
+#define VIDIOC_INT_RESET _IOW('d', 102, __u32)
+
+#define __stringify_1(x) #x
+#define __stringify(x) __stringify_1(x)
+
+#include "../../linux/drivers/media/video/cx18/cx18-version.h"
+
+/* GPIO */
+#define CX18_REG_GPIO_IN 0x02c72010
+#define CX18_REG_GPIO_OUT1 0x02c78100
+#define CX18_REG_GPIO_DIR1 0x02c78108
+#define CX18_REG_GPIO_OUT2 0x02c78104
+#define CX18_REG_GPIO_DIR2 0x02c7810c
+
+/* Options */
+enum Option {
+ OptSetDebugLevel = 'D',
+ OptSetDevice = 'd',
+ OptGetDebugLevel = 'e',
+ OptHelp = 'h',
+ OptSetGPIO = 'i',
+ OptListGPIO = 'I',
+ OptSetAudioRoute = 'v',
+ OptReset = 128,
+ OptVersion,
+ OptLast = 256
+};
+
+static char options[OptLast];
+
+static struct option long_options[] = {
+ /* Please keep in alphabetical order of the short option.
+ That makes it easier to see which options are still free. */
+ {"set-debug", required_argument, 0, OptSetDebugLevel},
+ {"device", required_argument, 0, OptSetDevice},
+ {"get-debug", no_argument, 0, OptGetDebugLevel},
+ {"help", no_argument, 0, OptHelp},
+ {"set-gpio", required_argument, 0, OptSetGPIO},
+ {"list-gpio", no_argument, 0, OptListGPIO},
+ {"audio-route", required_argument, 0, OptSetAudioRoute},
+ {"reset", required_argument, 0, OptReset},
+ {"version", no_argument, 0, OptVersion},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf(" -d, --device <dev> use device <dev> instead of /dev/video0\n");
+ printf(" -h, --help display this help message\n");
+ printf(" --reset <mask> reset the infrared receiver (1) or digitizer (2) [VIDIOC_INT_RESET]\n");
+ printf(" --version shows the version number of this utility.\n");
+ printf(" It should match the driver version.\n");
+ printf("\n");
+ printf("Expert options:\n");
+ printf(" -D, --set-debug <level>\n");
+ printf(" set the module debug variable\n");
+ printf(" 1/0x0001: warning\n");
+ printf(" 2/0x0002: info\n");
+ printf(" 4/0x0004: mailbox\n");
+ printf(" 8/0x0008: dma\n");
+ printf(" 16/0x0010: ioctl\n");
+ printf(" 32/0x0020: file\n");
+ printf(" 64/0x0040: i2c\n");
+ printf(" 128/0x0080: irq\n");
+ printf(" 256/0x0100: high volume\n");
+ printf(" -e, --get-debug query the module debug variable\n");
+ printf(" -I, --list-gpio\n");
+ printf(" show GPIO input/direction/output bits\n");
+ printf(" -i, --set-gpio [dir=<dir>,]val=<val>\n");
+ printf(" set GPIO direction bits to <dir> and set output to <val>\n");
+ printf(" -v, --audio-route=input=<in>,output=<out>\n");
+ printf(" set the audio input/output routing [VIDIOC_INT_S_AUDIO_ROUTING]\n");
+ exit(0);
+}
+
+static char *pts_to_string(char *str, unsigned long pts, float fps)
+{
+ static char buf[256];
+ int hours, minutes, seconds, fracsec;
+ int frame;
+ char *p = (str) ? str : buf;
+
+ static const int MPEG_CLOCK_FREQ = 90000;
+ seconds = pts / MPEG_CLOCK_FREQ;
+ fracsec = pts % MPEG_CLOCK_FREQ;
+
+ minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ frame = (int)ceilf(((float)fracsec / (float)MPEG_CLOCK_FREQ) * fps);
+
+ snprintf(p, sizeof(buf), "%d:%02d:%02d:%d", hours, minutes, seconds, frame);
+ return p;
+}
+
+static void print_debug_mask(int mask)
+{
+#define MASK_OR_NOTHING (mask ? " | " : "")
+ if (mask & CX18_DBGFLG_WARN) {
+ mask &= ~CX18_DBGFLG_WARN;
+ printf("CX18_DBGFLG_WARN%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_INFO) {
+ mask &= ~CX18_DBGFLG_INFO;
+ printf("CX18_DBGFLG_INFO%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_API) {
+ mask &= ~CX18_DBGFLG_API;
+ printf("CX18_DBGFLG_API%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_DMA) {
+ mask &= ~CX18_DBGFLG_DMA;
+ printf("CX18_DBGFLG_DMA%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_IOCTL) {
+ mask &= ~CX18_DBGFLG_IOCTL;
+ printf("CX18_DBGFLG_IOCTL%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_FILE) {
+ mask &= ~CX18_DBGFLG_FILE;
+ printf("CX18_DBGFLG_FILE%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_I2C) {
+ mask &= ~CX18_DBGFLG_I2C;
+ printf("CX18_DBGFLG_I2C%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_IRQ) {
+ mask &= ~CX18_DBGFLG_IRQ;
+ printf("CX18_DBGFLG_IRQ%s", MASK_OR_NOTHING);
+ }
+ if (mask & CX18_DBGFLG_HIGHVOL) {
+ mask &= ~CX18_DBGFLG_HIGHVOL;
+ printf("CX18_DBGFLG_HIGHVOL%s", MASK_OR_NOTHING);
+ }
+ if (mask)
+ printf("0x%08x", mask);
+ printf("\n");
+}
+
+static int dowrite(const char *buf, const char *fn)
+{
+ FILE *f = fopen(fn, "w");
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return errno;
+ }
+ fprintf(f, buf);
+ fclose(f);
+ return 0;
+}
+
+static char *doread(const char *fn)
+{
+ static char buf[1000];
+ FILE *f = fopen(fn, "r");
+ int s;
+
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return NULL;
+ }
+ s = fread(buf, 1, sizeof(buf) - 1, f);
+ buf[s] = 0;
+ fclose(f);
+ return buf;
+}
+
+static int doioctl(int fd, int request, void *parm, const char *name)
+{
+ int retVal;
+
+ printf("ioctl %s ", name);
+ retVal = ioctl(fd, request, parm);
+ if (retVal < 0)
+ printf("failed: %s\n", strerror(errno));
+ else
+ printf("ok\n");
+
+ return retVal;
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+ char *subopts[] = {
+#define SUB_VAL 0
+ "val",
+#define SUB_YUV_MODE 1
+ "mode",
+#define SUB_DIR 2
+ "dir",
+#define SUB_INPUT 3
+ "input",
+#define SUB_OUTPUT 4
+ "output",
+
+ NULL
+ };
+
+ int fd = -1;
+
+ /* bitfield for OptSetCodec */
+
+ /* command args */
+ char *device = strdup("/dev/video0"); /* -d device */
+ int ch;
+ int yuv_mode = 0;
+ struct v4l2_routing route; /* audio_route */
+ unsigned int gpio_out = 0x0; /* GPIO output data */
+ unsigned int gpio_dir = 0x0; /* GPIO direction bits */
+ int gpio_set_dir = 0;
+ int debug_level = 0;
+ __u32 reset = 0;
+ int new_debug_level, gdebug_level;
+ double timestamp;
+ char ptsstr[64];
+ char short_options[26 * 2 * 2 + 1];
+
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+ while (1) {
+ int option_index = 0;
+ int idx = 0;
+
+ for (i = 0; long_options[i].name; i++) {
+ if (!isalpha(long_options[i].val))
+ continue;
+ short_options[idx++] = long_options[i].val;
+ if (long_options[i].has_arg == required_argument)
+ short_options[idx++] = ':';
+ }
+ short_options[idx] = 0;
+ ch = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (ch == -1)
+ break;
+
+ options[(int)ch] = 1;
+ switch (ch) {
+ case OptHelp:
+ usage();
+ return 0;
+ case OptSetDebugLevel:{
+ debug_level = strtol(optarg, 0L, 0);
+ break;
+ }
+ case OptSetDevice:
+ device = strdup(optarg);
+ if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
+ char dev = device[0];
+
+ sprintf(device, "/dev/video%c", dev);
+ }
+ break;
+ case OptSetAudioRoute:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_INPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <input>\n");
+ usage();
+ }
+ route.input = strtol(value, 0L, 0);
+ break;
+ case SUB_OUTPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <output>\n");
+ usage();
+ }
+ route.output = strtol(value, 0L, 0);
+ break;
+ default:
+ printf
+ ("Invalid suboptions specified\n");
+ usage();
+ break;
+ }
+ }
+ break;
+ case OptReset:
+ reset = strtol(optarg, 0L, 0);
+ break;
+ case OptSetGPIO:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_DIR:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <dir>\n");
+ usage();
+ exit(1);
+ }
+ gpio_dir = strtoul(value, 0L, 0);
+ gpio_set_dir = 1;
+ break;
+ case SUB_VAL:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <val>\n");
+ usage();
+ exit(1);
+ }
+ gpio_out =
+ (unsigned short)strtoul(value, 0L, 0);
+ break;
+ default:
+ fprintf(stderr,
+ "Invalid suboptions specified\n");
+ usage();
+ exit(1);
+ break;
+ }
+ }
+ break;
+ case ':':
+ fprintf(stderr, "Option `%s' requires a value\n",
+ argv[optind]);
+ usage();
+ return 1;
+ case '?':
+ fprintf(stderr, "Unknown argument `%s'\n",
+ argv[optind]);
+ usage();
+ return 1;
+ }
+ }
+ if (optind < argc) {
+ printf("unknown arguments: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ usage();
+ return 1;
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", device,
+ strerror(errno));
+ exit(1);
+ }
+ free(device);
+
+ /* Setting Opts */
+
+ if (options[OptSetAudioRoute])
+ doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route, "VIDIOC_INT_S_AUDIO_ROUTING");
+
+ if (options[OptSetGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = CX18_REG_GPIO_DIR1;
+ reg.val = (unsigned)((gpio_dir & 0xffff) << 16);
+ if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO dir 1 set to 0x%08llx\n", reg.val);
+ reg.reg = CX18_REG_GPIO_DIR2;
+ reg.val = (unsigned)(gpio_dir & 0xffff0000);
+ if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO dir 2 set to 0x%08llx\n", reg.val);
+ reg.reg = CX18_REG_GPIO_OUT1;
+ reg.val = (unsigned)((gpio_dir & 0xffff) << 16) | (gpio_out & 0xffff);
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO out 1 set to 0x%08llx\n", reg.val);
+ reg.reg = CX18_REG_GPIO_OUT2;
+ reg.val = (unsigned)(gpio_dir & 0xffff0000) | (gpio_out >> 16);
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO out 2 set to 0x%08llx\n", reg.val);
+ }
+
+ if (options[OptListGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = CX18_REG_GPIO_IN;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO in: 0x%04llx\n", reg.val);
+ reg.reg = CX18_REG_GPIO_DIR1;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO dir: 0x%04llx\n", reg.val);
+ reg.reg = CX18_REG_GPIO_OUT1;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO out: 0x%04llx\n", reg.val);
+ }
+
+ if (options[OptSetDebugLevel]) {
+ char buf[20];
+ new_debug_level = debug_level;
+
+ sprintf(buf, "%d", debug_level);
+ if (dowrite(buf, "/sys/module/cx18/parameters/debug") == 0) {
+ printf(" set debug level: ");
+ print_debug_mask(new_debug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptGetDebugLevel]) {
+ char *buf;
+
+ gdebug_level = 0;
+ buf = doread("/sys/module/cx18/parameters/debug");
+ if (buf) {
+ gdebug_level = atol(buf);
+ printf(" debug level: ");
+ print_debug_mask(gdebug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptReset])
+ doioctl(fd, VIDIOC_INT_RESET, &reset, "VIDIOC_INT_RESET");
+
+ if (options[OptVersion])
+ printf("cx18ctl version " CX18_VERSION "\n");
+
+ close(fd);
+ exit(0);
+}
diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c
new file mode 100644
index 000000000..9d3170785
--- /dev/null
+++ b/v4l2-apps/util/ivtv-ctl.c
@@ -0,0 +1,687 @@
+/*
+ Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo dot com>
+
+ Cleanup and VBI and audio in/out options:
+ Copyright (C) 2004 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 <unistd.h>
+#include <features.h> /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <math.h>
+#include <linux/types.h>
+#include <sys/klog.h>
+
+#include <linux/videodev2.h>
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+
+/* copied from ivtv-driver.h */
+#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)
+
+/* Internals copied from media/v4l2-common.h */
+struct v4l2_routing {
+ __u32 input;
+ __u32 output;
+};
+#define VIDIOC_INT_S_AUDIO_ROUTING _IOW('d', 109, struct v4l2_routing)
+
+#define VIDIOC_INT_RESET _IOW('d', 102, __u32)
+
+#include <linux/ivtv.h>
+
+/* GPIO */
+#define IVTV_REG_GPIO_IN_OFFSET (0x9008 + 0x02000000)
+#define IVTV_REG_GPIO_OUT_OFFSET (0x900c + 0x02000000)
+#define IVTV_REG_GPIO_DIR_OFFSET (0x9020 + 0x02000000)
+
+/* Options */
+enum Option {
+ OptSetDebugLevel = 'D',
+ OptSetDevice = 'd',
+ OptGetDebugLevel = 'e',
+ OptHelp = 'h',
+ OptSetGPIO = 'i',
+ OptListGPIO = 'I',
+ OptPassThrough = 'K',
+ OptFrameSync = 'k',
+ OptSetAudioRoute = 'v',
+ OptReset = 128,
+ OptSetYuvMode,
+ OptGetYuvMode,
+ OptSetAudioMute,
+ OptSetStereoMode,
+ OptSetBilingualMode,
+ OptLast = 256
+};
+
+static char options[OptLast];
+
+static int app_result;
+
+static struct option long_options[] = {
+ /* Please keep in alphabetical order of the short option.
+ That makes it easier to see which options are still free. */
+ {"set-debug", required_argument, 0, OptSetDebugLevel},
+ {"device", required_argument, 0, OptSetDevice},
+ {"get-debug", no_argument, 0, OptGetDebugLevel},
+ {"help", no_argument, 0, OptHelp},
+ {"set-gpio", required_argument, 0, OptSetGPIO},
+ {"list-gpio", no_argument, 0, OptListGPIO},
+ {"passthrough", required_argument, 0, OptPassThrough},
+ {"sync", no_argument, 0, OptFrameSync},
+ {"audio-route", required_argument, 0, OptSetAudioRoute},
+ {"reset", required_argument, 0, OptReset},
+ {"get-yuv-mode", no_argument, 0, OptGetYuvMode},
+ {"set-yuv-mode", required_argument, 0, OptSetYuvMode},
+ {"set-audio-mute", required_argument, 0, OptSetAudioMute},
+ {"set-stereo-mode", required_argument, 0, OptSetStereoMode},
+ {"set-bilingual-mode", required_argument, 0, OptSetBilingualMode},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf(" -d, --device <dev> use device <dev> instead of /dev/video0\n");
+ printf(" -h, --help display this help message\n");
+ printf(" -K, --passthrough <mode>\n");
+ printf(" set passthrough mode: 1 = on, 0 = off [IVTV_IOC_PASSTHROUGH]\n");
+ printf(" --get-yuv-mode display the current yuv mode\n");
+ printf(" --set-yuv-mode mode=<mode>\n");
+ printf(" set the current yuv mode:\n");
+ printf(" mode 0: interlaced (top transmitted first)\n");
+ printf(" mode 1: interlaced (bottom transmitted first)\n");
+ printf(" mode 2: progressive\n");
+ printf(" mode 3: auto\n");
+ printf(" --set-audio-mute <mute>\n");
+ printf(" 0=enable audio during 1.5x and 0.5x playback\n");
+ printf(" 1=mute audio during 1.5x and 0.5x playback\n");
+ printf(" --set-stereo-mode <mode>\n");
+ printf(" mode 0: playback stereo as stereo\n");
+ printf(" mode 1: playback left stereo channel as mono\n");
+ printf(" mode 2: playback right stereo channel as mono\n");
+ printf(" mode 3: playback stereo as mono\n");
+ printf(" mode 4: playback stereo as swapped stereo\n");
+ printf(" --set-bilingual-mode <mode>\n");
+ printf(" mode 0: playback bilingual as stereo\n");
+ printf(" mode 1: playback left bilingual channel as mono\n");
+ printf(" mode 2: playback right bilingual channel as mono\n");
+ printf(" mode 3: playback bilingual as mono\n");
+ printf(" mode 4: playback bilingual as swapped stereo\n");
+ printf(" --reset <mask> reset the infrared receiver (1) or digitizer (2) [VIDIOC_INT_RESET]\n");
+ printf("\n");
+ printf("Expert options:\n");
+ printf(" -D, --set-debug <level>\n");
+ printf(" set the module debug variable\n");
+ printf(" 1/0x0001: warning\n");
+ printf(" 2/0x0002: info\n");
+ printf(" 4/0x0004: mailbox\n");
+ printf(" 8/0x0008: ioctl\n");
+ printf(" 16/0x0010: file\n");
+ printf(" 32/0x0020: dma\n");
+ printf(" 64/0x0040: irq\n");
+ printf(" 128/0x0080: decoder\n");
+ printf(" 256/0x0100: yuv\n");
+ printf(" 512/0x0200: i2c\n");
+ printf(" 1024/0x0400: high volume\n");
+ printf(" -e, --get-debug query the module debug variable\n");
+ printf(" -I, --list-gpio\n");
+ printf(" show GPIO input/direction/output bits\n");
+ printf(" -i, --set-gpio [dir=<dir>,]val=<val>\n");
+ printf(" set GPIO direction bits to <dir> and set output to <val>\n");
+ printf(" -k, --sync test vsync's capabilities [VIDEO_GET_EVENT]\n");
+ printf(" -v, --audio-route=input=<in>,output=<out>\n");
+ printf(" set the audio input/output routing [VIDIOC_INT_S_AUDIO_ROUTING]\n");
+ exit(0);
+}
+
+static char *pts_to_string(char *str, unsigned long pts, float fps)
+{
+ static char buf[256];
+ int hours, minutes, seconds, fracsec;
+ int frame;
+ char *p = (str) ? str : buf;
+
+ static const int MPEG_CLOCK_FREQ = 90000;
+ seconds = pts / MPEG_CLOCK_FREQ;
+ fracsec = pts % MPEG_CLOCK_FREQ;
+
+ minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ frame = (int)ceilf(((float)fracsec / (float)MPEG_CLOCK_FREQ) * fps);
+
+ snprintf(p, sizeof(buf), "%d:%02d:%02d:%d", hours, minutes, seconds, frame);
+ return p;
+}
+
+static void print_debug_mask(int mask)
+{
+#define MASK_OR_NOTHING (mask ? " | " : "")
+ if (mask & IVTV_DBGFLG_WARN) {
+ mask &= ~IVTV_DBGFLG_WARN;
+ printf("IVTV_DBGFLG_WARN%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_INFO) {
+ mask &= ~IVTV_DBGFLG_INFO;
+ printf("IVTV_DBGFLG_INFO%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_MB) {
+ mask &= ~IVTV_DBGFLG_MB;
+ printf("IVTV_DBGFLG_MB%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_DMA) {
+ mask &= ~IVTV_DBGFLG_DMA;
+ printf("IVTV_DBGFLG_DMA%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_IOCTL) {
+ mask &= ~IVTV_DBGFLG_IOCTL;
+ printf("IVTV_DBGFLG_IOCTL%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_FILE) {
+ mask &= ~IVTV_DBGFLG_FILE;
+ printf("IVTV_DBGFLG_FILE%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_I2C) {
+ mask &= ~IVTV_DBGFLG_I2C;
+ printf("IVTV_DBGFLG_I2C%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_IRQ) {
+ mask &= ~IVTV_DBGFLG_IRQ;
+ printf("IVTV_DBGFLG_IRQ%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_DEC) {
+ mask &= ~IVTV_DBGFLG_DEC;
+ printf("IVTV_DBGFLG_DEC%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_YUV) {
+ mask &= ~IVTV_DBGFLG_YUV;
+ printf("IVTV_DBGFLG_YUV%s", MASK_OR_NOTHING);
+ }
+ if (mask & IVTV_DBGFLG_HIGHVOL) {
+ mask &= ~IVTV_DBGFLG_HIGHVOL;
+ printf("IVTV_DBGFLG_HIGHVOL%s", MASK_OR_NOTHING);
+ }
+ if (mask)
+ printf("0x%08x", mask);
+ printf("\n");
+}
+
+static int dowrite(const char *buf, const char *fn)
+{
+ FILE *f = fopen(fn, "w");
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return errno;
+ }
+ fprintf(f, buf);
+ fclose(f);
+ return 0;
+}
+
+static char *doread(const char *fn)
+{
+ static char buf[1000];
+ FILE *f = fopen(fn, "r");
+ int s;
+
+ if (f == NULL) {
+ printf("failed: %s\n", strerror(errno));
+ return NULL;
+ }
+ s = fread(buf, 1, sizeof(buf) - 1, f);
+ buf[s] = 0;
+ fclose(f);
+ return buf;
+}
+
+static const char *field2s(int val)
+{
+ switch (val) {
+ case V4L2_FIELD_ANY:
+ return "Any";
+ case V4L2_FIELD_NONE:
+ return "None";
+ case V4L2_FIELD_TOP:
+ return "Top";
+ case V4L2_FIELD_BOTTOM:
+ return "Bottom";
+ case V4L2_FIELD_INTERLACED:
+ return "Interlaced";
+ case V4L2_FIELD_SEQ_TB:
+ return "Sequential Top-Bottom";
+ case V4L2_FIELD_SEQ_BT:
+ return "Sequential Bottom-Top";
+ case V4L2_FIELD_ALTERNATE:
+ return "Alternating";
+ case V4L2_FIELD_INTERLACED_TB:
+ return "Interlaced Top-Bottom";
+ case V4L2_FIELD_INTERLACED_BT:
+ return "Interlaced Bottom-Top";
+ default:
+ return "Unknown";
+ }
+}
+
+static int doioctl(int fd, int request, void *parm, const char *name)
+{
+ int retVal;
+
+ printf("ioctl %s ", name);
+ retVal = ioctl(fd, request, parm);
+ if (retVal < 0) {
+ app_result = -1;
+ printf("failed: %s\n", strerror(errno));
+ }
+ else
+ printf("ok\n");
+
+ return retVal;
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+ char *subopts[] = {
+#define SUB_VAL 0
+ "val",
+#define SUB_YUV_MODE 1
+ "mode",
+#define SUB_DIR 2
+ "dir",
+#define SUB_INPUT 3
+ "input",
+#define SUB_OUTPUT 4
+ "output",
+
+ NULL
+ };
+
+ int fd = -1;
+
+ /* bitfield for OptSetCodec */
+
+ /* command args */
+ char *device = strdup("/dev/video0"); /* -d device */
+ int ch;
+ int yuv_mode = 0;
+ struct v4l2_routing route; /* audio_route */
+ unsigned short gpio_out = 0x0; /* GPIO output data */
+ unsigned short gpio_dir = 0x0; /* GPIO direction bits */
+ int gpio_set_dir = 0;
+ int passthrough = 0;
+ int audio_mute = 0;
+ int stereo_mode = 0;
+ int bilingual_mode = 0;
+ int debug_level = 0;
+ __u32 reset = 0;
+ int new_debug_level, gdebug_level;
+ double timestamp;
+ char ptsstr[64];
+ char short_options[26 * 2 * 2 + 1];
+
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+ while (1) {
+ int option_index = 0;
+ int idx = 0;
+
+ for (i = 0; long_options[i].name; i++) {
+ if (!isalpha(long_options[i].val))
+ continue;
+ short_options[idx++] = long_options[i].val;
+ if (long_options[i].has_arg == required_argument)
+ short_options[idx++] = ':';
+ }
+ short_options[idx] = 0;
+ ch = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (ch == -1)
+ break;
+
+ options[(int)ch] = 1;
+ switch (ch) {
+ case OptSetYuvMode:
+ {
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_YUV_MODE:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <mode>\n");
+ usage();
+ return 1;
+
+ }
+ yuv_mode = strtol(value, 0L, 0);
+ if (yuv_mode < 0 || yuv_mode > 3) {
+ fprintf(stderr, "invalid yuv mode\n");
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case OptHelp:
+ usage();
+ return 0;
+ case OptSetDebugLevel:{
+ debug_level = strtol(optarg, 0L, 0);
+ break;
+ }
+ case OptSetDevice:
+ device = strdup(optarg);
+ if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
+ char dev = device[0];
+
+ sprintf(device, "/dev/video%c", dev);
+ }
+ break;
+ case OptSetAudioRoute:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_INPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <input>\n");
+ usage();
+ }
+ route.input = strtol(value, 0L, 0);
+ break;
+ case SUB_OUTPUT:
+ if (value == NULL) {
+ printf
+ ("No value given to suboption <output>\n");
+ usage();
+ }
+ route.output = strtol(value, 0L, 0);
+ break;
+ default:
+ printf
+ ("Invalid suboptions specified\n");
+ usage();
+ break;
+ }
+ }
+ break;
+ case OptReset:
+ reset = strtol(optarg, 0L, 0);
+ break;
+ case OptPassThrough:
+ passthrough = strtol(optarg, 0L, 0);
+ break;
+ case OptSetAudioMute:
+ audio_mute = strtol(optarg, 0L, 0);
+ break;
+ case OptSetStereoMode:
+ stereo_mode = strtol(optarg, 0L, 0);
+ break;
+ case OptSetBilingualMode:
+ bilingual_mode = strtol(optarg, 0L, 0);
+ break;
+ case OptSetGPIO:
+ subs = optarg;
+ while (*subs != '\0') {
+ switch (getsubopt(&subs, subopts, &value)) {
+ case SUB_DIR:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <dir>\n");
+ usage();
+ exit(1);
+ }
+ gpio_dir = strtol(value, 0L, 0);
+ gpio_set_dir = 1;
+ break;
+ case SUB_VAL:
+ if (value == NULL) {
+ fprintf(stderr,
+ "No value given to suboption <val>\n");
+ usage();
+ exit(1);
+ }
+ gpio_out = (unsigned short)strtol(value, 0L, 0);
+ break;
+ default:
+ fprintf(stderr,
+ "Invalid suboptions specified\n");
+ usage();
+ exit(1);
+ break;
+ }
+ }
+ break;
+ case ':':
+ fprintf(stderr, "Option `%s' requires a value\n",
+ argv[optind]);
+ usage();
+ return 1;
+ case '?':
+ fprintf(stderr, "Unknown argument `%s'\n",
+ argv[optind]);
+ usage();
+ return 1;
+ }
+ }
+ if (optind < argc) {
+ printf("unknown arguments: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ usage();
+ return 1;
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", device,
+ strerror(errno));
+ exit(1);
+ }
+ free(device);
+
+ /* Setting Opts */
+
+ if (options[OptSetAudioRoute])
+ doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route,
+ "VIDIOC_INT_S_AUDIO_ROUTING");
+
+ if (options[OptFrameSync]) {
+ printf("ioctl: VIDEO_GET_EVENT\n");
+
+ for (;;) {
+ struct video_event ev;
+ int fps = 30;
+ v4l2_std_id std;
+
+ if (ioctl(fd, VIDIOC_G_STD, &std) == 0)
+ fps = (std & V4L2_STD_525_60) ? 30 : 25;
+ if (ioctl(fd, VIDEO_GET_EVENT, &ev) < 0) {
+ fprintf(stderr, "ioctl: VIDEO_GET_EVENT failed\n");
+ break;
+ } else if (ev.timestamp == 0) {
+ unsigned long long pts = 0, frame = 0;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ timestamp =
+ (double)tv.tv_sec +
+ ((double)tv.tv_usec / 1000000.0);
+
+ ioctl(fd, VIDEO_GET_PTS, &pts);
+ ioctl(fd, VIDEO_GET_FRAME_COUNT, &frame);
+ pts_to_string(ptsstr, pts, fps);
+ printf("%10.6f: pts %-20s, %lld frames\n",
+ timestamp, ptsstr, frame);
+ }
+ }
+ }
+
+ if (options[OptSetGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = IVTV_REG_GPIO_DIR_OFFSET;
+ reg.val = gpio_dir;
+ if (gpio_set_dir && doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO dir set to 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_OUT_OFFSET;
+ reg.val = gpio_out;
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("GPIO out set to 0x%04llx\n", reg.val);
+ }
+
+ if (options[OptListGPIO]) {
+ struct v4l2_register reg;
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = IVTV_REG_GPIO_IN_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO in: 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_DIR_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO dir: 0x%04llx\n", reg.val);
+ reg.reg = IVTV_REG_GPIO_OUT_OFFSET;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) == 0)
+ printf("GPIO out: 0x%04llx\n", reg.val);
+ }
+
+ if (options[OptSetDebugLevel]) {
+ char buf[20];
+ new_debug_level = debug_level;
+
+ sprintf(buf, "%d", debug_level);
+ if (dowrite(buf, "/sys/module/ivtv/parameters/debug") == 0) {
+ printf(" set debug level: ");
+ print_debug_mask(new_debug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptGetDebugLevel]) {
+ char *buf = doread("/sys/module/ivtv/parameters/debug");
+
+ gdebug_level = 0;
+ if (buf) {
+ gdebug_level = atol(buf);
+ printf(" debug level: ");
+ print_debug_mask(gdebug_level);
+ printf("\n");
+ }
+ }
+
+ if (options[OptPassThrough]) {
+ int source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
+
+ doioctl(fd, VIDEO_SELECT_SOURCE, (void *)source,
+ "IVTV_IOC_PASSTHROUGH");
+ }
+
+ if (options[OptSetAudioMute]) {
+ doioctl(fd, AUDIO_SET_MUTE, (void *)audio_mute, "AUDIO_SET_MUTE");
+ }
+
+ if (options[OptSetStereoMode]) {
+ doioctl(fd, AUDIO_CHANNEL_SELECT,
+ (void *)stereo_mode, "AUDIO_CHANNEL_SELECT");
+ }
+
+ if (options[OptSetBilingualMode]) {
+ doioctl(fd, AUDIO_BILINGUAL_CHANNEL_SELECT,
+ (void *)bilingual_mode, "AUDIO_BILINGUAL_CHANNEL_SELECT");
+ }
+
+ if (options[OptReset])
+ doioctl(fd, VIDIOC_INT_RESET, &reset, "VIDIOC_INT_RESET");
+
+ if (options[OptSetYuvMode]) {
+ struct ivtv_dma_frame frame;
+ struct v4l2_format fmt;
+ const enum v4l2_field map[4] = {
+ V4L2_FIELD_INTERLACED_TB,
+ V4L2_FIELD_INTERLACED_BT,
+ V4L2_FIELD_NONE,
+ V4L2_FIELD_ANY,
+ };
+
+ printf("set yuv mode\n");
+ memset(&frame, 0, sizeof(frame));
+ frame.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, IVTV_IOC_DMA_FRAME, &frame) < 0) {
+ fprintf(stderr, "Unable to switch to user DMA YUV mode\n");
+ exit(1);
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ ioctl(fd, VIDIOC_G_FMT, &fmt);
+ fmt.fmt.pix.field = map[yuv_mode];
+ doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
+ }
+
+ if (options[OptGetYuvMode]) {
+ struct ivtv_dma_frame frame;
+ struct v4l2_format fmt;
+
+ memset(&frame, 0, sizeof(frame));
+ frame.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, IVTV_IOC_DMA_FRAME, &frame) < 0) {
+ fprintf(stderr, "Unable to switch to user DMA YUV mode\n");
+ exit(1);
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT");
+ printf("Current yuv_mode %d %s\n", fmt.fmt.pix.field,
+ field2s(fmt.fmt.pix.field));
+ }
+
+ close(fd);
+ exit(app_result);
+}
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index 198118ac6..d637e34d7 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -123,6 +123,8 @@ enum Option {
static char options[OptLast];
+static int app_result;
+
static unsigned capabilities;
typedef std::vector<struct v4l2_ext_control> ctrl_list;
@@ -715,7 +717,7 @@ static void printcropcap(const struct v4l2_cropcap &cropcap)
printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
}
-static int printfmt(struct v4l2_format vfmt)
+static void printfmt(struct v4l2_format vfmt)
{
const flag_def vbi_def[] = {
{ V4L2_VBI_UNSYNC, "unsynchronized" },
@@ -776,10 +778,7 @@ static int printfmt(struct v4l2_format vfmt)
break;
case V4L2_BUF_TYPE_PRIVATE:
break;
- default:
- return -1;
}
- return 0;
}
static void print_video_formats(int fd, enum v4l2_buf_type type)
@@ -999,10 +998,12 @@ static v4l2_std_id parse_ntsc(const char *ntsc)
static int doioctl(int fd, int request, void *parm, const char *name)
{
- int retVal;
+ int retVal = ioctl(fd, request, parm);
- if (!options[OptVerbose]) return ioctl(fd, request, parm);
- retVal = ioctl(fd, request, parm);
+ if (retVal < 0) {
+ app_result = -1;
+ }
+ if (!options[OptVerbose]) return retVal;
printf("%s: ", name);
if (retVal < 0)
printf("failed: %s\n", strerror(errno));
@@ -1068,9 +1069,7 @@ static void do_crop(int fd, unsigned int set_crop, struct v4l2_rect &vcrop, v4l2
struct v4l2_crop in_crop;
in_crop.type = type;
- if (ioctl(fd, VIDIOC_G_CROP, &in_crop) < 0)
- fprintf(stderr, "ioctl: VIDIOC_G_CROP failed\n");
- else {
+ if (doioctl(fd, VIDIOC_G_CROP, &in_crop, "VIDIOC_G_CROP") == 0) {
if (set_crop & CropWidth)
in_crop.c.width = vcrop.width;
if (set_crop & CropHeight)
@@ -1079,8 +1078,7 @@ static void do_crop(int fd, unsigned int set_crop, struct v4l2_rect &vcrop, v4l2
in_crop.c.left = vcrop.left;
if (set_crop & CropTop)
in_crop.c.top = vcrop.top;
- if (ioctl(fd, VIDIOC_S_CROP, &in_crop) < 0)
- fprintf(stderr, "ioctl: VIDIOC_S_CROP failed\n");
+ doioctl(fd, VIDIOC_S_CROP, &in_crop, "VIDIOC_S_CROP");
}
}
@@ -1603,43 +1601,35 @@ int main(int argc, char **argv)
struct v4l2_tuner vt;
memset(&vt, 0, sizeof(struct v4l2_tuner));
- if (ioctl(fd, VIDIOC_G_TUNER, &vt) < 0) {
- fprintf(stderr, "ioctl: VIDIOC_G_TUNER failed\n");
- exit(1);
+ if (doioctl(fd, VIDIOC_G_TUNER, &vt, "VIDIOC_G_TUNER") == 0) {
+ vt.audmode = mode;
+ doioctl(fd, VIDIOC_S_TUNER, &vt, "VIDIOC_S_TUNER");
}
- vt.audmode = mode;
- doioctl(fd, VIDIOC_S_TUNER, &vt, "VIDIOC_S_TUNER");
}
if (options[OptSetVideoFormat]) {
struct v4l2_format in_vfmt;
- printf("ioctl: VIDIOC_S_FMT\n");
+
in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
- fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
- else {
+ if (doioctl(fd, VIDIOC_G_FMT, &in_vfmt, "VIDIOC_G_FMT") == 0) {
if (set_fmts & FmtWidth)
in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
if (set_fmts & FmtHeight)
in_vfmt.fmt.pix.height = vfmt.fmt.pix.height;
- if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
- fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
}
}
if (options[OptSetVideoOutFormat]) {
struct v4l2_format in_vfmt;
- printf("ioctl: VIDIOC_S_FMT\n");
+
in_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
- fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
- else {
+ if (doioctl(fd, VIDIOC_G_FMT, &in_vfmt, "VIDIOC_G_FMT") == 0) {
if (set_fmts_out & FmtWidth)
in_vfmt.fmt.pix.width = vfmt_out.fmt.pix.width;
if (set_fmts_out & FmtHeight)
in_vfmt.fmt.pix.height = vfmt_out.fmt.pix.height;
- if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
- fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
}
}
@@ -1669,29 +1659,24 @@ int main(int argc, char **argv)
if (options[OptSetOutputOverlayFormat]) {
struct v4l2_format fmt;
- memset(&fmt, 0, sizeof(fmt));
+
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
- if (ioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") < 0)
- fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
- else {
+ if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0) {
if (set_overlay_fmt_out & FmtChromaKey)
fmt.fmt.win.chromakey = overlay_fmt_out.fmt.win.chromakey;
if (set_overlay_fmt_out & FmtGlobalAlpha)
fmt.fmt.win.global_alpha = overlay_fmt_out.fmt.win.global_alpha;
- if (ioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT") < 0)
- fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
}
}
if (options[OptSetFBuf]) {
struct v4l2_framebuffer fb;
- if (ioctl(fd, VIDIOC_G_FBUF, &fb, "VIDIOC_G_FBUF") < 0)
- fprintf(stderr, "ioctl: VIDIOC_G_FBUF failed\n");
- else {
+
+ if (doioctl(fd, VIDIOC_G_FBUF, &fb, "VIDIOC_G_FBUF") == 0) {
fb.flags &= ~set_fbuf;
fb.flags |= fbuf.flags;
- if (ioctl(fd, VIDIOC_S_FBUF, &fb) < 0)
- fprintf(stderr, "ioctl: VIDIOC_S_FBUF failed\n");
+ doioctl(fd, VIDIOC_S_FBUF, &fb, "VIDIOC_S_FBUF");
}
}
@@ -1763,69 +1748,53 @@ int main(int argc, char **argv)
if (options[OptGetVideoFormat]) {
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (doioctl(fd, VIDIOC_G_FMT, &vfmt, "VIDIOC_G_FMT") == 0)
- if (printfmt(vfmt) != 0)
- fprintf(stderr, "error printing result\n");
+ printfmt(vfmt);
}
if (options[OptGetVideoOutFormat]) {
vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out, "VIDIOC_G_FMT") == 0)
- if (printfmt(vfmt_out) != 0)
- fprintf(stderr, "error printing result\n");
+ printfmt(vfmt_out);
}
if (options[OptGetOverlayFormat]) {
struct v4l2_format fmt;
- memset(&fmt, 0, sizeof(fmt));
+
fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0)
- if (printfmt(fmt) != 0)
- fprintf(stderr, "error printing result\n");
+ printfmt(fmt);
}
if (options[OptGetOutputOverlayFormat]) {
struct v4l2_format fmt;
- memset(&fmt, 0, sizeof(fmt));
+
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0)
- if (printfmt(fmt) != 0)
- fprintf(stderr, "error printing result\n");
+ printfmt(fmt);
}
if (options[OptGetSlicedVbiFormat]) {
vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
- if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt,
- "VIDIOC_G_FMT") == 0)
- if (printfmt(vbi_fmt) != 0)
- fprintf(stderr,
- "error printing result\n");
+ if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt, "VIDIOC_G_FMT") == 0)
+ printfmt(vbi_fmt);
}
if (options[OptGetSlicedVbiOutFormat]) {
vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
- if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out,
- "VIDIOC_G_FMT") == 0)
- if (printfmt(vbi_fmt_out) != 0)
- fprintf(stderr,
- "error printing result\n");
+ if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out, "VIDIOC_G_FMT") == 0)
+ printfmt(vbi_fmt_out);
}
if (options[OptGetVbiFormat]) {
raw_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
- if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt,
- "VIDIOC_G_FMT") == 0)
- if (printfmt(raw_fmt) != 0)
- fprintf(stderr,
- "error printing result\n");
+ if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt, "VIDIOC_G_FMT") == 0)
+ printfmt(raw_fmt);
}
if (options[OptGetVbiOutFormat]) {
raw_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT;
- if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt_out,
- "VIDIOC_G_FMT") == 0)
- if (printfmt(raw_fmt_out) != 0)
- fprintf(stderr,
- "error printing result\n");
+ if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt_out, "VIDIOC_G_FMT") == 0)
+ printfmt(raw_fmt_out);
}
if (options[OptGetFBuf]) {
@@ -2188,5 +2157,5 @@ int main(int argc, char **argv)
}
close(fd);
- exit(0);
+ exit(app_result);
}
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
index e55cbb2a8..e24ae7140 100644
--- a/v4l2-apps/util/v4l2-dbg.cpp
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -533,6 +533,9 @@ int main(int argc, char **argv)
case V4L2_IDENT_CX23416:
print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride);
break;
+ case V4L2_IDENT_CX23418:
+ print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride);
+ break;
default:
/* By default print range 0-0xff */
print_regs(fd, &get_reg, 0, 0xff, stride);