diff options
67 files changed, 2822 insertions, 1057 deletions
diff --git a/linux/Documentation/dvb/bt8xx.txt b/linux/Documentation/dvb/bt8xx.txt index 52ed46206..4e7614e60 100644 --- a/linux/Documentation/dvb/bt8xx.txt +++ b/linux/Documentation/dvb/bt8xx.txt @@ -1,118 +1,78 @@ -How to get the Nebula, PCTV, FusionHDTV Lite and Twinhan DST cards working -========================================================================== +How to get the bt8xx cards working +================================== -This class of cards has a bt878a as the PCI interface, and -require the bttv driver. +1) General information +====================== -Please pay close attention to the warning about the bttv module -options below for the DST card. +This class of cards has a bt878a as the PCI interface, and require the bttv driver +for accessing the i2c bus and the gpio pins of the bt8xx chipset. +Please see Documentation/dvb/cards.txt => o Cards based on the Conexant Bt8xx PCI bridge: -1) General informations -======================= - -These drivers require the bttv driver to provide the means to access -the i2c bus and the gpio pins of the bt8xx chipset. - -Because of this, you need to enable -"Device drivers" => "Multimedia devices" - => "Video For Linux" => "BT848 Video For Linux" - -Furthermore you need to enable -"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices" - => "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards" +Compiling kernel please enable: +a.)"Device drivers" => "Multimedia devices" => "Video For Linux" => "BT848 Video For Linux" +b.)"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices" + => "DVB for Linux" "DVB Core Support" "Bt8xx based PCI Cards" 2) Loading Modules ================== -In general you need to load the bttv driver, which will handle the gpio and -i2c communication for us, plus the common dvb-bt8xx device driver. -The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110), TwinHan (dst), -FusionHDTV DVB-T Lite (mt352) and FusionHDTV5 Lite (lgdt330x) are loaded -automatically by the dvb-bt8xx device driver. - -3a) Nebula / Pinnacle PCTV / FusionHDTV Lite ---------------------------------------------- - - $ modprobe bttv (normally bttv is being loaded automatically by kmod) - $ modprobe dvb-bt8xx - -(or just place dvb-bt8xx in /etc/modules for automatic loading) - - -3b) TwinHan and Clones --------------------------- +In default cases bttv is loaded automatically. +To load the backend either place dvb-bt8xx in etc/modules, or apply manually: - $ modprobe bttv card=0x71 - $ modprobe dvb-bt8xx - $ modprobe dst + $ modprobe dvb-bt8xx -The value 0x71 will override the PCI type detection for dvb-bt8xx, -which is necessary for TwinHan cards. Omission of this parameter might result -in a system lockup. +All frontends will be loaded automatically. +People running udev please see Documentation/dvb/udev.txt. -If you're having an older card (blue color PCB) and card=0x71 locks up -your machine, try using 0x68, too. If that does not work, ask on the -mailing list. +In the following cases overriding the PCI type detection for dvb-bt8xx might be necessary: -The DST module takes a couple of useful parameters. +2a) Running TwinHan and Clones +------------------------------ -verbose takes values 0 to 4. These values control the verbosity level, -and can be used to debug also. + $ modprobe bttv card=113 + $ modprobe dvb-bt8xx + $ modprobe dst -verbose=0 means complete disabling of messages - 1 only error messages are displayed - 2 notifications are also displayed - 3 informational messages are also displayed - 4 debug setting +Useful parameters for verbosity level and debugging the dst module: -dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card. -0x20 means it has a Conditional Access slot. +verbose=0: messages are disabled + 1: only error messages are displayed + 2: notifications are displayed + 3: other useful messages are displayed + 4: debug setting +dst_addons=0: card is a free to air (FTA) card only + 0x20: card has a conditional access slot for scrambled channels -The autodetected values are determined by the cards 'response string' -which you can see in your logs e.g. +The autodetected values are determined by the cards' "response string". +In your logs see f. ex.: dst_get_device_id: Recognize [DSTMCI]. +For bug reports please send in a complete log with verbose=4 activated. +Please also see Documentation/dvb/ci.txt. -dst_get_device_id: Recognise [DSTMCI] - -If you need to sent in bug reports on the dst, please do send in a complete -log with the verbose=4 module parameter. For general usage, the default setting -of verbose=1 is ideal. - - -4) Multiple cards +2b) Running multiple cards -------------------------- -If you happen to be running multiple cards, it would be advisable to load -the bttv module with the card id. This would help to solve any module loading -problems that you might face. - -For example, if you have a Twinhan and Clones card along with a FusionHDTV5 Lite +Examples of card ID's: - $ modprobe bttv card=0x71 card=0x87 - -Here the order of the card id is important and should be the same as that of the -physical order of the cards. Here card=0x71 represents the Twinhan and clones -and card=0x87 represents Fusion HDTV5 Lite. These arguments can also be -specified in decimal, rather than hex: +Pinnacle PCTV Sat: 94 +Nebula Electronics Digi TV: 104 +pcHDTV HD-2000 TV: 112 +Twinhan DST and clones: 113 +Avermedia AverTV DVB-T 771: 123 +Avermedia AverTV DVB-T 761: 124 +DViCO FusionHDTV DVB-T Lite: 128 +DViCO FusionHDTV 5 Lite: 135 +Notice: The order of the card ID should be uprising: +Example: $ modprobe bttv card=113 card=135 + $ modprobe dvb-bt8xx -Some examples of card-id's - -Pinnacle Sat 0x5e (94) -Nebula Digi TV 0x68 (104) -PC HDTV 0x70 (112) -Twinhan 0x71 (113) -FusionHDTV DVB-T Lite 0x80 (128) -FusionHDTV5 Lite 0x87 (135) - -For a full list of card-id's, see the V4L Documentation within the kernel -source: linux/Documentation/video4linux/CARDLIST.bttv - -If you have problems with this please do ask on the mailing list. +For a full list of card ID's please see Documentation/video4linux/CARDLIST.bttv. +In case of further problems send questions to the mailing list: www.linuxdvb.org. --- Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, + Uwe Bugla, Michael Krufky diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c index fd9163d4b..2dde5a240 100644 --- a/linux/drivers/media/common/saa7146_fops.c +++ b/linux/drivers/media/common/saa7146_fops.c @@ -51,14 +51,15 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) /********************************************************************************/ /* common dma functions */ -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) +void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, + struct saa7146_buf *buf) { DEB_EE(("dev:%p, buf:%p\n",dev,buf)); BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); buf->vb.state = STATE_NEEDS_INIT; } diff --git a/linux/drivers/media/common/saa7146_vbi.c b/linux/drivers/media/common/saa7146_vbi.c index 3d403a760..510594fbd 100644 --- a/linux/drivers/media/common/saa7146_vbi.c +++ b/linux/drivers/media/common/saa7146_vbi.c @@ -237,7 +237,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e } if (buf->vb.size != size) - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); if (STATE_NEEDS_INIT == buf->vb.state) { buf->vb.width = llength; @@ -248,7 +248,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e saa7146_pgtable_free(dev->pci, &buf->pt[2]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); - err = videobuf_iolock(dev->pci,&buf->vb, NULL); + err = videobuf_iolock(q,&buf->vb, NULL); if (err) goto oops; err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen); @@ -262,7 +262,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e oops: DEB_VBI(("error out.\n")); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); return err; } @@ -302,7 +302,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_VBI(("vb:%p\n",vb)); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } static struct videobuf_queue_ops vbi_qops = { diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 4f1ccaee7..e24edb892 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -1276,7 +1276,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.field != field || buf->vb.field != fh->video_fmt.field || buf->fmt != &fh->video_fmt) { - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -1305,7 +1305,7 @@ static int buffer_prepare(struct videobuf_queue *q, saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); } - err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb); + err = videobuf_iolock(q,&buf->vb, &vv->ov_fb); if (err) goto oops; err = saa7146_pgtable_build(dev,buf); @@ -1319,7 +1319,7 @@ static int buffer_prepare(struct videobuf_queue *q, oops: DEB_D(("error out.\n")); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); return err; } @@ -1364,7 +1364,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_CAP(("vbuf:%p\n",vb)); - saa7146_dma_free(dev,buf); + saa7146_dma_free(dev,q,buf); } static struct videobuf_queue_ops video_qops = { diff --git a/linux/drivers/media/dvb/bt8xx/Makefile b/linux/drivers/media/dvb/bt8xx/Makefile index d188e4c67..9d197efb4 100644 --- a/linux/drivers/media/dvb/bt8xx/Makefile +++ b/linux/drivers/media/dvb/bt8xx/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c index 10ed8b8c0..57ab7b0f3 100644 --- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -523,6 +523,9 @@ static int cinergyt2_open (struct inode *inode, struct file *file) static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) { + dvb_net_release(&cinergyt2->dvbnet); + dvb_dmxdev_release(&cinergyt2->dmxdev); + dvb_dmx_release(&cinergyt2->demux); dvb_unregister_device(cinergyt2->fedev); dvb_unregister_adapter(&cinergyt2->adapter); @@ -955,6 +958,7 @@ static int cinergyt2_probe (struct usb_interface *intf, return 0; bailout: + dvb_net_release(&cinergyt2->dvbnet); dvb_dmxdev_release(&cinergyt2->dmxdev); dvb_dmx_release(&cinergyt2->demux); dvb_unregister_adapter(&cinergyt2->adapter); diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index a1a894d81..94233168d 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -161,7 +161,7 @@ comment "ATSC (North American/Korean Terresterial DTV) frontends" depends on DVB_CORE config DVB_NXT200X - tristate "Nextwave NXT2002/NXT2004 based" + tristate "NxtWave Communications NXT2002/NXT2004 based" depends on DVB_CORE select FW_LOADER help @@ -175,14 +175,14 @@ config DVB_NXT200X or /lib/firmware (depending on configuration of firmware hotplug). config DVB_OR51211 - tristate "or51211 based (pcHDTV HD2000 card)" + tristate "Oren OR51211 based" depends on DVB_CORE select FW_LOADER help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. config DVB_OR51132 - tristate "OR51132 based (pcHDTV HD3000 card)" + tristate "Oren OR51132 based" depends on DVB_CORE select FW_LOADER help diff --git a/linux/drivers/media/dvb/frontends/bsru6.h b/linux/drivers/media/dvb/frontends/bsru6.h new file mode 100644 index 000000000..2a5366ce7 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/bsru6.h @@ -0,0 +1,140 @@ +/* + * bsru6.h - ALPS BSRU6 tuner support (moved from budget-ci.c) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef BSRU6_H +#define BSRU6_H + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 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 */ + 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, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(i2c, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +#endif diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index c1510ebb8..10bb871fa 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 1 -void zl10353_dump_regs(struct dvb_frontend *fe) +static void zl10353_dump_regs(struct dvb_frontend *fe) { struct zl10353_state *state = fe->demodulator_priv; char buf[52], buf2[4]; diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 106022c39..87741cf17 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -68,6 +68,7 @@ #include "bsbe1.h" #include "lnbp21.h" +#include "bsru6.h" #define TS_WIDTH 376 #define TS_HEIGHT 512 @@ -84,6 +85,8 @@ static int hw_sections; static int rgb_on; static int volume = 255; static int budgetpatch; +static int wss_cfg_4_3 = 0x4008; +static int wss_cfg_16_9 = 0x0007; module_param_named(debug, av7110_debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); @@ -102,6 +105,10 @@ module_param(volume, int, 0444); MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); module_param(budgetpatch, int, 0444); MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); +module_param(wss_cfg_4_3, int, 0444); +MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); +module_param(wss_cfg_16_9, int, 0444); +MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data"); static void restart_feeds(struct av7110 *av7110); @@ -127,6 +134,13 @@ static void init_av7110_av(struct av7110 *av7110) if (ret < 0) printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret); + ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3); + if (ret < 0) + printk("dvb-ttpci: unable to configure 4:3 wss\n"); + ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9); + if (ret < 0) + printk("dvb-ttpci: unable to configure 16:9 wss\n"); + ret = av7710_set_video_mode(av7110, vidmode); if (ret < 0) printk("dvb-ttpci:cannot set video mode:%d\n",ret); @@ -1570,109 +1584,6 @@ static struct ves1x93_config alps_bsrv2_config = { .pll_set = alps_bsrv2_pll_set, }; - -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x30, - 0x03, 0x00, - 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 */ - 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, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg(fe, 0x13, aclk); - stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg(fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - int ret; - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - ret = i2c_transfer(i2c, &msg, 1); - if (ret != 1) - return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct av7110* av7110 = fe->dvb->priv; diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index 94cf38c7e..2f23ceab8 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -579,14 +579,11 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size return -EFAULT; if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23) return -EINVAL; - if (d.id) { + if (d.id) av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0]; - rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, - 2, 1, av7110->wssData); - } else { - av7110->wssData = 0; - rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0); - } + else + av7110->wssData = 0x8000; + rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData); return (rc < 0) ? rc : count; } diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 09b972b9f..5f91036f5 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -44,6 +44,7 @@ #include "tda1004x.h" #include "lnbp21.h" #include "bsbe1.h" +#include "bsru6.h" #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 @@ -476,123 +477,6 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) tasklet_schedule(&budget_ci->ciintf_irq_tasklet); } - -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 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 */ - 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, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { - aclk = 0xb7; - bclk = 0x47; - } else if (srate < 3000000) { - aclk = 0xb7; - bclk = 0x4b; - } else if (srate < 7000000) { - aclk = 0xb7; - bclk = 0x4f; - } else if (srate < 14000000) { - aclk = 0xb7; - bclk = 0x53; - } else if (srate < 30000000) { - aclk = 0xb6; - bclk = 0x53; - } else if (srate < 45000000) { - aclk = 0xb4; - bclk = 0x51; - } - - stv0299_writereg(fe, 0x13, aclk); - stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg(fe, 0x21, (ratio) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) -{ - u8 buf[4]; - u32 div; - struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - buf[3] = 0xC4; - - if (params->frequency > 1530000) - buf[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) - return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - - - - static u8 philips_su1278_tt_inittab[] = { 0x01, 0x0f, 0x02, 0x30, diff --git a/linux/drivers/media/dvb/ttpci/budget-patch.c b/linux/drivers/media/dvb/ttpci/budget-patch.c index 4f0fcc575..5ea95da4f 100644 --- a/linux/drivers/media/dvb/ttpci/budget-patch.c +++ b/linux/drivers/media/dvb/ttpci/budget-patch.c @@ -37,6 +37,8 @@ #include "ves1x93.h" #include "tda8083.h" +#include "bsru6.h" + #define budget_patch budget static struct saa7146_extension budget_extension; @@ -290,103 +292,6 @@ static struct ves1x93_config alps_bsrv2_config = { .pll_set = alps_bsrv2_pll_set, }; -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 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 */ - 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, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index bfb809250..c23c02d95 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -42,6 +42,7 @@ #include "tda8083.h" #include "s5h1420.h" #include "lnbp21.h" +#include "bsru6.h" static void Set22K (struct budget *budget, int state) { @@ -220,103 +221,6 @@ static struct ves1x93_config alps_bsrv2_config = .pll_set = alps_bsrv2_pll_set, }; -static u8 alps_bsru6_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 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 */ - 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, 0x52, - 0xff, 0xff -}; - -static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - - return 0; -} - -static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) -{ - u8 data[4]; - u32 div; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; - - div = (params->frequency + (125 - 1)) / 125; // round correctly - data[0] = (div >> 8) & 0x7f; - data[1] = div & 0xff; - data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; - data[3] = 0xC4; - - if (params->frequency > 1530000) data[3] = 0xc0; - - if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO; - return 0; -} - -static struct stv0299_config alps_bsru6_config = { - - .demod_address = 0x68, - .inittab = alps_bsru6_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, -}; - static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 9750ee1bb..762e35670 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -16,31 +16,7 @@ config VIDEO_ADV_DEBUG V4L devices. In doubt, say N. -config VIDEO_BT848 - tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C - select I2C_ALGOBIT - select FW_LOADER - select VIDEO_BTCX - select VIDEO_BUF - select VIDEO_IR - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_MSP3400 - ---help--- - Support for BT848 based frame grabber/overlay boards. This includes - the Miro, Hauppauge and STB boards. Please read the material in - <file:Documentation/video4linux/bttv/> for more information. - - To compile this driver as a module, choose M here: the - module will be called bttv. - -config VIDEO_BT848_DVB - bool "DVB/ATSC Support for bt878 based TV cards" - depends on VIDEO_BT848 && DVB_CORE - select DVB_BT8XX - ---help--- - This adds support for DVB/ATSC cards based on the BT878 chip. +source "drivers/media/video/bt8xx/Kconfig" config VIDEO_SAA6588 tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" @@ -344,14 +320,6 @@ config VIDEO_M32R_AR_M64278 Say Y here to use the Renesas M64278E-800 camera module, which supports VGA(640x480 pixcels) size of images. -config VIDEO_AUDIO_DECODER - tristate "Add support for additional audio chipsets" - depends on VIDEO_DEV && I2C && EXPERIMENTAL - select VIDEO_MSP3400 - ---help--- - Say Y here to compile drivers for WM8775, CS53L32A and - MSP34xx audio decoders. - config VIDEO_MSP3400 tristate "Micronas MSP34xx audio decoders" depends on VIDEO_DEV && I2C @@ -361,14 +329,44 @@ config VIDEO_MSP3400 To compile this driver as a module, choose M here: the module will be called msp3400 -config VIDEO_DECODER - tristate "Add support for additional video chipsets" +config VIDEO_CS53L32A + tristate "Cirrus Logic CS53L32A audio ADC" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Cirrus Logic CS53L32A low voltage + stereo A/D converter. + + To compile this driver as a module, choose M here: the + module will be called cs53l32a + +config VIDEO_WM8775 + tristate "Wolfson Microelectronics WM8775 audio ADC" depends on VIDEO_DEV && I2C && EXPERIMENTAL - select VIDEO_CX25840 ---help--- - Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 - video decoders. + Support for the Wolfson Microelectronics WM8775 + high performance stereo A/D Converter. + + To compile this driver as a module, choose M here: the + module will be called wm8775 source "drivers/media/video/cx25840/Kconfig" +config VIDEO_SAA711X + tristate "Philips SAA7113/4/5 video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Philips SAA7113/4/5 video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa7115 + +config VIDEO_SAA7127 + tristate "Philips SAA7127/9 digital video encoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Philips SAA7127/9 digital video encoders. + + To compile this driver as a module, choose M here: the + module will be called saa7127 + endmenu diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index ea0c029fb..27e7b37b1 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -2,9 +2,6 @@ # Makefile for the video capture/playback device drivers. # -bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ - bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ - bttv-input.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o @@ -15,8 +12,8 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o -obj-$(CONFIG_VIDEO_BT848) += bttv.o tvaudio.o \ - tda7432.o tda9875.o ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_BT848) += bt8xx/ +obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o @@ -44,10 +41,11 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o +obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o -obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o +obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o +obj-$(CONFIG_VIDEO_WM8775) += wm8775.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o @@ -64,7 +62,8 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o -obj-$(CONFIG_VIDEO_DECODER) += saa7115.o saa7127.o obj-$(CONFIG_VIDEO_CX25840) += cx25840/ +obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o +obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig new file mode 100644 index 000000000..085477c12 --- /dev/null +++ b/linux/drivers/media/video/bt8xx/Kconfig @@ -0,0 +1,25 @@ +config VIDEO_BT848 + tristate "BT848 Video For Linux" + depends on VIDEO_DEV && PCI && I2C + select I2C_ALGOBIT + select FW_LOADER + select VIDEO_BTCX + select VIDEO_BUF + select VIDEO_IR + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_MSP3400 + ---help--- + Support for BT848 based frame grabber/overlay boards. This includes + the Miro, Hauppauge and STB boards. Please read the material in + <file:Documentation/video4linux/bttv/> for more information. + + To compile this driver as a module, choose M here: the + module will be called bttv. + +config VIDEO_BT848_DVB + bool "DVB/ATSC Support for bt878 based TV cards" + depends on VIDEO_BT848 && DVB_CORE + select DVB_BT8XX + ---help--- + This adds support for DVB/ATSC cards based on the BT878 chip. diff --git a/linux/drivers/media/video/bt832.c b/linux/drivers/media/video/bt8xx/bt832.c index b155bbe91..b155bbe91 100644 --- a/linux/drivers/media/video/bt832.c +++ b/linux/drivers/media/video/bt8xx/bt832.c diff --git a/linux/drivers/media/video/bt832.h b/linux/drivers/media/video/bt8xx/bt832.h index 1ce8fa71f..1ce8fa71f 100644 --- a/linux/drivers/media/video/bt832.h +++ b/linux/drivers/media/video/bt8xx/bt832.h diff --git a/linux/drivers/media/video/bt848.h b/linux/drivers/media/video/bt8xx/bt848.h index 0bcd95303..0bcd95303 100644 --- a/linux/drivers/media/video/bt848.h +++ b/linux/drivers/media/video/bt8xx/bt848.h diff --git a/linux/drivers/media/video/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 47131de0d..47131de0d 100644 --- a/linux/drivers/media/video/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c diff --git a/linux/drivers/media/video/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 46aec8404..0b321480b 100644 --- a/linux/drivers/media/video/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1423,7 +1423,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, free_btres(btv,fh,RESOURCE_OVERLAY); if (NULL != old) { dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); - bttv_dma_free(btv, old); + bttv_dma_free(&fh->cap,btv, old); kfree(old); } dprintk("switch_overlay: done\n"); @@ -1433,7 +1433,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, /* ----------------------------------------------------------------------- */ /* video4linux (1) interface */ -static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, +static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, + struct bttv_buffer *buf, const struct bttv_format *fmt, unsigned int width, unsigned int height, enum v4l2_field field) @@ -1476,7 +1477,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, /* alloc risc memory */ if (STATE_NEEDS_INIT == buf->vb.state) { redo_dma_risc = 1; - if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) goto fail; } @@ -1488,7 +1489,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, return 0; fail: - bttv_dma_free(btv,buf); + bttv_dma_free(q,btv,buf); return rc; } @@ -1512,7 +1513,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_fh *fh = q->priv_data; - return bttv_prepare_buffer(fh->btv, buf, fh->fmt, + return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt, fh->width, fh->height, field); } @@ -1536,7 +1537,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_fh *fh = q->priv_data; - bttv_dma_free(fh->btv,buf); + bttv_dma_free(&fh->cap,fh->btv,buf); } static struct videobuf_queue_ops bttv_video_qops = { @@ -2522,7 +2523,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; - retval = bttv_prepare_buffer(btv,buf, + retval = bttv_prepare_buffer(&fh->cap,btv,buf, format_by_palette(vm->format), vm->width,vm->height,field); if (0 != retval) @@ -2554,8 +2555,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, retval = -EIO; /* fall through */ case STATE_DONE: - videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma); - bttv_dma_free(btv,buf); + videobuf_dma_sync(&fh->cap,&buf->vb.dma); + bttv_dma_free(&fh->cap,btv,buf); break; default: retval = -EINVAL; diff --git a/linux/drivers/media/video/bttv-gpio.c b/linux/drivers/media/video/bt8xx/bttv-gpio.c index 8682662b3..8682662b3 100644 --- a/linux/drivers/media/video/bttv-gpio.c +++ b/linux/drivers/media/video/bt8xx/bttv-gpio.c diff --git a/linux/drivers/media/video/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 87e6d867a..87e6d867a 100644 --- a/linux/drivers/media/video/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c diff --git a/linux/drivers/media/video/bttv-if.c b/linux/drivers/media/video/bt8xx/bttv-if.c index d264e0e53..d264e0e53 100644 --- a/linux/drivers/media/video/bttv-if.c +++ b/linux/drivers/media/video/bt8xx/bttv-if.c diff --git a/linux/drivers/media/video/bttv-input.c b/linux/drivers/media/video/bt8xx/bttv-input.c index 8a619ddb1..8a619ddb1 100644 --- a/linux/drivers/media/video/bttv-input.c +++ b/linux/drivers/media/video/bt8xx/bttv-input.c diff --git a/linux/drivers/media/video/bttv-risc.c b/linux/drivers/media/video/bt8xx/bttv-risc.c index 148e86a79..53dfe0f4d 100644 --- a/linux/drivers/media/video/bttv-risc.c +++ b/linux/drivers/media/video/bt8xx/bttv-risc.c @@ -514,11 +514,11 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, } void -bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) +bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); btcx_riscmem_free(btv->c.pci,&buf->bottom); btcx_riscmem_free(btv->c.pci,&buf->top); diff --git a/linux/drivers/media/video/bttv-vbi.c b/linux/drivers/media/video/bt8xx/bttv-vbi.c index d10d81f77..136218014 100644 --- a/linux/drivers/media/video/bttv-vbi.c +++ b/linux/drivers/media/video/bt8xx/bttv-vbi.c @@ -97,7 +97,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, return -EINVAL; if (STATE_NEEDS_INIT == buf->vb.state) { - if (0 != (rc = videobuf_iolock(btv->c.pci, &buf->vb, NULL))) + if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL))) goto fail; if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) goto fail; @@ -110,7 +110,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q, return 0; fail: - bttv_dma_free(btv,buf); + bttv_dma_free(q,btv,buf); return rc; } @@ -137,7 +137,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); dprintk("free %p\n",vb); - bttv_dma_free(fh->btv,buf); + bttv_dma_free(&fh->cap,fh->btv,buf); } struct videobuf_queue_ops bttv_vbi_qops = { diff --git a/linux/drivers/media/video/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index bdc3a19e3..bdc3a19e3 100644 --- a/linux/drivers/media/video/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h diff --git a/linux/drivers/media/video/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 5d92d713e..d5469ad2b 100644 --- a/linux/drivers/media/video/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -200,7 +200,8 @@ int bttv_buffer_activate_video(struct bttv *btv, struct bttv_buffer_set *set); int bttv_buffer_activate_vbi(struct bttv *btv, struct bttv_buffer *vbi); -void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); +void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv, + struct bttv_buffer *buf); /* overlay handling */ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, diff --git a/linux/drivers/media/video/cpia2/Kconfig b/linux/drivers/media/video/cpia2/Kconfig index 1c09ef981..513cc0927 100644 --- a/linux/drivers/media/video/cpia2/Kconfig +++ b/linux/drivers/media/video/cpia2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CPIA2 tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV + depends on VIDEO_DEV && USB ---help--- This is the video4linux driver for cameras based on Vision's CPiA2 (Colour Processor Interface ASIC), such as the Digital Blue QX5 diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index b52a243c3..e140996e6 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -15,20 +15,6 @@ config VIDEO_CX88 To compile this driver as a module, choose M here: the module will be called cx8800 -config VIDEO_CX88_DVB - tristate "DVB/ATSC Support for cx2388x based TV cards" - depends on VIDEO_CX88 && DVB_CORE - select VIDEO_BUF_DVB - ---help--- - This adds support for DVB/ATSC cards based on the - Connexant 2388x chip. - - To compile this driver as a module, choose M here: the - module will be called cx88-dvb. - - You must also select one or more DVB/ATSC demodulators. - If you are unsure which you need, choose all of them. - config VIDEO_CX88_ALSA tristate "ALSA DMA audio support" depends on VIDEO_CX88 && SND && EXPERIMENTAL @@ -44,6 +30,20 @@ config VIDEO_CX88_ALSA To compile this driver as a module, choose M here: the module will be called cx88-alsa. +config VIDEO_CX88_DVB + tristate "DVB/ATSC Support for cx2388x based TV cards" + depends on VIDEO_CX88 && DVB_CORE + select VIDEO_BUF_DVB + ---help--- + This adds support for DVB/ATSC cards based on the + Connexant 2388x chip. + + To compile this driver as a module, choose M here: the + module will be called cx88-dvb. + + You must also select one or more DVB/ATSC demodulators. + If you are unsure which you need, choose all of them. + config VIDEO_CX88_DVB_ALL_FRONTENDS bool "Build all supported frontends for cx2388x based TV cards" default y diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index e6cc40e04..8ecdb41af 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -317,7 +317,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); + videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc); videobuf_dma_free(&chip->dma_risc); btcx_riscmem_free(chip->pci,&chip->buf->risc); kfree(chip->buf); @@ -443,7 +443,7 @@ static int snd_cx88_hw_params(snd_pcm_substream_t * substream, videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); - videobuf_dma_pci_map(chip->pci,&buf->vb.dma); + videobuf_pci_dma_map(chip->pci,&buf->vb.dma); cx88_risc_databuffer(chip->pci, &buf->risc, diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index fc4cadeaf..0ffef13d5 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -1361,7 +1361,7 @@ bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_fh *fh = q->priv_data; - return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb, field); + return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field); } static void @@ -1374,8 +1374,7 @@ bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx8802_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb); + cx88_free_buffer(q, (struct cx88_buffer*)vb); } static struct videobuf_queue_ops blackbird_qops = { diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index e8bf7cf7c..9636dedcf 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -230,13 +230,13 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, } void -cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) +cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); - btcx_riscmem_free(pci, &buf->risc); + btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); buf->vb.state = STATE_NEEDS_INIT; } diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 4abad5835..2fdabe2f2 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -92,7 +92,7 @@ static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_dev *dev = q->priv_data; - return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field); + return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); } static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) @@ -103,8 +103,7 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx8802_dev *dev = q->priv_data; - cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb); + cx88_free_buffer(q, (struct cx88_buffer*)vb); } static struct videobuf_queue_ops dvb_qops = { diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 7d811004d..e0f9db668 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -216,8 +216,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, /* ------------------------------------------------------------------ */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, - enum v4l2_field field) +int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, + struct cx88_buffer *buf, enum v4l2_field field) { int size = dev->ts_packet_size * dev->ts_packet_count; int rc; @@ -232,7 +232,7 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, buf->vb.size = size; buf->vb.field = field /*V4L2_FIELD_TOP*/; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_databuffer(dev->pci, &buf->risc, buf->vb.dma.sglist, @@ -242,27 +242,27 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) { struct cx88_buffer *prev; - struct cx88_dmaqueue *q = &dev->mpegq; + struct cx88_dmaqueue *cx88q = &dev->mpegq; dprintk( 1, "cx8802_buf_queue\n" ); /* add jump to stopper */ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); - if (list_empty(&q->active)) { + if (list_empty(&cx88q->active)) { dprintk( 0, "queue is empty - first active\n" ); - list_add_tail(&buf->vb.queue,&q->active); - cx8802_start_dma(dev, q, buf); + list_add_tail(&buf->vb.queue,&cx88q->active); + cx8802_start_dma(dev, cx88q, buf); buf->vb.state = STATE_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + buf->count = cx88q->count++; + mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); dprintk(0,"[%p/%d] %s - first active\n", buf, buf->vb.i, __FUNCTION__); #if 0 @@ -271,10 +271,10 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) } else { dprintk( 1, "queue is not empty - append to active\n" ); - prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue); + list_add_tail(&buf->vb.queue,&cx88q->active); buf->vb.state = STATE_ACTIVE; - buf->count = q->count++; + 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__); diff --git a/linux/drivers/media/video/cx88/cx88-vbi.c b/linux/drivers/media/video/cx88/cx88-vbi.c index 800624d7c..bb5ae86c8 100644 --- a/linux/drivers/media/video/cx88/cx88-vbi.c +++ b/linux/drivers/media/video/cx88/cx88-vbi.c @@ -177,7 +177,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, buf->vb.size = size; buf->vb.field = V4L2_FIELD_SEQ_TB; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_buffer(dev->pci, &buf->risc, buf->vb.dma.sglist, @@ -189,7 +189,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } @@ -229,9 +229,8 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx8800_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci,buf); + cx88_free_buffer(q,buf); } struct videobuf_queue_ops cx8800_vbi_qops = { diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 4484744bc..1bcd20d23 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -590,7 +590,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (STATE_NEEDS_INIT == buf->vb.state) { init_buffer = 1; - if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) + if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; } @@ -640,7 +640,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; fail: - cx88_free_buffer(dev->pci,buf); + cx88_free_buffer(q,buf); return rc; } @@ -697,9 +697,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx8800_fh *fh = q->priv_data; - cx88_free_buffer(fh->dev->pci,buf); + cx88_free_buffer(q,buf); } static struct videobuf_queue_ops cx8800_video_qops = { @@ -1512,9 +1511,17 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, { int err; - dprintk(2, "CORE IOCTL: 0x%x\n", cmd ); - if (video_debug > 1) - v4l_print_ioctl(core->name,cmd); + if (video_debug) { + if (video_debug > 1) { + if (_IOC_DIR(cmd) & _IOC_WRITE) + v4l_printk_ioctl_arg("cx88(w)",cmd, arg); + else if (!_IOC_DIR(cmd) & _IOC_READ) { + v4l_print_ioctl("cx88", cmd); + } + } else + v4l_print_ioctl(core->name,cmd); + + } switch (cmd) { /* ---------- tv norms ---------- */ @@ -1751,7 +1758,19 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return video_usercopy(inode, file, cmd, arg, video_do_ioctl); + int retval; + + retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl); + + if (video_debug > 1) { + if (retval < 0) { + v4l_print_ioctl("cx88(err)", cmd); + printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval); + } else if (_IOC_DIR(cmd) & _IOC_READ) + v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg); + } + + return retval; } /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index a03be58aa..889ca7c61 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -526,7 +526,7 @@ extern int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value); extern void -cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf); +cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf); extern void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc); @@ -618,8 +618,8 @@ void cx88_ir_irq(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, - enum v4l2_field field); +int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev, + struct cx88_buffer *buf, enum v4l2_field field); void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); void cx8802_cancel_buffers(struct cx8802_dev *dev); diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig index 885fd0170..5a793ae7c 100644 --- a/linux/drivers/media/video/em28xx/Kconfig +++ b/linux/drivers/media/video/em28xx/Kconfig @@ -5,6 +5,7 @@ config VIDEO_EM28XX select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR + select VIDEO_SAA711X ---help--- This is a video4linux driver for Empia 28xx based TV cards. diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index cfae6f999..64d395472 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -121,23 +121,6 @@ static struct em28xx_tvnorm tvnorms[] = { } }; -static const unsigned char saa7114_i2c_init[] = { - 0x00,0x00,0x01,0x08,0x02,0xc4,0x03,0x30,0x04,0x90,0x05,0x90,0x06,0xeb,0x07,0xe0, - 0x08,0x88,0x09,0x40,0x0a,0x80,0x0b,0x44,0x0c,0x40,0x0d,0x00,0x0e,0x81,0x0f,0x2a, - 0x10,0x06,0x11,0x00,0x12,0xc8,0x13,0x80,0x14,0x00,0x15,0x11,0x16,0x01,0x17,0x42, - 0x18,0x40,0x19,0x80,0x40,0x00,0x41,0xff,0x42,0xff,0x43,0xff,0x44,0xff,0x45,0xff, - 0x46,0xff,0x47,0xff,0x48,0xff,0x49,0xff,0x4a,0xff,0x4b,0xff,0x4c,0xff,0x4d,0xff, - 0x4e,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,0x52,0xff,0x53,0xff,0x54,0x5f,0x55,0xff, - 0x56,0xff,0x57,0xff,0x58,0x00,0x59,0x47,0x5a,0x03,0x5b,0x03,0x5d,0x3e,0x5e,0x00, - 0x80,0x1c,0x83,0x01,0x84,0xa5,0x85,0x10,0x86,0x45,0x87,0x41,0x88,0xf0,0x88,0x00, - 0x88,0xf0,0x90,0x00,0x91,0x08,0x92,0x00,0x93,0x80,0x94,0x08,0x95,0x00,0x96,0xc0, - 0x97,0x02,0x98,0x13,0x99,0x00,0x9a,0x38,0x9b,0x01,0x9c,0x80,0x9d,0x02,0x9e,0x06, - 0x9f,0x01,0xa0,0x01,0xa1,0x00,0xa2,0x00,0xa4,0x80,0xa5,0x36,0xa6,0x36,0xa8,0x67, - 0xa9,0x04,0xaa,0x00,0xac,0x33,0xad,0x02,0xae,0x00,0xb0,0xcd,0xb1,0x04,0xb2,0xcd, - 0xb3,0x04,0xb4,0x01,0xb8,0x00,0xb9,0x00,0xba,0x00,0xbb,0x00,0xbc,0x00,0xbd,0x00, - 0xbe,0x00,0xbf,0x00 -}; - #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ @@ -164,77 +147,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = { } }; -/* FIXME: These are specific to saa711x - should be moved to its code */ -static struct v4l2_queryctrl saa711x_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ -#if 0 -/* Control in the saa7113 and not in the em28xx */ - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x10, - .flags = 0, - },{ -#endif - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue chroma balance", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - },{ - .id = V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma", - .minimum = 0x0, - .maximum = 0x3f, - .step = 0x1, - .default_value = 0x20, - .flags = 0, - } -}; - static struct usb_driver em28xx_usb_driver; static DEFINE_MUTEX(em28xx_sysfs_lock); @@ -279,55 +191,9 @@ static int em28xx_config(struct em28xx *dev) static void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_frequency f; - struct video_decoder_init em28xx_vdi = {.data = NULL }; - -#if 0 - if (dev->decoder == EM28XX_SAA7113) { - const unsigned char saa7113_i2c_init[] = { - 0x00, 0x00, /* PH7113_CHIP_VERSION 00 - ID byte */ - 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ - 0x02, 0xc2, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ - 0x03, 0x30, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ - 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ - 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ - 0x06, 0x89, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ - 0x07, 0x0d, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ - 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ - 0x09, 0x01, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ - 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ - 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ - 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ - 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ - 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ - 0x0f, 0x2a, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ - 0x10, 0x08, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ - 0x11, 0x0c, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ - 0x12, 0x07, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ - 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ - 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ - 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ - 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ - 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ - }; - - em28xx_vdi.data = saa7113_i2c_init; - em28xx_vdi.len = sizeof(saa7113_i2c_init); - } -#endif - - /* configure decoder */ - if(dev->model == EM2820_BOARD_MSI_VOX_USB_2){ - em28xx_vdi.data=saa7114_i2c_init; - em28xx_vdi.len=sizeof(saa7114_i2c_init); - } - - - em28xx_i2c_call_clients(dev, DECODER_INIT, &em28xx_vdi); - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); -/* em28xx_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ -/* em28xx_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ -/* em28xx_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ -/* em28xx_i2c_call_clients(dev,DECODER_DUMP, NULL); */ + em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input); + em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); /* configure tuner */ f.tuner = 0; @@ -370,8 +236,7 @@ static void video_mux(struct em28xx *dev, int index) dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - + em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input); em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); @@ -828,43 +693,6 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) -{ - s32 tmp; - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if ((tmp = em28xx_brightness_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_CONTRAST: - if ((ctrl->value = em28xx_contrast_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_SATURATION: - if ((ctrl->value = em28xx_saturation_get(dev)) < 0) - return -EIO; - return 0; - case V4L2_CID_RED_BALANCE: - if ((tmp = em28xx_v_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((tmp = em28xx_u_balance_get(dev)) < 0) - return -EIO; - ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ - return 0; - case V4L2_CID_GAMMA: - if ((ctrl->value = em28xx_gamma_get(dev)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - /* * em28xx_set_ctrl() * mute or set new saturation, brightness or contrast @@ -887,27 +715,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) } } -/*FIXME: should be moved to saa711x */ -static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - return em28xx_brightness_set(dev, ctrl->value); - case V4L2_CID_CONTRAST: - return em28xx_contrast_set(dev, ctrl->value); - case V4L2_CID_SATURATION: - return em28xx_saturation_set(dev, ctrl->value); - case V4L2_CID_RED_BALANCE: - return em28xx_v_balance_set(dev, ctrl->value); - case V4L2_CID_BLUE_BALANCE: - return em28xx_u_balance_set(dev, ctrl->value); - case V4L2_CID_GAMMA: - return em28xx_gamma_set(dev, ctrl->value); - default: - return -EINVAL; - } -} - /* * em28xx_stream_interrupt() * stops streaming @@ -1241,8 +1048,6 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, em28xx_set_norm(dev, dev->width, dev->height); - em28xx_i2c_call_clients(dev, DECODER_SET_NORM, - &tvnorms[i].mode); em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); @@ -1353,24 +1158,11 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,qc); - if (qc->type) - return 0; - else - return -EINVAL; - } -#if 1 /* FIXME: Should be at saa711x */ - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (qc->id && qc->id == saa711x_qctrl[i].id) { - memcpy(qc, &(saa711x_qctrl[i]), - sizeof(*qc)); - return 0; - } - } -#endif - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,qc); + if (qc->type) + return 0; + else + return -EINVAL; } case VIDIOC_G_CTRL: { @@ -1380,12 +1172,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, if (!dev->has_msp34xx) retval=em28xx_get_ctrl(dev, ctrl); if (retval==-EINVAL) { - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } - - return saa711x_get_ctrl(dev, ctrl); + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } else return retval; } case VIDIOC_S_CTRL: @@ -1406,33 +1194,8 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, } } - if (dev->decoder == EM28XX_TVP5150) { - em28xx_i2c_call_clients(dev,cmd,arg); - return 0; - } else if (!dev->has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < - em28xx_qctrl[i].minimum - || ctrl->value > - em28xx_qctrl[i].maximum) - return -ERANGE; - return em28xx_set_ctrl(dev, ctrl); - } - } - for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) { - if (ctrl->id == saa711x_qctrl[i].id) { - if (ctrl->value < - saa711x_qctrl[i].minimum - || ctrl->value > - saa711x_qctrl[i].maximum) - return -ERANGE; - return saa711x_set_ctrl(dev, ctrl); - } - } - } - - return -EINVAL; + em28xx_i2c_call_clients(dev,cmd,arg); + return 0; } /* --- tuner ioctls ------------------------------------------ */ case VIDIOC_G_TUNER: @@ -1924,7 +1687,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) - request_module("saa711x"); + request_module("saa7115"); if (dev->decoder == EM28XX_TVP5150) request_module("tvp5150"); if (dev->has_tuner) diff --git a/linux/drivers/media/video/font.h b/linux/drivers/media/video/font.h new file mode 100644 index 000000000..8b1fecc37 --- /dev/null +++ b/linux/drivers/media/video/font.h @@ -0,0 +1,407 @@ +static unsigned char rom8x16_bits[] = { +/* Character 0 (0x30): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** *** | + |** **** | + |**** ** | + |*** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xce, +0xde, +0xf6, +0xe6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 1 (0x31): + ht=16, width=8 + +--------+ + | | + | | + | ** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x18, +0x78, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x7e, +0x00, +0x00, +0x00, +0x00, + +/* Character 2 (0x32): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + |** ** | + |******* | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0x06, +0x0c, +0x18, +0x30, +0x60, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, + +/* Character 3 (0x33): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0x06, +0x06, +0x3c, +0x06, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 4 (0x34): + ht=16, width=8 + +--------+ + | | + | | + | ** | + | *** | + | **** | + | ** ** | + |** ** | + |** ** | + |******* | + | ** | + | ** | + | **** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x0c, +0x1c, +0x3c, +0x6c, +0xcc, +0xcc, +0xfe, +0x0c, +0x0c, +0x1e, +0x00, +0x00, +0x00, +0x00, + +/* Character 5 (0x35): + ht=16, width=8 + +--------+ + | | + | | + |******* | + |** | + |** | + |** | + |****** | + | ** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0xfe, +0xc0, +0xc0, +0xc0, +0xfc, +0x06, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 6 (0x36): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** | + |** | + |****** | + |** ** | + |** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc0, +0xc0, +0xfc, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 7 (0x37): + ht=16, width=8 + +--------+ + | | + | | + |******* | + |** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0xfe, +0xc6, +0x06, +0x0c, +0x18, +0x30, +0x30, +0x30, +0x30, +0x30, +0x00, +0x00, +0x00, +0x00, + +/* Character 8 (0x38): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** ** | + | ***** | + |** ** | + |** ** | + |** ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, + +/* Character 9 (0x39): + ht=16, width=8 + +--------+ + | | + | | + | ***** | + |** ** | + |** ** | + |** ** | + |** ** | + | ****** | + | ** | + | ** | + |** ** | + | ***** | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7e, +0x06, +0x06, +0xc6, +0x7c, +0x00, +0x00, +0x00, +0x00, +/* Character : (0x3a): + ht=16, width=8 + +--------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | | + | | + | ** | + | ** | + | | + | | + | | + | | + | | + +--------+ */ +0x00, +0x00, +0x00, +0x00, +0x00, +0x0c, +0x0c, +0x00, +0x00, +0x0c, +0x0c, +0x00, +0x00, +0x00, +0x00, +0x00, +}; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 9391d06a0..cedefda72 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -1,7 +1,7 @@ /* mxb - v4l2 driver for the Multimedia eXtension Board - Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> + Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de> Visit http://www.mihu.de/linux/saa7146/mxb/ for further details about this card. @@ -329,6 +329,7 @@ static int mxb_init_done(struct saa7146_dev* dev) struct video_decoder_init init; struct i2c_msg msg; struct tuner_setup tun_setup; + v4l2_std_id std = V4L2_STD_PAL_BG; int i = 0, err = 0; struct tea6415c_multiplex vm; @@ -363,6 +364,9 @@ static int mxb_init_done(struct saa7146_dev* dev) mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); + /* set a default video standard */ + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + /* mute audio on tea6420s */ mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); @@ -923,17 +927,21 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) int one = 1; if(V4L2_STD_PAL_I == std->id ) { + v4l2_std_id std = V4L2_STD_PAL_I; DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } else { + v4l2_std_id std = V4L2_STD_PAL_BG; DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } return 0; } diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 262b033f4..9824ad267 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -4,7 +4,7 @@ config VIDEO_PVRUSB2 select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM - select VIDEO_DECODER + select VIDEO_SAA711X select VIDEO_MSP3400 ---help--- This is a video4linux driver for Conexant 23416 based diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index aa3600ad9..4f70190ca 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1,4 +1,4 @@ -/* saa7115 - Philips SAA7114/SAA7115 video decoder driver +/* saa7115 - Philips SAA7113/SAA7114/SAA7115 video decoder driver * * Based on saa7114 driver by Maxim Yevtyushkin, which is based on * the saa7111 driver by Dave Perks. @@ -16,6 +16,7 @@ * (2/17/2003) * * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> + * SAA7113 support by Mauro Carvalho Chehab <mchehab@infradead.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,8 +47,9 @@ #endif #include <asm/div64.h> -MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); -MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); +MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); +MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " + "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); static int debug = 0; @@ -59,7 +61,10 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { + 0x4a >>1, 0x48 >>1, /* SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */ + I2C_CLIENT_END }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; @@ -112,10 +117,12 @@ static inline int saa7115_read(struct i2c_client *client, u8 reg) Hauppauge driver sets. */ static const unsigned char saa7115_init_auto_input[] = { + /* Front-End Part */ 0x01, 0x48, /* white peak control disabled */ 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ 0x04, 0x90, /* analog gain set to 0 */ 0x05, 0x90, /* analog gain set to 0 */ + /* Decoder Part */ 0x06, 0xeb, /* horiz sync begin = -21 */ 0x07, 0xe0, /* horiz sync stop = -17 */ 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ @@ -134,6 +141,8 @@ static const unsigned char saa7115_init_auto_input[] = { 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ 0x1d, 0x01, /* combfilter control 0x01 = recommended */ + + /* Power Device Control */ 0x88, 0xd0, /* reset device */ 0x88, 0xf0, /* set device programmed, all in operational mode */ 0x00, 0x00 @@ -349,6 +358,35 @@ static const unsigned char saa7115_cfg_vbi_off[] = { 0x00, 0x00 }; +#if 1 /* saa7113 init codes */ +static const unsigned char saa7113_init_auto_input[] = { + 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ + 0x02, 0xc2, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ + 0x03, 0x30, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ + 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ + 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ + 0x06, 0x89, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ + 0x07, 0x0d, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ + 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ + 0x09, 0x01, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ + 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ + 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ + 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ + 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ + 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ + 0x0f, 0x2a, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ + 0x10, 0x08, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ + 0x11, 0x0c, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ + 0x12, 0x07, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ + 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ + 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ + 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ + 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ + 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ + 0x00, 0x00 +}; +#endif + static const unsigned char saa7115_init_misc[] = { 0x38, 0x03, /* audio stuff */ 0x39, 0x10, @@ -688,10 +726,35 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) saa7115_writeregs(client, saa7115_cfg_50hz_video); } + /* Register 0E - Bits D6-D4 on NO-AUTO mode + (SAA7113 doesn't have auto mode) + 50 Hz / 625 lines 60 Hz / 525 lines + 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz) + 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz) + 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz) + 011 NTSC N (3.58MHz) PAL M (3.58MHz) + 100 reserved NTSC-Japan (3.58MHz) + */ + if (state->ident == V4L2_IDENT_SAA7113) { + u8 reg = saa7115_read(client, 0x0e) & 0x8f; + + if (std == V4L2_STD_PAL_M) { + reg|=0x30; + } else if (std == V4L2_STD_PAL_N) { + reg|=0x20; + } else if (std == V4L2_STD_PAL_60) { + reg|=0x10; + } else if (std == V4L2_STD_NTSC_M_JP) { + reg|=0x40; + } + saa7115_write(client, 0x0e, reg); + } + + state->std = std; /* restart task B if needed */ - if (taskb && state->ident == V4L2_IDENT_SAA7114) { + if (taskb && state->ident != V4L2_IDENT_SAA7115) { saa7115_writeregs(client, saa7115_cfg_vbi_on); } @@ -714,7 +777,7 @@ static void saa7115_log_status(struct i2c_client *client) int vcr; v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); - if (client->name[6] == '4') { + if (state->ident != V4L2_IDENT_SAA7115) { /* status for the saa7114 */ reg1f = saa7115_read(client, 0x1f); signalOk = (reg1f & 0xc1) == 0x81; @@ -762,8 +825,8 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo u8 lcr[24]; int i, x; - /* saa7114 doesn't yet support VBI */ - if (state->ident == V4L2_IDENT_SAA7114) + /* saa7113/71144 doesn't yet support VBI */ + if (state->ident != V4L2_IDENT_SAA7115) return; for (i = 0; i <= 23; i++) @@ -1280,14 +1343,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) saa7115_write(client, 0, 5); chip_id = saa7115_read(client, 0) & 0x0f; - if (chip_id != 4 && chip_id != 5) { + if (chip_id <3 && chip_id > 5) { v4l_dbg(1, debug, client, "saa7115 not found\n"); kfree(client); return 0; } - if (chip_id == 4) { - snprintf(client->name, sizeof(client->name) - 1, "saa7114"); - } + snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL); @@ -1304,13 +1365,27 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) state->contrast = 64; state->hue = 0; state->sat = 64; - state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; + switch (chip_id) { + case 3: + state->ident = V4L2_IDENT_SAA7113; + break; + case 4: + state->ident = V4L2_IDENT_SAA7114; + break; + default: + state->ident = V4L2_IDENT_SAA7115; + break; + } + state->audclk_freq = 48000; v4l_dbg(1, debug, client, "writing init values\n"); /* init to 60hz/48khz */ - saa7115_writeregs(client, saa7115_init_auto_input); + if (state->ident==V4L2_IDENT_SAA7113) + saa7115_writeregs(client, saa7113_init_auto_input); + else + saa7115_writeregs(client, saa7115_init_auto_input); saa7115_writeregs(client, saa7115_init_misc); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index 8a174f185..393a3a3bd 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -518,7 +518,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, /* release the old buffer */ if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } @@ -534,12 +534,12 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, return err; } - if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { + if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) { dsp_buffer_free(dev); return err; } if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -548,7 +548,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, dev->dmasound.dma.sglen, 0))) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -582,7 +582,7 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 53717ff9c..fa242c5d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -70,8 +70,8 @@ static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); -static int no_overlay=-1; -module_param(no_overlay, int, 0444); +int saa7134_no_overlay=-1; +module_param_named(no_overlay, saa7134_no_overlay, int, 0444); MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" " [some VIA/SIS chipsets are known to have problem with overlay]"); @@ -319,12 +319,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt) /* ------------------------------------------------------------------ */ -void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf) +void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) { BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); + videobuf_dma_unmap(q, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); buf->vb.state = STATE_NEEDS_INIT; } @@ -914,11 +914,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: quirk: this driver and your " "chipset may not work together" " in overlay mode.\n",dev->name); - if (!no_overlay) { + if (!saa7134_no_overlay) { printk(KERN_INFO "%s: quirk: overlay " "mode will be disabled.\n", dev->name); - no_overlay = 1; + saa7134_no_overlay = 1; } else { printk(KERN_INFO "%s: quirk: overlay " "mode will be forced. Use this" @@ -1028,6 +1028,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, v4l2_prio_init(&dev->prio); /* register v4l devices */ + if (saa7134_no_overlay <= 0) { + saa7134_video_template.type |= VID_TYPE_OVERLAY; + } else { + printk("bttv: Overlay support disabled.\n"); + } dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[dev->nr]); diff --git a/linux/drivers/media/video/saa7134/saa7134-oss.c b/linux/drivers/media/video/saa7134/saa7134-oss.c index b57fa81cd..a88f8b5bb 100644 --- a/linux/drivers/media/video/saa7134/saa7134-oss.c +++ b/linux/drivers/media/video/saa7134/saa7134-oss.c @@ -143,7 +143,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) unsigned long flags; /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) + if (0 != (err = videobuf_pci_dma_map(dev->pci,&dev->dmasound.dma))) return err; if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) goto fail1; @@ -232,7 +232,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) fail2: saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma); return err; } @@ -250,7 +250,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev) /* unlock buffer */ saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); + videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index fdb2d9261..1f9c2fe98 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -91,7 +91,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return -EINVAL; if (buf->vb.size != size) { - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -100,7 +100,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, buf->vb.size = size; buf->pt = &dev->ts.pt_ts; - err = videobuf_iolock(dev->pci,&buf->vb,NULL); + err = videobuf_iolock(q,&buf->vb,NULL); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -128,7 +128,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -154,10 +154,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_dev *dev = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } struct videobuf_queue_ops saa7134_ts_qops = { diff --git a/linux/drivers/media/video/saa7134/saa7134-vbi.c b/linux/drivers/media/video/saa7134/saa7134-vbi.c index 125a6c838..44909bd1f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-vbi.c +++ b/linux/drivers/media/video/saa7134/saa7134-vbi.c @@ -143,7 +143,7 @@ static int buffer_prepare(struct videobuf_queue *q, return -EINVAL; if (buf->vb.size != size) - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); if (STATE_NEEDS_INIT == buf->vb.state) { buf->vb.width = llength; @@ -151,7 +151,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.size = size; buf->pt = &fh->pt_vbi; - err = videobuf_iolock(dev->pci,&buf->vb,NULL); + err = videobuf_iolock(q,&buf->vb,NULL); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -167,7 +167,7 @@ static int buffer_prepare(struct videobuf_queue *q, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -204,11 +204,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = q->priv_data; - struct saa7134_dev *dev = fh->dev; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } struct videobuf_queue_ops saa7134_vbi_qops = { diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index a034776ae..3bd76fe3a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -997,7 +997,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.size != size || buf->vb.field != field || buf->fmt != fh->fmt) { - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); } if (STATE_NEEDS_INIT == buf->vb.state) { @@ -1008,7 +1008,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->fmt = fh->fmt; buf->pt = &fh->pt_cap; - err = videobuf_iolock(dev->pci,&buf->vb,&dev->ovbuf); + err = videobuf_iolock(q,&buf->vb,&dev->ovbuf); if (err) goto oops; err = saa7134_pgtable_build(dev->pci,buf->pt, @@ -1023,7 +1023,7 @@ static int buffer_prepare(struct videobuf_queue *q, return 0; oops: - saa7134_dma_free(dev,buf); + saa7134_dma_free(q,buf); return err; } @@ -1049,10 +1049,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); - saa7134_dma_free(fh->dev,buf); + saa7134_dma_free(q,buf); } static struct videobuf_queue_ops video_qops = { @@ -1473,6 +1472,10 @@ static int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, f->fmt.pix.height * f->fmt.pix.bytesperline; return 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } f->fmt.win = fh->win; return 0; case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -1537,6 +1540,10 @@ static int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } err = verify_preview(dev,&f->fmt.win); if (0 != err) return err; @@ -1567,6 +1574,10 @@ static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, fh->cap.field = f->fmt.pix.field; return 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } err = verify_preview(dev,&f->fmt.win); if (0 != err) return err; @@ -1726,11 +1737,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, cap->version = SAA7134_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TUNER; + if (saa7134_no_overlay <= 0) { + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + } if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET)) cap->capabilities &= ~V4L2_CAP_TUNER; @@ -1981,6 +1994,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file, switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (saa7134_no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } if (index >= FORMATS) return -EINVAL; if (f->type == V4L2_BUF_TYPE_VIDEO_OVERLAY && @@ -2041,6 +2058,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file, int *on = arg; if (*on) { + if (saa7134_no_overlay > 0) { + printk ("no_overlay\n"); + return -EINVAL; + } + if (!res_get(dev,fh,RESOURCE_OVERLAY)) return -EBUSY; spin_lock_irqsave(&dev->slock,flags); @@ -2296,7 +2318,7 @@ static struct file_operations radio_fops = struct video_device saa7134_video_template = { .name = "saa7134-video", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = 0, .fops = &video_fops, diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 9666b35c9..85f18e61e 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -579,6 +579,7 @@ struct saa7134_dev { /* saa7134-core.c */ extern struct list_head saa7134_devlist; +extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); @@ -600,7 +601,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, unsigned int state); void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); void saa7134_buffer_timeout(unsigned long data); -void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf); +void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); int saa7134_set_dmabits(struct saa7134_dev *dev); diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index f39e4f54c..9cc13ec8e 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -24,6 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "compat.h" + #include <linux/module.h> #include <linux/ioctl.h> #include <linux/i2c.h> @@ -221,10 +223,18 @@ static int detach(struct i2c_client *client) } static struct i2c_driver driver = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) &&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) .owner = THIS_MODULE, +#endif +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .name = "tda9840", - .id = I2C_DRIVERID_TDA9840, .flags = I2C_DF_NOTIFY, +#else + .driver = { + .name = "tda9840", + }, +#endif + .id = I2C_DRIVERID_TDA9840, .attach_adapter = attach, .detach_client = detach, .command = command, diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index ad09e4c1c..12e83ad21 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. */ +#include "compat.h" + #include <linux/module.h> #include <linux/ioctl.h> #include <linux/i2c.h> @@ -190,10 +192,18 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) } static struct i2c_driver driver = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) &&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) .owner = THIS_MODULE, +#endif +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .name = "tea6415c", - .id = I2C_DRIVERID_TEA6415C, .flags = I2C_DF_NOTIFY, +#else + .driver = { + .name = "tea6415c", + }, +#endif + .id = I2C_DRIVERID_TEA6415C, .attach_adapter = attach, .detach_client = detach, .command = command, diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index dd8279ad5..d22eac01b 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "compat.h" + #include <linux/module.h> #include <linux/ioctl.h> #include <linux/i2c.h> @@ -167,10 +169,18 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) } static struct i2c_driver driver = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) &&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) .owner = THIS_MODULE, +#endif +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .name = "tea6420", - .id = I2C_DRIVERID_TEA6420, .flags = I2C_DF_NOTIFY, +#else + .driver = { + .name = "tea6420", + }, +#endif + .id = I2C_DRIVERID_TEA6420, .attach_adapter = attach, .detach_client = detach, .command = command, diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 27158d0b9..b9c56e5e5 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -501,7 +501,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08d, frames=%d, userbits=0x%08x", + "flags=0x%08d, frames=%d, userbits=0x%08x\n", s,tc->hours,tc->minutes,tc->seconds, tc->type, tc->flags, tc->frames, (__u32) tc->userbits); break; @@ -509,8 +509,8 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOC_QUERYCAP: { struct v4l2_capability *p=arg; - printk ("%s: driver=%s, card=%s, bus=%s, version=%d, " - "capabilities=%d\n", s, + printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, " + "capabilities=0x%08x\n", s, p->driver,p->card,p->bus_info, p->version, p->capabilities); diff --git a/linux/drivers/media/video/video-buf.c b/linux/drivers/media/video/video-buf.c index 4a83c6943..e2d5e03c9 100644 --- a/linux/drivers/media/video/video-buf.c +++ b/linux/drivers/media/video/video-buf.c @@ -2,15 +2,20 @@ * $Id: video-buf.c,v 1.25 2006/01/11 19:28:02 mchehab Exp $ * * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. + * memory management and PCI DMA. + * Right now, bttv, saa7134, saa7146 and cx88 use it. * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB 1.1 - * as data often must be uncompressed by the drivers). + * to touch the video data. + * + * device specific map/unmap/sync stuff now are mapped as operations + * to allow its usage by USB and virtual devices. * * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] + * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> + * (c) 2006 Ted Walther and John Sokol * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -169,6 +174,9 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); return -ENOMEM; } + dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", + (unsigned long)dma->vmalloc, + nr_pages << PAGE_SHIFT); memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); dma->nr_pages = nr_pages; return 0; @@ -188,8 +196,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -199,7 +209,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) } if (dma->vmalloc) { dma->sglist = videobuf_vmalloc_to_sg - (dma->vmalloc,dma->nr_pages); + (dma->vmalloc,dma->nr_pages); } if (dma->bus_addr) { dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); @@ -214,13 +224,14 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) dprintk(1,"scatterlist is NULL\n"); return -ENOMEM; } - if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages, - dma->direction); + if (q->ops->vb_map_sg) { + dma->sglen = q->ops->vb_map_sg(dev,dma->sglist, + dma->nr_pages, dma->direction); + } if (0 == dma->sglen) { printk(KERN_WARNING - "%s: pci_map_sg failed\n",__FUNCTION__); + "%s: videobuf_map_sg failed\n",__FUNCTION__); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -230,29 +241,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(!dma->sglen); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - if (!dma->bus_addr) - pci_dma_sync_sg(dev,dma->sglist,dma->nr_pages,dma->direction); -#else - if (!dma->bus_addr) - pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction); -#endif + if (!dma->bus_addr && q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); + return 0; } -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma) +int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { + void *dev=q->dev; + MAGIC_CHECK(dma->magic,MAGIC_DMABUF); if (!dma->sglen) return 0; - if (!dma->bus_addr) - pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction); + if (!dma->bus_addr && q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages, + dma->direction); kfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; @@ -325,7 +338,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) } int -videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, +videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) { int err,pages; @@ -364,7 +377,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, default: BUG(); } - err = videobuf_dma_pci_map(pci,&vb->dma); + err = videobuf_dma_map(q,&vb->dma); if (0 != err) return err; @@ -373,9 +386,46 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, /* --------------------------------------------------------------------- */ +void videobuf_queue_pci(struct videobuf_queue* q) +{ + /* If not specified, defaults to PCI map sg */ + if (!q->ops->vb_map_sg) + q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) + if (!q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg; +#else + if (!q->ops->vb_dma_sync_sg) + q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu; +#endif + if (!q->ops->vb_unmap_sg) + q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; +} + +int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + + q.dev=pci; + q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + + return (videobuf_dma_unmap(&q,dma)); +} + +int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +{ + struct videobuf_queue q; + + q.dev=pci; + q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + + return (videobuf_dma_unmap(&q,dma)); +} + void videobuf_queue_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - struct pci_dev *pci, + void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -384,13 +434,15 @@ void videobuf_queue_init(struct videobuf_queue* q, { memset(q,0,sizeof(*q)); q->irqlock = irqlock; - q->pci = pci; + q->dev = dev; q->type = type; q->field = field; q->msize = msize; q->ops = ops; q->priv_data = priv; + videobuf_queue_pci(q); + mutex_init(&q->lock); INIT_LIST_HEAD(&q->stream); } @@ -434,11 +486,12 @@ videobuf_queue_is_busy(struct videobuf_queue *q) void videobuf_queue_cancel(struct videobuf_queue *q) { - unsigned long flags; + unsigned long flags=0; int i; /* remove queued buffers from list */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -447,7 +500,8 @@ videobuf_queue_cancel(struct videobuf_queue *q) q->bufs[i]->state = STATE_ERROR; } } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); /* free all buffers + clear queue */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { @@ -541,19 +595,29 @@ videobuf_reqbufs(struct videobuf_queue *q, unsigned int size,count; int retval; - if (req->type != q->type) + if (req->type != q->type) { + dprintk(1,"reqbufs: queue type invalid\n"); return -EINVAL; - if (req->count < 1) + } + if (req->count < 1) { + dprintk(1,"reqbufs: count invalid (%d)\n",req->count); return -EINVAL; + } if (req->memory != V4L2_MEMORY_MMAP && req->memory != V4L2_MEMORY_USERPTR && - req->memory != V4L2_MEMORY_OVERLAY) + req->memory != V4L2_MEMORY_OVERLAY) { + dprintk(1,"reqbufs: memory type invalid\n"); return -EINVAL; + } - if (q->streaming) + if (q->streaming) { + dprintk(1,"reqbufs: streaming already exists\n"); return -EBUSY; - if (!list_empty(&q->stream)) + } + if (!list_empty(&q->stream)) { + dprintk(1,"reqbufs: stream running\n"); return -EBUSY; + } mutex_lock(&q->lock); count = req->count; @@ -566,8 +630,10 @@ videobuf_reqbufs(struct videobuf_queue *q, count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(q,count,size,req->memory); - if (retval < 0) + if (retval < 0) { + dprintk(1,"reqbufs: mmap setup returned %d\n",retval); goto done; + } req->count = count; @@ -579,12 +645,18 @@ videobuf_reqbufs(struct videobuf_queue *q, int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { - if (unlikely(b->type != q->type)) + if (unlikely(b->type != q->type)) { + dprintk(1,"querybuf: Wrong type.\n"); return -EINVAL; - if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) + } + if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { + dprintk(1,"querybuf: index out of range.\n"); return -EINVAL; - if (unlikely(NULL == q->bufs[b->index])) + } + if (unlikely(NULL == q->bufs[b->index])) { + dprintk(1,"querybuf: buffer is null.\n"); return -EINVAL; + } videobuf_status(b,q->bufs[b->index],q->type); return 0; } @@ -595,31 +667,45 @@ videobuf_qbuf(struct videobuf_queue *q, { struct videobuf_buffer *buf; enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"qbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"qbuf: Wrong type.\n"); goto done; - if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) + } + if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { + dprintk(1,"qbuf: index out of range.\n"); goto done; + } buf = q->bufs[b->index]; - if (NULL == buf) + if (NULL == buf) { + dprintk(1,"qbuf: buffer is null.\n"); goto done; + } MAGIC_CHECK(buf->magic,MAGIC_BUFFER); - if (buf->memory != b->memory) + if (buf->memory != b->memory) { + dprintk(1,"qbuf: memory type is wrong.\n"); goto done; + } if (buf->state == STATE_QUEUED || - buf->state == STATE_ACTIVE) + buf->state == STATE_ACTIVE) { + dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; + } if (b->flags & V4L2_BUF_FLAG_INPUT) { - if (b->input >= q->inputs) + if (b->input >= q->inputs) { + dprintk(1,"qbuf: wrong input.\n"); goto done; + } buf->input = b->input; } else { buf->input = UNSET; @@ -627,12 +713,16 @@ videobuf_qbuf(struct videobuf_queue *q, switch (b->memory) { case V4L2_MEMORY_MMAP: - if (0 == buf->baddr) + if (0 == buf->baddr) { + dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n"); goto done; + } break; case V4L2_MEMORY_USERPTR: - if (b->length < buf->bsize) + if (b->length < buf->bsize) { + dprintk(1,"qbuf: buffer length is not enough\n"); goto done; + } if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) q->ops->buf_release(q,buf); buf->baddr = b->m.userptr; @@ -641,20 +731,27 @@ videobuf_qbuf(struct videobuf_queue *q, buf->boff = b->m.offset; break; default: + dprintk(1,"qbuf: wrong memory type\n"); goto done; } + dprintk(1,"qbuf: requesting next field\n"); field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,buf,field); - if (0 != retval) + if (0 != retval) { + dprintk(1,"qbuf: buffer_prepare returned %d\n",retval); goto done; + } list_add_tail(&buf->stream,&q->stream); if (q->streaming) { - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); } + dprintk(1,"qbuf: succeded\n"); retval = 0; done: @@ -671,26 +768,39 @@ videobuf_dqbuf(struct videobuf_queue *q, mutex_lock(&q->lock); retval = -EBUSY; - if (q->reading) + if (q->reading) { + dprintk(1,"dqbuf: Reading running...\n"); goto done; + } retval = -EINVAL; - if (b->type != q->type) + if (b->type != q->type) { + dprintk(1,"dqbuf: Wrong type.\n"); goto done; - if (list_empty(&q->stream)) + } + if (list_empty(&q->stream)) { + dprintk(1,"dqbuf: stream running\n"); goto done; + } buf = list_entry(q->stream.next, struct videobuf_buffer, stream); retval = videobuf_waiton(buf, nonblocking, 1); - if (retval < 0) + if (retval < 0) { + dprintk(1,"dqbuf: waiton returned %d\n",retval); goto done; + } switch (buf->state) { case STATE_ERROR: + dprintk(1,"dqbuf: state is error\n"); retval = -EIO; - /* fall through */ + videobuf_dma_sync(q,&buf->dma); + buf->state = STATE_IDLE; + break; case STATE_DONE: - videobuf_dma_pci_sync(q->pci,&buf->dma); + dprintk(1,"dqbuf: state is done\n"); + videobuf_dma_sync(q,&buf->dma); buf->state = STATE_IDLE; break; default: + dprintk(1,"dqbuf: state invalid\n"); retval = -EINVAL; goto done; } @@ -707,7 +817,7 @@ int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; struct list_head *list; - unsigned long flags; + unsigned long flags=0; int retval; mutex_lock(&q->lock); @@ -718,13 +828,15 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->streaming) goto done; q->streaming = 1; - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); list_for_each(list,&q->stream) { buf = list_entry(list, struct videobuf_buffer, stream); if (buf->state == STATE_PREPARED) q->ops->buf_queue(q,buf); } - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); done: mutex_unlock(&q->lock); @@ -752,7 +864,7 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int retval; /* setup stuff */ @@ -769,12 +881,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, goto done; /* start capture & wait */ - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; else @@ -794,7 +908,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int nonblocking) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; unsigned size, nbufs, bytes; int retval; @@ -816,6 +930,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, /* need to capture a new frame */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); + dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf); if (NULL == q->read_buf) goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; @@ -827,9 +942,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, q->read_buf = NULL; goto done; } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_off = 0; } @@ -837,7 +954,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; - videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + videobuf_dma_sync(q,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) { /* catch I/O errors */ @@ -873,7 +990,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, int videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; - unsigned long flags; + unsigned long flags=0; int count = 0, size = 0; int err, i; @@ -894,10 +1011,12 @@ int videobuf_read_start(struct videobuf_queue *q) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < count; i++) q->ops->buf_queue(q,q->bufs[i]); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->reading = 1; return 0; } @@ -925,7 +1044,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, { unsigned int *fc, bytes; int err, retval; - unsigned long flags; + unsigned long flags=0; dprintk(2,"%s\n",__FUNCTION__); mutex_lock(&q->lock); @@ -992,9 +1111,11 @@ 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); - spin_lock_irqsave(q->irqlock,flags); + if (q->irqlock) + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); - spin_unlock_irqrestore(q->irqlock,flags); + if (q->irqlock) + spin_unlock_irqrestore(q->irqlock,flags); q->read_buf = NULL; } if (retval < 0) @@ -1267,11 +1388,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init); EXPORT_SYMBOL_GPL(videobuf_dma_init_user); EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_map); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync); -EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap); +EXPORT_SYMBOL_GPL(videobuf_dma_map); +EXPORT_SYMBOL_GPL(videobuf_dma_sync); +EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); +EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); + EXPORT_SYMBOL_GPL(videobuf_alloc); EXPORT_SYMBOL_GPL(videobuf_waiton); EXPORT_SYMBOL_GPL(videobuf_iolock); diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c new file mode 100644 index 000000000..2dfbf65f2 --- /dev/null +++ b/linux/drivers/media/video/vivi.c @@ -0,0 +1,1543 @@ +/* + * Virtual Video driver - This code emulates a real video device with v4l2 api + * + * Copyright (c) 2006 by: + * Mauro Carvalho Chehab <mchehab--a.t--infradead.org> + * Ted Walther <ted--a.t--enumera.com> + * John Sokol <sokol--a.t--videotechnology.com> + * http://v4l.videotechnology.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the BSD Licence, GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version + */ +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/random.h> +#include <linux/version.h> +#include <linux/videodev2.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#include <linux/videodev.h> +#include <linux/interrupt.h> +#endif +#include <media/video-buf.h> +#include <media/v4l2-common.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include <linux/kthread.h> +#endif +#include <linux/highmem.h> + +/* Wake up at about 30 fps */ +#define WAKE_NUMERATOR 30 +#define WAKE_DENOMINATOR 1001 +#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ + +/* These timers are for 1 fps - used only for testing */ +//#define WAKE_DENOMINATOR 30 /* hack for testing purposes */ +//#define BUFFER_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ + +#include "font.h" + +#ifndef kzalloc +#define kzalloc(size, flags) \ +({ \ + void *__ret = kmalloc(size, flags); \ + if (__ret) \ + memset(__ret, 0, size); \ + __ret; \ +}) +#endif + +MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); +MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define VIVI_MAJOR_VERSION 0 +#define VIVI_MINOR_VERSION 4 +#define VIVI_RELEASE 0 +#define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) + +static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ +module_param(video_nr, int, 0); + +static int debug = 0; +module_param(debug, int, 0); + +static unsigned int vid_limit = 16; +module_param(vid_limit,int,0644); +MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); + +/* supported controls */ +static struct v4l2_queryctrl vivi_qctrl[] = { + { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 65535, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 127, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 127, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 0x1, + .default_value = 0, + .flags = 0, + } +}; + +static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; + +#define dprintk(level,fmt, arg...) \ + do { \ + if (debug >= (level)) \ + printk(KERN_DEBUG "vivi: " fmt , ## arg); \ + } while (0) + +/* ------------------------------------------------------------------ + Basic structures + ------------------------------------------------------------------*/ + +struct vivi_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; +}; + +static struct vivi_fmt format = { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, +}; + +struct sg_to_addr { + int pos; + struct scatterlist *sg; +}; + +/* buffer for one video frame */ +struct vivi_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct vivi_fmt *fmt; + + struct sg_to_addr *to_addr; +}; + +struct vivi_dmaqueue { + struct list_head active; + struct list_head queued; + struct timer_list timeout; + + /* thread for generating video stream*/ + struct task_struct *kthread; + wait_queue_head_t wq; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + struct semaphore *notify; + int rmmod:1; +#endif + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +static LIST_HEAD(vivi_devlist); + +struct vivi_dev { + struct list_head vivi_devlist; + + struct semaphore lock; + + int users; + + /* various device info */ + unsigned int resources; + struct video_device video_dev; + + struct vivi_dmaqueue vidq; + + /* Several counters */ + int h,m,s,us,jiffies; + char timestr[13]; +}; + +struct vivi_fh { + struct vivi_dev *dev; + + /* video capture */ + struct vivi_fmt *fmt; + unsigned int width,height; + struct videobuf_queue vb_vidq; + + enum v4l2_buf_type type; +}; + +/* ------------------------------------------------------------------ + DMA and thread functions + ------------------------------------------------------------------*/ + +/* Bars and Colors should match positions */ + +enum colors { + WHITE, + AMBAR, + CYAN, + GREEN, + MAGENTA, + RED, + BLUE +}; + +static u8 bars[8][3] = { + /* R G B */ + {204,204,204}, /* white */ + {208,208, 0}, /* ambar */ + { 0,206,206}, /* cyan */ + { 0,239, 0}, /* green */ + {239, 0,239}, /* magenta */ + {205, 0, 0}, /* red */ + { 0, 0,255}, /* blue */ + { 0, 0, 0} +}; + +#define TO_Y(r,g,b) (((16829*r +33039*g +6416*b + 32768)>>16)+16) +/* RGB to V(Cr) Color transform */ +#define TO_V(r,g,b) (((28784*r -24103*g -4681*b + 32768)>>16)+128) +/* RGB to U(Cb) Color transform */ +#define TO_U(r,g,b) (((-9714*r -19070*g +28784*b + 32768)>>16)+128) + +#define TSTAMP_MIN_Y 24 +#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 +#define TSTAMP_MIN_X 64 + +void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) +{ + int i, pos=0; + + for (i=0;i<vb->dma.nr_pages;i++) { + to_addr[i].sg=&vb->dma.sglist[i]; + to_addr[i].pos=pos; + pos += vb->dma.sglist[i].length; + } +} + +inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) +{ + int p1=0,p2=pages-1,p3=pages/2; + + /* Sanity test */ + BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length); + + while (p1+1<p2) { + if (pos < to_addr[p3].pos) { + p2=p3; + } else { + p1=p3; + } + p3=(p1+p2)/2; + } + if (pos >= to_addr[p2].pos) + p1=p2; + + return (p1); +} + +void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, + int hmax, int line, char *timestr) +{ + int w,i,j,pos=inipos,pgpos,oldpg,y; + char *p,*s,*basep; + struct page *pg; + u8 chr,r,g,b,color; + + /* Get first addr pointed to pixel position */ + oldpg=get_addr_pos(pos,pages,to_addr); + pg=pfn_to_page(to_addr[oldpg].sg->dma_address >> PAGE_SHIFT); + basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; + + /* We will just duplicate the second pixel at the packet */ + wmax/=2; + + /* Generate a standard color bar pattern */ + for (w=0;w<wmax;w++) { + r=bars[w*7/wmax][0]; + g=bars[w*7/wmax][1]; + b=bars[w*7/wmax][2]; + + for (color=0;color<4;color++) { + pgpos=get_addr_pos(pos,pages,to_addr); + if (pgpos!=oldpg) { + pg=pfn_to_page(to_addr[pgpos].sg->dma_address >> PAGE_SHIFT); + kunmap_atomic(basep, KM_BOUNCE_READ); + basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset; + oldpg=pgpos; + } + p=basep+pos-to_addr[pgpos].pos; + + switch (color) { + case 0: + case 2: + *p=TO_Y(r,g,b); /* Luminance */ + break; + case 1: + *p=TO_U(r,g,b); /* Cb */ + break; + case 3: + *p=TO_V(r,g,b); /* Cr */ + break; + } + pos++; + } + } + + /* Checks if it is possible to show timestamp */ + if (TSTAMP_MAX_Y>=hmax) + goto end; + if (TSTAMP_MIN_X+strlen(timestr)>=wmax) + goto end; + + /* Print stream time */ + if (line>=TSTAMP_MIN_Y && line<=TSTAMP_MAX_Y) { + j=TSTAMP_MIN_X; + for (s=timestr;*s;s++) { + chr=rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y]; + for (i=0;i<7;i++) { + if (chr&1<<(7-i)) { /* Font color*/ + r=bars[BLUE][0]; + g=bars[BLUE][1]; + b=bars[BLUE][2]; + r=g=b=0; + g=198; + } else { /* Background color */ + r=bars[WHITE][0]; + g=bars[WHITE][1]; + b=bars[WHITE][2]; + r=g=b=0; + } + + pos=inipos+j*2; + for (color=0;color<4;color++) { + pgpos=get_addr_pos(pos,pages,to_addr); + if (pgpos!=oldpg) { + pg=pfn_to_page(to_addr[pgpos]. + sg->dma_address + >> PAGE_SHIFT); + kunmap_atomic(basep, + KM_BOUNCE_READ); + basep= kmap_atomic(pg, + KM_BOUNCE_READ)+ + to_addr[pgpos].sg->offset; + oldpg=pgpos; + } + p=basep+pos-to_addr[pgpos].pos; + + y=TO_Y(r,g,b); + + switch (color) { + case 0: + case 2: + *p=TO_Y(r,g,b); /* Luminance */ + break; + case 1: + *p=TO_U(r,g,b); /* Cb */ + break; + case 3: + *p=TO_V(r,g,b); /* Cr */ + break; + } + pos++; + } + j++; + } + } + } + +#if 0 /* This will require a different logic */ + /* Generate random noise */ + if (line>6*hmax/7) { + if (line>6*hmax/7) { + p=get_addr_pos(inipos+j/2,pages,to_addr); + +// get_random_bytes(buf+wmax-(wmax/7), wmax/7); + kunmap_atomic(p, KM_BOUNCE_READ); + } + } + +#endif + +end: + kunmap_atomic(basep, KM_BOUNCE_READ); +} +static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) +{ + int h,pos=0; + int hmax = buf->vb.height; + int wmax = buf->vb.width; + struct videobuf_buffer *vb=&buf->vb; + struct sg_to_addr *to_addr=buf->to_addr; + struct timeval ts; + + /* Test if DMA mapping is ready */ + if (!vb->dma.sglist[0].dma_address) + return; + + prep_to_addr(to_addr,vb); + + /* Check if there is enough memory */ + BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); + + for (h=0;h<hmax;h++) { + gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr); + pos += wmax*2; + } + + /* Updates stream time */ + + dev->us+=jiffies_to_usecs(jiffies-dev->jiffies); + dev->jiffies=jiffies; + if (dev->us>=1000000) { + dev->us-=1000000; + dev->s++; + if (dev->s>=60) { + dev->s-=60; + dev->m++; + if (dev->m>60) { + dev->m-=60; + dev->h++; + if (dev->h>24) + dev->h-=24; + } + } + } + sprintf(dev->timestr,"%02d:%02d:%02d:%03d", + dev->h,dev->m,dev->s,(dev->us+500)/1000); + + dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr, + (unsigned long)buf->vb.dma.vmalloc,pos); + + /* Advice that buffer was filled */ + buf->vb.state = STATE_DONE; + buf->vb.field_count++; + do_gettimeofday(&ts); + buf->vb.ts = ts; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +static int restart_video_queue(struct vivi_dmaqueue *dma_q); + +static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) +{ + struct vivi_buffer *buf; + struct vivi_dev *dev= container_of(dma_q,struct vivi_dev,vidq); + + int bc; + + /* Announces videobuf that all went ok */ + for (bc = 0;; bc++) { + if (list_empty(&dma_q->active)) { + dprintk(1,"No active queue to serve\n"); + break; + } + + buf = list_entry(dma_q->active.next, + struct vivi_buffer, vb.queue); + + /* Nobody is waiting something to be done, just return */ + if (!waitqueue_active(&buf->vb.done)) { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + return; + } + + do_gettimeofday(&buf->vb.ts); + dprintk(2,"[%p/%d] wakeup\n",buf,buf->vb.i); + + /* Fill buffer */ + vivi_fillbuff(dev,buf); + } + if (list_empty(&dma_q->active)) { + del_timer(&dma_q->timeout); + } else { + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + } + if (bc != 1) + dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); +} + +void vivi_sleep(struct vivi_dmaqueue *dma_q) +{ + int timeout; + DECLARE_WAITQUEUE(wait, current); + + dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); + + add_wait_queue(&dma_q->wq, &wait); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if (!(q->rmmod || signal_pending(current))) { +#else + if (!kthread_should_stop()) { +#endif + dma_q->frame++; + + /* Calculate time to wake up */ + timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies; + + if (timeout <= 0) { + int old=dma_q->frame; + dma_q->frame=(jiffies_to_msecs(jiffies-dma_q->ini_jiffies)*WAKE_DENOMINATOR)/(WAKE_NUMERATOR*1000)+1; + + timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies; + + dprintk(1,"underrun, losed %d frames. " + "Now, frame is %d. Waking on %d jiffies\n", + dma_q->frame-old,dma_q->frame,timeout); + } else + dprintk(1,"will sleep for %i jiffies\n",timeout); + + vivi_thread_tick(dma_q); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) + schedule_timeout_interruptible (timeout); +#else + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(timeout); +#endif + } +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + if (current->flags & PF_FREEZE) { + refrigerator (PF_FREEZE); + } +#endif + + remove_wait_queue(&dma_q->wq, &wait); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12) + try_to_freeze(); +#endif +} + +int vivi_thread(void *data) +{ + struct vivi_dmaqueue *dma_q=data; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + daemonize(); + exit_files(current); + reparent_to_init(); + + spin_lock_irq(SIGMASK_LOCK(current)); + sigfillset(¤t->blocked); + spin_unlock_irq(SIGMASK_LOCK(current)); + strcpy(current->comm, "vivi"); + + dma_q->kthread = current; + if (dma_q->notify != NULL) + up(dma_q->notify); +#endif + dprintk(1,"thread started\n"); + + for (;;) { + vivi_sleep(dma_q); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if (dma_q->rmmod || signal_pending(current)) +#else + if (kthread_should_stop()) +#endif + break; + } + dprintk(1, "thread: exit\n"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + dma_q->kthread = NULL; + + if (dma_q->notify != NULL) + up(dma_q->notify); +#endif + return 0; +} + +int vivi_start_thread(struct vivi_dmaqueue *dma_q) +{ + dma_q->frame=0; + dma_q->ini_jiffies=jiffies; + + dprintk(1,"%s\n",__FUNCTION__); + init_waitqueue_head(&dma_q->wq); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi"); + + if (dma_q->kthread == NULL) { + printk(KERN_ERR "vivi: kernel_thread() failed\n"); + return -EINVAL; + } +#else + DECLARE_MUTEX_LOCKED(sem); + + dma_q->kthread = NULL; + dma_q->notify = &sem; + kernel_thread(vivi_thread, dma_q, 0); + down(&sem); + dma_q->notify = NULL; +#endif + dprintk(1,"returning from %s\n",__FUNCTION__); + return 0; +} + +void vivi_stop_thread(struct vivi_dmaqueue *dma_q) +{ + dprintk(1,"%s\n",__FUNCTION__); + /* shutdown control thread */ + if (dma_q->kthread) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + DECLARE_MUTEX_LOCKED(sem); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* shutdown control thread */ + dma_q->notify = &sem; + dma_q->rmmod = 1; + wake_up_interruptible(&dma_q->wq); + down(&sem); + dma_q->notify = NULL; +#else + kthread_stop(dma_q->kthread); +#endif + dma_q->kthread=NULL; + } +} + +static int restart_video_queue(struct vivi_dmaqueue *dma_q) +{ + struct vivi_buffer *buf, *prev; + struct list_head *item; + + dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q); + + if (!list_empty(&dma_q->active)) { + buf = list_entry(dma_q->active.next, struct vivi_buffer, vb.queue); + dprintk(2,"restart_queue [%p/%d]: restart dma\n", + buf, buf->vb.i); + + dprintk(1,"Restarting video dma\n"); + vivi_stop_thread(dma_q); +// vivi_start_thread(dma_q); + + /* cancel all outstanding capture / vbi requests */ + list_for_each(item,&dma_q->active) { + buf = list_entry(item, struct vivi_buffer, vb.queue); + + list_del(&buf->vb.queue); + buf->vb.state = STATE_ERROR; + wake_up(&buf->vb.done); + } + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + + return 0; + } + + prev = NULL; + for (;;) { + if (list_empty(&dma_q->queued)) + return 0; + buf = list_entry(dma_q->queued.next, struct vivi_buffer, vb.queue); + if (NULL == prev) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&dma_q->active); + + dprintk(1,"Restarting video dma\n"); + vivi_stop_thread(dma_q); + vivi_start_thread(dma_q); + + buf->vb.state = STATE_ACTIVE; + mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2,"[%p/%d] restart_queue - first active\n", + buf,buf->vb.i); + + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&dma_q->active); + buf->vb.state = STATE_ACTIVE; + dprintk(2,"[%p/%d] restart_queue - move to active\n", + buf,buf->vb.i); + } else { + return 0; + } + prev = buf; + } +} + +static void vivi_vid_timeout(unsigned long data) +{ + struct vivi_dev *dev = (struct vivi_dev*)data; + struct vivi_dmaqueue *vidq = &dev->vidq; + struct vivi_buffer *buf; + + while (!list_empty(&vidq->active)) { + buf = list_entry(vidq->active.next, struct vivi_buffer, vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = STATE_ERROR; + wake_up(&buf->vb.done); + printk("vivi/0: [%p/%d] timeout\n", buf, buf->vb.i); + } + + restart_video_queue(vidq); +} + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct vivi_fh *fh = vq->priv_data; + + *size = fh->width*fh->height*2; + + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + return 0; +} + +void +free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) +{ + dprintk(1,"%s\n",__FUNCTION__); + + if (in_interrupt()) + BUG(); + + /*FIXME: Maybe a spinlock is required here */ + kfree(buf->to_addr); + buf->to_addr=NULL; + + videobuf_waiton(&buf->vb,0,0); + videobuf_dma_unmap(vq, &buf->vb.dma); + videobuf_dma_free(&buf->vb.dma); + buf->vb.state = STATE_NEEDS_INIT; +} + +#define norm_maxw() 1024 +#define norm_maxh() 768 +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct vivi_fh *fh = vq->priv_data; + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + int rc, init_buffer = 0; + +// dprintk(1,"%s, field=%d\n",__FUNCTION__,field); + + BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > norm_maxw() || + fh->height < 32 || fh->height > norm_maxh()) + return -EINVAL; + buf->vb.size = fh->width*fh->height*2; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + if (buf->fmt != fh->fmt || + buf->vb.width != fh->width || + buf->vb.height != fh->height || + buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; + } + + if (STATE_NEEDS_INIT == buf->vb.state) { + if (0 != (rc = videobuf_iolock(vq,&buf->vb,NULL))) + goto fail; + } + + buf->vb.state = STATE_PREPARED; + + if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { + rc=-ENOMEM; + goto fail; + } + + return 0; + +fail: + free_buffer(vq,buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + struct vivi_buffer *prev; + + if (!list_empty(&vidq->queued)) { + dprintk(1,"adding vb queue=0x%08lx\n",(unsigned long)&buf->vb.queue); + list_add_tail(&buf->vb.queue,&vidq->queued); + buf->vb.state = STATE_QUEUED; + dprintk(2,"[%p/%d] buffer_queue - append to queued\n", + buf, buf->vb.i); + } else if (list_empty(&vidq->active)) { + list_add_tail(&buf->vb.queue,&vidq->active); + + buf->vb.state = STATE_ACTIVE; + mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2,"[%p/%d] buffer_queue - first active\n", + buf, buf->vb.i); + + vivi_start_thread(vidq); + } else { + prev = list_entry(vidq->active.prev, struct vivi_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue,&vidq->active); + buf->vb.state = STATE_ACTIVE; + dprintk(2,"[%p/%d] buffer_queue - append to active\n", + buf, buf->vb.i); + + } else { + list_add_tail(&buf->vb.queue,&vidq->queued); + buf->vb.state = STATE_QUEUED; + dprintk(2,"[%p/%d] buffer_queue - first queued\n", + buf, buf->vb.i); + } + } +} + +static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb); + struct vivi_fh *fh = vq->priv_data; + struct vivi_dev *dev = (struct vivi_dev*)fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + + dprintk(1,"%s\n",__FUNCTION__); + + vivi_stop_thread(vidq); + + free_buffer(vq,buf); +} + +int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, + int direction) +{ + int i; + + dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents); + BUG_ON(direction == DMA_NONE); + + for (i = 0; i < nents; i++ ) { + BUG_ON(!sg[i].page); + + sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset; + } + + return nents; +} + +int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, + int direction) +{ + dprintk(1,"%s\n",__FUNCTION__); + return 0; +} + +int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages, + int direction) +{ +// dprintk(1,"%s\n",__FUNCTION__); + +// flush_write_buffers(); + return 0; +} + +static struct videobuf_queue_ops vivi_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, + + /* Non-pci handling routines */ + .vb_map_sg = vivi_map_sg, + .vb_dma_sync_sg = vivi_dma_sync_sg, + .vb_unmap_sg = vivi_unmap_sg, +}; + +/* ------------------------------------------------------------------ + IOCTL handling + ------------------------------------------------------------------*/ + +static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, + struct v4l2_format *f) +{ + struct vivi_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + + if (format.fourcc != f->fmt.pix.pixelformat) { + dprintk(1,"Fourcc format invalid.\n"); + return -EINVAL; + } + fmt=&format; + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { +// field=V4L2_FIELD_INTERLACED; + field=V4L2_FIELD_SEQ_TB; + } else if (V4L2_FIELD_INTERLACED != field) { + dprintk(1,"Field type invalid.\n"); + return -EINVAL; + } + + maxw = norm_maxw(); + maxh = norm_maxh(); + + f->fmt.pix.field = field; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) +{ + /* is it free? */ + down(&dev->lock); + if (dev->resources) { + /* no, someone else uses it */ + up(&dev->lock); + return 0; + } + /* it's free, grab it */ + dev->resources =1; + dprintk(1,"res: get\n"); + up(&dev->lock); + return 1; +} + +static inline int res_locked(struct vivi_dev *dev) +{ + return (dev->resources); +} + +static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) +{ + down(&dev->lock); + dev->resources = 0; + dprintk(1,"res: put\n"); + up(&dev->lock); +} + +static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; + int ret=0; + + if (debug) { + if (_IOC_DIR(cmd) & _IOC_WRITE) + v4l_printk_ioctl_arg("vivi(w)",cmd, arg); + else if (!_IOC_DIR(cmd) & _IOC_READ) { + v4l_print_ioctl("vivi", cmd); + } + } + + switch(cmd) { + /* --- capabilities ------------------------------------------ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = (struct v4l2_capability*)arg; + + memset(cap, 0, sizeof(*cap)); + + strcpy(cap->driver, "vivi"); + strcpy(cap->card, "vivi"); + cap->version = VIVI_VERSION; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + break; + } + /* --- capture ioctls ---------------------------------------- */ + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + enum v4l2_buf_type type; + unsigned int index; + + index = f->index; + type = f->type; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (index > 0){ + ret=-EINVAL; + break; + } + memset(f,0,sizeof(*f)); + + f->index = index; + f->type = type; + strlcpy(f->description,format.name,sizeof(f->description)); + f->pixelformat = format.fourcc; + break; + default: + ret=-EINVAL; + } + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = (struct v4l2_format *)arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vb_vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + break; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1,"Only capture supported.\n"); + ret=-EINVAL; + break; + } + + ret = vivi_try_fmt(dev,fh,f); + if (ret < 0) + break; + + fh->fmt = &format; + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vb_vidq.field = f->fmt.pix.field; + fh->type = f->type; + + break; + } + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = arg; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + + ret=vivi_try_fmt(dev,fh,f); + break; + } + case VIDIOC_REQBUFS: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_reqbufs(&fh->vb_vidq, arg); + break; + case VIDIOC_QUERYBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_querybuf(&fh->vb_vidq, arg); + break; + case VIDIOC_QBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_qbuf(&fh->vb_vidq, arg); + break; + case VIDIOC_DQBUF: + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret=videobuf_dqbuf(&fh->vb_vidq, arg, + file->f_flags & O_NONBLOCK); + break; +#ifdef HAVE_V4L1 + /* --- streaming capture ------------------------------------- */ + case VIDIOCGMBUF: + { + struct video_mbuf *mbuf = arg; + struct videobuf_queue *q=&fh->vb_vidq; + struct v4l2_requestbuffers req; + unsigned int i; + + memset(&req,0,sizeof(req)); + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + ret = videobuf_reqbufs(q,&req); + if (ret < 0) + break; + memset(mbuf,0,sizeof(*mbuf)); + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; + } + break; + } +#endif + case VIDIOC_STREAMON: + { + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (!res_get(dev,fh)) + return -EBUSY; + ret=videobuf_streamon(&fh->vb_vidq); + break; + } + case VIDIOC_STREAMOFF: + { + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + ret=-EINVAL; + break; + } + ret = videobuf_streamoff(&fh->vb_vidq); + if (ret < 0) + break; + res_free(dev,fh); + break; + } + /* ---------- tv norms ---------- */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = arg; + + if (e->index>0) { + ret=-EINVAL; + break; + } + ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); + + /* Allows vivi to use different fps from video std */ + e->frameperiod.numerator = WAKE_NUMERATOR; + e->frameperiod.denominator = WAKE_DENOMINATOR; + + break; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + + *id = V4L2_STD_NTSC_M; + break; + } + case VIDIOC_S_STD: + { + break; + } + /* ------ input switching ---------- */ + case VIDIOC_ENUMINPUT: + { /* only one input in this sample driver */ + struct v4l2_input *inp = arg; + + if (inp->index != 0) { + ret=-EINVAL; + break; + } + memset(inp, 0, sizeof(*inp)); + + inp->index = 0; + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_NTSC_M; + strcpy(inp->name,"Camera"); + break; + } + case VIDIOC_G_INPUT: + { + unsigned int *i = arg; + + *i = 0; + break; + } + case VIDIOC_S_INPUT: + { + unsigned int *i = arg; + + if (*i > 0) + ret=-EINVAL; + break; + } + + /* --- controls ---------------------------------------------- */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (qc->id && qc->id == vivi_qctrl[i].id) { + memcpy(qc, &(vivi_qctrl[i]), + sizeof(*qc)); + break; + } + + ret=-EINVAL; + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + ctrl->value=qctl_regs[i]; + break; + } + + ret=-EINVAL; + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + int i; + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + if (ctrl->value < + vivi_qctrl[i].minimum + || ctrl->value > + vivi_qctrl[i].maximum) { + ret=-ERANGE; + break; + } + qctl_regs[i]=ctrl->value; + break; + } + ret=-EINVAL; + break; + } + default: + ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); + } + + if (debug) { + if (ret<0) { + v4l_print_ioctl("vivi(err)", cmd); + dprintk(1,"errcode=%d\n",ret); + } else if (_IOC_DIR(cmd) & _IOC_READ) + v4l_printk_ioctl_arg("vivi(r)",cmd, arg); + } + + return ret; +} + +static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); +} + +/* ------------------------------------------------------------------ + File operations for the device + ------------------------------------------------------------------*/ + +#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8) + +static int vivi_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct vivi_dev *h,*dev = NULL; + struct vivi_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + int i; + + printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor); + + list_for_each(list,&vivi_devlist) { + h = list_entry(list, struct vivi_dev, vivi_devlist); + if (h->video_dev.minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + if (NULL == dev) + return -ENODEV; + +#if 0 /* Avoids an oops at read() - seems to be semaphore related */ + if (dev->users) { + printk(KERN_INFO "this driver can be opened only once (users=%d)\n",dev->users); + return -EBUSY; + } +#endif + + /* If more than one user, mutex should be added */ + dev->users++; + + dprintk(1,"open minor=%d type=%s users=%d\n", + minor,v4l2_type_names[type],dev->users); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh),GFP_KERNEL); + if (NULL == fh) { + dev->users--; + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fh->fmt = &format; + fh->width = 640; + fh->height = 480; + + /* Put all controls at a sane state */ + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + qctl_regs[i] =vivi_qctrl[i].default_value; + + dprintk(1,"Open: fh=0x%08lx, dev=0x%08lx, dev->vidq=0x%08lx\n", + (unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq); + dprintk(1,"Open: list_empty queued=%d\n",list_empty(&dev->vidq.queued)); + dprintk(1,"Open: list_empty active=%d\n",list_empty(&dev->vidq.active)); + + /* Resets frame counters */ + dev->h=0; + dev->m=0; + dev->s=0; + dev->us=0; + dev->jiffies=jiffies; + sprintf(dev->timestr,"%02d:%02d:%02d:%03d", + dev->h,dev->m,dev->s,(dev->us+500)/1000); + + videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, + NULL, NULL, + fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct vivi_buffer),fh); + + return 0; +} + +static ssize_t +vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct vivi_fh *fh = file->private_data; + + if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (res_locked(fh->dev)) + return -EBUSY; + return videobuf_read_one(&fh->vb_vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); + } + return 0; +} + +static unsigned int +vivi_poll(struct file *file, struct poll_table_struct *wait) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_buffer *buf; + + dprintk(1,"%s\n",__FUNCTION__); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + return POLLERR; + + if (res_get(fh->dev,fh)) { + dprintk(1,"poll: mmap interface\n"); + /* streaming capture */ + if (list_empty(&fh->vb_vidq.stream)) + return POLLERR; + buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream); + } else { + dprintk(1,"poll: read() interface\n"); + /* read() capture */ + buf = (struct vivi_buffer*)fh->vb_vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == STATE_DONE || + buf->vb.state == STATE_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + +static int vivi_release(struct inode *inode, struct file *file) +{ + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; + struct vivi_dmaqueue *vidq = &dev->vidq; + + int minor = iminor(inode); + + vivi_stop_thread(vidq); + videobuf_mmap_free(&fh->vb_vidq); + + kfree (fh); + + dev->users--; + + printk(KERN_DEBUG "vivi: close called (minor=%d, users=%d)\n",minor,dev->users); + + return 0; +} + +static int +vivi_mmap(struct file *file, struct vm_area_struct * vma) +{ + struct vivi_fh *fh = file->private_data; + int ret; + + dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); + + ret=videobuf_mmap_mapper(&fh->vb_vidq, vma); + + dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, + ret); + + return ret; +} + +static struct file_operations vivi_fops = { + .owner = THIS_MODULE, + .open = vivi_open, + .release = vivi_release, + .read = vivi_read, + .poll = vivi_poll, + .ioctl = vivi_ioctl, + .mmap = vivi_mmap, + .llseek = no_llseek, +}; + +static struct video_device vivi = { + .name = "VTM Virtual Video Capture Board", + .type = VID_TYPE_CAPTURE, + .hardware = 0, + .fops = &vivi_fops, + .minor = -1, +// .release = video_device_release, +}; +/* ------------------------------------------------------------------ + Initialization and module stuff + ------------------------------------------------------------------*/ + +static int __init vivi_init(void) +{ + int ret; + struct vivi_dev *dev; + + dev = kzalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) + return -ENOMEM; + list_add_tail(&dev->vivi_devlist,&vivi_devlist); + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + + /* initialize locks */ + init_MUTEX(&dev->lock); + + dev->vidq.timeout.function = vivi_vid_timeout; + dev->vidq.timeout.data = (unsigned long)dev; + init_timer(&dev->vidq.timeout); + + ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); + printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); + return ret; +} + +static void __exit vivi_exit(void) +{ + struct vivi_dev *h; + struct list_head *list; + + list_for_each(list,&vivi_devlist) { + h = list_entry(list, struct vivi_dev, vivi_devlist); + kfree (h); + } + video_unregister_device(&vivi); +} + +module_init(vivi_init); +module_exit(vivi_exit); diff --git a/linux/include/media/saa7146_vv.h b/linux/include/media/saa7146_vv.h index e5e749e98..4507cb61a 100644 --- a/linux/include/media/saa7146_vv.h +++ b/linux/include/media/saa7146_vv.h @@ -197,7 +197,8 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi); int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf); void saa7146_buffer_timeout(unsigned long data); -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf); +void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q, + struct saa7146_buf *buf); int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv); int saa7146_vv_release(struct saa7146_dev* dev); diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index a69118bbc..9ddebdd2a 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -109,6 +109,7 @@ enum v4l2_chip_ident { V4L2_IDENT_UNKNOWN = 0, /* module saa7115: reserved range 100-149 */ + V4L2_IDENT_SAA7113 = 103, V4L2_IDENT_SAA7114 = 104, V4L2_IDENT_SAA7115 = 105, diff --git a/linux/include/media/video-buf.h b/linux/include/media/video-buf.h index dd2bb1800..c6be316ce 100644 --- a/linux/include/media/video-buf.h +++ b/linux/include/media/video-buf.h @@ -2,15 +2,20 @@ * $Id: video-buf.h,v 1.11 2005/10/17 21:18:42 mchehab Exp $ * * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. + * memory management and PCI DMA. + * Right now, bttv, saa7134, saa7146 and cx88 use it. * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB as - * data often must be uncompressed by the drivers). + * to touch the video data. + * + * device specific map/unmap/sync stuff now are mapped as file operations + * to allow its usage by USB and virtual devices. * * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> + * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> + * (c) 2006 Ted Walther and John Sokol * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,6 +44,9 @@ struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset); +struct videobuf_buffer; +struct videobuf_queue; + /* --------------------------------------------------------------------- */ /* @@ -50,7 +58,7 @@ struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, * pointer + length. The kernel version just wants the size and * does memory allocation too using vmalloc_32(). * - * videobuf_dma_pci_*() + * videobuf_dma_*() * see Documentation/DMA-mapping.txt, these functions to * basically the same. The map function does also build a * scatterlist for the buffer (and unmap frees it ...) @@ -87,12 +95,18 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, int nr_pages); int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages); -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma); -int videobuf_dma_pci_sync(struct pci_dev *dev, - struct videobuf_dmabuf *dma); -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma); int videobuf_dma_free(struct videobuf_dmabuf *dma); +int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); +int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); +int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); + + /*FIXME: these variants are used only on *-alsa code, where videobuf is + * used without queue + */ +int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); +int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); + /* --------------------------------------------------------------------- */ /* @@ -116,9 +130,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma); * */ -struct videobuf_buffer; -struct videobuf_queue; - struct videobuf_mapping { unsigned int count; unsigned long start; @@ -165,6 +176,10 @@ struct videobuf_buffer { struct timeval ts; }; +typedef int (vb_map_sg_t)(void *dev,struct scatterlist *sglist,int nr_pages, + int direction); + + struct videobuf_queue_ops { int (*buf_setup)(struct videobuf_queue *q, unsigned int *count, unsigned int *size); @@ -175,6 +190,14 @@ struct videobuf_queue_ops { struct videobuf_buffer *vb); void (*buf_release)(struct videobuf_queue *q, struct videobuf_buffer *vb); + + /* Helper operations - device dependent. + * If null, videobuf_init defaults all to PCI handling + */ + + vb_map_sg_t *vb_map_sg; + vb_map_sg_t *vb_dma_sync_sg; + vb_map_sg_t *vb_unmap_sg; }; struct videobuf_queue { @@ -184,7 +207,7 @@ struct videobuf_queue { struct semaphore lock; #endif spinlock_t *irqlock; - struct pci_dev *pci; + void *dev; /* on pci, points to struct pci_dev */ enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ @@ -209,12 +232,15 @@ struct videobuf_queue { void* videobuf_alloc(unsigned int size); int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); -int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf); +int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf); + +/* Maps fops to PCI stuff */ +void videobuf_queue_pci(struct videobuf_queue* q); void videobuf_queue_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - struct pci_dev *pci, + void *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, diff --git a/mailimport b/mailimport index b563eecd9..e6e4df411 100755 --- a/mailimport +++ b/mailimport @@ -28,6 +28,10 @@ if [ "$TMPDIR" == "" ]; then TMPDIR=/tmp fi +if [ "$EDITOR" == "" ]; then + EDITOR=nano +fi + DIR=$TMPDIR/mailimport$$ mkdir $DIR if [ "$?" != "0" ]; then @@ -39,26 +43,35 @@ TMP2=$DIR/patchheader apply_patch () { next=$1 - pdir=linux - echo patch -s -t -p1 --dry-run -l -N -d $pdir -i $next - patch -s -t -p1 --dry-run -l -N -d $pdir -i $next - if [ "$?" != "0" ]; then - pdir=. + unset cont + until [ "$cont" == "0" ]; do + cont=1 + pdir=linux echo patch -s -t -p1 --dry-run -l -N -d $pdir -i $next patch -s -t -p1 --dry-run -l -N -d $pdir -i $next if [ "$?" != "0" ]; then - $head $next + pdir=. + echo patch -s -t -p1 --dry-run -l -N -d $pdir -i $next + patch -s -t -p1 --dry-run -l -N -d $pdir -i $next + fi + + if [ "$?" != "0" ]; then echo "*** ERROR: Patch didn't applied well" if [ "$exitonerror" != "" ]; then + $head $next exit - else - return fi + echo "** Edit file $next" + sleep 1 + $EDITOR $next + else + echo "Patch applied OK against $pdir" + cont=0 fi - fi + done - nano $next + $EDITOR $next unset cont until [ "$cont" == "0" ]; do @@ -68,7 +81,7 @@ apply_patch () { if [ "`grep '^Bad:' $TMP2`" != "" ]; then echo "*** ERROR: Patch bad formed. Please fix." sleep 1 - nano $next + $EDITOR $next cont=1 fi done diff --git a/v4l/Make.config b/v4l/Make.config index 65bc8dfea..7d8ae8e8d 100644 --- a/v4l/Make.config +++ b/v4l/Make.config @@ -9,7 +9,6 @@ CONFIG_VIDEO_TVAUDIO := m CONFIG_VIDEO_CX88 := m CONFIG_TVP5150 := m -CONFIG_SAA711X := m #enable experimental support for xc3028 tuner CONFIG_XC3028 := m @@ -26,6 +25,7 @@ CONFIG_VIDEO_IVTV := n CONFIG_DVB_FIRESAT := n +CONFIG_VIRTUAL_DEVICE := m CONFIG_VIDEO_CPIA2 := m CONFIG_VIDEO_CX88_IVTV := n diff --git a/v4l/Makefile b/v4l/Makefile index a81db15c9..fd757e928 100644 --- a/v4l/Makefile +++ b/v4l/Makefile @@ -97,7 +97,6 @@ obj-$(CONFIG_VIDEO_CX88) += btcx-risc.o cx88xx.o cx8800.o cx8802.o \ cx88-blackbird.o tveeprom.o obj-$(CONFIG_VIDEO_CX88_IVTV) += cx88-ivtv.o obj-$(CONFIG_TVP5150) += tvp5150.o -obj-$(CONFIG_SAA711X) += saa711x.o obj-$(CONFIG_EM28XX) += em28xx.o tveeprom.o obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840.o saa7127.o bt832.o @@ -109,6 +108,7 @@ ifeq ($(CONFIG_VIDEO_ALSA),y) # obj-$(CONFIG_VIDEO_BTTV) += bt87x.o endif +obj-$(CONFIG_VIRTUAL_DEVICE) += vivi.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o saa6752hs.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134-oss.o obj-$(CONFIG_VIDEO_IR) += ir-common.o @@ -310,13 +310,12 @@ inst_video := btcx-risc.ko bttv.ko tda9887.ko tuner.ko tvaudio.ko tveeprom.ko sa #inst_video += bt87x.ko inst_video += tvmixer.ko v4l1-compat.ko v4l2-common.ko wm8775.ko cs53l32a.ko inst_video += video-buf.ko video-buf-dvb.ko -ifeq ($(CONFIG_VIDEO_DEV),m) inst_video += videodev.ko -endif inst_video += ir-kbd-i2c.ko msp3400.ko -inst_video += tvp5150.ko saa711x.ko saa7134-alsa.ko saa7134-oss.ko +inst_video += tvp5150.ko saa7134-alsa.ko saa7134-oss.ko inst_video += saa7115.ko cx25840.ko saa7127.ko compat_ioctl32.ko inst_cx88 := cx88xx.ko cx8800.ko cx8802.ko cx88-alsa.ko cx88-dvb.ko +inst_video += vivi.ko inst_cx88 += cx88-blackbird.ko cx88-vp3054-i2c.ko cx88-ivtv.ko inst_saa7134 := saa6752hs.ko saa7134.ko saa7134-empress.ko saa7134-dvb.ko inst_em28xx := em28xx.ko diff --git a/v4l/scripts/cardlist b/v4l/scripts/cardlist index e368e6b4f..901d3fb18 100755 --- a/v4l/scripts/cardlist +++ b/v4l/scripts/cardlist @@ -1,6 +1,6 @@ #!/bin/sh -scripts/bttv.pl ../linux/drivers/media/video/bttv.h ../linux/drivers/media/video/bttv-cards.c \ +scripts/bttv.pl ../linux/drivers/media/video/bt8xx/bttv.h ../linux/drivers/media/video/bt8xx/bttv-cards.c \ | perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.bttv scripts/cx88.pl ../linux/drivers/media/video/cx88/cx88.h ../linux/drivers/media/video/cx88/cx88-cards.c \ diff --git a/v4l/scripts/insmod.sh b/v4l/scripts/insmod.sh index bf22a69ce..e4ebb1494 100755 --- a/v4l/scripts/insmod.sh +++ b/v4l/scripts/insmod.sh @@ -122,6 +122,8 @@ case "$1" in insmod ./saa6752hs.ko insmod ./em28xx.ko + insmod ./vivi.ko + echo ;; debug) @@ -232,6 +234,7 @@ case "$1" in insmod ./saa6752hs.ko insmod ./em28xx.ko + insmod ./vivi.ko echo ;; unload) @@ -246,7 +249,7 @@ case "$1" in # video4linux cards rmmod cx88-alsa cx88-blackbird cx88-dvb cx88-vp3054-i2c cx8802 cx8800 \ cx88xx saa7134-oss saa7134-alsa saa7134-empress saa7134-dvb \ - saa7134 dvb-bt8xx dst_ca dst bt878 bttv em28xx + saa7134 dvb-bt8xx dst_ca dst bt878 bttv em28xx vivi # frontends rmmod dib3000mb dib3000mc dib3000_common nxt200x ves1x93 \ |