diff options
| author | Michael Hunold <hunold@linuxtv.org> | 2004-04-25 18:52:23 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-25 18:52:23 -0700 |
| commit | 9dab501baa8cab962e014213529c3dce960e2ef4 (patch) | |
| tree | fa81c60b3d88ce3ce52a60466e16b8038b6f9629 | |
| parent | 196c4ebdac1bcb919ff0c798526412d8f28239b7 (diff) | |
[PATCH] V4L: Update the saa7146 driver
- [DVB] saa7146 driver updates:
- remove bogus v_calc and h_calc parameters, which can be easily
retrieved from other values
- add class parameter to i2c initialization
- let resource handling provide more useful informations
- sanitize overlay/capture locking
| -rw-r--r-- | drivers/media/common/saa7146_fops.c | 12 | ||||
| -rw-r--r-- | drivers/media/common/saa7146_hlp.c | 4 | ||||
| -rw-r--r-- | drivers/media/common/saa7146_i2c.c | 7 | ||||
| -rw-r--r-- | drivers/media/common/saa7146_video.c | 335 | ||||
| -rw-r--r-- | include/media/saa7146.h | 2 | ||||
| -rw-r--r-- | include/media/saa7146_vv.h | 10 |
6 files changed, 186 insertions, 184 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 40064909e04a..26995e2d5d46 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -10,14 +10,14 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - if (fh->resources & bit) + if (fh->resources & bit) { + DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources)); /* have it already allocated */ return 1; + } /* is it free? */ - DEB_D(("getting lock...\n")); down(&dev->lock); - DEB_D(("got lock\n")); if (vv->resources & bit) { DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); /* no, someone else uses it */ @@ -27,7 +27,7 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) /* it's free, grab it */ fh->resources |= bit; vv->resources |= bit; - DEB_D(("res: get %d\n",bit)); + DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); up(&dev->lock); return 1; } @@ -51,12 +51,10 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) if ((fh->resources & bits) != bits) BUG(); - DEB_D(("getting lock...\n")); down(&dev->lock); - DEB_D(("got lock\n")); fh->resources &= ~bits; vv->resources &= ~bits; - DEB_D(("res: put %d\n",bits)); + DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); up(&dev->lock); } diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index fffe73fd8812..bdae7fab33a4 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -536,13 +536,13 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e /* set vertical scale */ hps_v_scale = 0; /* all bits get set by the function-call */ hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/ - calculate_v_scale_registers(dev, field, vv->standard->v_calc, height, &hps_v_scale, &hps_v_gain); + calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain); /* set horizontal scale */ hps_ctrl = 0; hps_h_prescale = 0; /* all bits get set in the function */ hps_h_scale = 0; - calculate_h_scale_registers(dev, vv->standard->h_calc, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale); + calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale); /* set hyo and hxo */ calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl); diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index ff94b635ec1c..18bc5b671b9a 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -400,7 +400,7 @@ static struct i2c_algorithm saa7146_algo = { .functionality = saa7146_i2c_func, }; -int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) +int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate) { DEB_EE(("bitrate: 0x%08x\n",bitrate)); @@ -417,16 +417,13 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c i2c_adapter->data = dev; #else i2c_set_adapdata(i2c_adapter,dev); + i2c_adapter->class = class; #endif i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo_data = NULL; i2c_adapter->id = I2C_ALGO_SAA7146; i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; i2c_adapter->retries = SAA7146_I2C_RETRIES; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#else - i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG; -#endif } return 0; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 1dec1678e752..93299758d7ad 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -5,6 +5,12 @@ static int memory = 32; MODULE_PARM(memory,"i"); MODULE_PARM_DESC(memory, "maximum memory usage for capture buffers (default: 32Mb)"); +#define IS_CAPTURE_ACTIVE(fh) \ + (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh)) + +#define IS_OVERLAY_ACTIVE(fh) \ + (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh)) + /* format descriptions for capture and preview */ static struct saa7146_format formats[] = { { @@ -260,24 +266,31 @@ int saa7146_start_preview(struct saa7146_fh *fh) return -EAGAIN; } - /* check if overlay is running */ - if( 0 != vv->ov_data ) { - if( fh != vv->ov_data->fh ) { - DEB_D(("overlay is running in another open.\n")); - return -EAGAIN; + /* check if streaming capture is running */ + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_D(("streaming capture is active.\n")); + return -EBUSY; } + + /* check if overlay is running */ + if (IS_OVERLAY_ACTIVE(fh) != 0) { + if (vv->video_fh == fh) { DEB_D(("overlay is already active.\n")); return 0; } + DEB_D(("overlay is already active in another open.\n")); + return -EBUSY; + } - if( 0 != vv->streaming ) { - DEB_D(("streaming capture is active.\n")); + if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { + DEB_D(("cannot get necessary overlay resources\n")); return -EBUSY; } err = try_win(dev,&fh->ov.win); if (0 != err) { - return err; + saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); + return -EBUSY; } vv->ov_data = &fh->ov; @@ -288,11 +301,14 @@ int saa7146_start_preview(struct saa7146_fh *fh) vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field])); if (0 != (ret = saa7146_enable_overlay(fh))) { - vv->ov_data = NULL; DEB_D(("enabling overlay failed: %d\n",ret)); + saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); return ret; } + vv->video_status = STATUS_OVERLAY; + vv->video_fh = fh; + return 0; } @@ -303,20 +319,30 @@ int saa7146_stop_preview(struct saa7146_fh *fh) DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - /* check if overlay is running */ - if( 0 == vv->ov_data ) { - DEB_D(("overlay is not active.\n")); - return 0; + /* check if streaming capture is running */ + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_D(("streaming capture is active.\n")); + return -EBUSY; } - if( fh != vv->ov_data->fh ) { - DEB_D(("overlay is active, but for another open.\n")); + /* check if overlay is running at all */ + if ((vv->video_status & STATUS_OVERLAY) == 0) { + DEB_D(("no active overlay.\n")); return 0; } - vv->ov_data = NULL; + if (vv->video_fh != fh) { + DEB_D(("overlay is active, but in another open.\n")); + return -EBUSY; + } + + vv->video_status = 0; + vv->video_fh = NULL; + saa7146_disable_overlay(fh); + saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); + return 0; } @@ -325,15 +351,14 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - unsigned long flags; int err; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh)); - if( fh == vv->streaming ) { - DEB_EE(("streaming capture is active")); - return -EAGAIN; + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_EE(("streaming capture is active\n")); + return -EBUSY; } err = try_fmt(fh,f); if (0 != err) @@ -359,16 +384,13 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; - /* check if we have an active overlay */ - if( vv->ov_data != NULL ) { - if( fh == vv->ov_data->fh) { - spin_lock_irqsave(&dev->slock,flags); + up(&dev->lock); + + /* check if our current overlay is active */ + if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); saa7146_start_preview(fh); - spin_unlock_irqrestore(&dev->slock,flags); - } } - up(&dev->lock); return 0; default: DEB_D(("unknown format type '%d'\n",f->type)); @@ -480,8 +502,6 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) struct saa7146_vv *vv = dev->vv_data; const struct v4l2_queryctrl* ctrl; - unsigned long flags; - int restart_overlay = 0; ctrl = ctrl_by_id(c->id); if (NULL == ctrl) { @@ -489,6 +509,8 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) return -EINVAL; } + down(&dev->lock); + switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: @@ -528,35 +550,31 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) break; } case V4L2_CID_HFLIP: - /* fixme: we can supfhrt changing VFLIP and HFLIP here... */ - if( 0 != vv->streaming ) { + /* fixme: we can support changing VFLIP and HFLIP here... */ + if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); + up(&dev->lock); return -EINVAL; } vv->hflip = c->value; - restart_overlay = 1; break; case V4L2_CID_VFLIP: - if( 0 != vv->streaming ) { + if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); + up(&dev->lock); return -EINVAL; } vv->vflip = c->value; - restart_overlay = 1; break; default: { return -EINVAL; } } - if( 0 != restart_overlay ) { - if( 0 != vv->ov_data ) { - if( fh == vv->ov_data->fh ) { - spin_lock_irqsave(&dev->slock,flags); + up(&dev->lock); + + if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); saa7146_start_preview(fh); - spin_unlock_irqrestore(&dev->slock,flags); - } - } } return 0; } @@ -687,21 +705,30 @@ static int video_begin(struct saa7146_fh *fh) struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct saa7146_format *fmt = NULL; - unsigned long flags; unsigned int resource; - int ret = 0; + int ret = 0, err = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - if( fh == vv->streaming ) { + if ((vv->video_status & STATUS_CAPTURE) != 0) { + if (vv->video_fh == fh) { DEB_S(("already capturing.\n")); - return -EBUSY; + return 0; } - if( vv->streaming != 0 ) { - DEB_S(("already capturing, but in another open.\n")); + DEB_S(("already capturing in another open.\n")); return -EBUSY; } + if ((vv->video_status & STATUS_OVERLAY) != 0) { + DEB_S(("warning: suspending overlay video for streaming capture.\n")); + vv->ov_suspend = vv->video_fh; + err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ + if (0 != err) { + DEB_D(("suspending video failed. aborting\n")); + return err; + } + } + fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); /* we need to have a valid format set here */ BUG_ON(NULL == fmt); @@ -715,19 +742,22 @@ static int video_begin(struct saa7146_fh *fh) ret = saa7146_res_get(fh, resource); if (0 == ret) { DEB_S(("cannot get capture resource %d\n",resource)); + if (vv->ov_suspend != NULL) { + saa7146_start_preview(vv->ov_suspend); + vv->ov_suspend = NULL; + } return -EBUSY; } - spin_lock_irqsave(&dev->slock,flags); - /* clear out beginning of streaming bit (rps register 0)*/ saa7146_write(dev, MC2, MASK_27 ); /* enable rps0 irqs */ IER_ENABLE(dev, MASK_27); - vv->streaming = fh; - spin_unlock_irqrestore(&dev->slock,flags); + vv->video_fh = fh; + vv->video_status = STATUS_CAPTURE; + return 0; } @@ -741,9 +771,14 @@ static int video_end(struct saa7146_fh *fh, struct file *file) u32 dmas = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - if( vv->streaming != fh ) { + if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { DEB_S(("not capturing.\n")); - return -EINVAL; + return 0; + } + + if (vv->video_fh != fh) { + DEB_S(("capturing, but in another open.\n")); + return -EBUSY; } fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); @@ -757,8 +792,6 @@ static int video_end(struct saa7146_fh *fh, struct file *file) resource = RESOURCE_DMA1_HPS; dmas = MASK_22; } - saa7146_res_free(fh, resource); - spin_lock_irqsave(&dev->slock,flags); /* disable rps0 */ @@ -770,13 +803,20 @@ static int video_end(struct saa7146_fh *fh, struct file *file) /* shut down all used video dma transfers */ saa7146_write(dev, MC1, dmas); - vv->streaming = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - return 0; + vv->video_fh = NULL; + vv->video_status = 0; + + saa7146_res_free(fh, resource); + + if (vv->ov_suspend != NULL) { + saa7146_start_preview(vv->ov_suspend); + vv->ov_suspend = NULL; } + return 0; +} /* * This function is _not_ called directly, but from @@ -790,7 +830,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - unsigned long flags; int err = 0, result = 0, ee = 0; struct saa7146_use_ops *ops; @@ -867,17 +906,12 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int { struct v4l2_framebuffer *fb = arg; struct saa7146_format *fmt; - struct saa7146_fh *ov_fh = NULL; - int restart_overlay = 0; DEB_EE(("VIDIOC_S_FBUF\n")); -/* - if(!capable(CAP_SYS_ADMIN)) { // && !capable(CAP_SYS_RAWIO)) { - DEB_D(("VIDIOC_S_FBUF: not CAP_SYS_ADMIN or CAP_SYS_RAWIO.\n")); + if(!capable(CAP_SYS_ADMIN) && + !capable(CAP_SYS_RAWIO)) return -EPERM; - } -*/ /* check args */ fmt = format_by_fourcc(dev,fb->fmt.pixelformat); @@ -890,13 +924,16 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat)); } - down(&dev->lock); - if( vv->ov_data != NULL ) { - ov_fh = vv->ov_data->fh; - saa7146_stop_preview(ov_fh); - restart_overlay = 1; + /* check if overlay is running */ + if (IS_OVERLAY_ACTIVE(fh) != 0) { + if (vv->video_fh != fh) { + DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n")); + return -EBUSY; + } } + down(&dev->lock); + /* ok, accept it */ vv->ov_fb = *fb; vv->ov_fmt = fmt; @@ -904,10 +941,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width*fmt->depth/8; - if( 0 != restart_overlay ) { - saa7146_start_preview(ov_fh); - } - up(&dev->lock); return 0; @@ -966,11 +999,13 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return get_control(fh,arg); } case VIDIOC_S_CTRL: + + + + { DEB_EE(("VIDIOC_S_CTRL\n")); - down(&dev->lock); err = set_control(fh,arg); - up(&dev->lock); return err; } case VIDIOC_G_PARM: @@ -1029,29 +1064,27 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int case VIDIOC_S_STD: { v4l2_std_id *id = arg; - int i; - - int restart_overlay = 0; int found = 0; - - struct saa7146_fh *ov_fh = NULL; + int i, err; DEB_EE(("VIDIOC_S_STD\n")); - if( 0 != vv->streaming ) { + if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { + DEB_D(("cannot change video standard while streaming capture is active\n")); return -EBUSY; } - DEB_D(("before getting lock...\n")); - down(&dev->lock); - DEB_D(("got lock\n")); - - if( vv->ov_data != NULL ) { - ov_fh = vv->ov_data->fh; - saa7146_stop_preview(ov_fh); - restart_overlay = 1; + if ((vv->video_status & STATUS_OVERLAY) != 0) { + vv->ov_suspend = vv->video_fh; + err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ + if (0 != err) { + DEB_D(("suspending video failed. aborting\n")); + return err; + } } + down(&dev->lock); + for(i = 0; i < dev->ext_vv_data->num_stds; i++) if (*id & dev->ext_vv_data->stds[i].id) break; @@ -1062,11 +1095,13 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int found = 1; } - if( 0 != restart_overlay ) { - saa7146_start_preview(ov_fh); - } up(&dev->lock); + if (vv->ov_suspend != NULL) { + saa7146_start_preview(vv->ov_suspend); + vv->ov_suspend = NULL; + } + if( 0 == found ) { DEB_EE(("VIDIOC_S_STD: standard not found.\n")); return -EINVAL; @@ -1076,49 +1111,20 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return 0; } case VIDIOC_OVERLAY: + + + + { int on = *(int *)arg; int err = 0; - if( NULL == vv->ov_fmt && on != 0 ) { - DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n")); - return -EAGAIN; - } - DEB_D(("VIDIOC_OVERLAY on:%d\n",on)); - if( 0 != on ) { - if( vv->ov_data != NULL ) { - if( fh != vv->ov_data->fh) { - DEB_D(("overlay already active in another open\n")); - return -EAGAIN; - } - } - - if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { - DEB_D(("cannot get overlay resources\n")); - return -EBUSY; - } - - spin_lock_irqsave(&dev->slock,flags); + if (on != 0) { err = saa7146_start_preview(fh); - spin_unlock_irqrestore(&dev->slock,flags); - return err; - } - - if( vv->ov_data != NULL ) { - if( fh != vv->ov_data->fh) { - DEB_D(("overlay is active, but in another open\n")); - return -EAGAIN; - } } else { - DEB_D(("overlay is not active\n")); - return 0; - } - spin_lock_irqsave(&dev->slock,flags); err = saa7146_stop_preview(fh); - spin_unlock_irqrestore(&dev->slock,flags); - /* free resources */ - saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); + } return err; } case VIDIOC_REQBUFS: { @@ -1149,11 +1155,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int int *type = arg; DEB_D(("VIDIOC_STREAMON, type:%d\n",*type)); - if( fh == vv->streaming ) { - DEB_D(("already capturing.\n")); - return 0; - } - err = video_begin(fh); if( 0 != err) { return err; @@ -1166,13 +1167,26 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type)); - if( fh != vv->streaming ) { - DEB_D(("this open is not capturing.\n")); - return -EINVAL; + /* ugly: we need to copy some checks from video_end(), + because videobuf_streamoff() relies on the capture running. + check and fix this */ + if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { + DEB_S(("not capturing.\n")); + return 0; + } + + if (vv->video_fh != fh) { + DEB_S(("capturing, but in another open.\n")); + return -EBUSY; } err = videobuf_streamoff(file,q); + if (0 != err) { + DEB_D(("warning: videobuf_streamoff() failed.\n")); video_end(fh, file); + } else { + err = video_end(fh, file); + } return err; } case VIDIOCGMBUF: @@ -1406,20 +1420,16 @@ static void video_close(struct saa7146_dev *dev, struct file *file) { struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data; struct saa7146_vv *vv = dev->vv_data; - unsigned long flags; + int err; - if( 0 != vv->ov_data ) { - if( fh == vv->ov_data->fh ) { - spin_lock_irqsave(&dev->slock,flags); - saa7146_stop_preview(fh); - spin_unlock_irqrestore(&dev->slock,flags); - saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); - } + if (IS_CAPTURE_ACTIVE(fh) != 0) { + err = video_end(fh, file); + } else if (IS_OVERLAY_ACTIVE(fh) != 0) { + err = saa7146_stop_preview(fh); } - if( fh == vv->streaming ) { - video_end(fh, file); - } + /* hmm, why is this function declared void? */ + /* return err */ } @@ -1447,23 +1457,16 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p struct saa7146_vv *vv = dev->vv_data; ssize_t ret = 0; - int restart_overlay = 0; - struct saa7146_fh *ov_fh = NULL; - DEB_EE(("called.\n")); + if ((vv->video_status & STATUS_CAPTURE) != 0) { /* fixme: should we allow read() captures while streaming capture? */ - if( 0 != vv->streaming ) { + if (vv->video_fh == fh) { DEB_S(("already capturing.\n")); return -EBUSY; } - - /* stop any active overlay */ - if( vv->ov_data != NULL ) { - ov_fh = vv->ov_data->fh; - saa7146_stop_preview(ov_fh); - saa7146_res_free(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); - restart_overlay = 1; + DEB_S(("already capturing in another open.\n")); + return -EBUSY; } ret = video_begin(fh); @@ -1472,16 +1475,16 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p } ret = videobuf_read_one(file,&fh->video_q , data, count, ppos); + if (ret != 0) { video_end(fh, file); - + } else { + ret = video_end(fh, file); + } out: /* restart overlay if it was active before */ - if( 0 != restart_overlay ) { - if (0 == saa7146_res_get(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { - DEB_D(("cannot get overlay resources again!\n")); - BUG(); - } - saa7146_start_preview(ov_fh); + if (vv->ov_suspend != NULL) { + saa7146_start_preview(vv->ov_suspend); + vv->ov_suspend = NULL; } return ret; diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 5e9f64e67bc8..e62f03fb4c5d 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -154,7 +154,7 @@ struct saa7146_dev }; /* from saa7146_i2c.c */ -int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); +int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate); int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num, int retries); /* from saa7146_core.c */ diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index 50ab25907eec..60cd29e52f2d 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -44,11 +44,9 @@ struct saa7146_standard int v_offset; /* number of lines of vertical offset before processing */ int v_field; /* number of lines in a field for HPS to process */ - int v_calc; /* number of vertical active lines */ int h_offset; /* horizontal offset of processing window */ int h_pixels; /* number of horizontal pixels to process */ - int h_calc; /* number of horizontal active pixels */ int v_max_out; int h_max_out; @@ -104,6 +102,9 @@ struct saa7146_fh { unsigned int resources; /* resource management for device open */ }; +#define STATUS_OVERLAY 0x01 +#define STATUS_CAPTURE 0x02 + struct saa7146_vv { int vbi_minor; @@ -117,14 +118,17 @@ struct saa7146_vv int video_minor; + int video_status; + struct saa7146_fh *video_fh; + /* video overlay */ struct v4l2_framebuffer ov_fb; struct saa7146_format *ov_fmt; struct saa7146_overlay *ov_data; + struct saa7146_fh *ov_suspend; /* video capture */ struct saa7146_dmaqueue video_q; - struct saa7146_fh *streaming; enum v4l2_field last_field; /* common: fixme? shouldn't this be in saa7146_fh? |
