]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/video/cx18/cx18-fileops.c
V4L/DVB (13906): cx18: Start IDX streams automatically as an internal associated...
[mv-sheeva.git] / drivers / media / video / cx18 / cx18-fileops.c
index 4e278db31cc9a56679fb614868fa62fef2ee65bd..b1ad03f61019b69b0c591dcfca74b136fc5502e2 100644 (file)
 
 /* This function tries to claim the stream for a specific file descriptor.
    If no one else is using this stream then the stream is claimed and
-   associated VBI streams are also automatically claimed.
+   associated VBI and IDX streams are also automatically claimed.
    Possible error returns: -EBUSY if someone else has claimed
    the stream or 0 on success. */
 static int cx18_claim_stream(struct cx18_open_id *id, int type)
 {
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[type];
-       struct cx18_stream *s_vbi;
-       int vbi_type;
+       struct cx18_stream *s_assoc;
+
+       /* Nothing should ever try to directly claim the IDX stream */
+       if (type == CX18_ENC_STREAM_TYPE_IDX) {
+               CX18_WARN("MPEG Index stream cannot be claimed "
+                         "directly, but something tried.\n");
+               return -EINVAL;
+       }
 
        if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
                /* someone already claimed this stream */
@@ -67,21 +73,27 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
        }
        s->id = id->open_id;
 
-       /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI
-          (provided VBI insertion is on and sliced VBI is selected), for all
-          other streams we're done */
-       if (type == CX18_ENC_STREAM_TYPE_MPG &&
-           cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) {
-               vbi_type = CX18_ENC_STREAM_TYPE_VBI;
-       } else {
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to claim:
+        * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
+        * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
+        * (We don't yet fix up MPEG Index entries for our inserted packets).
+        *
+        * For all other streams we're done.
+        */
+       if (type != CX18_ENC_STREAM_TYPE_MPG)
                return 0;
-       }
-       s_vbi = &cx->streams[vbi_type];
 
-       set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
+               s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       else if (!cx18_stream_enabled(s_assoc))
+               return 0;
+
+       set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
 
        /* mark that it is used internally */
-       set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags);
+       set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
        return 0;
 }
 
@@ -90,9 +102,17 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
 static void cx18_release_stream(struct cx18_stream *s)
 {
        struct cx18 *cx = s->cx;
-       struct cx18_stream *s_vbi;
+       struct cx18_stream *s_assoc;
 
        s->id = -1;
+       if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
+               /*
+                * The IDX stream is only used internally, and can
+                * only be indirectly unclaimed by unclaiming the MPG stream.
+                */
+               return;
+       }
+
        if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
                test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
                /* this stream is still in use internally */
@@ -105,24 +125,34 @@ static void cx18_release_stream(struct cx18_stream *s)
 
        cx18_flush_queues(s);
 
-       /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI,
-          for all other streams we're done */
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
-               s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       else
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to release the
+        * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
+        *
+        * For all other streams we're done.
+        */
+       if (s->type != CX18_ENC_STREAM_TYPE_MPG)
                return;
 
-       /* clear internal use flag */
-       if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
-               /* was already cleared */
-               return;
+       /* Unclaim the associated MPEG Index stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+               cx18_flush_queues(s_assoc);
        }
-       if (s_vbi->id != -1) {
-               /* VBI stream still claimed by a file descriptor */
-               return;
+
+       /* Unclaim the associated VBI stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               if (s_assoc->id == -1) {
+                       /*
+                        * The VBI stream is not still claimed by a file
+                        * descriptor, so completely unclaim it.
+                        */
+                       clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+                       cx18_flush_queues(s_assoc);
+               }
        }
-       clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
-       cx18_flush_queues(s_vbi);
 }
 
 static void cx18_dualwatch(struct cx18 *cx)
@@ -498,6 +528,7 @@ int cx18_start_capture(struct cx18_open_id *id)
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
        struct cx18_stream *s_vbi;
+       struct cx18_stream *s_idx;
 
        if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
                /* you cannot read from these stream types. */
@@ -516,25 +547,33 @@ int cx18_start_capture(struct cx18_open_id *id)
                return 0;
        }
 
-       /* Start VBI capture if required */
+       /* Start associated VBI or IDX stream capture if required */
        s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-           !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
-               /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
-                  automatically when the MPG stream is claimed.
-                  We only need to start the VBI capturing. */
-               if (cx18_start_v4l2_encode_stream(s_vbi)) {
-                       CX18_DEBUG_WARN("VBI capture start failed\n");
-
-                       /* Failure, clean up and return an error */
-                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
-                       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-                       /* also releases the associated VBI stream */
-                       cx18_release_stream(s);
-                       return -EIO;
+       s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /*
+                * The VBI and IDX streams should have been claimed
+                * automatically, if for internal use, when the MPG stream was
+                * claimed.  We only need to start these streams capturing.
+                */
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_idx)) {
+                               CX18_DEBUG_WARN("IDX capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("IDX capture started\n");
+               }
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_vbi)) {
+                               CX18_DEBUG_WARN("VBI capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("VBI insertion started\n");
                }
-               CX18_DEBUG_INFO("VBI insertion started\n");
        }
 
        /* Tell the card to start capturing */
@@ -547,19 +586,29 @@ int cx18_start_capture(struct cx18_open_id *id)
                return 0;
        }
 
-       /* failure, clean up */
+start_failed:
        CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
 
-       /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
-          automatically when the MPG stream is released.
-          We only need to stop the VBI capturing. */
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
-               cx18_stop_v4l2_encode_stream(s_vbi, 0);
-               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+       /*
+        * The associated VBI and IDX streams for internal use are released
+        * automatically when the MPG stream is released.  We only need to stop
+        * the associated stream.
+        */
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /* Stop the IDX stream which is always for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+               }
+               /* Stop the VBI stream, if only running for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+               }
        }
        clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-       cx18_release_stream(s);
+       cx18_release_stream(s); /* Also releases associated streams */
        return -EIO;
 }
 
@@ -618,6 +667,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
 {
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
 
        CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
@@ -625,17 +676,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
 
        /* Stop capturing */
        if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               struct cx18_stream *s_vbi =
-                       &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-
                CX18_DEBUG_INFO("close stopping capture\n");
-               /* Special case: a running VBI capture for VBI insertion
-                  in the mpeg stream. Need to stop that too. */
-               if (id->type == CX18_ENC_STREAM_TYPE_MPG &&
-                   test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
-                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-                       CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
-                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+               if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
+                       /* Stop internal use associated VBI and IDX streams */
+                       if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping embedded VBI "
+                                               "capture\n");
+                               cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       }
+                       if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping IDX capture\n");
+                               cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       }
                }
                if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
                    test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
@@ -758,8 +811,8 @@ int cx18_v4l2_open(struct file *filp)
 
        mutex_lock(&cx->serialize_lock);
        if (cx18_init_on_first_open(cx)) {
-               CX18_ERR("Failed to initialize on minor %d\n",
-                        video_dev->minor);
+               CX18_ERR("Failed to initialize on %s\n",
+                        video_device_node_name(video_dev));
                mutex_unlock(&cx->serialize_lock);
                return -ENXIO;
        }