diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-streams.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6af88ae9295f..287117187499 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)) { |
@@ -812,7 +807,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
812 | then = jiffies; | 807 | then = jiffies; |
813 | /* Make sure DMA is complete */ | 808 | /* Make sure DMA is complete */ |
814 | add_wait_queue(&s->waitq, &wait); | 809 | add_wait_queue(&s->waitq, &wait); |
815 | set_current_state(TASK_INTERRUPTIBLE); | ||
816 | do { | 810 | do { |
817 | /* check if DMA is pending */ | 811 | /* check if DMA is pending */ |
818 | if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */ | 812 | if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */ |
@@ -827,9 +821,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
827 | } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) { | 821 | } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) { |
828 | break; | 822 | break; |
829 | } | 823 | } |
830 | 824 | } while (!ivtv_sleep_timeout(HZ / 100, 1) && then + HZ * 2 > jiffies); | |
831 | ivtv_sleep_timeout(HZ / 100, 1); | ||
832 | } while (then + HZ * 2 > jiffies); | ||
833 | 825 | ||
834 | set_current_state(TASK_RUNNING); | 826 | set_current_state(TASK_RUNNING); |
835 | remove_wait_queue(&s->waitq, &wait); | 827 | remove_wait_queue(&s->waitq, &wait); |
@@ -840,17 +832,30 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
840 | /* Clear capture and no-read bits */ | 832 | /* Clear capture and no-read bits */ |
841 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | 833 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); |
842 | 834 | ||
835 | /* ensure these global cleanup actions are done only once */ | ||
836 | mutex_lock(&itv->serialize_lock); | ||
837 | |||
843 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | 838 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) |
844 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | 839 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); |
845 | 840 | ||
846 | if (atomic_read(&itv->capturing) > 0) { | 841 | if (atomic_read(&itv->capturing) > 0) { |
842 | mutex_unlock(&itv->serialize_lock); | ||
847 | return 0; | 843 | return 0; |
848 | } | 844 | } |
849 | 845 | ||
850 | /* Set the following Interrupt mask bits for capture */ | 846 | /* Set the following Interrupt mask bits for capture */ |
851 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | 847 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); |
852 | 848 | ||
849 | /* event notification (off) */ | ||
850 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | ||
851 | /* type: 0 = refresh */ | ||
852 | /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ | ||
853 | ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); | ||
854 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | ||
855 | } | ||
856 | |||
853 | wake_up(&s->waitq); | 857 | wake_up(&s->waitq); |
858 | mutex_unlock(&itv->serialize_lock); | ||
854 | 859 | ||
855 | return 0; | 860 | return 0; |
856 | } | 861 | } |