diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-driver.c | 11 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-fileops.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-ioctl.c | 19 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-streams.c | 116 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-streams.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-yuv.c | 160 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtv-yuv.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/video/ivtv/ivtvfb.c | 19 |
8 files changed, 184 insertions, 149 deletions
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index f8bc6afc1..21a28853f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -1007,8 +1007,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); - mutex_lock(&itv->serialize_lock); - /* PCI Device Setup */ if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { if (retval == -EIO) @@ -1068,7 +1066,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_DEBUG_INFO("activating i2c...\n"); if (init_ivtv_i2c(itv)) { IVTV_ERR("Could not initialize i2c\n"); - goto free_irq; + goto free_io; } IVTV_DEBUG_INFO("Active card count: %d.\n", ivtv_cards_active); @@ -1180,7 +1178,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_ERR("Failed to register irq %d\n", retval); goto free_streams; } - mutex_unlock(&itv->serialize_lock); + retval = ivtv_streams_register(itv); + if (retval) { + IVTV_ERR("Error %d registering devices\n", retval); + goto free_irq; + } IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); return 0; @@ -1199,7 +1201,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); free_workqueue: destroy_workqueue(itv->irq_work_queues); - mutex_unlock(&itv->serialize_lock); err: if (retval == 0) retval = -ENODEV; diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index 0e0605cc0..a200a8a95 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -822,6 +822,11 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) crystal_freq.flags = 0; ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); } + if (atomic_read(&itv->capturing) > 0) { + /* Undo video mute */ + ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, + itv->params.video_mute | (itv->params.video_mute_yuv << 8)); + } /* Done! Unmute and continue. */ ivtv_unmute(itv); ivtv_release_stream(s); @@ -892,6 +897,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) if (atomic_read(&itv->capturing) > 0) { /* switching to radio while capture is in progress is not polite */ + ivtv_release_stream(s); kfree(item); return -EBUSY; } diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 10862dbb2..b01aaa752 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -555,6 +555,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, /* set window size */ if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + struct cx2341x_mpeg_params *p = &itv->params; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; @@ -566,23 +567,25 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) - if (itv->params.width != 720 || itv->params.height != (itv->is_50hz ? 576 : 480)) - itv->params.video_temporal_filter = 0; + if (p->width != 720 || p->height != (itv->is_50hz ? 576 : 480)) + p->video_temporal_filter = 0; else - itv->params.video_temporal_filter = 8; + p->video_temporal_filter = 8; #endif - if (!set_fmt || (itv->params.width == w && itv->params.height == h)) + if (!set_fmt || (p->width == w && p->height == h)) return 0; if (atomic_read(&itv->capturing) > 0) return -EBUSY; - itv->params.width = w; - itv->params.height = h; + p->width = w; + p->height = h; if (w != 720 || h != (itv->is_50hz ? 576 : 480)) - itv->params.video_temporal_filter = 0; + p->video_temporal_filter = 0; else - itv->params.video_temporal_filter = 8; + p->video_temporal_filter = 8; + if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) + fmt->fmt.pix.width /= 2; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); return ivtv_get_fmt(itv, streamtype, fmt); } diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index fd135985e..aa03e61ef 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -166,10 +166,9 @@ static void ivtv_stream_init(struct ivtv *itv, int type) ivtv_queue_init(&s->q_io); } -static int ivtv_reg_dev(struct ivtv *itv, int type) +static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; - int vfl_type = ivtv_stream_info[type].vfl_type; int minor_offset = ivtv_stream_info[type].minor_offset; int minor; @@ -187,15 +186,12 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; - if (minor_offset >= 0) - /* card number + user defined offset + device offset */ - minor = itv->num + ivtv_first_minor + minor_offset; - else - minor = -1; + /* card number + user defined offset + device offset */ + minor = itv->num + ivtv_first_minor + minor_offset; /* User explicitly selected 0 buffers for these streams, so don't create them. */ - if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE && + if (ivtv_stream_info[type].dma != PCI_DMA_NONE && itv->options.kilobytes[type] == 0) { IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); return 0; @@ -223,21 +219,53 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) s->v4l2dev->fops = ivtv_stream_info[type].fops; s->v4l2dev->release = video_device_release; - if (minor >= 0) { - /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, minor) && - video_register_device(s->v4l2dev, vfl_type, -1)) { - IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", - s->name, minor); - video_device_release(s->v4l2dev); - s->v4l2dev = NULL; - return -ENOMEM; - } + return 0; +} + +/* Initialize v4l2 variables and prepare v4l2 devices */ +int ivtv_streams_setup(struct ivtv *itv) +{ + int type; + + /* Setup V4L2 Devices */ + for (type = 0; type < IVTV_MAX_STREAMS; type++) { + /* Prepare device */ + if (ivtv_prep_dev(itv, type)) + break; + + if (itv->streams[type].v4l2dev == NULL) + continue; + + /* Allocate Stream */ + if (ivtv_stream_alloc(&itv->streams[type])) + break; } - else { - /* Don't register a 'hidden' stream (OSD) */ - IVTV_INFO("Created framebuffer stream for %s\n", s->name); + if (type == IVTV_MAX_STREAMS) return 0; + + /* One or more streams could not be initialized. Clean 'em all up. */ + ivtv_streams_cleanup(itv); + return -ENOMEM; +} + +static int ivtv_reg_dev(struct ivtv *itv, int type) +{ + struct ivtv_stream *s = &itv->streams[type]; + int vfl_type = ivtv_stream_info[type].vfl_type; + int minor; + + if (s->v4l2dev == NULL) + return 0; + + minor = s->v4l2dev->minor; + /* Register device. First try the desired minor, then any free one. */ + if (video_register_device(s->v4l2dev, vfl_type, minor) && + video_register_device(s->v4l2dev, vfl_type, -1)) { + IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", + s->name, minor); + video_device_release(s->v4l2dev); + s->v4l2dev = NULL; + return -ENOMEM; } switch (vfl_type) { @@ -262,27 +290,18 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) return 0; } -/* Initialize v4l2 variables and register v4l2 devices */ -int ivtv_streams_setup(struct ivtv *itv) +/* Register v4l2 devices */ +int ivtv_streams_register(struct ivtv *itv) { int type; + int err = 0; - /* Setup V4L2 Devices */ - for (type = 0; type < IVTV_MAX_STREAMS; type++) { - /* Register Device */ - if (ivtv_reg_dev(itv, type)) - break; - - if (itv->streams[type].v4l2dev == NULL) - continue; + /* Register V4L2 devices */ + for (type = 0; type < IVTV_MAX_STREAMS; type++) + err |= ivtv_reg_dev(itv, type); - /* Allocate Stream */ - if (ivtv_stream_alloc(&itv->streams[type])) - break; - } - if (type == IVTV_MAX_STREAMS) { + if (err == 0) return 0; - } /* One or more streams could not be initialized. Clean 'em all up. */ ivtv_streams_cleanup(itv); @@ -303,11 +322,8 @@ void ivtv_streams_cleanup(struct ivtv *itv) continue; ivtv_stream_free(&itv->streams[type]); - /* Free Device */ - if (vdev->minor == -1) /* 'Hidden' never registered stream (OSD) */ - video_device_release(vdev); - else /* All others, just unregister. */ - video_unregister_device(vdev); + /* Unregister device */ + video_unregister_device(vdev); } } @@ -425,6 +441,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) { u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv *itv = s->itv; + struct cx2341x_mpeg_params *p = &itv->params; int captype = 0, subtype = 0; int enable_passthrough = 0; @@ -445,7 +462,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) } itv->mpg_data_received = itv->vbi_data_inserted = 0; itv->dualwatch_jiffies = jiffies; - itv->dualwatch_stereo_mode = itv->params.audio_properties & 0x0300; + itv->dualwatch_stereo_mode = p->audio_properties & 0x0300; itv->search_pack_header = 0; break; @@ -477,9 +494,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) s->subtype = subtype; s->buffers_stolen = 0; - /* mute/unmute video */ - ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? 1 : 0); - /* Clear Streamoff flags in case left from last capture */ clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); @@ -536,7 +550,12 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) itv->pgm_info_offset, itv->pgm_info_num); /* Setup API for Stream */ - cx2341x_update(itv, ivtv_api_func, NULL, &itv->params); + cx2341x_update(itv, ivtv_api_func, NULL, p); + + /* mute if capturing radio */ + if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) + ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, + 1 | (p->video_mute_yuv << 8)); } /* Vsync Setup */ @@ -585,6 +604,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) { u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv *itv = s->itv; + struct cx2341x_mpeg_params *p = &itv->params; int datatype; if (s->v4l2dev == NULL) @@ -623,7 +643,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) break; } if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, - itv->params.width, itv->params.height, itv->params.audio_properties)) { + p->width, p->height, p->audio_properties)) { IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); } return 0; diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.h b/linux/drivers/media/video/ivtv/ivtv-streams.h index 8f5f5b1c7..3d76a415f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.h +++ b/linux/drivers/media/video/ivtv/ivtv-streams.h @@ -22,6 +22,7 @@ #define IVTV_STREAMS_H int ivtv_streams_setup(struct ivtv *itv); +int ivtv_streams_register(struct ivtv *itv); void ivtv_streams_cleanup(struct ivtv *itv); /* Capture related */ diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c index e2288f224..9091c4837 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.c +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c @@ -710,7 +710,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo /* If there's nothing to safe to display, we may as well stop now */ if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { - return 0; + return IVTV_YUV_UPDATE_INVALID; } /* Ensure video remains inside OSD area */ @@ -791,7 +791,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo /* Check again. If there's nothing to safe to display, stop now */ if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { - return 0; + return IVTV_YUV_UPDATE_INVALID; } /* Both x offset & width are linked, so they have to be done together */ @@ -840,110 +840,118 @@ void ivtv_yuv_work_handler (struct ivtv *itv) if (!(yuv_update = ivtv_yuv_window_setup (itv, &window))) return; - /* Update horizontal settings */ - if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) - ivtv_yuv_handle_horizontal(itv, &window); + if (yuv_update & IVTV_YUV_UPDATE_INVALID) { + write_reg(0x01008080, 0x2898); + } else if (yuv_update) { + write_reg(0x00108080, 0x2898); - if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) - ivtv_yuv_handle_vertical(itv, &window); + if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) + ivtv_yuv_handle_horizontal(itv, &window); + + if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) + ivtv_yuv_handle_vertical(itv, &window); + } memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info)); } static void ivtv_yuv_init (struct ivtv *itv) { + struct yuv_playback_info *yi = &itv->yuv_info; + IVTV_DEBUG_YUV("ivtv_yuv_init\n"); /* Take a snapshot of the current register settings */ - itv->yuv_info.reg_2834 = read_reg(0x02834); - itv->yuv_info.reg_2838 = read_reg(0x02838); - itv->yuv_info.reg_283c = read_reg(0x0283c); - itv->yuv_info.reg_2840 = read_reg(0x02840); - itv->yuv_info.reg_2844 = read_reg(0x02844); - itv->yuv_info.reg_2848 = read_reg(0x02848); - itv->yuv_info.reg_2854 = read_reg(0x02854); - itv->yuv_info.reg_285c = read_reg(0x0285c); - itv->yuv_info.reg_2864 = read_reg(0x02864); - itv->yuv_info.reg_2870 = read_reg(0x02870); - itv->yuv_info.reg_2874 = read_reg(0x02874); - itv->yuv_info.reg_2898 = read_reg(0x02898); - itv->yuv_info.reg_2890 = read_reg(0x02890); - - itv->yuv_info.reg_289c = read_reg(0x0289c); - itv->yuv_info.reg_2918 = read_reg(0x02918); - itv->yuv_info.reg_291c = read_reg(0x0291c); - itv->yuv_info.reg_2920 = read_reg(0x02920); - itv->yuv_info.reg_2924 = read_reg(0x02924); - itv->yuv_info.reg_2928 = read_reg(0x02928); - itv->yuv_info.reg_292c = read_reg(0x0292c); - itv->yuv_info.reg_2930 = read_reg(0x02930); - itv->yuv_info.reg_2934 = read_reg(0x02934); - itv->yuv_info.reg_2938 = read_reg(0x02938); - itv->yuv_info.reg_293c = read_reg(0x0293c); - itv->yuv_info.reg_2940 = read_reg(0x02940); - itv->yuv_info.reg_2944 = read_reg(0x02944); - itv->yuv_info.reg_2948 = read_reg(0x02948); - itv->yuv_info.reg_294c = read_reg(0x0294c); - itv->yuv_info.reg_2950 = read_reg(0x02950); - itv->yuv_info.reg_2954 = read_reg(0x02954); - itv->yuv_info.reg_2958 = read_reg(0x02958); - itv->yuv_info.reg_295c = read_reg(0x0295c); - itv->yuv_info.reg_2960 = read_reg(0x02960); - itv->yuv_info.reg_2964 = read_reg(0x02964); - itv->yuv_info.reg_2968 = read_reg(0x02968); - itv->yuv_info.reg_296c = read_reg(0x0296c); - itv->yuv_info.reg_2970 = read_reg(0x02970); - - itv->yuv_info.v_filter_1 = -1; - itv->yuv_info.v_filter_2 = -1; - itv->yuv_info.h_filter = -1; + yi->reg_2834 = read_reg(0x02834); + yi->reg_2838 = read_reg(0x02838); + yi->reg_283c = read_reg(0x0283c); + yi->reg_2840 = read_reg(0x02840); + yi->reg_2844 = read_reg(0x02844); + yi->reg_2848 = read_reg(0x02848); + yi->reg_2854 = read_reg(0x02854); + yi->reg_285c = read_reg(0x0285c); + yi->reg_2864 = read_reg(0x02864); + yi->reg_2870 = read_reg(0x02870); + yi->reg_2874 = read_reg(0x02874); + yi->reg_2898 = read_reg(0x02898); + yi->reg_2890 = read_reg(0x02890); + + yi->reg_289c = read_reg(0x0289c); + yi->reg_2918 = read_reg(0x02918); + yi->reg_291c = read_reg(0x0291c); + yi->reg_2920 = read_reg(0x02920); + yi->reg_2924 = read_reg(0x02924); + yi->reg_2928 = read_reg(0x02928); + yi->reg_292c = read_reg(0x0292c); + yi->reg_2930 = read_reg(0x02930); + yi->reg_2934 = read_reg(0x02934); + yi->reg_2938 = read_reg(0x02938); + yi->reg_293c = read_reg(0x0293c); + yi->reg_2940 = read_reg(0x02940); + yi->reg_2944 = read_reg(0x02944); + yi->reg_2948 = read_reg(0x02948); + yi->reg_294c = read_reg(0x0294c); + yi->reg_2950 = read_reg(0x02950); + yi->reg_2954 = read_reg(0x02954); + yi->reg_2958 = read_reg(0x02958); + yi->reg_295c = read_reg(0x0295c); + yi->reg_2960 = read_reg(0x02960); + yi->reg_2964 = read_reg(0x02964); + yi->reg_2968 = read_reg(0x02968); + yi->reg_296c = read_reg(0x0296c); + yi->reg_2970 = read_reg(0x02970); + + yi->v_filter_1 = -1; + yi->v_filter_2 = -1; + yi->h_filter = -1; /* Set some valid size info */ - itv->yuv_info.osd_x_offset = read_reg(0x02a04) & 0x00000FFF; - itv->yuv_info.osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF; + yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF; + yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF; /* Bit 2 of reg 2878 indicates current decoder output format 0 : NTSC 1 : PAL */ if (read_reg(0x2878) & 4) - itv->yuv_info.decode_height = 576; + yi->decode_height = 576; else - itv->yuv_info.decode_height = 480; + yi->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->osd_info) { + yi->osd_vis_w = 720 - yi->osd_x_offset; + yi->osd_vis_h = yi->decode_height - yi->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; + /* If no visible size set, assume full size */ + if (!yi->osd_vis_w) + yi->osd_vis_w = 720 - yi->osd_x_offset; + + if (!yi->osd_vis_h) + yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; + else { + /* If output video standard has changed, requested height may + not be legal */ + if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) { + IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n", + yi->osd_vis_h + yi->osd_y_offset, + yi->decode_height); + yi->osd_vis_h = yi->decode_height - yi->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); - if (itv->yuv_info.blanking_ptr) { - itv->yuv_info.blanking_dmaptr = pci_map_single(itv->dev, itv->yuv_info.blanking_ptr, 720*16, PCI_DMA_TODEVICE); - } + yi->blanking_ptr = kzalloc(720*16, GFP_KERNEL); + if (yi->blanking_ptr) + yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); else { - itv->yuv_info.blanking_dmaptr = 0; - IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n"); + yi->blanking_dmaptr = 0; + IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); } - IVTV_DEBUG_WARN("Enable video output\n"); - write_reg_sync(0x00108080, 0x2898); - /* Enable YUV decoder output */ write_reg_sync(0x01, IVTV_REG_VDM); set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); - atomic_set(&itv->yuv_info.next_dma_frame,0); + atomic_set(&yi->next_dma_frame, 0); } int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.h b/linux/drivers/media/video/ivtv/ivtv-yuv.h index f7215eeca..3b966f0a2 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.h +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.h @@ -34,6 +34,7 @@ #define IVTV_YUV_UPDATE_HORIZONTAL 0x01 #define IVTV_YUV_UPDATE_VERTICAL 0x02 +#define IVTV_YUV_UPDATE_INVALID 0x04 extern const u32 yuv_offset[4]; diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c index 9684048fe..4a7512d90 100644 --- a/linux/drivers/media/video/ivtv/ivtvfb.c +++ b/linux/drivers/media/video/ivtv/ivtvfb.c @@ -166,9 +166,6 @@ struct osd_info { unsigned long fb_end_aligned_physaddr; #endif - /* Current osd mode */ - int osd_mode; - /* Store the buffer offset */ int set_osd_coords_x; int set_osd_coords_y; @@ -470,13 +467,11 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); } - /* Change osd mode if needed. - Although rare, things can go wrong. The extra mode - change seems to help... */ - if (osd_mode != -1 && osd_mode != oi->osd_mode) { + /* Set video mode. Although rare, the display can become scrambled even + if we don't change mode. Always 'bounce' to osd_mode via mode 0 */ + if (osd_mode != -1) { ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0); ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode); - oi->osd_mode = osd_mode; } oi->bits_per_pixel = var->bits_per_pixel; @@ -882,9 +877,6 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) oi->bits_per_pixel = osd_depth; oi->bytes_per_pixel = oi->bits_per_pixel / 8; - /* Invalidate current osd mode to force a mode switch later */ - oi->osd_mode = -1; - /* Horizontal size & position */ if (osd_xres > 720) osd_xres = 720; @@ -1177,9 +1169,12 @@ static void ivtvfb_cleanup(void) for (i = 0; i < ivtv_cards_active; i++) { itv = ivtv_cards[i]; if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { + if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { + IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i); + return; + } IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i); ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); - unregister_framebuffer(&itv->osd_info->ivtvfb_info); ivtvfb_release_buffers(itv); itv->osd_video_pbase = 0; } |