diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-08-03 18:42:33 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-08-03 18:42:33 -0300 |
commit | 2c888a66d88e5aefc1bdb302c7cd7323b63e389f (patch) | |
tree | 75348f946cc95400e870fbd29d38d6311fe32359 /linux/drivers/media/video | |
parent | 33c78c13eddb4c4a04755bd86526fc21536a3c8b (diff) | |
parent | 4ff0e90195667bad0ed6a181d045fb8d71f7d053 (diff) | |
download | mediapointer-dvb-s2-2c888a66d88e5aefc1bdb302c7cd7323b63e389f.tar.gz mediapointer-dvb-s2-2c888a66d88e5aefc1bdb302c7cd7323b63e389f.tar.bz2 |
merge: http://linuxtv.org/hg/~tap/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-driver.h | 7 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-fb.c | 43 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-ioctl.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-irq.c | 22 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-yuv.c | 33 |
5 files changed, 73 insertions, 35 deletions
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h index f4fe889d9..a6a52bae7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.h +++ b/linux/drivers/media/video/ivtv/ivtv-driver.h @@ -538,6 +538,7 @@ struct yuv_frame_info u32 tru_w; u32 tru_h; u32 offset_y; + int lace_mode; }; #define IVTV_YUV_MODE_INTERLACED 0x00 @@ -610,7 +611,6 @@ struct yuv_playback_info int decode_height; int frame_interlaced; - int frame_interlaced_last; int lace_mode; int lace_threshold; @@ -621,6 +621,11 @@ struct yuv_playback_info u32 yuv_forced_update; int update_frame; + + int sync_field[4]; /* Field to sync on */ + int field_delay[4]; /* Flag to extend duration of previous frame */ + u8 fields_lapsed; /* Counter used when delaying a frame */ + struct yuv_frame_info new_frame_info[4]; struct yuv_frame_info old_frame_info; struct yuv_frame_info old_frame_info_args; diff --git a/linux/drivers/media/video/ivtv/ivtv-fb.c b/linux/drivers/media/video/ivtv/ivtv-fb.c index 00765da8a..d2cc03172 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fb.c +++ b/linux/drivers/media/video/ivtv/ivtv-fb.c @@ -164,11 +164,6 @@ MODULE_LICENSE("GPL"); #define IVTV_OSD_BPP_32 0x04 struct osd_info { - /* Timing info for modes */ - u32 pixclock; - u32 hlimit; - u32 vlimit; - /* Physical base address */ unsigned long video_pbase; /* Relative base address (relative to start of decoder memory) */ @@ -579,10 +574,25 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) { struct osd_info *oi = itv->osd_info; - int osd_height_limit = itv->is_50hz ? 576 : 480; + int osd_height_limit; + u32 pixclock, hlimit, vlimit; IVTV_FB_DEBUG_INFO("ivtvfb_check_var\n"); + /* Set base references for mode calcs. */ + if (itv->is_50hz) { + pixclock = 84316; + hlimit = 776; + vlimit = 591; + osd_height_limit = 576; + } + else { + pixclock = 83926; + hlimit = 776; + vlimit = 495; + osd_height_limit = 480; + } + /* Check the bits per pixel */ if (osd_compat) { if (var->bits_per_pixel != 32) { @@ -723,8 +733,8 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) } /* Maintain overall 'size' for a constant refresh rate */ - var->right_margin = oi->hlimit - var->left_margin - var->xres; - var->lower_margin = oi->vlimit - var->upper_margin - var->yres; + var->right_margin = hlimit - var->left_margin - var->xres; + var->lower_margin = vlimit - var->upper_margin - var->yres; /* Fixed sync times */ var->hsync_len = 24; @@ -733,9 +743,10 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) /* Non-interlaced / interlaced mode is used to switch the OSD filter on or off. Adjust the clock timings to maintain a constant vertical refresh rate. */ - var->pixclock = oi->pixclock; if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) - var->pixclock /= 2; + var->pixclock = pixclock / 2; + else + var->pixclock = pixclock; IVTV_FB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", var->xres, var->yres, @@ -875,18 +886,6 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) struct v4l2_rect start_window; int max_height; - /* Set base references for mode calcs. */ - if (itv->is_50hz) { - oi->pixclock = 84316; - oi->hlimit = 776; - oi->vlimit = 591; - } - else { - oi->pixclock = 83926; - oi->hlimit = 776; - oi->vlimit = 495; - } - /* Color mode */ if (osd_compat) osd_depth = 32; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index e3a05f8fd..d865e3ec5 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1202,6 +1202,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; + ivtv_set_osd_alpha(itv); break; } @@ -1246,7 +1247,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void IVTV_INFO("Tuner: %s\n", test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); cx2341x_log_status(&itv->params, itv->name); - IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); + IVTV_INFO("Version: %s Status flags: 0x%08lx\n", IVTV_VERSION, itv->i_flags); for (i = 0; i < IVTV_MAX_STREAMS; i++) { struct ivtv_stream *s = &itv->streams[i]; diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index 405f7e4b7..65622c1e4 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -704,17 +704,21 @@ static void ivtv_irq_vsync(struct ivtv *itv) if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); - if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) || + if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 && + ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) || (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) { int next_dma_frame = last_dma_frame; - if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { - write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); - write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); - write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); - write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); - next_dma_frame = (next_dma_frame + 1) & 0x3; - atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); + if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) { + if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { + write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); + write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); + write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); + write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); + next_dma_frame = (next_dma_frame + 1) & 0x3; + atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); + itv->yuv_info.fields_lapsed = -1; + } } } if (frame != (itv->lastVsyncFrame & 1)) { @@ -755,6 +759,8 @@ static void ivtv_irq_vsync(struct ivtv *itv) set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); } } + + itv->yuv_info.fields_lapsed ++; } } diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c index bcea09542..fa8c76f3d 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.c +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c @@ -612,7 +612,6 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi itv->yuv_info.v_filter_2 = v_filter_2; } - itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced; } /* Modify the supplied coordinate information to fit the visible osd area */ @@ -799,6 +798,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo (itv->yuv_info.old_frame_info.src_y != window->src_y) || (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || + (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) || (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { yuv_update |= IVTV_YUV_UPDATE_VERTICAL; @@ -898,8 +898,21 @@ static void ivtv_yuv_init (struct ivtv *itv) itv->yuv_info.decode_height = 480; /* If no visible size set, assume full size */ - if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; - if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; + if (!itv->yuv_info.osd_vis_w) + itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; + + if (!itv->yuv_info.osd_vis_h) { + itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; + } else { + /* If output video standard has changed, requested height may + not be legal */ + if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) { + IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n", + itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset, + itv->yuv_info.decode_height); + itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; + } + } /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL); @@ -927,6 +940,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) int rc = 0; int got_sig = 0; int frame, next_fill_frame, last_fill_frame; + int register_update = 0; IVTV_DEBUG_INFO("yuv_prep_frame\n"); @@ -940,6 +954,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) /* Buffers are full - Overwrite the last frame */ next_fill_frame = frame; frame = (frame - 1) & 3; + register_update = itv->yuv_info.new_frame_info[frame].update; } /* Take a snapshot of the yuv coordinate information */ @@ -955,6 +970,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; + /* Snapshot field order */ + itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field; + /* Are we going to offset the Y plane */ if (args->src.height + args->src.top < 512-16) itv->yuv_info.new_frame_info[frame].offset_y = 1; @@ -970,6 +988,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) itv->yuv_info.new_frame_info[frame].update = 0; itv->yuv_info.new_frame_info[frame].interlaced_y = 0; itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; + itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode; if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], sizeof (itv->yuv_info.new_frame_info[frame]))) { @@ -978,6 +997,14 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ } + itv->yuv_info.new_frame_info[frame].update |= register_update; + + /* Should this frame be delayed ? */ + if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3]) + itv->yuv_info.field_delay[frame] = 1; + else + itv->yuv_info.field_delay[frame] = 0; + /* DMA the frame */ mutex_lock(&itv->udma.lock); |