diff options
Diffstat (limited to 'drivers/media')
28 files changed, 417 insertions, 210 deletions
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index c120114c241..5c63c8e24ee 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -4,5 +4,6 @@ config VIDEO_SAA7146 config VIDEO_SAA7146_VV tristate + depends on VIDEO_DEV select VIDEO_BUF select VIDEO_SAA7146 diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index efd2b746815..03ef88acd9b 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -11,7 +11,7 @@ menuconfig DVB_CAPTURE_DRIVERS ---help--- Say Y to select Digital TV adapters -if DVB_CAPTURE_DRIVERS +if DVB_CAPTURE_DRIVERS && DVB_CORE comment "Supported SAA7146 based PCI Adapters" depends on DVB_CORE && PCI && I2C diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile index 1a1c3bca55f..bff00b58bf6 100644 --- a/drivers/media/dvb/b2c2/Makefile +++ b/drivers/media/dvb/b2c2/Makefile @@ -1,8 +1,11 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ - flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \ - flexcop-dma.o + flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o +ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) +b2c2-flexcop-objs += flexcop-dma.o +endif + b2c2-flexcop-pci-objs = flexcop-pci.o obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 34d7abc900d..b40af48a2ed 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -118,6 +118,7 @@ struct cinergyt2 { struct dvb_demux demux; struct usb_device *udev; struct mutex sem; + struct mutex wq_sem; struct dvb_adapter adapter; struct dvb_device *fedev; struct dmxdev dmxdev; @@ -482,14 +483,14 @@ static int cinergyt2_open (struct inode *inode, struct file *file) struct cinergyt2 *cinergyt2 = dvbdev->priv; int err = -ERESTARTSYS; - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem)) + goto out; - if ((err = dvb_generic_open(inode, file))) { - mutex_unlock(&cinergyt2->sem); - return err; - } + if (mutex_lock_interruptible(&cinergyt2->sem)) + goto out_unlock1; + if ((err = dvb_generic_open(inode, file))) + goto out_unlock2; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { cinergyt2_sleep(cinergyt2, 0); @@ -498,8 +499,12 @@ static int cinergyt2_open (struct inode *inode, struct file *file) atomic_inc(&cinergyt2->inuse); +out_unlock2: mutex_unlock(&cinergyt2->sem); - return 0; +out_unlock1: + mutex_unlock(&cinergyt2->wq_sem); +out: + return err; } static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) @@ -519,16 +524,17 @@ static int cinergyt2_release (struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; - if (mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; + mutex_lock(&cinergyt2->wq_sem); if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { - cancel_delayed_work(&cinergyt2->query_work); - flush_scheduled_work(); + cancel_rearming_delayed_work(&cinergyt2->query_work); + + mutex_lock(&cinergyt2->sem); cinergyt2_sleep(cinergyt2, 1); + mutex_unlock(&cinergyt2->sem); } - mutex_unlock(&cinergyt2->sem); + mutex_unlock(&cinergyt2->wq_sem); if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { warn("delayed unregister in release"); @@ -839,13 +845,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { - cancel_delayed_work(&cinergyt2->rc_query_work); + cancel_rearming_delayed_work(&cinergyt2->rc_query_work); input_unregister_device(cinergyt2->rc_input_dev); } static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { - cancel_delayed_work(&cinergyt2->rc_query_work); + cancel_rearming_delayed_work(&cinergyt2->rc_query_work); } static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) @@ -908,6 +914,7 @@ static int cinergyt2_probe (struct usb_interface *intf, usb_set_intfdata (intf, (void *) cinergyt2); mutex_init(&cinergyt2->sem); + mutex_init(&cinergyt2->wq_sem); init_waitqueue_head (&cinergyt2->poll_wq); INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); @@ -975,11 +982,8 @@ static void cinergyt2_disconnect (struct usb_interface *intf) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - flush_scheduled_work(); - cinergyt2_unregister_rc(cinergyt2); - - cancel_delayed_work(&cinergyt2->query_work); + cancel_rearming_delayed_work(&cinergyt2->query_work); wake_up_interruptible(&cinergyt2->poll_wq); cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); @@ -993,21 +997,21 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem)) return -ERESTARTSYS; if (1) { - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); - cinergyt2_suspend_rc(cinergyt2); - cancel_delayed_work(&cinergyt2->query_work); + cancel_rearming_delayed_work(&cinergyt2->query_work); + + mutex_lock(&cinergyt2->sem); if (cinergyt2->streaming) cinergyt2_stop_stream_xfer(cinergyt2); - flush_scheduled_work(); cinergyt2_sleep(cinergyt2, 1); + mutex_unlock(&cinergyt2->sem); } - mutex_unlock(&cinergyt2->sem); + mutex_unlock(&cinergyt2->wq_sem); return 0; } @@ -1015,9 +1019,15 @@ static int cinergyt2_resume (struct usb_interface *intf) { struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); struct dvbt_set_parameters_msg *param = &cinergyt2->param; + int err = -ERESTARTSYS; - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) - return -ERESTARTSYS; + if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem)) + goto out; + + if (mutex_lock_interruptible(&cinergyt2->sem)) + goto out_unlock1; + + err = 0; if (!cinergyt2->sleeping) { cinergyt2_sleep(cinergyt2, 0); @@ -1030,7 +1040,10 @@ static int cinergyt2_resume (struct usb_interface *intf) cinergyt2_resume_rc(cinergyt2); mutex_unlock(&cinergyt2->sem); - return 0; +out_unlock1: + mutex_unlock(&cinergyt2->wq_sem); +out: + return err; } static const struct usb_device_id cinergyt2_table [] __devinitdata = { diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index ccc429cbbad..0f2d4b41556 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -41,6 +41,7 @@ struct tda10086_state { /* private demod data */ u32 frequency; u32 symbol_rate; + bool has_lock; }; static int debug = 0; @@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe) // misc setup tda10086_write_byte(state, 0x01, 0x94); tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP - tda10086_write_byte(state, 0x03, 0x64); + tda10086_write_byte(state, 0x03, 0xe4); tda10086_write_byte(state, 0x04, 0x43); tda10086_write_byte(state, 0x0c, 0x0c); tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold @@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe) // setup AGC tda10086_write_byte(state, 0x05, 0x0B); tda10086_write_byte(state, 0x37, 0x63); - tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it + tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it tda10086_write_byte(state, 0x40, 0x64); tda10086_write_byte(state, 0x41, 0x4f); tda10086_write_byte(state, 0x42, 0x43); @@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe, dprintk ("%s\n", __FUNCTION__); + // modify parameters for tuning + tda10086_write_byte(state, 0x02, 0x35); + state->has_lock = false; + // set params if (fe->ops.tuner_ops.set_params) { fe->ops.tuner_ops.set_params(fe, fe_params); @@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status) *fe_status |= FE_HAS_VITERBI; if (val & 0x08) *fe_status |= FE_HAS_SYNC; - if (val & 0x10) + if (val & 0x10) { *fe_status |= FE_HAS_LOCK; + if (!state->has_lock) { + state->has_lock = true; + // modify parameters for stable reception + tda10086_write_byte(state, 0x02, 0x00); + } + } return 0; } @@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal) dprintk ("%s\n", __FUNCTION__); - _str = tda10086_read_byte(state, 0x43); + _str = 0xff - tda10086_read_byte(state, 0x43); *signal = (_str << 8) | _str; return 0; @@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr) dprintk ("%s\n", __FUNCTION__); - _snr = tda10086_read_byte(state, 0x1c); + _snr = 0xff - tda10086_read_byte(state, 0x1c); *snr = (_snr << 8) | _snr; return 0; diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index 79f971dc52b..bd3ebc28483 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO buf[3] = div >> 7; buf[4] = div << 1; - buf[5] = 0xff; // basedband filter to max - buf[6] = 0xfe; // gains at max + no RF attenuation + buf[5] = 0x77; // baseband cut-off 19 MHz + buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation buf[7] = 0x83; // charge pumps at high, tests off buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports. buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 2557ac9620d..b611f2b1f8b 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -529,7 +529,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, if (bi->type != BUDGET_FS_ACTIVY) saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - if (budget_register(budget) == 0) + if ((ret = budget_register(budget)) == 0) return 0; /* Everything OK */ /* An error occurred, cleanup resources */ diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index a6ac82a609d..194b102140e 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -9,7 +9,7 @@ menuconfig RADIO_ADAPTERS ---help--- Say Y here to enable selecting AM/FM radio adapters. -if RADIO_ADAPTERS +if RADIO_ADAPTERS && VIDEO_DEV config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index fdf5d6e46ea..5e6f17df204 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -94,7 +94,6 @@ struct gemtek_pci_card { u32 iobase; u32 length; - u8 chiprev; u16 model; u32 current_frequency; @@ -415,7 +414,6 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci goto err_pci; } - pci_read_config_byte( pci_dev, PCI_REVISION_ID, &card->chiprev ); pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model ); pci_set_drvdata( pci_dev, card ); @@ -436,7 +434,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci gemtek_pci_mute( card ); printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - card->chiprev, card->iobase, card->iobase + card->length - 1 ); + pci_dev->revision, card->iobase, card->iobase + card->length - 1 ); return 0; diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 5cb3f54b548..4d45a40016d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -11,7 +11,7 @@ menuconfig VIDEO_CAPTURE_DRIVERS webcams, analog TV, and hybrid analog/digital TV. Some of those devices also supports FM radio. -if VIDEO_CAPTURE_DRIVERS +if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" @@ -691,7 +691,7 @@ menuconfig V4L_USB_DRIVERS depends on USB default y -if V4L_USB_DRIVERS +if V4L_USB_DRIVERS && USB source "drivers/media/video/pvrusb2/Kconfig" diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 1c38723d316..b1fedb0f643 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1331,7 +1331,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) /* Call with btv->lock down. */ static void -set_input(struct bttv *btv, unsigned int input) +set_input(struct bttv *btv, unsigned int input, unsigned int norm) { unsigned long flags; @@ -1350,7 +1350,7 @@ set_input(struct bttv *btv, unsigned int input) } audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); - set_tvnorm(btv,btv->tvnorm); + set_tvnorm(btv, norm); i2c_vidiocschan(btv); } @@ -1441,7 +1441,7 @@ static void bttv_reinit_bt848(struct bttv *btv) init_bt848(btv); btv->pll.pll_current = -1; - set_input(btv,btv->input); + set_input(btv, btv->input, btv->tvnorm); } static int get_control(struct bttv *btv, struct v4l2_control *c) @@ -2011,8 +2011,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - btv->tvnorm = v->norm; - set_input(btv,v->channel); + set_input(btv, v->channel, v->norm); mutex_unlock(&btv->lock); return 0; } @@ -2148,7 +2147,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (*i > bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; mutex_lock(&btv->lock); - set_input(btv,*i); + set_input(btv, *i, btv->tvnorm); mutex_unlock(&btv->lock); return 0; } @@ -4780,7 +4779,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, bt848_hue(btv,32768); bt848_sat(btv,32768); audio_mute(btv, 1); - set_input(btv,0); + set_input(btv, 0, btv->tvnorm); bttv_crop_reset(&btv->crop[0], btv->tvnorm); btv->crop[1] = btv->crop[0]; /* current = default */ disclaim_vbi_lines(btv); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index b0466b88f52..a80b1cb1abe 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1034,6 +1034,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, if (unlikely(UNSET == core->tuner_type)) return -EINVAL; + if (0 != t->index) + return -EINVAL; strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 15012f88b80..91e9e90c14a 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -86,7 +86,7 @@ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ V4L2_CAP_SLICED_VBI_CAPTURE) #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ - V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS) + V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) struct ivtv_card_video_input { u8 video_type; /* video input type */ diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e29f949adf5..efc66355339 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->dma_timer.data = (unsigned long)itv; itv->cur_dma_stream = -1; + itv->cur_pio_stream = -1; itv->audio_stereo_mode = AUDIO_STEREO; itv->audio_bilingual_mode = AUDIO_MONO_LEFT; diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 552f04511ea..e6e56f175f3 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -237,6 +237,7 @@ extern const u32 yuv_offset[4]; #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) +#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25) #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) @@ -247,7 +248,8 @@ extern const u32 yuv_offset[4]; #define IVTV_IRQ_DEC_VSYNC (0x1 << 10) /* IRQ Masks */ -#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ) +#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\ + IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE) #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) @@ -374,6 +376,9 @@ struct ivtv_mailbox_data { #define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ +#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */ +#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */ + /* per-ivtv, i_flags */ #define IVTV_F_I_DMA 0 /* DMA in progress */ #define IVTV_F_I_UDMA 1 /* UDMA in progress */ @@ -390,8 +395,11 @@ struct ivtv_mailbox_data { #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ -#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */ -#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */ +#define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */ +#define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */ +#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ +#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ +#define IVTV_F_I_PIO 19 /* PIO in progress */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ @@ -484,6 +492,7 @@ struct ivtv_stream { /* Base Dev SG Array for cx23415/6 */ struct ivtv_SG_element *SGarray; + struct ivtv_SG_element *PIOarray; dma_addr_t SG_handle; int SG_length; @@ -706,6 +715,7 @@ struct ivtv { atomic_t decoding; /* count number of active decoding streams */ u32 irq_rr_idx; /* Round-robin stream index */ int cur_dma_stream; /* index of stream doing DMA */ + int cur_pio_stream; /* index of stream doing PIO */ u32 dma_data_req_offset; u32 dma_data_req_size; int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 8976487a65f..555d5e6369c 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -32,6 +32,8 @@ #include "ivtv-yuv.h" #include "ivtv-controls.h" #include "ivtv-ioctl.h" +#include "ivtv-cards.h" +#include <media/saa7115.h> /* This function tries to claim the stream for a specific file descriptor. If no one else is using this stream then the stream is claimed and @@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); /* Select correct audio input (i.e. TV tuner or Line in) */ ivtv_audio_set_io(itv); + if (itv->hw_flags & IVTV_HW_SAA711X) + { + struct v4l2_crystal_freq crystal_freq; + crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; + crystal_freq.flags = 0; + ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + } /* Done! Unmute and continue. */ ivtv_unmute(itv); ivtv_release_stream(s); @@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); /* Select the correct audio input (i.e. radio tuner) */ ivtv_audio_set_io(itv); + if (itv->hw_flags & IVTV_HW_SAA711X) + { + struct v4l2_crystal_freq crystal_freq; + crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; + crystal_freq.flags = SAA7115_FREQ_FL_APLL; + ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); + } /* Done! Unmute and continue. */ ivtv_unmute(itv); } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 1989ec1cb97..57af1762de1 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, itv->yuv_info.yuv_forced_update = 1; return 0; } - if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, - r.width, r.height, r.left, r.top)) - itv->main_rect = r; - else - return -EINVAL; } return 0; } @@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void return ivtv_get_fmt(itv, id->type, fmt); } + case VIDIOC_CROPCAP: { + struct v4l2_cropcap *cropcap = arg; + + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + cropcap->bounds.top = cropcap->bounds.left = 0; + cropcap->bounds.width = 720; + if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + cropcap->bounds.height = itv->is_50hz ? 576 : 480; + cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; + cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; + } else { + cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; + cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; + cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; + } + cropcap->defrect = cropcap->bounds; + return 0; + } + case VIDIOC_S_CROP: { struct v4l2_crop *crop = arg; + if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { + if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, + crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { + itv->main_rect = crop->c; + return 0; + } + return -EINVAL; + } if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); @@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void case VIDIOC_G_CROP: { struct v4l2_crop *crop = arg; + if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { + crop->c = itv->main_rect; + return 0; + } if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); @@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void if (itv->hw_flags & IVTV_HW_CX25840) { itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; } - IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std); + IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); /* Tuner */ ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); @@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void (s->buffers - s->q_free.buffers) * 100 / s->buffers, (s->buffers * s->buf_size) / 1024, s->buffers); } - IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted); + IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); break; } @@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: case VIDIOC_ENUM_FMT: + case VIDIOC_CROPCAP: case VIDIOC_G_CROP: case VIDIOC_S_CROP: case VIDIOC_G_FREQUENCY: diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index c3a047b381b..ba98bf054f2 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -31,8 +31,6 @@ #define DMA_MAGIC_COOKIE 0x000001fe -#define SLICED_VBI_PIO 1 - static void ivtv_dma_dec_start(struct ivtv_stream *s); static const int ivtv_stream_map[] = { @@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = { IVTV_ENC_STREAM_TYPE_VBI, }; -static inline int ivtv_use_pio(struct ivtv_stream *s) + +static void ivtv_pio_work_handler(struct ivtv *itv) { - struct ivtv *itv = s->itv; + struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream]; + struct ivtv_buffer *buf; + struct list_head *p; + int i = 0; + + IVTV_DEBUG_DMA("ivtv_pio_work_handler\n"); + if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || + s->v4l2dev == NULL || !ivtv_use_pio(s)) { + itv->cur_pio_stream = -1; + /* trigger PIO complete user interrupt */ + write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); + return; + } + IVTV_DEBUG_DMA("Process PIO %s\n", s->name); + buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list); + list_for_each(p, &s->q_dma.list) { + struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); + u32 size = s->PIOarray[i].size & 0x3ffff; - return s->dma == PCI_DMA_NONE || - (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); + /* Copy the data from the card to the buffer */ + if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { + memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size); + } + else { + memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size); + } + if (s->PIOarray[i].size & 0x80000000) + break; + i++; + } + write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); } void ivtv_irq_work_handler(struct work_struct *work) @@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work) DEFINE_WAIT(wait); + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) + ivtv_pio_work_handler(itv); + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) - vbi_work_handler(itv); + ivtv_vbi_work_handler(itv); if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) ivtv_yuv_work_handler(itv); @@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA } s->buffers_stolen = rc; - /* got the buffers, now fill in SGarray (DMA) or copy the data from the card - to the buffers (PIO). */ + /* got the buffers, now fill in SGarray (DMA) */ buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); memset(buf->buf, 0, 128); list_for_each(p, &s->q_predma.list) { @@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA if (skip_bufs-- > 0) continue; - if (!ivtv_use_pio(s)) { - s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); - s->SGarray[idx].src = cpu_to_le32(offset); - s->SGarray[idx].size = cpu_to_le32(s->buf_size); - } + s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); + s->SGarray[idx].src = cpu_to_le32(offset); + s->SGarray[idx].size = cpu_to_le32(s->buf_size); buf->bytesused = (size < s->buf_size) ? size : s->buf_size; - /* If PIO, then copy the data from the card to the buffer */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { - memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused); - } - else if (ivtv_use_pio(s)) { - memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused); - } - s->q_predma.bytesused += buf->bytesused; size -= buf->bytesused; offset += s->buf_size; @@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s) u32 *u32buf; int x = 0; - if (ivtv_use_pio(s)) { - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - s->SG_length = 0; - } IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", s->name, s->dma_offset); list_for_each(p, &s->q_dma.list) { @@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s) if (buf) buf->bytesused += s->dma_last_offset; if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { - /* Parse and Groom VBI Data */ - s->q_dma.bytesused -= buf->bytesused; - ivtv_process_vbi_data(itv, buf, 0, s->type); - s->q_dma.bytesused += buf->bytesused; + list_for_each(p, &s->q_dma.list) { + buf = list_entry(p, struct ivtv_buffer, list); + + /* Parse and Groom VBI Data */ + s->q_dma.bytesused -= buf->bytesused; + ivtv_process_vbi_data(itv, buf, 0, s->type); + s->q_dma.bytesused += buf->bytesused; + } if (s->id == -1) { ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); return; @@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; int i; + IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name); + if (s->q_predma.bytesused) ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - IVTV_DEBUG_DMA("start DMA for %s\n", s->name); - s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); + + if (ivtv_use_dma(s)) + s->SGarray[s->SG_length - 1].size = + cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); /* If this is an MPEG stream, and VBI data is also pending, then append the VBI DMA to the MPEG DMA and transfer both sets of data at once. @@ -368,7 +389,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && s->SG_length + s_vbi->SG_length <= s->buffers) { ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); - s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); + if (ivtv_use_dma(s_vbi)) + s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); for (i = 0; i < s_vbi->SG_length; i++) { s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; } @@ -381,14 +403,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) /* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); - /* Sync Hardware SG List of buffers */ - ivtv_stream_sync_for_device(s); - write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); - write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); - set_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + HZ / 10; - add_timer(&itv->dma_timer); + if (ivtv_use_pio(s)) { + for (i = 0; i < s->SG_length; i++) { + s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); + s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size); + } + set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags); + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); + set_bit(IVTV_F_I_PIO, &itv->i_flags); + itv->cur_pio_stream = s->type; + } + else { + /* Sync Hardware SG List of buffers */ + ivtv_stream_sync_for_device(s); + write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); + write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); + set_bit(IVTV_F_I_DMA, &itv->i_flags); + itv->cur_dma_stream = s->type; + itv->dma_timer.expires = jiffies + HZ / 10; + add_timer(&itv->dma_timer); + } } static void ivtv_dma_dec_start(struct ivtv_stream *s) @@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) wake_up(&itv->dma_waitq); } +static void ivtv_irq_enc_pio_complete(struct ivtv *itv) +{ + struct ivtv_stream *s; + + if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) { + itv->cur_pio_stream = -1; + return; + } + s = &itv->streams[itv->cur_pio_stream]; + IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name); + s->SG_length = 0; + clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + clear_bit(IVTV_F_I_PIO, &itv->i_flags); + itv->cur_pio_stream = -1; + dma_post(s); + if (s->type == IVTV_ENC_STREAM_TYPE_MPG) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0); + else if (s->type == IVTV_ENC_STREAM_TYPE_YUV) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1); + else if (s->type == IVTV_ENC_STREAM_TYPE_PCM) + ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2); + clear_bit(IVTV_F_I_PIO, &itv->i_flags); + if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { + u32 tmp; + + s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; + tmp = s->dma_offset; + s->dma_offset = itv->vbi.dma_offset; + dma_post(s); + s->dma_offset = tmp; + } + wake_up(&itv->dma_waitq); +} + static void ivtv_irq_dma_err(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; @@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0]]]; if (!stream_enc_dma_append(s, data)) { - if (ivtv_use_pio(s)) { - dma_post(s); - ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]); - } - else { - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); - } + set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } @@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - if (ivtv_use_pio(s)) { - if (stream_enc_dma_append(s, data)) - return; - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - s->SG_length = 0; - dma_post(s); - return; - } /* If more than two VBI buffers are pending, then clear the old ones and start with this new one. This can happen during transition stages when MPEG capturing is @@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) if (!stream_enc_dma_append(s, data) && !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); + set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } -static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) +static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; @@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && !stream_enc_dma_append(s, data)) { - dma_post(s); + set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags); } } @@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv) } if (frame != (itv->lastVsyncFrame & 1)) { struct ivtv_stream *s = ivtv_get_output_stream(itv); - int work = 0; itv->lastVsyncFrame += 1; if (frame == 0) { @@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) /* Send VBI to saa7127 */ if (frame) { set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); - work = 1; + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } /* Check if we need to update the yuv registers */ @@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv) itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.yuv_forced_update = 0; set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); - work = 1; + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } } - if (work) - queue_work(itv->irq_work_queues, &itv->irq_work_queue); } } @@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ivtv_irq_enc_dma_complete(itv); } + if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) { + ivtv_irq_enc_pio_complete(itv); + } + if (combo & IVTV_IRQ_DMA_ERR) { ivtv_irq_dma_err(itv); } @@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) } if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { - ivtv_irq_dev_vbi_reinsert(itv); + ivtv_irq_dec_vbi_reinsert(itv); } if (combo & IVTV_IRQ_ENC_EOS) { @@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) } } + if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { + for (i = 0; i < IVTV_MAX_STREAMS; i++) { + int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS; + struct ivtv_stream *s = &itv->streams[idx]; + + if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags)) + continue; + if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG) + ivtv_dma_enc_start(s); + break; + } + } + + if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) + queue_work(itv->irq_work_queues, &itv->irq_work_queue); + spin_unlock(&itv->dma_reg_lock); /* If we've just handled a 'forced' vsync, it's safest to say it diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index ccfcef1ad91..a04f9387f63 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c @@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s) s->dma != PCI_DMA_NONE ? "DMA " : "", s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - /* Allocate DMA SG Arrays */ - if (s->dma != PCI_DMA_NONE) { - s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); - if (s->SGarray == NULL) { - IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); + if (ivtv_might_use_pio(s)) { + s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); + if (s->PIOarray == NULL) { + IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name); return -ENOMEM; } - s->SG_length = 0; + } + + /* Allocate DMA SG Arrays */ + s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); + if (s->SGarray == NULL) { + IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); + if (ivtv_might_use_pio(s)) { + kfree(s->PIOarray); + s->PIOarray = NULL; + } + return -ENOMEM; + } + s->SG_length = 0; + if (ivtv_might_use_dma(s)) { s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); ivtv_stream_sync_for_cpu(s); } @@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) break; } INIT_LIST_HEAD(&buf->list); - if (s->dma != PCI_DMA_NONE) { + if (ivtv_might_use_dma(s)) { buf->dma_handle = pci_map_single(s->itv->dev, buf->buf, s->buf_size + 256, s->dma); ivtv_buf_sync_for_cpu(s, buf); @@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* empty q_free */ while ((buf = ivtv_dequeue(s, &s->q_free))) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_might_use_dma(s)) pci_unmap_single(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); kfree(buf->buf); @@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s) sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); s->SG_handle = IVTV_DMA_UNMAPPED; } + kfree(s->SGarray); + kfree(s->PIOarray); + s->PIOarray = NULL; s->SGarray = NULL; s->SG_length = 0; } diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h index 903edd4b438..2ed8d548255 100644 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ b/drivers/media/video/ivtv/ivtv-queue.h @@ -20,18 +20,43 @@ */ #define IVTV_DMA_UNMAPPED ((u32) -1) +#define SLICED_VBI_PIO 1 /* ivtv_buffer utility functions */ + +static inline int ivtv_might_use_pio(struct ivtv_stream *s) +{ + return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI); +} + +static inline int ivtv_use_pio(struct ivtv_stream *s) +{ + struct ivtv *itv = s->itv; + + return s->dma == PCI_DMA_NONE || + (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); +} + +static inline int ivtv_might_use_dma(struct ivtv_stream *s) +{ + return s->dma != PCI_DMA_NONE; +} + +static inline int ivtv_use_dma(struct ivtv_stream *s) +{ + return !ivtv_use_pio(s); +} + static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_use_dma(s)) pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); } static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) { - if (s->dma != PCI_DMA_NONE) + if (ivtv_use_dma(s)) pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, s->buf_size + 256, s->dma); } @@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s); static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) { - pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, - sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); + if (ivtv_use_dma(s)) + pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, + sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); } static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) { - pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, - sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); + if (ivtv_use_dma(s)) + pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, + sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 01a41a844a3..6af88ae9295 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags)) return 0; - IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags); + IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); /* Stop Decoder */ if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 5efa5a86781..3ba46e07ea1 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv) } -void vbi_work_handler(struct ivtv *itv) +void ivtv_vbi_work_handler(struct ivtv *itv) { struct v4l2_sliced_vbi_data data; diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index cdaea697b3e..ec211b49702 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, int ivtv_used_line(struct ivtv *itv, int line, int field); void ivtv_disable_vbi(struct ivtv *itv); void ivtv_set_vbi(unsigned long arg); -void vbi_work_handler(struct ivtv *itv); +void ivtv_vbi_work_handler(struct ivtv *itv); diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 664aba8b4d8..7533fc20331 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1809,7 +1809,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, { int ret = -EBUSY; unsigned long mchip_adr; - u8 revision; if (meye.mchip_dev != NULL) { printk(KERN_ERR "meye: only one device allowed!\n"); @@ -1885,7 +1884,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outreqirq; } - pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8); pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64); @@ -1939,7 +1937,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", MEYE_DRIVER_VERSION); printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", - revision, mchip_adr, meye.mchip_irq); + meye.mchip_dev->revision, mchip_adr, meye.mchip_irq); return 0; diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 74839f98b7c..c1a392e4717 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -75,10 +75,6 @@ struct saa7111 { int norm; int input; int enable; - int bright; - int contrast; - int hue; - int sat; }; #define I2C_SAA7111 0x48 @@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } +static inline void +saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) +{ + struct saa7111 *decoder = i2c_get_clientdata(client); + + if (decoder->reg[reg] != value) { + decoder->reg[reg] = value; + i2c_smbus_write_byte_data(client, reg, value); + } +} + static int saa7111_write_block (struct i2c_client *client, const u8 *data, @@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client, { struct video_picture *pic = arg; - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7111_write(client, 0x0a, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7111_write(client, 0x0b, - decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7111_write(client, 0x0c, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7111_write(client, 0x0d, - (decoder->hue - 32768) >> 8); - } + /* We want 0 to 255 we get 0-65535 */ + saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8); + /* We want 0 to 127 we get 0-65535 */ + saa7111_write(client, 0x0b, pic->contrast >> 9); + /* We want 0 to 127 we get 0-65535 */ + saa7111_write(client, 0x0c, pic->colour >> 9); + /* We want -128 to 127 we get 0-65535 */ + saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); } break; @@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter, decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; i2c_set_clientdata(client, decoder); i = i2c_attach_client(client); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 7b56041186d..30395d6b5f1 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -1005,7 +1005,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) int saa7134_tvaudio_fini(struct saa7134_dev *dev) { /* shutdown tvaudio thread */ - if (dev->thread.pid >= 0) { + if (dev->thread.pid > 0) { dev->thread.shutdown = 1; wake_up_interruptible(&dev->thread.wq); wait_for_completion(&dev->thread.exit); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 9118a6227ea..7df071eb0a3 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb) if (!USBVISION_IS_OPERATIONAL(usbvision)) return; + /* any urb with wrong status is ignored without acknowledgement */ + if (urb->status == -ENOENT) { + return; + } + f = &usbvision->curFrame; /* Manage streaming interruption */ @@ -1436,18 +1441,21 @@ static void usbvision_isocIrq(struct urb *urb) if (usbvision->streaming == Stream_On) { /* If we collected enough data let's parse! */ - if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ - /*If we don't have a frame we're current working on, complain */ - if(!list_empty(&(usbvision->inqueue))) { - if (!(*f)) { - (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); - } - usbvision_parse_data(usbvision); - } - else { - PDEBUG(DBG_IRQ, "received data, but no one needs it"); - scratch_reset(usbvision); + if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) && + (!list_empty(&(usbvision->inqueue))) ) { + if (!(*f)) { + (*f) = list_entry(usbvision->inqueue.next, + struct usbvision_frame, + frame); } + usbvision_parse_data(usbvision); + } + else { + /*If we don't have a frame + we're current working on, complain */ + PDEBUG(DBG_IRQ, + "received data, but no one needs it"); + scratch_reset(usbvision); } } else { @@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb) urb->dev = usbvision->dev; errCode = usb_submit_urb (urb, GFP_ATOMIC); - /* Disable this warning. By design of the driver. */ - // if(errCode) { - // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); - // } + if(errCode) { + err("%s: usb_submit_urb failed: error %d", + __FUNCTION__, errCode); + } return; } @@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) { struct usb_device *dev = usbvision->dev; int bufIdx, errCode, regValue; - const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; + int sb_size; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -EFAULT; @@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) usbvision->last_error = errCode; return -EBUSY; } + sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; - regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; + regValue = (16 - usbvision_read_reg(usbvision, + USBVISION_ALTER_REG)) & 0x0F; usbvision->usb_bandwidth = regValue >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); + PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", + usbvision->usb_bandwidth); @@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) return -ENOMEM; } usbvision->sbuf[bufIdx].urb = urb; - usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma); + usbvision->sbuf[bufIdx].data = + usb_buffer_alloc(usbvision->dev, + sb_size, + GFP_KERNEL, + &urb->transfer_dma); urb->dev = dev; urb->context = usbvision; urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); @@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) for (j = k = 0; j < USBVISION_URB_FRAMES; j++, k += usbvision->isocPacketSize) { urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = usbvision->isocPacketSize; + urb->iso_frame_desc[j].length = + usbvision->isocPacketSize; } } /* Submit all URBs */ for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); + errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, + GFP_KERNEL); if (errCode) { - err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); + err("%s: usb_submit_urb(%d) failed: error %d", + __FUNCTION__, bufIdx, errCode); } } usbvision->streaming = Stream_Idle; - PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); + PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", + __FUNCTION__, + usbvision->video_endp); return 0; } @@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) void usbvision_stop_isoc(struct usb_usbvision *usbvision) { int bufIdx, errCode, regValue; - const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; + int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) return; @@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) errCode = usb_set_interface(usbvision->dev, usbvision->iface, usbvision->ifaceAlt); if (errCode < 0) { - err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); + err("%s: usb_set_interface() failed: error %d", + __FUNCTION__, errCode); usbvision->last_error = errCode; } - regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); + regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; + usbvision->isocPacketSize = + (regValue == 0) ? 0 : (regValue * 64) - 1; + PDEBUG(DBG_ISOC, "ISO Packet Length:%d", + usbvision->isocPacketSize); usbvision->usb_bandwidth = regValue >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); + PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", + usbvision->usb_bandwidth); } } diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index bd6f6422ed5..c759d00d701 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -146,7 +146,6 @@ #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask #define USBVISION_URB_FRAMES 32 -#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023 #define USBVISION_NUM_HEADERMARKER 20 #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ |