aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2007-08-18 10:46:05 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:05:31 -0400
commit3562c43be8cfd6e300508d7c33acebf3369eacd3 (patch)
tree3b2aab0d4e078ddf5445d2ab82eea2838bcf01ba /drivers/media/video/ivtv
parentda80be21362376443c6ee9918dfff408e83e0c39 (diff)
V4L/DVB (6045): ivtv: fix handling of INITIALIZE_INPUT fw call
The CX2341X_ENC_INITIALIZE_INPUT firmware call requires careful handling, otherwise the computer can freeze or the top-third of the screen can start flickering. This patch ensures that CX2341X_ENC_INITIALIZE_INPUT is called at the right time and in the right way. In addition the stop capture handling was improved so that the last pending DMA transfer is also processed. Otherwise this would be the first data that arrived when a new capture was started which is not what you want. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c19
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c3
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c28
3 files changed, 19 insertions, 31 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 9e867b5229d1..908e640c274d 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -892,12 +892,20 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
892 return -EBUSY; 892 return -EBUSY;
893 } 893 }
894 894
895 if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
896 if (atomic_read(&itv->capturing) > 0) {
897 /* switching to radio while capture is
898 in progress is not polite */
899 kfree(item);
900 return -EBUSY;
901 }
902 }
903 /* Mark that the radio is being used. */
904 set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
895 /* We have the radio */ 905 /* We have the radio */
896 ivtv_mute(itv); 906 ivtv_mute(itv);
897 /* Switch tuner to radio */ 907 /* Switch tuner to radio */
898 ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); 908 ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL);
899 /* Mark that the radio is being used. */
900 set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
901 /* Select the correct audio input (i.e. radio tuner) */ 909 /* Select the correct audio input (i.e. radio tuner) */
902 ivtv_audio_set_io(itv); 910 ivtv_audio_set_io(itv);
903 if (itv->hw_flags & IVTV_HW_SAA711X) 911 if (itv->hw_flags & IVTV_HW_SAA711X)
@@ -931,13 +939,8 @@ void ivtv_mute(struct ivtv *itv)
931 939
932void ivtv_unmute(struct ivtv *itv) 940void ivtv_unmute(struct ivtv *itv)
933{ 941{
934 /* initialize or refresh input */
935 if (atomic_read(&itv->capturing) == 0)
936 ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
937
938 ivtv_msleep_timeout(100, 0);
939
940 if (atomic_read(&itv->capturing)) { 942 if (atomic_read(&itv->capturing)) {
943 ivtv_msleep_timeout(100, 0);
941 ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); 944 ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
942 ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0); 945 ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
943 } 946 }
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index cee6c558c69c..734f2d2ffa62 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -906,6 +906,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
906 IVTV_DEBUG_INFO("Input unchanged\n"); 906 IVTV_DEBUG_INFO("Input unchanged\n");
907 break; 907 break;
908 } 908 }
909 if (atomic_read(&itv->capturing) > 0) {
910 return -EBUSY;
911 }
909 IVTV_DEBUG_INFO("Changing input from %d to %d\n", 912 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
910 itv->active_input, inp); 913 itv->active_input, inp);
911 914
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 405e2e3fcb49..0582b9d57c55 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -554,9 +554,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
554 clear_bit(IVTV_F_I_EOS, &itv->i_flags); 554 clear_bit(IVTV_F_I_EOS, &itv->i_flags);
555 555
556 /* Initialize Digitizer for Capture */ 556 /* Initialize Digitizer for Capture */
557 itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0);
558 ivtv_msleep_timeout(300, 1);
557 ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); 559 ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
558 560 itv->video_dec_func(itv, VIDIOC_STREAMON, 0);
559 ivtv_msleep_timeout(100, 0);
560 } 561 }
561 562
562 /* begin_capture */ 563 /* begin_capture */
@@ -713,7 +714,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
713 int cap_type; 714 int cap_type;
714 unsigned long then; 715 unsigned long then;
715 int stopmode; 716 int stopmode;
716 u32 data[CX2341X_MBOX_MAX_DATA];
717 717
718 if (s->v4l2dev == NULL) 718 if (s->v4l2dev == NULL)
719 return -EINVAL; 719 return -EINVAL;
@@ -793,27 +793,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
793 } 793 }
794 794
795 then = jiffies; 795 then = jiffies;
796 /* Make sure DMA is complete */
797 add_wait_queue(&s->waitq, &wait);
798 do {
799 /* check if DMA is pending */
800 if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */
801 (read_reg(IVTV_REG_DMASTATUS) & 0x02)) {
802 /* Check for last DMA */
803 ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0);
804
805 if (data[0] == 1) {
806 IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]);
807 break;
808 }
809 } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) {
810 break;
811 }
812 } while (!ivtv_msleep_timeout(10, 1) &&
813 then + msecs_to_jiffies(2000) > jiffies);
814 796
815 set_current_state(TASK_RUNNING); 797 /* Handle any pending interrupts */
816 remove_wait_queue(&s->waitq, &wait); 798 ivtv_msleep_timeout(100, 1);
817 } 799 }
818 800
819 atomic_dec(&itv->capturing); 801 atomic_dec(&itv->capturing);