aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-05-25 10:21:27 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-06-05 05:35:45 -0400
commit31554ae599a8ff6854bf8ecbedc1946c64854388 (patch)
tree33169d397f17069e72d72695f6adb59a4a25b210 /drivers/media/video
parentbe303e16dbd210077c697aaf2f0960413166b53d (diff)
V4L/DVB (7931): cx18: allow for simultaneous digital and analog capture
The HVR-1600 can do both analog and digital capture at the same time. Due to a driver bug -EBUSY would be returned when attempting to setup an analog capture while a digital capture was already in progress. Separate the two internally. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/cx18/cx18-controls.c6
-rw-r--r--drivers/media/video/cx18/cx18-driver.c2
-rw-r--r--drivers/media/video/cx18/cx18-driver.h3
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c10
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c12
-rw-r--r--drivers/media/video/cx18/cx18-streams.c16
6 files changed, 27 insertions, 22 deletions
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 2bdac5ebbb0d..87cf41021665 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -159,7 +159,7 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt
159{ 159{
160 if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) 160 if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
161 return -EINVAL; 161 return -EINVAL;
162 if (atomic_read(&cx->capturing) > 0) 162 if (atomic_read(&cx->ana_capturing) > 0)
163 return -EBUSY; 163 return -EBUSY;
164 164
165 /* First try to allocate sliced VBI buffers if needed. */ 165 /* First try to allocate sliced VBI buffers if needed. */
@@ -235,7 +235,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
235 CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); 235 CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
236 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { 236 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
237 struct cx2341x_mpeg_params p = cx->params; 237 struct cx2341x_mpeg_params p = cx->params;
238 int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd); 238 int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd);
239 239
240 if (err) 240 if (err)
241 return err; 241 return err;
@@ -295,7 +295,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
295 CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); 295 CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
296 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) 296 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
297 return cx2341x_ext_ctrls(&cx->params, 297 return cx2341x_ext_ctrls(&cx->params,
298 atomic_read(&cx->capturing), arg, cmd); 298 atomic_read(&cx->ana_capturing), arg, cmd);
299 return -EINVAL; 299 return -EINVAL;
300 } 300 }
301 301
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 0dd4e0529970..472f88e64199 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -889,7 +889,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
889 889
890 /* Stop all captures */ 890 /* Stop all captures */
891 CX18_DEBUG_INFO("Stopping all streams\n"); 891 CX18_DEBUG_INFO("Stopping all streams\n");
892 if (atomic_read(&cx->capturing) > 0) 892 if (atomic_read(&cx->tot_capturing) > 0)
893 cx18_stop_all_captures(cx); 893 cx18_stop_all_captures(cx);
894 894
895 /* Interrupts */ 895 /* Interrupts */
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index a2a6c58d12fe..9c6a53477a1b 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -380,7 +380,8 @@ struct cx18 {
380 int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ 380 int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
381 struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ 381 struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */
382 unsigned long i_flags; /* global cx18 flags */ 382 unsigned long i_flags; /* global cx18 flags */
383 atomic_t capturing; /* count number of active capture streams */ 383 atomic_t ana_capturing; /* count number of active analog capture streams */
384 atomic_t tot_capturing; /* total count number of active capture streams */
384 spinlock_t lock; /* lock access to this struct */ 385 spinlock_t lock; /* lock access to this struct */
385 int search_pack_header; 386 int search_pack_header;
386 387
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 0b3141db174b..d0d7888f269a 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -318,7 +318,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
318 size_t tot_written = 0; 318 size_t tot_written = 0;
319 int single_frame = 0; 319 int single_frame = 0;
320 320
321 if (atomic_read(&cx->capturing) == 0 && s->id == -1) { 321 if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
322 /* shouldn't happen */ 322 /* shouldn't happen */
323 CX18_DEBUG_WARN("Stream %s not initialized before read\n", 323 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
324 s->name); 324 s->name);
@@ -581,7 +581,7 @@ int cx18_v4l2_close(struct inode *inode, struct file *filp)
581 cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); 581 cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
582 /* Select correct audio input (i.e. TV tuner or Line in) */ 582 /* Select correct audio input (i.e. TV tuner or Line in) */
583 cx18_audio_set_io(cx); 583 cx18_audio_set_io(cx);
584 if (atomic_read(&cx->capturing) > 0) { 584 if (atomic_read(&cx->ana_capturing) > 0) {
585 /* Undo video mute */ 585 /* Undo video mute */
586 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, 586 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
587 cx->params.video_mute | 587 cx->params.video_mute |
@@ -627,7 +627,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
627 } 627 }
628 628
629 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { 629 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
630 if (atomic_read(&cx->capturing) > 0) { 630 if (atomic_read(&cx->ana_capturing) > 0) {
631 /* switching to radio while capture is 631 /* switching to radio while capture is
632 in progress is not polite */ 632 in progress is not polite */
633 cx18_release_stream(s); 633 cx18_release_stream(s);
@@ -694,7 +694,7 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
694 694
695void cx18_mute(struct cx18 *cx) 695void cx18_mute(struct cx18 *cx)
696{ 696{
697 if (atomic_read(&cx->capturing)) 697 if (atomic_read(&cx->ana_capturing))
698 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, 698 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
699 cx18_find_handle(cx), 1); 699 cx18_find_handle(cx), 1);
700 CX18_DEBUG_INFO("Mute\n"); 700 CX18_DEBUG_INFO("Mute\n");
@@ -702,7 +702,7 @@ void cx18_mute(struct cx18 *cx)
702 702
703void cx18_unmute(struct cx18 *cx) 703void cx18_unmute(struct cx18 *cx)
704{ 704{
705 if (atomic_read(&cx->capturing)) { 705 if (atomic_read(&cx->ana_capturing)) {
706 cx18_msleep_timeout(100, 0); 706 cx18_msleep_timeout(100, 0);
707 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, 707 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
708 cx18_find_handle(cx), 12); 708 cx18_find_handle(cx), 12);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index dbdcb86ec5aa..4151f1e5493f 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -247,7 +247,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
247 247
248 if (!set_fmt || (cx->params.width == w && cx->params.height == h)) 248 if (!set_fmt || (cx->params.width == w && cx->params.height == h))
249 return 0; 249 return 0;
250 if (atomic_read(&cx->capturing) > 0) 250 if (atomic_read(&cx->ana_capturing) > 0)
251 return -EBUSY; 251 return -EBUSY;
252 252
253 cx->params.width = w; 253 cx->params.width = w;
@@ -264,7 +264,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
264 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 264 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
265 if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && 265 if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI &&
266 cx->vbi.sliced_in->service_set && 266 cx->vbi.sliced_in->service_set &&
267 atomic_read(&cx->capturing) > 0) 267 atomic_read(&cx->ana_capturing) > 0)
268 return -EBUSY; 268 return -EBUSY;
269 if (set_fmt) { 269 if (set_fmt) {
270 cx->vbi.sliced_in->service_set = 0; 270 cx->vbi.sliced_in->service_set = 0;
@@ -293,7 +293,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
293 return 0; 293 return 0;
294 if (set == 0) 294 if (set == 0)
295 return -EINVAL; 295 return -EINVAL;
296 if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0) 296 if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
297 return -EBUSY; 297 return -EBUSY;
298 cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); 298 cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
299 memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); 299 memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
@@ -581,7 +581,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
581 break; 581 break;
582 582
583 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || 583 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
584 atomic_read(&cx->capturing) > 0) { 584 atomic_read(&cx->ana_capturing) > 0) {
585 /* Switching standard would turn off the radio or mess 585 /* Switching standard would turn off the radio or mess
586 with already running streams, prevent that by 586 with already running streams, prevent that by
587 returning EBUSY. */ 587 returning EBUSY. */
@@ -677,7 +677,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
677 enc->flags = 0; 677 enc->flags = 0;
678 if (try) 678 if (try)
679 return 0; 679 return 0;
680 if (!atomic_read(&cx->capturing)) 680 if (!atomic_read(&cx->ana_capturing))
681 return -EPERM; 681 return -EPERM;
682 if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) 682 if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
683 return 0; 683 return 0;
@@ -689,7 +689,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg
689 enc->flags = 0; 689 enc->flags = 0;
690 if (try) 690 if (try)
691 return 0; 691 return 0;
692 if (!atomic_read(&cx->capturing)) 692 if (!atomic_read(&cx->ana_capturing))
693 return -EPERM; 693 return -EPERM;
694 if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) 694 if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
695 return 0; 695 return 0;
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index dee6cc988090..5a065869401c 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -444,7 +444,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
444 s->handle = data[0]; 444 s->handle = data[0];
445 cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); 445 cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
446 446
447 if (atomic_read(&cx->capturing) == 0 && !ts) { 447 if (atomic_read(&cx->ana_capturing) == 0 && !ts) {
448 /* Stuff from Windows, we don't know what it is */ 448 /* Stuff from Windows, we don't know what it is */
449 cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); 449 cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
450 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); 450 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
@@ -467,7 +467,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
467 cx2341x_update(cx, cx18_api_func, NULL, &cx->params); 467 cx2341x_update(cx, cx18_api_func, NULL, &cx->params);
468 } 468 }
469 469
470 if (atomic_read(&cx->capturing) == 0) { 470 if (atomic_read(&cx->tot_capturing) == 0) {
471 clear_bit(CX18_F_I_EOS, &cx->i_flags); 471 clear_bit(CX18_F_I_EOS, &cx->i_flags);
472 write_reg(7, CX18_DSP0_INTERRUPT_MASK); 472 write_reg(7, CX18_DSP0_INTERRUPT_MASK);
473 } 473 }
@@ -493,7 +493,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
493 } 493 }
494 494
495 /* you're live! sit back and await interrupts :) */ 495 /* you're live! sit back and await interrupts :) */
496 atomic_inc(&cx->capturing); 496 if (!ts)
497 atomic_inc(&cx->ana_capturing);
498 atomic_inc(&cx->tot_capturing);
497 return 0; 499 return 0;
498} 500}
499 501
@@ -524,7 +526,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
524 526
525 CX18_DEBUG_INFO("Stop Capture\n"); 527 CX18_DEBUG_INFO("Stop Capture\n");
526 528
527 if (atomic_read(&cx->capturing) == 0) 529 if (atomic_read(&cx->tot_capturing) == 0)
528 return 0; 530 return 0;
529 531
530 if (s->type == CX18_ENC_STREAM_TYPE_MPG) 532 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
@@ -538,7 +540,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
538 CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); 540 CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
539 } 541 }
540 542
541 atomic_dec(&cx->capturing); 543 if (s->type != CX18_ENC_STREAM_TYPE_TS)
544 atomic_dec(&cx->ana_capturing);
545 atomic_dec(&cx->tot_capturing);
542 546
543 /* Clear capture and no-read bits */ 547 /* Clear capture and no-read bits */
544 clear_bit(CX18_F_S_STREAMING, &s->s_flags); 548 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
@@ -546,7 +550,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
546 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); 550 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
547 s->handle = 0xffffffff; 551 s->handle = 0xffffffff;
548 552
549 if (atomic_read(&cx->capturing) > 0) 553 if (atomic_read(&cx->tot_capturing) > 0)
550 return 0; 554 return 0;
551 555
552 write_reg(5, CX18_DSP0_INTERRUPT_MASK); 556 write_reg(5, CX18_DSP0_INTERRUPT_MASK);