Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 174138
b: refs/heads/master
c: 52fcb3e
h: refs/heads/master
v: v3
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Dec 5, 2009
1 parent 9a1964e commit 2e46729
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 174 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fa655dda5ce6e5ac4a9b94fd451358edca2ddab8
refs/heads/master: 52fcb3ecc6707f52dfe4297f96b7609d4ba517fb
6 changes: 6 additions & 0 deletions trunk/drivers/media/video/cx18/cx18-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;

/* IVTV style VBI insertion into MPEG streams */
INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list);
INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list);
INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list);
list_add(&cx->vbi.sliced_mpeg_buf.list,
&cx->vbi.sliced_mpeg_mdl.buf_list);
return 0;
}

Expand Down
45 changes: 31 additions & 14 deletions trunk/drivers/media/video/cx18/cx18-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ struct cx18_options {
int radio; /* enable/disable radio */
};

/* per-buffer bit flags */
#define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */
/* per-mdl bit flags */
#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */

/* per-stream, s_flags */
#define CX18_F_S_CLAIMED 3 /* this stream is claimed */
Expand All @@ -274,15 +274,26 @@ struct cx18_options {
struct cx18_buffer {
struct list_head list;
dma_addr_t dma_handle;
u32 id;
unsigned long b_flags;
unsigned skipped;
char *buf;

u32 bytesused;
u32 readpos;
};

struct cx18_mdl {
struct list_head list;
u32 id; /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */

unsigned int skipped;
unsigned long m_flags;

struct list_head buf_list;
struct cx18_buffer *curr_buf; /* current buffer in list for reading */

u32 bytesused;
u32 readpos;
};

struct cx18_queue {
struct list_head list;
atomic_t depth;
Expand Down Expand Up @@ -346,14 +357,20 @@ struct cx18_stream {
PCI_DMA_NONE */
wait_queue_head_t waitq;

/* Buffer Stats */
u32 buffers;
u32 buf_size;
/* Buffers */
struct list_head buf_pool; /* buffers not attached to an MDL */
u32 buffers; /* total buffers owned by this stream */
u32 buf_size; /* size in bytes of a single buffer */

/* MDL sizes - all stream MDLs are the same size */
u32 bufs_per_mdl;
u32 mdl_size; /* total bytes in all buffers in a mdl */

/* Buffer Queues */
struct cx18_queue q_free; /* free buffers */
struct cx18_queue q_busy; /* busy buffers - in use by firmware */
struct cx18_queue q_full; /* full buffers - data for user apps */
/* MDL Queues */
struct cx18_queue q_free; /* free - in rotation, not committed */
struct cx18_queue q_busy; /* busy - in use by firmware */
struct cx18_queue q_full; /* full - data for user apps */
struct cx18_queue q_idle; /* idle - not in rotation */

struct work_struct out_work_order;

Expand Down Expand Up @@ -481,10 +498,11 @@ struct vbi_info {
u32 inserted_frame;

/*
* A dummy driver stream transfer buffer with a copy of the next
* A dummy driver stream transfer mdl & buffer with a copy of the next
* sliced_mpeg_data[] buffer for output to userland apps.
* Only used in cx18-fileops.c, but its state needs to persist at times.
*/
struct cx18_mdl sliced_mpeg_mdl;
struct cx18_buffer sliced_mpeg_buf;
};

Expand All @@ -511,7 +529,6 @@ struct cx18 {
u8 is_60hz;
u8 nof_inputs; /* number of video inputs */
u8 nof_audio_inputs; /* number of audio inputs */
u16 buffer_id; /* buffer ID counter */
u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* Hardware description of the board */
unsigned int free_mdl_idx;
Expand Down
128 changes: 96 additions & 32 deletions trunk/drivers/media/video/cx18/cx18-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,12 @@ static void cx18_dualwatch(struct cx18 *cx)
}


static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err)
static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
int *err)
{
struct cx18 *cx = s->cx;
struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
struct cx18_buffer *buf;
struct cx18_mdl *mdl;
DEFINE_WAIT(wait);

*err = 0;
Expand All @@ -185,32 +186,33 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
}
if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
!test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) {
while ((mdl = cx18_dequeue(s_vbi,
&s_vbi->q_full))) {
/* byteswap and process VBI data */
cx18_process_vbi_data(cx, buf,
cx18_process_vbi_data(cx, mdl,
s_vbi->type);
cx18_stream_put_buf_fw(s_vbi, buf);
cx18_stream_put_mdl_fw(s_vbi, mdl);
}
}
buf = &cx->vbi.sliced_mpeg_buf;
if (buf->readpos != buf->bytesused)
return buf;
mdl = &cx->vbi.sliced_mpeg_mdl;
if (mdl->readpos != mdl->bytesused)
return mdl;
}

/* do we have new data? */
buf = cx18_dequeue(s, &s->q_full);
if (buf) {
if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP,
&buf->b_flags))
return buf;
mdl = cx18_dequeue(s, &s->q_full);
if (mdl) {
if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
&mdl->m_flags))
return mdl;
if (s->type == CX18_ENC_STREAM_TYPE_MPG)
/* byteswap MPG data */
cx18_buf_swap(buf);
cx18_mdl_swap(mdl);
else {
/* byteswap and process VBI data */
cx18_process_vbi_data(cx, buf, s->type);
cx18_process_vbi_data(cx, mdl, s->type);
}
return buf;
return mdl;
}

/* return if end of stream */
Expand Down Expand Up @@ -241,21 +243,28 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
}
}

static void cx18_setup_sliced_vbi_buf(struct cx18 *cx)
static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
{
struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;

cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx];
cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx];
cx->vbi.sliced_mpeg_buf.readpos = 0;
buf->buf = cx->vbi.sliced_mpeg_data[idx];
buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
buf->readpos = 0;

mdl->curr_buf = NULL;
mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
mdl->readpos = 0;
}

static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
{
struct cx18 *cx = s->cx;
size_t len = buf->bytesused - buf->readpos;

*stop = false;
if (len > ucount)
len = ucount;
if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
Expand Down Expand Up @@ -335,7 +344,8 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
/* We declare we actually found a Program Pack*/
cx->search_pack_header = 0; /* expect vid PES */
len = (char *)q - start;
cx18_setup_sliced_vbi_buf(cx);
cx18_setup_sliced_vbi_mdl(cx);
*stop = true;
break;
}
}
Expand All @@ -352,6 +362,60 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
return len;
}

/**
* list_entry_is_past_end - check if a previous loop cursor is off list end
* @pos: the type * previously used as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Check if the entry's list_head is the head of the list, thus it's not a
* real entry but was the loop cursor that walked past the end
*/
#define list_entry_is_past_end(pos, head, member) \
(&pos->member == (head))

static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
{
size_t tot_written = 0;
int rc;
bool stop = false;

if (mdl->curr_buf == NULL)
mdl->curr_buf = list_first_entry(&mdl->buf_list,
struct cx18_buffer, list);

if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
/*
* For some reason we've exhausted the buffers, but the MDL
* object still said some data was unread.
* Fix that and bail out.
*/
mdl->readpos = mdl->bytesused;
return 0;
}

list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {

if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
continue;

rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
ucount - tot_written, &stop);
if (rc < 0)
return rc;
mdl->readpos += rc;
tot_written += rc;

if (stop || /* Forced stopping point for VBI insertion */
tot_written >= ucount || /* Reader request statisfied */
mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
break;
}
return tot_written;
}

static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
size_t tot_count, int non_block)
{
Expand All @@ -373,12 +437,12 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
single_frame = 1;

for (;;) {
struct cx18_buffer *buf;
struct cx18_mdl *mdl;
int rc;

buf = cx18_get_buffer(s, non_block, &rc);
mdl = cx18_get_mdl(s, non_block, &rc);
/* if there is no data available... */
if (buf == NULL) {
if (mdl == NULL) {
/* if we got data, then return that regardless */
if (tot_written)
break;
Expand All @@ -392,20 +456,20 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
return rc;
}

rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written,
rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
tot_count - tot_written);

if (buf != &cx->vbi.sliced_mpeg_buf) {
if (buf->readpos == buf->bytesused)
cx18_stream_put_buf_fw(s, buf);
if (mdl != &cx->vbi.sliced_mpeg_mdl) {
if (mdl->readpos == mdl->bytesused)
cx18_stream_put_mdl_fw(s, mdl);
else
cx18_push(s, buf, &s->q_full);
} else if (buf->readpos == buf->bytesused) {
cx18_push(s, mdl, &s->q_full);
} else if (mdl->readpos == mdl->bytesused) {
int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;

cx->vbi.sliced_mpeg_size[idx] = 0;
cx->vbi.inserted_frame++;
cx->vbi_data_inserted += buf->bytesused;
cx->vbi_data_inserted += mdl->bytesused;
}
if (rc < 0)
return rc;
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/media/video/cx18/cx18-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,8 @@ static int cx18_log_status(struct file *file, void *fh)
continue;
CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
s->name, s->s_flags,
atomic_read(&s->q_full.depth) * 100 / s->buffers,
atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
/ s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
Expand Down
Loading

0 comments on commit 2e46729

Please sign in to comment.