diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-18 15:53:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-18 15:53:54 -0500 |
commit | 4a7c1ff2362b7bfbc04990f42c21cefdff57f997 (patch) | |
tree | 82ac9c30ca95b6a92084f5535e6406866eb99cf3 /drivers/media/video/ivtv | |
parent | 9278e634b4e063f415b46923a9ca4e74f42ec932 (diff) | |
parent | 36be126cb0ebe3000a65c1049f339a3e882a9a47 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (57 commits)
[media] as3645a: Fix compilation by including slab.h
[media] s5p-fimc: Remove linux/version.h include from fimc-mdevice.c
[media] s5p-mfc: Remove linux/version.h include from s5p_mfc.c
[media] ds3000: using logical && instead of bitwise &
[media] v4l2-ctrls: make control names consistent
[media] DVB: dib0700, add support for Nova-TD LEDs
[media] DVB: dib0700, add corrected Nova-TD frontend_attach
[media] DVB: dib0700, separate stk7070pd initialization
[media] DVB: dib0700, move Nova-TD Stick to a separate set
[media] : add MODULE_FIRMWARE to dib0700
[media] DVB-CORE: remove superfluous DTV_CMDs
[media] s5p-jpeg: adapt to recent videobuf2 changes
[media] s5p-g2d: fixed a bug in controls setting function
[media] s5p-mfc: Fix volatile controls setup
[media] drivers/media/video/s5p-mfc/s5p_mfc.c: adjust double test
[media] drivers/media/video/s5p-fimc/fimc-capture.c: adjust double test
[media] s5p-fimc: Fix incorrect control ID assignment
[media] dvb_frontend: Don't call get_frontend() if idle
[media] DocBook/dvbproperty.xml: Remove DTV_MODULATION from ISDB-T
[media] DocBook/dvbproperty.xml: Fix ISDB-T delivery system parameters
...
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 3 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 3 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 118 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 22 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 4 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 2 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 22 |
7 files changed, 72 insertions, 102 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 544af91cbdc1..3949b7dc2368 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
731 | 731 | ||
732 | init_kthread_work(&itv->irq_work, ivtv_irq_work_handler); | 732 | init_kthread_work(&itv->irq_work, ivtv_irq_work_handler); |
733 | 733 | ||
734 | /* start counting open_id at 1 */ | ||
735 | itv->open_id = 1; | ||
736 | |||
737 | /* Initial settings */ | 734 | /* Initial settings */ |
738 | itv->cxhdl.port = CX2341X_PORT_MEMORY; | 735 | itv->cxhdl.port = CX2341X_PORT_MEMORY; |
739 | itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI; | 736 | itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI; |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 8f9cc17b518e..06f3d78389bf 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -332,7 +332,7 @@ struct ivtv_stream { | |||
332 | const char *name; /* name of the stream */ | 332 | const char *name; /* name of the stream */ |
333 | int type; /* stream type */ | 333 | int type; /* stream type */ |
334 | 334 | ||
335 | u32 id; | 335 | struct v4l2_fh *fh; /* pointer to the streaming filehandle */ |
336 | spinlock_t qlock; /* locks access to the queues */ | 336 | spinlock_t qlock; /* locks access to the queues */ |
337 | unsigned long s_flags; /* status flags, see above */ | 337 | unsigned long s_flags; /* status flags, see above */ |
338 | int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ | 338 | int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ |
@@ -379,7 +379,6 @@ struct ivtv_stream { | |||
379 | 379 | ||
380 | struct ivtv_open_id { | 380 | struct ivtv_open_id { |
381 | struct v4l2_fh fh; | 381 | struct v4l2_fh fh; |
382 | u32 open_id; /* unique ID for this file descriptor */ | ||
383 | int type; /* stream type */ | 382 | int type; /* stream type */ |
384 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ | 383 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ |
385 | struct ivtv *itv; | 384 | struct ivtv *itv; |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 38f052257f46..2cd6c89b7d91 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type) | |||
50 | 50 | ||
51 | if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { | 51 | if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { |
52 | /* someone already claimed this stream */ | 52 | /* someone already claimed this stream */ |
53 | if (s->id == id->open_id) { | 53 | if (s->fh == &id->fh) { |
54 | /* yes, this file descriptor did. So that's OK. */ | 54 | /* yes, this file descriptor did. So that's OK. */ |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI || | 57 | if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI || |
58 | type == IVTV_ENC_STREAM_TYPE_VBI)) { | 58 | type == IVTV_ENC_STREAM_TYPE_VBI)) { |
59 | /* VBI is handled already internally, now also assign | 59 | /* VBI is handled already internally, now also assign |
60 | the file descriptor to this stream for external | 60 | the file descriptor to this stream for external |
61 | reading of the stream. */ | 61 | reading of the stream. */ |
62 | s->id = id->open_id; | 62 | s->fh = &id->fh; |
63 | IVTV_DEBUG_INFO("Start Read VBI\n"); | 63 | IVTV_DEBUG_INFO("Start Read VBI\n"); |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
@@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type) | |||
67 | IVTV_DEBUG_INFO("Stream %d is busy\n", type); | 67 | IVTV_DEBUG_INFO("Stream %d is busy\n", type); |
68 | return -EBUSY; | 68 | return -EBUSY; |
69 | } | 69 | } |
70 | s->id = id->open_id; | 70 | s->fh = &id->fh; |
71 | if (type == IVTV_DEC_STREAM_TYPE_VBI) { | 71 | if (type == IVTV_DEC_STREAM_TYPE_VBI) { |
72 | /* Enable reinsertion interrupt */ | 72 | /* Enable reinsertion interrupt */ |
73 | ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); | 73 | ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); |
@@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s) | |||
104 | struct ivtv *itv = s->itv; | 104 | struct ivtv *itv = s->itv; |
105 | struct ivtv_stream *s_vbi; | 105 | struct ivtv_stream *s_vbi; |
106 | 106 | ||
107 | s->id = -1; | 107 | s->fh = NULL; |
108 | if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && | 108 | if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && |
109 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { | 109 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { |
110 | /* this stream is still in use internally */ | 110 | /* this stream is still in use internally */ |
@@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s) | |||
136 | /* was already cleared */ | 136 | /* was already cleared */ |
137 | return; | 137 | return; |
138 | } | 138 | } |
139 | if (s_vbi->id != -1) { | 139 | if (s_vbi->fh) { |
140 | /* VBI stream still claimed by a file descriptor */ | 140 | /* VBI stream still claimed by a file descriptor */ |
141 | return; | 141 | return; |
142 | } | 142 | } |
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, | |||
268 | } | 268 | } |
269 | 269 | ||
270 | /* wait for more data to arrive */ | 270 | /* wait for more data to arrive */ |
271 | mutex_unlock(&itv->serialize_lock); | ||
271 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 272 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
272 | /* New buffers might have become available before we were added to the waitqueue */ | 273 | /* New buffers might have become available before we were added to the waitqueue */ |
273 | if (!s->q_full.buffers) | 274 | if (!s->q_full.buffers) |
274 | schedule(); | 275 | schedule(); |
275 | finish_wait(&s->waitq, &wait); | 276 | finish_wait(&s->waitq, &wait); |
277 | mutex_lock(&itv->serialize_lock); | ||
276 | if (signal_pending(current)) { | 278 | if (signal_pending(current)) { |
277 | /* return if a signal was received */ | 279 | /* return if a signal was received */ |
278 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | 280 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); |
@@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co | |||
357 | size_t tot_written = 0; | 359 | size_t tot_written = 0; |
358 | int single_frame = 0; | 360 | int single_frame = 0; |
359 | 361 | ||
360 | if (atomic_read(&itv->capturing) == 0 && s->id == -1) { | 362 | if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) { |
361 | /* shouldn't happen */ | 363 | /* shouldn't happen */ |
362 | IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); | 364 | IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); |
363 | return -EIO; | 365 | return -EIO; |
@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ | |||
507 | 509 | ||
508 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); | 510 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); |
509 | 511 | ||
510 | mutex_lock(&itv->serialize_lock); | ||
511 | rc = ivtv_start_capture(id); | 512 | rc = ivtv_start_capture(id); |
512 | mutex_unlock(&itv->serialize_lock); | ||
513 | if (rc) | 513 | if (rc) |
514 | return rc; | 514 | return rc; |
515 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | 515 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); |
@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c | |||
584 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 584 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
585 | 585 | ||
586 | /* Start decoder (returns 0 if already started) */ | 586 | /* Start decoder (returns 0 if already started) */ |
587 | mutex_lock(&itv->serialize_lock); | ||
588 | rc = ivtv_start_decoding(id, itv->speed); | 587 | rc = ivtv_start_decoding(id, itv->speed); |
589 | mutex_unlock(&itv->serialize_lock); | ||
590 | if (rc) { | 588 | if (rc) { |
591 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); | 589 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); |
592 | 590 | ||
@@ -627,11 +625,13 @@ retry: | |||
627 | break; | 625 | break; |
628 | if (filp->f_flags & O_NONBLOCK) | 626 | if (filp->f_flags & O_NONBLOCK) |
629 | return -EAGAIN; | 627 | return -EAGAIN; |
628 | mutex_unlock(&itv->serialize_lock); | ||
630 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 629 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
631 | /* New buffers might have become free before we were added to the waitqueue */ | 630 | /* New buffers might have become free before we were added to the waitqueue */ |
632 | if (!s->q_free.buffers) | 631 | if (!s->q_free.buffers) |
633 | schedule(); | 632 | schedule(); |
634 | finish_wait(&s->waitq, &wait); | 633 | finish_wait(&s->waitq, &wait); |
634 | mutex_lock(&itv->serialize_lock); | ||
635 | if (signal_pending(current)) { | 635 | if (signal_pending(current)) { |
636 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | 636 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); |
637 | return -EINTR; | 637 | return -EINTR; |
@@ -686,12 +686,14 @@ retry: | |||
686 | if (mode == OUT_YUV) | 686 | if (mode == OUT_YUV) |
687 | ivtv_yuv_setup_stream_frame(itv); | 687 | ivtv_yuv_setup_stream_frame(itv); |
688 | 688 | ||
689 | mutex_unlock(&itv->serialize_lock); | ||
689 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | 690 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
690 | while (!(got_sig = signal_pending(current)) && | 691 | while (!(got_sig = signal_pending(current)) && |
691 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { | 692 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { |
692 | schedule(); | 693 | schedule(); |
693 | } | 694 | } |
694 | finish_wait(&itv->dma_waitq, &wait); | 695 | finish_wait(&itv->dma_waitq, &wait); |
696 | mutex_lock(&itv->serialize_lock); | ||
695 | if (got_sig) { | 697 | if (got_sig) { |
696 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); | 698 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); |
697 | return -EINTR; | 699 | return -EINTR; |
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | |||
756 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 758 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
757 | int rc; | 759 | int rc; |
758 | 760 | ||
759 | mutex_lock(&itv->serialize_lock); | ||
760 | rc = ivtv_start_capture(id); | 761 | rc = ivtv_start_capture(id); |
761 | mutex_unlock(&itv->serialize_lock); | ||
762 | if (rc) { | 762 | if (rc) { |
763 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", | 763 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", |
764 | s->name, rc); | 764 | s->name, rc); |
@@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) | |||
808 | id->type == IVTV_ENC_STREAM_TYPE_VBI) && | 808 | id->type == IVTV_ENC_STREAM_TYPE_VBI) && |
809 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { | 809 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { |
810 | /* Also used internally, don't stop capturing */ | 810 | /* Also used internally, don't stop capturing */ |
811 | s->id = -1; | 811 | s->fh = NULL; |
812 | } | 812 | } |
813 | else { | 813 | else { |
814 | ivtv_stop_v4l2_encode_stream(s, gop_end); | 814 | ivtv_stop_v4l2_encode_stream(s, gop_end); |
@@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp) | |||
861 | 861 | ||
862 | IVTV_DEBUG_FILE("close %s\n", s->name); | 862 | IVTV_DEBUG_FILE("close %s\n", s->name); |
863 | 863 | ||
864 | v4l2_fh_del(fh); | ||
865 | v4l2_fh_exit(fh); | ||
866 | |||
867 | /* Easy case first: this stream was never claimed by us */ | ||
868 | if (s->id != id->open_id) { | ||
869 | kfree(id); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* 'Unclaim' this stream */ | ||
874 | |||
875 | /* Stop radio */ | 864 | /* Stop radio */ |
876 | mutex_lock(&itv->serialize_lock); | 865 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD && |
877 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { | 866 | v4l2_fh_is_singular_file(filp)) { |
878 | /* Closing radio device, return to TV mode */ | 867 | /* Closing radio device, return to TV mode */ |
879 | ivtv_mute(itv); | 868 | ivtv_mute(itv); |
880 | /* Mark that the radio is no longer in use */ | 869 | /* Mark that the radio is no longer in use */ |
@@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp) | |||
890 | if (atomic_read(&itv->capturing) > 0) { | 879 | if (atomic_read(&itv->capturing) > 0) { |
891 | /* Undo video mute */ | 880 | /* Undo video mute */ |
892 | ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, | 881 | ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, |
893 | v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) | | 882 | v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) | |
894 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); | 883 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); |
895 | } | 884 | } |
896 | /* Done! Unmute and continue. */ | 885 | /* Done! Unmute and continue. */ |
897 | ivtv_unmute(itv); | 886 | ivtv_unmute(itv); |
898 | ivtv_release_stream(s); | 887 | } |
899 | } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | 888 | |
889 | v4l2_fh_del(fh); | ||
890 | v4l2_fh_exit(fh); | ||
891 | |||
892 | /* Easy case first: this stream was never claimed by us */ | ||
893 | if (s->fh != &id->fh) { | ||
894 | kfree(id); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | /* 'Unclaim' this stream */ | ||
899 | |||
900 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | ||
900 | struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; | 901 | struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; |
901 | 902 | ||
902 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 903 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); |
@@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp) | |||
911 | ivtv_stop_capture(id, 0); | 912 | ivtv_stop_capture(id, 0); |
912 | } | 913 | } |
913 | kfree(id); | 914 | kfree(id); |
914 | mutex_unlock(&itv->serialize_lock); | ||
915 | return 0; | 915 | return 0; |
916 | } | 916 | } |
917 | 917 | ||
918 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | 918 | int ivtv_v4l2_open(struct file *filp) |
919 | { | 919 | { |
920 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
921 | struct video_device *vdev = video_devdata(filp); | 920 | struct video_device *vdev = video_devdata(filp); |
922 | #endif | 921 | struct ivtv_stream *s = video_get_drvdata(vdev); |
923 | struct ivtv *itv = s->itv; | 922 | struct ivtv *itv = s->itv; |
924 | struct ivtv_open_id *item; | 923 | struct ivtv_open_id *item; |
925 | int res = 0; | 924 | int res = 0; |
926 | 925 | ||
927 | IVTV_DEBUG_FILE("open %s\n", s->name); | 926 | IVTV_DEBUG_FILE("open %s\n", s->name); |
928 | 927 | ||
928 | if (ivtv_init_on_first_open(itv)) { | ||
929 | IVTV_ERR("Failed to initialize on device %s\n", | ||
930 | video_device_node_name(vdev)); | ||
931 | return -ENXIO; | ||
932 | } | ||
933 | |||
929 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 934 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
930 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ | 935 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ |
931 | if (ivtv_fw_debug) { | 936 | if (ivtv_fw_debug) { |
@@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
966 | return -ENOMEM; | 971 | return -ENOMEM; |
967 | } | 972 | } |
968 | v4l2_fh_init(&item->fh, s->vdev); | 973 | v4l2_fh_init(&item->fh, s->vdev); |
969 | if (res < 0) { | ||
970 | v4l2_fh_exit(&item->fh); | ||
971 | kfree(item); | ||
972 | return res; | ||
973 | } | ||
974 | item->itv = itv; | 974 | item->itv = itv; |
975 | item->type = s->type; | 975 | item->type = s->type; |
976 | 976 | ||
977 | item->open_id = itv->open_id++; | ||
978 | filp->private_data = &item->fh; | 977 | filp->private_data = &item->fh; |
978 | v4l2_fh_add(&item->fh); | ||
979 | 979 | ||
980 | if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { | 980 | if (item->type == IVTV_ENC_STREAM_TYPE_RAD && |
981 | /* Try to claim this stream */ | 981 | v4l2_fh_is_singular_file(filp)) { |
982 | if (ivtv_claim_stream(item, item->type)) { | ||
983 | /* No, it's already in use */ | ||
984 | v4l2_fh_exit(&item->fh); | ||
985 | kfree(item); | ||
986 | return -EBUSY; | ||
987 | } | ||
988 | |||
989 | if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | 982 | if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { |
990 | if (atomic_read(&itv->capturing) > 0) { | 983 | if (atomic_read(&itv->capturing) > 0) { |
991 | /* switching to radio while capture is | 984 | /* switching to radio while capture is |
992 | in progress is not polite */ | 985 | in progress is not polite */ |
993 | ivtv_release_stream(s); | 986 | v4l2_fh_del(&item->fh); |
994 | v4l2_fh_exit(&item->fh); | 987 | v4l2_fh_exit(&item->fh); |
995 | kfree(item); | 988 | kfree(item); |
996 | return -EBUSY; | 989 | return -EBUSY; |
@@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
1022 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); | 1015 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
1023 | itv->yuv_info.stream_size = 0; | 1016 | itv->yuv_info.stream_size = 0; |
1024 | } | 1017 | } |
1025 | v4l2_fh_add(&item->fh); | ||
1026 | return 0; | 1018 | return 0; |
1027 | } | 1019 | } |
1028 | 1020 | ||
1029 | int ivtv_v4l2_open(struct file *filp) | ||
1030 | { | ||
1031 | int res; | ||
1032 | struct ivtv *itv = NULL; | ||
1033 | struct ivtv_stream *s = NULL; | ||
1034 | struct video_device *vdev = video_devdata(filp); | ||
1035 | |||
1036 | s = video_get_drvdata(vdev); | ||
1037 | itv = s->itv; | ||
1038 | |||
1039 | mutex_lock(&itv->serialize_lock); | ||
1040 | if (ivtv_init_on_first_open(itv)) { | ||
1041 | IVTV_ERR("Failed to initialize on device %s\n", | ||
1042 | video_device_node_name(vdev)); | ||
1043 | mutex_unlock(&itv->serialize_lock); | ||
1044 | return -ENXIO; | ||
1045 | } | ||
1046 | res = ivtv_serialized_open(s, filp); | ||
1047 | mutex_unlock(&itv->serialize_lock); | ||
1048 | return res; | ||
1049 | } | ||
1050 | |||
1051 | void ivtv_mute(struct ivtv *itv) | 1021 | void ivtv_mute(struct ivtv *itv) |
1052 | { | 1022 | { |
1053 | if (atomic_read(&itv->capturing)) | 1023 | if (atomic_read(&itv->capturing)) |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index ecafa697326e..c4bc48143098 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) | |||
179 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); | 179 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); |
180 | 180 | ||
181 | /* Wait for any DMA to finish */ | 181 | /* Wait for any DMA to finish */ |
182 | mutex_unlock(&itv->serialize_lock); | ||
182 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | 183 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
183 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | 184 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { |
184 | got_sig = signal_pending(current); | 185 | got_sig = signal_pending(current); |
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) | |||
188 | schedule(); | 189 | schedule(); |
189 | } | 190 | } |
190 | finish_wait(&itv->dma_waitq, &wait); | 191 | finish_wait(&itv->dma_waitq, &wait); |
192 | mutex_lock(&itv->serialize_lock); | ||
191 | if (got_sig) | 193 | if (got_sig) |
192 | return -EINTR; | 194 | return -EINTR; |
193 | 195 | ||
@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) | |||
1107 | * happens within the first 100 lines of the top field. | 1109 | * happens within the first 100 lines of the top field. |
1108 | * Make 4 attempts to sync to the decoder before giving up. | 1110 | * Make 4 attempts to sync to the decoder before giving up. |
1109 | */ | 1111 | */ |
1112 | mutex_unlock(&itv->serialize_lock); | ||
1110 | for (f = 0; f < 4; f++) { | 1113 | for (f = 0; f < 4; f++) { |
1111 | prepare_to_wait(&itv->vsync_waitq, &wait, | 1114 | prepare_to_wait(&itv->vsync_waitq, &wait, |
1112 | TASK_UNINTERRUPTIBLE); | 1115 | TASK_UNINTERRUPTIBLE); |
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) | |||
1115 | schedule_timeout(msecs_to_jiffies(25)); | 1118 | schedule_timeout(msecs_to_jiffies(25)); |
1116 | } | 1119 | } |
1117 | finish_wait(&itv->vsync_waitq, &wait); | 1120 | finish_wait(&itv->vsync_waitq, &wait); |
1121 | mutex_lock(&itv->serialize_lock); | ||
1118 | 1122 | ||
1119 | if (f == 4) | 1123 | if (f == 4) |
1120 | IVTV_WARN("Mode change failed to sync to decoder\n"); | 1124 | IVTV_WARN("Mode change failed to sync to decoder\n"); |
@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, | |||
1842 | return 0; | 1846 | return 0; |
1843 | } | 1847 | } |
1844 | 1848 | ||
1845 | static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | 1849 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1846 | unsigned int cmd, unsigned long arg) | ||
1847 | { | 1850 | { |
1848 | struct video_device *vfd = video_devdata(filp); | 1851 | struct video_device *vfd = video_devdata(filp); |
1849 | long ret; | 1852 | long ret; |
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1855 | return ret; | 1858 | return ret; |
1856 | } | 1859 | } |
1857 | 1860 | ||
1858 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
1859 | { | ||
1860 | struct ivtv_open_id *id = fh2id(filp->private_data); | ||
1861 | struct ivtv *itv = id->itv; | ||
1862 | long res; | ||
1863 | |||
1864 | /* DQEVENT can block, so this should not run with the serialize lock */ | ||
1865 | if (cmd == VIDIOC_DQEVENT) | ||
1866 | return ivtv_serialized_ioctl(itv, filp, cmd, arg); | ||
1867 | mutex_lock(&itv->serialize_lock); | ||
1868 | res = ivtv_serialized_ioctl(itv, filp, cmd, arg); | ||
1869 | mutex_unlock(&itv->serialize_lock); | ||
1870 | return res; | ||
1871 | } | ||
1872 | |||
1873 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { | 1861 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { |
1874 | .vidioc_querycap = ivtv_querycap, | 1862 | .vidioc_querycap = ivtv_querycap, |
1875 | .vidioc_s_audio = ivtv_s_audio, | 1863 | .vidioc_s_audio = ivtv_s_audio, |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 9c29e964d400..1b3b9578bf47 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s) | |||
288 | ivtv_process_vbi_data(itv, buf, 0, s->type); | 288 | ivtv_process_vbi_data(itv, buf, 0, s->type); |
289 | s->q_dma.bytesused += buf->bytesused; | 289 | s->q_dma.bytesused += buf->bytesused; |
290 | } | 290 | } |
291 | if (s->id == -1) { | 291 | if (s->fh == NULL) { |
292 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); | 292 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); |
293 | return; | 293 | return; |
294 | } | 294 | } |
295 | } | 295 | } |
296 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); | 296 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); |
297 | if (s->id != -1) | 297 | if (s->fh) |
298 | wake_up(&s->waitq); | 298 | wake_up(&s->waitq); |
299 | } | 299 | } |
300 | 300 | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index e7794dc1330e..c6e28b4ebbed 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type) | |||
159 | s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size; | 159 | s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size; |
160 | spin_lock_init(&s->qlock); | 160 | spin_lock_init(&s->qlock); |
161 | init_waitqueue_head(&s->waitq); | 161 | init_waitqueue_head(&s->waitq); |
162 | s->id = -1; | ||
163 | s->sg_handle = IVTV_DMA_UNMAPPED; | 162 | s->sg_handle = IVTV_DMA_UNMAPPED; |
164 | ivtv_queue_init(&s->q_free); | 163 | ivtv_queue_init(&s->q_free); |
165 | ivtv_queue_init(&s->q_full); | 164 | ivtv_queue_init(&s->q_full); |
@@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
214 | s->vdev->fops = ivtv_stream_info[type].fops; | 213 | s->vdev->fops = ivtv_stream_info[type].fops; |
215 | s->vdev->release = video_device_release; | 214 | s->vdev->release = video_device_release; |
216 | s->vdev->tvnorms = V4L2_STD_ALL; | 215 | s->vdev->tvnorms = V4L2_STD_ALL; |
216 | s->vdev->lock = &itv->serialize_lock; | ||
217 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); | 217 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); |
218 | ivtv_set_funcs(s->vdev); | 218 | ivtv_set_funcs(s->vdev); |
219 | return 0; | 219 | return 0; |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index dcbab6ad4c26..2ad65eb29832 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) | |||
1149 | { | 1149 | { |
1150 | struct yuv_playback_info *yi = &itv->yuv_info; | 1150 | struct yuv_playback_info *yi = &itv->yuv_info; |
1151 | struct ivtv_dma_frame dma_args; | 1151 | struct ivtv_dma_frame dma_args; |
1152 | int res; | ||
1152 | 1153 | ||
1153 | ivtv_yuv_setup_stream_frame(itv); | 1154 | ivtv_yuv_setup_stream_frame(itv); |
1154 | 1155 | ||
1155 | /* We only need to supply source addresses for this */ | 1156 | /* We only need to supply source addresses for this */ |
1156 | dma_args.y_source = src; | 1157 | dma_args.y_source = src; |
1157 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); | 1158 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); |
1158 | return ivtv_yuv_udma_frame(itv, &dma_args); | 1159 | /* Wait for frame DMA. Note that serialize_lock is locked, |
1160 | so to allow other processes to access the driver while | ||
1161 | we are waiting unlock first and later lock again. */ | ||
1162 | mutex_unlock(&itv->serialize_lock); | ||
1163 | res = ivtv_yuv_udma_frame(itv, &dma_args); | ||
1164 | mutex_lock(&itv->serialize_lock); | ||
1165 | return res; | ||
1159 | } | 1166 | } |
1160 | 1167 | ||
1161 | /* IVTV_IOC_DMA_FRAME ioctl handler */ | 1168 | /* IVTV_IOC_DMA_FRAME ioctl handler */ |
1162 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | 1169 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) |
1163 | { | 1170 | { |
1164 | /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | 1171 | int res; |
1165 | 1172 | ||
1173 | /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | ||
1166 | ivtv_yuv_next_free(itv); | 1174 | ivtv_yuv_next_free(itv); |
1167 | ivtv_yuv_setup_frame(itv, args); | 1175 | ivtv_yuv_setup_frame(itv, args); |
1168 | return ivtv_yuv_udma_frame(itv, args); | 1176 | /* Wait for frame DMA. Note that serialize_lock is locked, |
1177 | so to allow other processes to access the driver while | ||
1178 | we are waiting unlock first and later lock again. */ | ||
1179 | mutex_unlock(&itv->serialize_lock); | ||
1180 | res = ivtv_yuv_udma_frame(itv, args); | ||
1181 | mutex_lock(&itv->serialize_lock); | ||
1182 | return res; | ||
1169 | } | 1183 | } |
1170 | 1184 | ||
1171 | void ivtv_yuv_close(struct ivtv *itv) | 1185 | void ivtv_yuv_close(struct ivtv *itv) |
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv) | |||
1174 | int h_filter, v_filter_1, v_filter_2; | 1188 | int h_filter, v_filter_1, v_filter_2; |
1175 | 1189 | ||
1176 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); | 1190 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); |
1191 | mutex_unlock(&itv->serialize_lock); | ||
1177 | ivtv_waitq(&itv->vsync_waitq); | 1192 | ivtv_waitq(&itv->vsync_waitq); |
1193 | mutex_lock(&itv->serialize_lock); | ||
1178 | 1194 | ||
1179 | yi->running = 0; | 1195 | yi->running = 0; |
1180 | atomic_set(&yi->next_dma_frame, -1); | 1196 | atomic_set(&yi->next_dma_frame, -1); |