diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-22 19:20:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-22 19:20:22 -0700 |
commit | ad792f4f46e12bae58298fc64f5139b99664a773 (patch) | |
tree | 3d20c3a0840b00deb95fe62fdff1bc6e59eb37fe /drivers/media/video/ivtv | |
parent | 3650b0a304663d98a63c68f9020eb1ded477989e (diff) | |
parent | f40aa808bad19a079a0e122e326d6970df141afb (diff) |
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (37 commits)
V4L/DVB (6382): saa7134: fix NULL dereference at suspend time for cards without IR receiver
V4L/DVB (6380): ivtvfb: Removal of the 'osd_compat' module option
V4L/DVB (6379): patch which improves GotView Saa7135 remote control
V4L/DVB (6378b): Updates info about the removal of V4L1 at feature-removal-schedule.txt
V4L/DVB (6378a): Removal of VIDIOC_[G|S]_MPEGCOMP from feature-removal-schedule.txt
V4L/DVB (6378): DiB0700-device: Using 1.10 firmware
V4L/DVB (6357): pvrusb2: Improve encoder chip health tracking
V4L/DVB (6356): "while (!ca->wakeup)" breaks the CAM initialisation
V4L/DVB (6352): ir-kbd-i2c: Missing break statement
V4L/DVB (6350): V4L: possible leak in em28xx_init_isoc
V4L/DVB (6348): ivtv: undo video mute when closing the radio
V4L/DVB (6347): ivtv: fix video mute when radio is used
V4L/DVB (6346): ivtvfb: YUV output size fix when ivtvfb is not loaded
V4L/DVB (6345): ivtvfb: YUV handling of an image which is not visible in the display area
V4L/DVB (6343): ivtvfb: check return value of unregister_framebuffer
V4L/DVB (6342): ivtv: fix circular locking (bug 9037)
V4L/DVB (6341): ivtv: fix resizing MPEG1 streams
V4L/DVB (6340): ivtvfb: screen mode change sometimes goes wrong
V4L/DVB (6339): ivtv: set the video color to black instead of green when capturing from the radio
V4L/DVB (6338): ivtv: fix incorrect EBUSY return
...
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 11 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 8 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 13 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 116 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.h | 1 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 160 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.h | 1 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtvfb.c | 92 |
8 files changed, 200 insertions, 202 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index fd7a932e1d3..6d2dd8764f8 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1003,8 +1003,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) @@ -1064,7 +1062,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); @@ -1176,7 +1174,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; @@ -1195,7 +1197,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/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index da50fa4a72a..a200a8a95a2 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/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; } @@ -947,7 +953,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) if (itv == NULL) { /* Couldn't find a device registered on that minor, shouldn't happen! */ - IVTV_WARN("No ivtv device found on minor %d\n", minor); + printk(KERN_WARNING "No ivtv device found on minor %d\n", minor); return -ENXIO; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 206eee7542d..fd6826f472e 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/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,17 +567,19 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; - 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/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index fd135985e70..aa03e61ef31 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/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/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h index 8f5f5b1c7c8..3d76a415fbd 100644 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ b/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/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index e2288f224ab..9091c4837bb 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/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/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index f7215eeca01..3b966f0a204 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/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/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 9684048fe56..52ffd154a3d 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -55,7 +55,6 @@ static int ivtvfb_card_id = -1; static int ivtvfb_debug = 0; static int osd_laced; -static int osd_compat; static int osd_depth; static int osd_upper; static int osd_left; @@ -65,7 +64,6 @@ static int osd_xres; module_param(ivtvfb_card_id, int, 0444); module_param_named(debug,ivtvfb_debug, int, 0644); module_param(osd_laced, bool, 0444); -module_param(osd_compat, bool, 0444); module_param(osd_depth, int, 0444); module_param(osd_upper, int, 0444); module_param(osd_left, int, 0444); @@ -80,12 +78,6 @@ MODULE_PARM_DESC(debug, "Debug level (bitmask). Default: errors only\n" "\t\t\t(debug = 3 gives full debugging)"); -MODULE_PARM_DESC(osd_compat, - "Compatibility mode - Display size is locked (use for old X drivers)\n" - "\t\t\t0=off\n" - "\t\t\t1=on\n" - "\t\t\tdefault off"); - /* Why upper, left, xres, yres, depth, laced ? To match terminology used by fbset. Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */ @@ -166,9 +158,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 +459,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; @@ -579,14 +566,6 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) osd_height_limit = 480; } - /* Check the bits per pixel */ - if (osd_compat) { - if (var->bits_per_pixel != 32) { - IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); - return -EINVAL; - } - } - if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) { var->transp.offset = 24; var->transp.length = 8; @@ -638,32 +617,20 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) } /* Check the resolution */ - if (osd_compat) { - if (var->xres != oi->ivtvfb_defined.xres || - var->yres != oi->ivtvfb_defined.yres || - var->xres_virtual != oi->ivtvfb_defined.xres_virtual || - var->yres_virtual != oi->ivtvfb_defined.yres_virtual) { - IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d (virtual %dx%d)\n", - var->xres, var->yres, var->xres_virtual, var->yres_virtual); - return -EINVAL; - } + if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { + IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n", + var->xres, var->yres); + return -EINVAL; } - else { - if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { - IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n", - var->xres, var->yres); - return -EINVAL; - } - /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ - if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || - var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || - var->xres_virtual < var->xres || - var->yres_virtual < var->yres) { - IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", - var->xres_virtual, var->yres_virtual); - return -EINVAL; - } + /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ + if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || + var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || + var->xres_virtual < var->xres || + var->yres_virtual < var->yres) { + IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", + var->xres_virtual, var->yres_virtual); + return -EINVAL; } /* Some extra checks if in 8 bit mode */ @@ -877,17 +844,15 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) /* Color mode */ - if (osd_compat) osd_depth = 32; - if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) osd_depth = 8; + if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) + osd_depth = 8; 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; + if (osd_xres > 720) + osd_xres = 720; /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */ if (osd_depth == 8) @@ -895,10 +860,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) else if (osd_depth == 16) osd_xres &= ~1; - if (osd_xres) - start_window.width = osd_xres; - else - start_window.width = osd_compat ? 720: 640; + start_window.width = osd_xres ? osd_xres : 640; /* Check horizontal start (osd_left). */ if (osd_left && osd_left + start_window.width > 721) { @@ -921,10 +883,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) if (osd_yres > max_height) osd_yres = max_height; - if (osd_yres) - start_window.height = osd_yres; - else - start_window.height = osd_compat ? max_height : (itv->is_50hz ? 480 : 400); + start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400; /* Check vertical start (osd_upper). */ if (osd_upper + start_window.height > max_height + 1) { @@ -1127,10 +1086,6 @@ static int ivtvfb_init_card(struct ivtv *itv) /* Enable the osd */ ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); - /* Note if we're running in compatibility mode */ - if (osd_compat) - IVTVFB_INFO("Running in compatibility mode. Display resize & mode change disabled\n"); - /* Allocate DMA */ ivtv_udma_alloc(itv); return 0; @@ -1177,9 +1132,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; } |