aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-12-31 20:09:51 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:10:30 -0500
commit82acdc84cc4acc11389bdc648b23b15426d2038c (patch)
tree17f9bc1f4f20611a17f6d1063270e44fc932de2c /drivers/media
parentef99179710d6ec04d6783afdf8387523c7087920 (diff)
V4L/DVB (13908): cx18: Add initial working VIDIOC_G_ENC_INDEX ioctl() support
VIDIOC_G_ENC_INDEX support see the light of day. Some notes: 1. With default capture parameters, the CX23418 seems to transfer 192 index entries (4.5 kB worth) at 10 second intervals. 2. Index streams don't seem to be supported for MPEG 2 TS streams 3. The index entries seem to claim every frame is a B-Frame. Possible firmware bug. 4. The cx18 driver does not try to capture an index stream when inserting sliced VBI into the MPEg stream as the offsets would need fixup. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/cx18/cx18-driver.h12
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c12
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c135
3 files changed, 146 insertions, 13 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index ff3426206765..930bab647467 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -288,6 +288,18 @@ struct cx18_options {
288#define CX18_SLICED_TYPE_WSS_625 (5) 288#define CX18_SLICED_TYPE_WSS_625 (5)
289#define CX18_SLICED_TYPE_VPS (7) 289#define CX18_SLICED_TYPE_VPS (7)
290 290
291/**
292 * list_entry_is_past_end - check if a previous loop cursor is off list end
293 * @pos: the type * previously used as a loop cursor.
294 * @head: the head for your list.
295 * @member: the name of the list_struct within the struct.
296 *
297 * Check if the entry's list_head is the head of the list, thus it's not a
298 * real entry but was the loop cursor that walked past the end
299 */
300#define list_entry_is_past_end(pos, head, member) \
301 (&pos->member == (head))
302
291struct cx18_buffer { 303struct cx18_buffer {
292 struct list_head list; 304 struct list_head list;
293 dma_addr_t dma_handle; 305 dma_addr_t dma_handle;
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index b1ad03f61019..d522d84906e1 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -392,18 +392,6 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
392 return len; 392 return len;
393} 393}
394 394
395/**
396 * list_entry_is_past_end - check if a previous loop cursor is off list end
397 * @pos: the type * previously used as a loop cursor.
398 * @head: the head for your list.
399 * @member: the name of the list_struct within the struct.
400 *
401 * Check if the entry's list_head is the head of the list, thus it's not a
402 * real entry but was the loop cursor that walked past the end
403 */
404#define list_entry_is_past_end(pos, head, member) \
405 (&pos->member == (head))
406
407static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, 395static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
408 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) 396 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
409{ 397{
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 3e4fc192fdec..b81dd0ea8eb9 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -775,10 +775,143 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
775 return 0; 775 return 0;
776} 776}
777 777
778static int _cx18_process_idx_data(struct cx18_buffer *buf,
779 struct v4l2_enc_idx *idx)
780{
781 int consumed, remaining;
782 struct v4l2_enc_idx_entry *e_idx;
783 struct cx18_enc_idx_entry *e_buf;
784
785 /* Frame type lookup: 1=I, 2=P, 4=B */
786 const int mapping[8] = {
787 -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
788 -1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
789 };
790
791 /*
792 * Assumption here is that a buf holds an integral number of
793 * struct cx18_enc_idx_entry objects and is properly aligned.
794 * This is enforced by the module options on IDX buffer sizes.
795 */
796 remaining = buf->bytesused - buf->readpos;
797 consumed = 0;
798 e_idx = &idx->entry[idx->entries];
799 e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];
800
801 while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
802 idx->entries < V4L2_ENC_IDX_ENTRIES) {
803
804 e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
805 | le32_to_cpu(e_buf->offset_low);
806
807 e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
808 | le32_to_cpu(e_buf->pts_low);
809
810 e_idx->length = le32_to_cpu(e_buf->length);
811
812 e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];
813
814 e_idx->reserved[0] = 0;
815 e_idx->reserved[1] = 0;
816
817 idx->entries++;
818 e_idx = &idx->entry[idx->entries];
819 e_buf++;
820
821 remaining -= sizeof(struct cx18_enc_idx_entry);
822 consumed += sizeof(struct cx18_enc_idx_entry);
823 }
824
825 /* Swallow any partial entries at the end, if there are any */
826 if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
827 consumed += remaining;
828
829 buf->readpos += consumed;
830 return consumed;
831}
832
833static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
834 struct v4l2_enc_idx *idx)
835{
836 if (s->type != CX18_ENC_STREAM_TYPE_IDX)
837 return -EINVAL;
838
839 if (mdl->curr_buf == NULL)
840 mdl->curr_buf = list_first_entry(&mdl->buf_list,
841 struct cx18_buffer, list);
842
843 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
844 /*
845 * For some reason we've exhausted the buffers, but the MDL
846 * object still said some data was unread.
847 * Fix that and bail out.
848 */
849 mdl->readpos = mdl->bytesused;
850 return 0;
851 }
852
853 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
854
855 /* Skip any empty buffers in the MDL */
856 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
857 continue;
858
859 mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);
860
861 /* exit when MDL drained or request satisfied */
862 if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
863 mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
864 mdl->readpos >= mdl->bytesused)
865 break;
866 }
867 return 0;
868}
869
778static int cx18_g_enc_index(struct file *file, void *fh, 870static int cx18_g_enc_index(struct file *file, void *fh,
779 struct v4l2_enc_idx *idx) 871 struct v4l2_enc_idx *idx)
780{ 872{
781 return -EINVAL; 873 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
874 struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
875 s32 tmp;
876 struct cx18_mdl *mdl;
877
878 if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
879 return -EINVAL;
880
881 /* Compute the best case number of entries we can buffer */
882 tmp = s->buffers -
883 s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
884 if (tmp <= 0)
885 tmp = 1;
886 tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);
887
888 /* Fill out the header of the return structure */
889 idx->entries = 0;
890 idx->entries_cap = tmp;
891 memset(idx->reserved, 0, sizeof(idx->reserved));
892
893 /* Pull IDX MDLs and buffers from q_full and populate the entries */
894 do {
895 mdl = cx18_dequeue(s, &s->q_full);
896 if (mdl == NULL) /* No more IDX data right now */
897 break;
898
899 /* Extract the Index entry data from the MDL and buffers */
900 cx18_process_idx_data(s, mdl, idx);
901 if (mdl->readpos < mdl->bytesused) {
902 /* We finished with data remaining, push the MDL back */
903 cx18_push(s, mdl, &s->q_full);
904 break;
905 }
906
907 /* We drained this MDL, schedule it to go to the firmware */
908 cx18_enqueue(s, mdl, &s->q_free);
909
910 } while (idx->entries < V4L2_ENC_IDX_ENTRIES);
911
912 /* Tell the work handler to send free IDX MDLs to the firmware */
913 cx18_stream_load_fw_queue(s);
914 return 0;
782} 915}
783 916
784static int cx18_encoder_cmd(struct file *file, void *fh, 917static int cx18_encoder_cmd(struct file *file, void *fh,