Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 76518
b: refs/heads/master
c: 77aded6
h: refs/heads/master
v: v3
  • Loading branch information
Ian Armstrong authored and Mauro Carvalho Chehab committed Jan 25, 2008
1 parent c1f6f57 commit d3217d4
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 71 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: 3b5c1c8e71eb8fe2297a5884db59108e3c8b44c5
refs/heads/master: 77aded6ba51f01335840ce8e18b413067810b68e
6 changes: 6 additions & 0 deletions trunk/drivers/media/video/ivtv/ivtv-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,12 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
itv->is_50hz = 1;
itv->is_out_50hz = 1;
}

itv->yuv_info.osd_full_w = 720;
itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480;
itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;

itv->params.video_gop_size = itv->is_60hz ? 15 : 12;

itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/media/video/ivtv/ivtv-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ struct yuv_playback_info
u32 osd_vis_w;
u32 osd_vis_h;

u32 osd_full_w;
u32 osd_full_h;

int decode_height;

int lace_mode;
Expand All @@ -491,6 +494,10 @@ struct yuv_playback_info

u8 draw_frame; /* PVR350 buffer to draw into */
u8 max_frames_buffered; /* Maximum number of frames to buffer */

struct v4l2_rect main_rect;
u32 v4l2_src_w;
u32 v4l2_src_h;
};

#define IVTV_VBI_FRAMES 32
Expand Down
23 changes: 22 additions & 1 deletion trunk/drivers/media/video/ivtv/ivtv-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,24 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
set_bit(IVTV_F_S_APPL_IO, &s->s_flags);

retry:
/* If possible, just DMA the entire frame - Check the data transfer size
since we may get here before the stream has been fully set-up */
if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
while (count >= itv->dma_data_req_size) {
if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) {
bytes_written += itv->dma_data_req_size;
user_buf += itv->dma_data_req_size;
count -= itv->dma_data_req_size;
} else {
break;
}
}
if (count == 0) {
IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
return bytes_written;
}
}

for (;;) {
/* Gather buffers */
while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io)))
Expand Down Expand Up @@ -660,6 +678,9 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
if (s->q_full.length >= itv->dma_data_req_size) {
int got_sig;

if (mode == OUT_YUV)
ivtv_yuv_setup_stream_frame(itv);

prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
Expand Down Expand Up @@ -946,7 +967,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
/* For yuv, we need to know the dma size before we start */
itv->dma_data_req_size =
itv->params.width * itv->params.height * 3 / 2;
1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
itv->yuv_info.stream_size = 0;
}
return 0;
Expand Down
120 changes: 78 additions & 42 deletions trunk/drivers/media/video/ivtv/ivtv-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
fmt->fmt.pix.height = itv->main_rect.height;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
if (itv->output_mode == OUT_UDMA_YUV) {
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
case IVTV_YUV_MODE_INTERLACED:
fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
Expand All @@ -386,14 +386,13 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
break;
}
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
fmt->fmt.pix.bytesperline = 720;
fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w;
fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h;
/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
fmt->fmt.pix.sizeimage =
fmt->fmt.pix.height * fmt->fmt.pix.width +
fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
}
else if (itv->output_mode == OUT_YUV ||
streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
1080 * ((fmt->fmt.pix.height + 31) & ~31);
} else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) {
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
fmt->fmt.pix.sizeimage =
Expand Down Expand Up @@ -490,6 +489,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
struct v4l2_format *fmt, int set_fmt)
{
struct yuv_playback_info *yi = &itv->yuv_info;
struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
u16 set;

Expand All @@ -505,39 +505,52 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
r.width = fmt->fmt.pix.width;
r.height = fmt->fmt.pix.height;
ivtv_get_fmt(itv, streamtype, fmt);
if (itv->output_mode != OUT_UDMA_YUV) {
/* TODO: would setting the rect also be valid for this mode? */
fmt->fmt.pix.width = r.width;
fmt->fmt.pix.height = r.height;
}
if (itv->output_mode == OUT_UDMA_YUV) {
/* TODO: add checks for validity */
fmt->fmt.pix.width = r.width;
fmt->fmt.pix.height = r.height;
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
fmt->fmt.pix.field = field;
if (fmt->fmt.pix.width < 2)
fmt->fmt.pix.width = 2;
if (fmt->fmt.pix.width > 720)
fmt->fmt.pix.width = 720;
if (fmt->fmt.pix.height < 2)
fmt->fmt.pix.height = 2;
if (fmt->fmt.pix.height > 576)
fmt->fmt.pix.height = 576;
}
if (set_fmt) {
if (itv->output_mode == OUT_UDMA_YUV) {
switch (field) {
case V4L2_FIELD_NONE:
itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
break;
case V4L2_FIELD_ANY:
itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO;
break;
case V4L2_FIELD_INTERLACED_BT:
itv->yuv_info.lace_mode =
IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
break;
case V4L2_FIELD_INTERLACED_TB:
default:
itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED;
break;
}
itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
/* Return now if we already have some frame data */
if (yi->stream_size)
return -EBUSY;

/* Force update of yuv registers */
itv->yuv_info.yuv_forced_update = 1;
return 0;
yi->v4l2_src_w = r.width;
yi->v4l2_src_h = r.height;

switch (field) {
case V4L2_FIELD_NONE:
yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
break;
case V4L2_FIELD_ANY:
yi->lace_mode = IVTV_YUV_MODE_AUTO;
break;
case V4L2_FIELD_INTERLACED_BT:
yi->lace_mode =
IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
break;
case V4L2_FIELD_INTERLACED_TB:
default:
yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
break;
}
yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;

if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
itv->dma_data_req_size =
1080 * ((yi->v4l2_src_h + 31) & ~31);

/* Force update of yuv registers */
yi->yuv_forced_update = 1;
return 0;
}
return 0;
}
Expand Down Expand Up @@ -703,8 +716,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
{
struct ivtv_open_id *id = NULL;
u32 data[CX2341X_MBOX_MAX_DATA];
int streamtype = 0;

if (filp) id = (struct ivtv_open_id *)filp->private_data;
if (filp) {
id = (struct ivtv_open_id *)filp->private_data;
streamtype = id->type;
}

switch (cmd) {
case VIDIOC_G_PRIORITY:
Expand Down Expand Up @@ -822,6 +839,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
cropcap->bounds.height = itv->is_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
} else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
cropcap->bounds.width = itv->yuv_info.osd_full_w;
cropcap->bounds.height = itv->yuv_info.osd_full_h;
cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
} else {
cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
Expand All @@ -836,10 +858,15 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void

if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
itv->main_rect = crop->c;
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
itv->yuv_info.main_rect = crop->c;
return 0;
} else {
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
itv->main_rect = crop->c;
return 0;
}
}
return -EINVAL;
}
Expand All @@ -853,7 +880,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void

if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
crop->c = itv->main_rect;
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
crop->c = itv->yuv_info.main_rect;
else
crop->c = itv->main_rect;
return 0;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Expand All @@ -864,7 +894,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_ENUM_FMT: {
static struct v4l2_fmtdesc formats[] = {
{ 0, 0, 0,
"HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
"HM12 (YUV 4:2:2)", V4L2_PIX_FMT_HM12,
{ 0, 0, 0, 0 }
},
{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,
Expand Down Expand Up @@ -1043,6 +1073,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
itv->main_rect.height = itv->params.height;
ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
720, itv->main_rect.height, 0, 0);
itv->yuv_info.main_rect = itv->main_rect;
if (!itv->osd_info) {
itv->yuv_info.osd_full_w = 720;
itv->yuv_info.osd_full_h =
itv->is_out_50hz ? 576 : 480;
}
}
break;
}
Expand Down
26 changes: 23 additions & 3 deletions trunk/drivers/media/video/ivtv/ivtv-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,30 @@ static void dma_post(struct ivtv_stream *s)
void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
{
struct ivtv *itv = s->itv;
struct yuv_playback_info *yi = &itv->yuv_info;
u8 frame = yi->draw_frame;
struct yuv_frame_info *f = &yi->new_frame_info[frame];
struct ivtv_buffer *buf;
u32 y_size = itv->params.height * itv->params.width;
u32 y_size = 720 * ((f->src_h + 31) & ~31);
u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
int y_done = 0;
int bytes_written = 0;
unsigned long flags = 0;
int idx = 0;

IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);

/* Insert buffer block for YUV if needed */
if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
if (yi->blanking_dmaptr) {
s->sg_pending[idx].src = yi->blanking_dmaptr;
s->sg_pending[idx].dst = offset;
s->sg_pending[idx].size = 720 * 16;
}
offset += 720 * 16;
idx++;
}

list_for_each_entry(buf, &s->q_predma.list, list) {
/* YUV UV Offset from Y Buffer */
if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
Expand Down Expand Up @@ -713,8 +728,11 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data);

if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2;
itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0];
itv->dma_data_req_size =
1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
itv->dma_data_req_offset = data[1];
if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
ivtv_yuv_frame_complete(itv);
s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
}
else {
Expand All @@ -728,6 +746,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
}
else {
if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
ivtv_yuv_setup_stream_frame(itv);
clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0);
Expand Down
17 changes: 1 addition & 16 deletions trunk/drivers/media/video/ivtv/ivtv-streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,27 +661,12 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)

IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);

/* Clear Streamoff */
if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
/* Initialize Decoder */
/* Reprogram Decoder YUV Buffers for YUV */
write_reg(yuv_offset[0] >> 4, 0x82c);
write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
write_reg(yuv_offset[0] >> 4, 0x834);
write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);

write_reg_sync(0x00000000 | (0x0c << 16) | (0x0b << 8), 0x2d24);

write_reg_sync(0x00108080, 0x2898);
/* Enable YUV decoder output */
write_reg_sync(0x01, IVTV_REG_VDM);
}

ivtv_setup_v4l2_decode_stream(s);

/* set dma size to 65536 bytes */
ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);

/* Clear Streamoff */
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);

/* Zero out decoder counters */
Expand Down
Loading

0 comments on commit d3217d4

Please sign in to comment.