--- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -32,6 +32,7 @@ #include #include #include #include +#include #include "saa7134-reg.h" #include "saa7134.h" @@ -360,6 +361,38 @@ void saa7134_buffer_timeout(unsigned lon spin_unlock_irqrestore(&dev->slock,flags); } +/* resends a current buffer in queue after resume */ + +int saa7134_buffer_requeue(struct saa7134_dev *dev, + struct saa7134_dmaqueue *q) +{ + struct saa7134_buf *buf , *next ; + unsigned long flags; + + spin_lock_irqsave(&dev->slock,flags); + + buf = q->curr; + next = buf; + + dprintk("buffer_requeue\n"); + + if (!buf) { + spin_unlock_irqrestore(&dev->slock,flags); + return 0; + } + + dprintk("buffer_requeue : resending active buffers \n"); + + if (!list_empty(&q->queue)) + next = list_entry(q->queue.next,struct saa7134_buf, + vb.queue); + + buf->activate(dev,buf,next); + spin_unlock_irqrestore(&dev->slock,flags); + + return 0; +} + /* ------------------------------------------------------------------ */ int saa7134_set_dmabits(struct saa7134_dev *dev) @@ -615,6 +648,39 @@ static irqreturn_t saa7134_irq(int irq, /* ------------------------------------------------------------------ */ /* early init (no i2c, no irq) */ + +static int saa7134_hw_enable1(struct saa7134_dev *dev) +{ + /* RAM FIFO config */ + saa_writel(SAA7134_FIFO_SIZE, 0x08070503); + saa_writel(SAA7134_THRESHOULD,0x02020202); + + /* enable audio + video processing */ + saa_writel(SAA7134_MAIN_CTRL, + SAA7134_MAIN_CTRL_VPLLE | + SAA7134_MAIN_CTRL_APLLE | + SAA7134_MAIN_CTRL_EXOSC | + SAA7134_MAIN_CTRL_EVFE1 | + SAA7134_MAIN_CTRL_EVFE2 | + SAA7134_MAIN_CTRL_ESFE | + SAA7134_MAIN_CTRL_EBDAC); + + /* + * Initialize OSS _after_ enabling audio clock PLL and audio processing. + * OSS initialization writes to registers via the audio DSP; these + * writes will fail unless the audio clock has been started. At worst, + * audio will not work. + */ + + /* enable peripheral devices */ + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + + /* set vertical line numbering start (vbi needs this) */ + saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); + + return 0; +} + static int saa7134_hwinit1(struct saa7134_dev *dev) { dprintk("hwinit1\n"); @@ -631,44 +697,16 @@ static int saa7134_hwinit1(struct saa713 saa7134_ts_init1(dev); saa7134_input_init1(dev); - /* RAM FIFO config */ - saa_writel(SAA7134_FIFO_SIZE, 0x08070503); - saa_writel(SAA7134_THRESHOULD,0x02020202); - - /* enable audio + video processing */ - saa_writel(SAA7134_MAIN_CTRL, - SAA7134_MAIN_CTRL_VPLLE | - SAA7134_MAIN_CTRL_APLLE | - SAA7134_MAIN_CTRL_EXOSC | - SAA7134_MAIN_CTRL_EVFE1 | - SAA7134_MAIN_CTRL_EVFE2 | - SAA7134_MAIN_CTRL_ESFE | - SAA7134_MAIN_CTRL_EBDAC); - - /* - * Initialize OSS _after_ enabling audio clock PLL and audio processing. - * OSS initialization writes to registers via the audio DSP; these - * writes will fail unless the audio clock has been started. At worst, - * audio will not work. - */ - - /* enable peripheral devices */ - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); - - /* set vertical line numbering start (vbi needs this) */ - saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); + saa7134_hw_enable1(dev); return 0; } /* late init (with i2c + irq) */ -static int saa7134_hwinit2(struct saa7134_dev *dev) +static int saa7134_hw_enable2(struct saa7134_dev *dev) { - unsigned int irq2_mask; - dprintk("hwinit2\n"); - saa7134_video_init2(dev); - saa7134_tvaudio_init2(dev); + unsigned int irq2_mask; /* enable IRQ's */ irq2_mask = @@ -694,6 +732,20 @@ static int saa7134_hwinit2(struct saa713 return 0; } +static int saa7134_hwinit2(struct saa7134_dev *dev) +{ + + dprintk("hwinit2\n"); + + saa7134_video_init2(dev); + saa7134_tvaudio_init2(dev); + + saa7134_hw_enable2(dev); + + return 0; +} + + /* shutdown */ static int saa7134_hwfini(struct saa7134_dev *dev) { @@ -1093,6 +1145,62 @@ static void __devexit saa7134_finidev(st kfree(dev); } +static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) +{ + + /* Disable card's IRQs to prevent it from resuming computer */ + + struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + + saa_writel(SAA7134_IRQ1, 0); + saa_writel(SAA7134_IRQ2, 0); + + + pci_set_power_state(pci_dev, pci_choose_state(pci_dev,state)); + pci_save_state(pci_dev); + + return 0; +} + +static int saa7134_resume(struct pci_dev *pci_dev) +{ + + struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + + pci_restore_state(pci_dev); + pci_set_power_state(pci_dev, PCI_D0); + + /* Do things that are done in saa7134_initdev , except of initializing memory structures.*/ + + saa7134_board_init1(dev); + + if (saa7134_boards[dev->board].video_out) + saa7134_videoport_init(dev); + + if (card_has_mpeg(dev)) + saa7134_ts_init_hw(dev); + + saa7134_hw_enable1(dev); + + saa7134_set_decoder(dev); + + saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); + + saa7134_board_init2(dev); + saa7134_hw_enable2(dev); + + + saa7134_tvaudio_setvolume(dev,dev->ctl_volume); + saa7134_enable_i2s(dev); + + /*recapture unfinished buffer(s)*/ + saa7134_buffer_requeue(dev , &dev->video_q); + saa7134_buffer_requeue(dev , &dev->vbi_q); + saa7134_buffer_requeue(dev , &dev->ts_q); + + return 0; +} + /* ----------------------------------------------------------- */ int saa7134_ts_register(struct saa7134_mpeg_ops *ops) @@ -1134,6 +1242,8 @@ static struct pci_driver saa7134_pci_dri .id_table = saa7134_pci_tbl, .probe = saa7134_initdev, .remove = __devexit_p(saa7134_finidev), + .suspend = saa7134_suspend, + .resume = saa7134_resume }; static int saa7134_init(void) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 60a90a2..0838ccf 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -176,6 +176,18 @@ static unsigned int ts_nr_packets = 64; module_param(ts_nr_packets, int, 0444); MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); +int saa7134_ts_init_hw(struct saa7134_dev *dev) +{ + saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ + saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); + saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); + saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); + saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + + return 0; +} + int saa7134_ts_init1(struct saa7134_dev *dev) { /* sanitycheck insmod options */ @@ -199,12 +211,7 @@ int saa7134_ts_init1(struct saa7134_dev saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); /* init TS hw */ - saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ - saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ - saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); - saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); - saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); - saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + saa7134_ts_init_hw(dev); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index dd759d6..4298ca4 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -884,7 +884,7 @@ static int tvaudio_thread_ddep(void *dat /* ------------------------------------------------------------------ */ /* common stuff + external entry points */ -static void saa7134_enable_i2s(struct saa7134_dev *dev) + void saa7134_enable_i2s(struct saa7134_dev *dev) { int i2s_format; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index f2cb630..11d930b 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -542,22 +542,13 @@ void res_free(struct saa7134_dev *dev, s /* ------------------------------------------------------------------ */ -static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) +void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) { - int luma_control,sync_control,mux; + dprintk("set tv norm = %s\n",norm->name); dev->tvnorm = norm; - mux = card_in(dev,dev->ctl_input).vmux; - luma_control = norm->luma_control; - sync_control = norm->sync_control; - - if (mux > 5) - luma_control |= 0x80; /* svideo */ - if (noninterlaced || dev->nosignal) - sync_control |= 0x20; - /* setup cropping */ dev->crop_bounds.left = norm->h_start; dev->crop_defrect.left = norm->h_start; @@ -572,6 +563,34 @@ static void set_tvnorm(struct saa7134_de dev->crop_current = dev->crop_defrect; + saa7134_set_decoder(dev); + + saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); +} + +static void video_mux(struct saa7134_dev *dev, int input) +{ + dprintk("video input = %d [%s]\n",input,card_in(dev,input).name); + dev->ctl_input = input; + set_tvnorm(dev,dev->tvnorm); + saa7134_tvaudio_setinput(dev,&card_in(dev,input)); +} + +void saa7134_set_decoder(struct saa7134_dev *dev) +{ + int luma_control,sync_control,mux; + + struct saa7134_tvnorm *norm = dev->tvnorm; + mux = card_in(dev,dev->ctl_input).vmux; + + luma_control = norm->luma_control; + sync_control = norm->sync_control; + + if (mux > 5) + luma_control |= 0x80; /* svideo */ + if (noninterlaced || dev->nosignal) + sync_control |= 0x20; + /* setup video decoder */ saa_writeb(SAA7134_INCR_DELAY, 0x08); saa_writeb(SAA7134_ANALOG_IN_CTRL1, 0xc0 | mux); @@ -602,16 +621,6 @@ static void set_tvnorm(struct saa7134_de saa_writeb(SAA7134_MISC_VGATE_MSB, norm->vgate_misc); saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); - - saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); -} - -static void video_mux(struct saa7134_dev *dev, int input) -{ - dprintk("video input = %d [%s]\n",input,card_in(dev,input).name); - dev->ctl_input = input; - set_tvnorm(dev,dev->tvnorm); - saa7134_tvaudio_setinput(dev,&card_in(dev,input)); } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) @@ -2419,35 +2428,41 @@ int saa7134_video_init1(struct saa7134_d dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.dev = dev; - if (saa7134_boards[dev->board].video_out) { - /* enable video output */ - int vo = saa7134_boards[dev->board].video_out; - int video_reg; - unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; - saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); - video_reg = video_out[vo][1]; - if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) - video_reg &= ~VP_T_CODE_P_INVERTED; - saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); - saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); - video_reg = video_out[vo][5]; - if (vid_port_opts & SET_CLOCK_NOT_DELAYED) - video_reg &= ~VP_CLK_CTRL2_DELAYED; - if (vid_port_opts & SET_CLOCK_INVERTED) - video_reg |= VP_CLK_CTRL1_INVERTED; - saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg); - video_reg = video_out[vo][6]; - if (vid_port_opts & SET_VSYNC_OFF) { - video_reg &= ~VP_VS_TYPE_MASK; - video_reg |= VP_VS_TYPE_OFF; - } - saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg); - saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); - } + if (saa7134_boards[dev->board].video_out) + saa7134_videoport_init(dev); + + return 0; +} +int saa7134_videoport_init(struct saa7134_dev *dev) +{ + /* enable video output */ + int vo = saa7134_boards[dev->board].video_out; + int video_reg; + unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; + saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); + video_reg = video_out[vo][1]; + if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) + video_reg &= ~VP_T_CODE_P_INVERTED; + saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); + saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); + saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]); + saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); + video_reg = video_out[vo][5]; + if (vid_port_opts & SET_CLOCK_NOT_DELAYED) + video_reg &= ~VP_CLK_CTRL2_DELAYED; + if (vid_port_opts & SET_CLOCK_INVERTED) + video_reg |= VP_CLK_CTRL1_INVERTED; + saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg); + video_reg = video_out[vo][6]; + if (vid_port_opts & SET_VSYNC_OFF) { + video_reg &= ~VP_VS_TYPE_MASK; + video_reg |= VP_VS_TYPE_OFF; + } + saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg); + saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); + saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); + return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index b3e3957..25650ae 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -583,6 +583,9 @@ void saa7134_buffer_next(struct saa7134_ void saa7134_buffer_timeout(unsigned long data); void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); +int saa7134_buffer_requeue(struct saa7134_dev *dev, + struct saa7134_dmaqueue *q); + int saa7134_set_dmabits(struct saa7134_dev *dev); extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev); @@ -615,6 +618,10 @@ void saa7134_i2c_call_clients(struct saa extern struct video_device saa7134_video_template; extern struct video_device saa7134_radio_template; +void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm); +int saa7134_videoport_init(struct saa7134_dev *dev); +void saa7134_set_decoder(struct saa7134_dev *dev); + int saa7134_common_ioctl(struct saa7134_dev *dev, unsigned int cmd, void *arg); @@ -639,6 +646,8 @@ void saa7134_irq_ts_done(struct saa7134_ int saa7134_ts_register(struct saa7134_mpeg_ops *ops); void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); +int saa7134_ts_init_hw(struct saa7134_dev *dev); + /* ----------------------------------------------------------- */ /* saa7134-vbi.c */ @@ -667,6 +676,8 @@ int saa7134_tvaudio_do_scan(struct saa71 int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value); +void saa7134_enable_i2s(struct saa7134_dev *dev); + /* ----------------------------------------------------------- */ /* saa7134-oss.c */ -- 1.4.2