diff options
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 1 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 1 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 30 |
3 files changed, 21 insertions, 11 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 28a53c42020d..ab7c3f6d3531 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
| @@ -623,6 +623,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
| 623 | itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ | 623 | itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ |
| 624 | itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ | 624 | itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ |
| 625 | 625 | ||
| 626 | mutex_init(&itv->serialize_lock); | ||
| 626 | mutex_init(&itv->i2c_bus_lock); | 627 | mutex_init(&itv->i2c_bus_lock); |
| 627 | mutex_init(&itv->udma.lock); | 628 | mutex_init(&itv->udma.lock); |
| 628 | 629 | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 48afd4270cbf..65ebddab3fe1 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
| @@ -722,6 +722,7 @@ struct ivtv { | |||
| 722 | int search_pack_header; | 722 | int search_pack_header; |
| 723 | 723 | ||
| 724 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ | 724 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ |
| 725 | struct mutex serialize_lock; /* lock used to serialize starting streams */ | ||
| 725 | 726 | ||
| 726 | /* User based DMA for OSD */ | 727 | /* User based DMA for OSD */ |
| 727 | struct ivtv_user_dma udma; | 728 | struct ivtv_user_dma udma; |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6af88ae9295f..d538efaf61c9 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
| @@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
| 446 | if (s->v4l2dev == NULL) | 446 | if (s->v4l2dev == NULL) |
| 447 | return -EINVAL; | 447 | return -EINVAL; |
| 448 | 448 | ||
| 449 | /* Big serialization lock to ensure no two streams are started | ||
| 450 | simultaneously: that can give all sorts of weird results. */ | ||
| 451 | mutex_lock(&itv->serialize_lock); | ||
| 449 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); | 452 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); |
| 450 | 453 | ||
| 451 | switch (s->type) { | 454 | switch (s->type) { |
| @@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
| 487 | 0, sizeof(itv->vbi.sliced_mpeg_size)); | 490 | 0, sizeof(itv->vbi.sliced_mpeg_size)); |
| 488 | break; | 491 | break; |
| 489 | default: | 492 | default: |
| 493 | mutex_unlock(&itv->serialize_lock); | ||
| 490 | return -EINVAL; | 494 | return -EINVAL; |
| 491 | } | 495 | } |
| 492 | s->subtype = subtype; | 496 | s->subtype = subtype; |
| @@ -568,6 +572,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
| 568 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) | 572 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) |
| 569 | { | 573 | { |
| 570 | IVTV_DEBUG_WARN( "Error starting capture!\n"); | 574 | IVTV_DEBUG_WARN( "Error starting capture!\n"); |
| 575 | mutex_unlock(&itv->serialize_lock); | ||
| 571 | return -EINVAL; | 576 | return -EINVAL; |
| 572 | } | 577 | } |
| 573 | 578 | ||
| @@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
| 583 | 588 | ||
| 584 | /* you're live! sit back and await interrupts :) */ | 589 | /* you're live! sit back and await interrupts :) */ |
| 585 | atomic_inc(&itv->capturing); | 590 | atomic_inc(&itv->capturing); |
| 591 | mutex_unlock(&itv->serialize_lock); | ||
| 586 | return 0; | 592 | return 0; |
| 587 | } | 593 | } |
| 588 | 594 | ||
| @@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
| 762 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ | 768 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ |
| 763 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); | 769 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); |
| 764 | 770 | ||
| 765 | /* only run these if we're shutting down the last cap */ | ||
| 766 | if (atomic_read(&itv->capturing) - 1 == 0) { | ||
| 767 | /* event notification (off) */ | ||
| 768 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | ||
| 769 | /* type: 0 = refresh */ | ||
| 770 | /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ | ||
| 771 | ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); | ||
| 772 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | ||
| 773 | } | ||
| 774 | } | ||
| 775 | |||
| 776 | then = jiffies; | 771 | then = jiffies; |
| 777 | 772 | ||
| 778 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { | 773 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { |
| @@ -840,17 +835,30 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
| 840 | /* Clear capture and no-read bits */ | 835 | /* Clear capture and no-read bits */ |
| 841 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | 836 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); |
| 842 | 837 | ||
| 838 | /* ensure these global cleanup actions are done only once */ | ||
| 839 | mutex_lock(&itv->serialize_lock); | ||
| 840 | |||
| 843 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | 841 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) |
| 844 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | 842 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); |
| 845 | 843 | ||
| 846 | if (atomic_read(&itv->capturing) > 0) { | 844 | if (atomic_read(&itv->capturing) > 0) { |
| 845 | mutex_unlock(&itv->serialize_lock); | ||
| 847 | return 0; | 846 | return 0; |
| 848 | } | 847 | } |
| 849 | 848 | ||
| 850 | /* Set the following Interrupt mask bits for capture */ | 849 | /* Set the following Interrupt mask bits for capture */ |
| 851 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | 850 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); |
| 852 | 851 | ||
| 852 | /* event notification (off) */ | ||
| 853 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | ||
| 854 | /* type: 0 = refresh */ | ||
| 855 | /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ | ||
| 856 | ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); | ||
| 857 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | ||
| 858 | } | ||
| 859 | |||
| 853 | wake_up(&s->waitq); | 860 | wake_up(&s->waitq); |
| 861 | mutex_unlock(&itv->serialize_lock); | ||
| 854 | 862 | ||
| 855 | return 0; | 863 | return 0; |
| 856 | } | 864 | } |
