diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2007-10-11 23:57:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-10-22 10:01:41 -0400 |
commit | c458473ebf31755373ca2f8063c9ec9744205924 (patch) | |
tree | 3852d3810dcaa4a1dddc684b7f735b493861e9df | |
parent | 7e7f05ca156d34b80e53105e4ef9bc1497a68439 (diff) |
V4L/DVB (6329): Additional Fixes for saa7134 suspend/resume
Fixes few more problems I found in my saa7134 resume code:
* Race between IRQ handler and .suspend()/.resume() functions
* Removes timeout timers on active buffers - those
buffers will be recaptured after resume
* Adds suspend/resume for IR code - probably
necessary if using polling mode
* Adds #ifdef CONFIG_PM overs suspend code
* Runs a quirk in set_tvnorm in suspend/resume too
* Rearranges the order of calls in saa7134_resume to
be exactly as in saa7134_initdev thus the card is
initialized in exactly the same way
* Since DMA audio capture suspend/resume isn't yet supported,
avoid re-enabling it on resume for now
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/saa7134/saa7134-core.c | 42 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 4 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-tvaudio.c | 2 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-video.c | 25 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134.h | 6 |
5 files changed, 57 insertions, 22 deletions
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 1a4a24471f20..410242a91f43 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -429,7 +429,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) | |||
429 | 429 | ||
430 | assert_spin_locked(&dev->slock); | 430 | assert_spin_locked(&dev->slock); |
431 | 431 | ||
432 | if (dev->inresume) | 432 | if (dev->insuspend) |
433 | return 0; | 433 | return 0; |
434 | 434 | ||
435 | /* video capture -- dma 0 + video task A */ | 435 | /* video capture -- dma 0 + video task A */ |
@@ -563,6 +563,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) | |||
563 | unsigned long report,status; | 563 | unsigned long report,status; |
564 | int loop, handled = 0; | 564 | int loop, handled = 0; |
565 | 565 | ||
566 | if (dev->insuspend) | ||
567 | goto out; | ||
568 | |||
566 | for (loop = 0; loop < 10; loop++) { | 569 | for (loop = 0; loop < 10; loop++) { |
567 | report = saa_readl(SAA7134_IRQ_REPORT); | 570 | report = saa_readl(SAA7134_IRQ_REPORT); |
568 | status = saa_readl(SAA7134_IRQ_STATUS); | 571 | status = saa_readl(SAA7134_IRQ_STATUS); |
@@ -1163,6 +1166,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1163 | kfree(dev); | 1166 | kfree(dev); |
1164 | } | 1167 | } |
1165 | 1168 | ||
1169 | #ifdef CONFIG_PM | ||
1166 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) | 1170 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) |
1167 | { | 1171 | { |
1168 | 1172 | ||
@@ -1176,6 +1180,17 @@ static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) | |||
1176 | saa_writel(SAA7134_IRQ2, 0); | 1180 | saa_writel(SAA7134_IRQ2, 0); |
1177 | saa_writel(SAA7134_MAIN_CTRL, 0); | 1181 | saa_writel(SAA7134_MAIN_CTRL, 0); |
1178 | 1182 | ||
1183 | synchronize_irq(pci_dev->irq); | ||
1184 | dev->insuspend = 1; | ||
1185 | |||
1186 | /* Disable timeout timers - if we have active buffers, we will | ||
1187 | fill them on resume*/ | ||
1188 | |||
1189 | del_timer(&dev->video_q.timeout); | ||
1190 | del_timer(&dev->vbi_q.timeout); | ||
1191 | del_timer(&dev->ts_q.timeout); | ||
1192 | saa7134_ir_stop(dev); | ||
1193 | |||
1179 | pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); | 1194 | pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); |
1180 | pci_save_state(pci_dev); | 1195 | pci_save_state(pci_dev); |
1181 | 1196 | ||
@@ -1194,24 +1209,27 @@ static int saa7134_resume(struct pci_dev *pci_dev) | |||
1194 | /* Do things that are done in saa7134_initdev , | 1209 | /* Do things that are done in saa7134_initdev , |
1195 | except of initializing memory structures.*/ | 1210 | except of initializing memory structures.*/ |
1196 | 1211 | ||
1197 | dev->inresume = 1; | ||
1198 | saa7134_board_init1(dev); | 1212 | saa7134_board_init1(dev); |
1199 | 1213 | ||
1214 | /* saa7134_hwinit1 */ | ||
1200 | if (saa7134_boards[dev->board].video_out) | 1215 | if (saa7134_boards[dev->board].video_out) |
1201 | saa7134_videoport_init(dev); | 1216 | saa7134_videoport_init(dev); |
1202 | |||
1203 | if (card_has_mpeg(dev)) | 1217 | if (card_has_mpeg(dev)) |
1204 | saa7134_ts_init_hw(dev); | 1218 | saa7134_ts_init_hw(dev); |
1205 | 1219 | if (dev->remote) | |
1220 | saa7134_ir_start(dev, dev->remote); | ||
1206 | saa7134_hw_enable1(dev); | 1221 | saa7134_hw_enable1(dev); |
1207 | saa7134_set_decoder(dev); | 1222 | |
1208 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | 1223 | |
1209 | saa7134_board_init2(dev); | 1224 | saa7134_board_init2(dev); |
1210 | saa7134_hw_enable2(dev); | ||
1211 | 1225 | ||
1226 | /*saa7134_hwinit2*/ | ||
1227 | saa7134_set_tvnorm_hw(dev); | ||
1212 | saa7134_tvaudio_setmute(dev); | 1228 | saa7134_tvaudio_setmute(dev); |
1213 | saa7134_tvaudio_setvolume(dev, dev->ctl_volume); | 1229 | saa7134_tvaudio_setvolume(dev, dev->ctl_volume); |
1230 | saa7134_tvaudio_do_scan(dev); | ||
1214 | saa7134_enable_i2s(dev); | 1231 | saa7134_enable_i2s(dev); |
1232 | saa7134_hw_enable2(dev); | ||
1215 | 1233 | ||
1216 | /*resume unfinished buffer(s)*/ | 1234 | /*resume unfinished buffer(s)*/ |
1217 | spin_lock_irqsave(&dev->slock, flags); | 1235 | spin_lock_irqsave(&dev->slock, flags); |
@@ -1219,13 +1237,19 @@ static int saa7134_resume(struct pci_dev *pci_dev) | |||
1219 | saa7134_buffer_requeue(dev, &dev->vbi_q); | 1237 | saa7134_buffer_requeue(dev, &dev->vbi_q); |
1220 | saa7134_buffer_requeue(dev, &dev->ts_q); | 1238 | saa7134_buffer_requeue(dev, &dev->ts_q); |
1221 | 1239 | ||
1240 | /* FIXME: Disable DMA audio sound - temporary till proper support | ||
1241 | is implemented*/ | ||
1242 | |||
1243 | dev->dmasound.dma_running = 0; | ||
1244 | |||
1222 | /* start DMA now*/ | 1245 | /* start DMA now*/ |
1223 | dev->inresume = 0; | 1246 | dev->insuspend = 0; |
1224 | saa7134_set_dmabits(dev); | 1247 | saa7134_set_dmabits(dev); |
1225 | spin_unlock_irqrestore(&dev->slock, flags); | 1248 | spin_unlock_irqrestore(&dev->slock, flags); |
1226 | 1249 | ||
1227 | return 0; | 1250 | return 0; |
1228 | } | 1251 | } |
1252 | #endif | ||
1229 | 1253 | ||
1230 | /* ----------------------------------------------------------- */ | 1254 | /* ----------------------------------------------------------- */ |
1231 | 1255 | ||
@@ -1262,8 +1286,10 @@ static struct pci_driver saa7134_pci_driver = { | |||
1262 | .id_table = saa7134_pci_tbl, | 1286 | .id_table = saa7134_pci_tbl, |
1263 | .probe = saa7134_initdev, | 1287 | .probe = saa7134_initdev, |
1264 | .remove = __devexit_p(saa7134_finidev), | 1288 | .remove = __devexit_p(saa7134_finidev), |
1289 | #ifdef CONFIG_PM | ||
1265 | .suspend = saa7134_suspend, | 1290 | .suspend = saa7134_suspend, |
1266 | .resume = saa7134_resume | 1291 | .resume = saa7134_resume |
1292 | #endif | ||
1267 | }; | 1293 | }; |
1268 | 1294 | ||
1269 | static int saa7134_init(void) | 1295 | static int saa7134_init(void) |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 80d2644f765a..d4907ce4e51f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -159,7 +159,7 @@ static void saa7134_input_timer(unsigned long data) | |||
159 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 159 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
160 | } | 160 | } |
161 | 161 | ||
162 | static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | 162 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) |
163 | { | 163 | { |
164 | if (ir->polling) { | 164 | if (ir->polling) { |
165 | setup_timer(&ir->timer, saa7134_input_timer, | 165 | setup_timer(&ir->timer, saa7134_input_timer, |
@@ -182,7 +182,7 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | 184 | ||
185 | static void saa7134_ir_stop(struct saa7134_dev *dev) | 185 | void saa7134_ir_stop(struct saa7134_dev *dev) |
186 | { | 186 | { |
187 | if (dev->remote->polling) | 187 | if (dev->remote->polling) |
188 | del_timer_sync(&dev->remote->timer); | 188 | del_timer_sync(&dev->remote->timer); |
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 1b9e39a5ea47..976318d50828 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c | |||
@@ -231,7 +231,7 @@ static void mute_input_7134(struct saa7134_dev *dev) | |||
231 | } | 231 | } |
232 | 232 | ||
233 | if (dev->hw_mute == mute && | 233 | if (dev->hw_mute == mute && |
234 | dev->hw_input == in && !dev->inresume) { | 234 | dev->hw_input == in && !dev->insuspend) { |
235 | dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", | 235 | dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", |
236 | mute,in->name); | 236 | mute,in->name); |
237 | return; | 237 | return; |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 2b0897770531..3b9ffb4b648a 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -560,15 +560,8 @@ void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) | |||
560 | 560 | ||
561 | dev->crop_current = dev->crop_defrect; | 561 | dev->crop_current = dev->crop_defrect; |
562 | 562 | ||
563 | saa7134_set_decoder(dev); | 563 | saa7134_set_tvnorm_hw(dev); |
564 | 564 | ||
565 | if (card_in(dev, dev->ctl_input).tv) { | ||
566 | if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290) | ||
567 | && ((card(dev).tuner_config == 1) | ||
568 | || (card(dev).tuner_config == 2))) | ||
569 | saa7134_set_gpio(dev, 22, 5); | ||
570 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &norm->id); | ||
571 | } | ||
572 | } | 565 | } |
573 | 566 | ||
574 | static void video_mux(struct saa7134_dev *dev, int input) | 567 | static void video_mux(struct saa7134_dev *dev, int input) |
@@ -579,7 +572,8 @@ static void video_mux(struct saa7134_dev *dev, int input) | |||
579 | saa7134_tvaudio_setinput(dev, &card_in(dev, input)); | 572 | saa7134_tvaudio_setinput(dev, &card_in(dev, input)); |
580 | } | 573 | } |
581 | 574 | ||
582 | void saa7134_set_decoder(struct saa7134_dev *dev) | 575 | |
576 | static void saa7134_set_decoder(struct saa7134_dev *dev) | ||
583 | { | 577 | { |
584 | int luma_control, sync_control, mux; | 578 | int luma_control, sync_control, mux; |
585 | 579 | ||
@@ -630,6 +624,19 @@ void saa7134_set_decoder(struct saa7134_dev *dev) | |||
630 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); | 624 | saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); |
631 | } | 625 | } |
632 | 626 | ||
627 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) | ||
628 | { | ||
629 | saa7134_set_decoder(dev); | ||
630 | |||
631 | if (card_in(dev, dev->ctl_input).tv) { | ||
632 | if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290) | ||
633 | && ((card(dev).tuner_config == 1) | ||
634 | || (card(dev).tuner_config == 2))) | ||
635 | saa7134_set_gpio(dev, 22, 5); | ||
636 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | ||
637 | } | ||
638 | } | ||
639 | |||
633 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) | 640 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) |
634 | { | 641 | { |
635 | static const struct { | 642 | static const struct { |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 28ec6804bd5d..fe0a8439b878 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -524,7 +524,7 @@ struct saa7134_dev { | |||
524 | unsigned int hw_mute; | 524 | unsigned int hw_mute; |
525 | int last_carrier; | 525 | int last_carrier; |
526 | int nosignal; | 526 | int nosignal; |
527 | unsigned int inresume; | 527 | unsigned int insuspend; |
528 | 528 | ||
529 | /* SAA7134_MPEG_* */ | 529 | /* SAA7134_MPEG_* */ |
530 | struct saa7134_ts ts; | 530 | struct saa7134_ts ts; |
@@ -632,7 +632,7 @@ extern struct video_device saa7134_radio_template; | |||
632 | 632 | ||
633 | void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm); | 633 | void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm); |
634 | int saa7134_videoport_init(struct saa7134_dev *dev); | 634 | int saa7134_videoport_init(struct saa7134_dev *dev); |
635 | void saa7134_set_decoder(struct saa7134_dev *dev); | 635 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); |
636 | 636 | ||
637 | int saa7134_common_ioctl(struct saa7134_dev *dev, | 637 | int saa7134_common_ioctl(struct saa7134_dev *dev, |
638 | unsigned int cmd, void *arg); | 638 | unsigned int cmd, void *arg); |
@@ -706,6 +706,8 @@ int saa7134_input_init1(struct saa7134_dev *dev); | |||
706 | void saa7134_input_fini(struct saa7134_dev *dev); | 706 | void saa7134_input_fini(struct saa7134_dev *dev); |
707 | void saa7134_input_irq(struct saa7134_dev *dev); | 707 | void saa7134_input_irq(struct saa7134_dev *dev); |
708 | void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); | 708 | void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); |
709 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); | ||
710 | void saa7134_ir_stop(struct saa7134_dev *dev); | ||
709 | 711 | ||
710 | 712 | ||
711 | /* | 713 | /* |