V4L/DVB: cx18, cx23885, v4l2 doc, MAINTAINERS: Update Andy Walls' email address
[safe/jmp/linux-2.6] / drivers / media / video / cx18 / cx18-streams.c
index 9be603c..9045f1e 100644 (file)
@@ -4,7 +4,7 @@
  *  Derived from ivtv-streams.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -319,11 +319,27 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
 
        /* Teardown all streams */
        for (type = 0; type < CX18_MAX_STREAMS; type++) {
-               if (cx->streams[type].dvb.enabled) {
-                       cx18_dvb_unregister(&cx->streams[type]);
-                       cx->streams[type].dvb.enabled = false;
+
+               /* No struct video_device, but can have buffers allocated */
+               if (type == CX18_ENC_STREAM_TYPE_TS) {
+                       if (cx->streams[type].dvb.enabled) {
+                               cx18_dvb_unregister(&cx->streams[type]);
+                               cx->streams[type].dvb.enabled = false;
+                               cx18_stream_free(&cx->streams[type]);
+                       }
+                       continue;
+               }
+
+               /* No struct video_device, but can have buffers allocated */
+               if (type == CX18_ENC_STREAM_TYPE_IDX) {
+                       if (cx->stream_buffers[type] != 0) {
+                               cx->stream_buffers[type] = 0;
+                               cx18_stream_free(&cx->streams[type]);
+                       }
+                       continue;
                }
 
+               /* If struct video_device exists, can have buffers allocated */
                vdev = cx->streams[type].video_dev;
 
                cx->streams[type].video_dev = NULL;
@@ -340,11 +356,6 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
        }
 }
 
-static inline bool cx18_stream_enabled(struct cx18_stream *s)
-{
-       return s->video_dev || s->dvb.enabled;
-}
-
 static void cx18_vbi_setup(struct cx18_stream *s)
 {
        struct cx18 *cx = s->cx;
@@ -363,7 +374,10 @@ static void cx18_vbi_setup(struct cx18_stream *s)
        }
 
        /* setup VBI registers */
-       v4l2_subdev_call(cx->sd_av, video, s_fmt, &cx->vbi.in);
+       if (raw)
+               v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi);
+       else
+               v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced);
 
        /*
         * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw
@@ -452,6 +466,32 @@ static void cx18_vbi_setup(struct cx18_stream *s)
        cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
 }
 
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx)
+{
+       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       struct cx18_mdl *mdl;
+
+       if (!cx18_stream_enabled(s))
+               return;
+
+       /* Return if the firmware is not running low on MDLs */
+       if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=
+                                           CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN)
+               return;
+
+       /* Return if there are no MDLs to rotate back to the firmware */
+       if (atomic_read(&s->q_full.depth) < 2)
+               return;
+
+       /*
+        * Take the oldest IDX MDL still holding data, and discard its index
+        * entries by scheduling the MDL to go back to the firmware
+        */
+       mdl = cx18_dequeue(s, &s->q_full);
+       if (mdl != NULL)
+               cx18_enqueue(s, mdl, &s->q_free);
+}
+
 static
 struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
                                           struct cx18_mdl *mdl)
@@ -551,6 +591,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
        struct cx18 *cx = s->cx;
        int captype = 0;
        struct cx18_api_func_private priv;
+       struct cx18_stream *s_idx;
 
        if (!cx18_stream_enabled(s))
                return -EINVAL;
@@ -566,6 +607,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
                cx->search_pack_header = 0;
                break;
 
+       case CX18_ENC_STREAM_TYPE_IDX:
+               captype = CAPTURE_CHANNEL_TYPE_INDEX;
+               break;
        case CX18_ENC_STREAM_TYPE_TS:
                captype = CAPTURE_CHANNEL_TYPE_TS;
                break;
@@ -640,11 +684,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
                        cx18_vbi_setup(s);
 
                /*
-                * assign program index info.
-                * Mask 7: select I/P/B, Num_req: 400 max
-                * FIXME - currently we have this hardcoded as disabled
+                * Select to receive I, P, and B frame index entries, if the
+                * index stream is enabled.  Otherwise disable index entry
+                * generation.
                 */
-               cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0);
+               s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+               cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2,
+                                s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);
 
                /* Call out to the common CX2341x API setup for user controls */
                priv.cx = cx;
@@ -702,6 +748,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
        atomic_inc(&cx->tot_capturing);
        return 0;
 }
+EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);
 
 void cx18_stop_all_captures(struct cx18 *cx)
 {
@@ -767,6 +814,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
 
        return 0;
 }
+EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream);
 
 u32 cx18_find_handle(struct cx18 *cx)
 {