V4L/DVB (13907): cx18: Perform automatic rotation of very old, unread IDX buffers
authorAndy Walls <awalls@radix.net>
Thu, 31 Dec 2009 21:27:13 +0000 (18:27 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 26 Feb 2010 18:10:30 +0000 (15:10 -0300)
According to the v4l2 spec, very old MPEG index entries needs to be discarded
in favor of newer index entries.  This change ensures the firmware always has
buffers for index entries at the expense of the oldest unread buffers.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-streams.h

index f231dd09c720aa52f46458bc3913e62ea23ad016..0ac0e2c993a5cca6fd890cedca40e7805f163af2 100644 (file)
@@ -223,8 +223,11 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
                CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
                                  s->name, mdl->bytesused);
 
-               if (s->type != CX18_ENC_STREAM_TYPE_TS)
+               if (s->type != CX18_ENC_STREAM_TYPE_TS) {
                        cx18_enqueue(s, mdl, &s->q_full);
+                       if (s->type == CX18_ENC_STREAM_TYPE_IDX)
+                               cx18_stream_rotate_idx_mdls(cx);
+               }
                else {
                        cx18_mdl_send_to_dvb(s, mdl);
                        cx18_enqueue(s, mdl, &s->q_free);
index 9755f4416e962f57be4ba308a46a2726ef7d9be9..680e7da5e5e48b48e88ae4c872f5c141463b4f00 100644 (file)
@@ -463,6 +463,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)
index 7b36225c4abe0575780d5ac810ef209b08bbf133..0bff0fa2976370f77dc677673bb93529bcbba647 100644 (file)
@@ -28,6 +28,9 @@ int cx18_streams_setup(struct cx18 *cx);
 int cx18_streams_register(struct cx18 *cx);
 void cx18_streams_cleanup(struct cx18 *cx, int unregister);
 
+#define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3)
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
+
 static inline bool cx18_stream_enabled(struct cx18_stream *s)
 {
        return s->video_dev || s->dvb.enabled ||