int saa7146_stop_preview(struct saa7146_fh *fh)
{
	struct saa7146_dev *dev = fh->dev;
	struct saa7146_vv *vv = dev->vv_data;

	DEB_EE(("dev:%p, fh:%p\n",dev,fh));

	/* 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 at all */
	if ((vv->video_status & STATUS_OVERLAY) == 0) {
		DEB_D(("no active overlay.\n"));
		return 0;
	}

	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;
}
int saa7146_start_preview(struct saa7146_fh *fh)
{
	struct saa7146_dev *dev = fh->dev;
	struct saa7146_vv *vv = dev->vv_data;
	struct v4l2_format fmt;
	int ret = 0, err = 0;

	DEB_EE("dev:%p, fh:%p\n", dev, fh);

	/* check if we have overlay information */
	if (vv->ov.fh == NULL) {
		DEB_D("no overlay data available. try S_FMT first.\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 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
		DEB_D("cannot get necessary overlay resources\n");
		return -EBUSY;
	}

	fmt.fmt.win = vv->ov.win;
	err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
	if (0 != err) {
		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
		return -EBUSY;
	}
	vv->ov.win = fmt.fmt.win;

	DEB_D("%dx%d+%d+%d %s field=%s\n",
	      vv->ov.win.w.width, vv->ov.win.w.height,
	      vv->ov.win.w.left, vv->ov.win.w.top,
	      vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]);

	if (0 != (ret = saa7146_enable_overlay(fh))) {
		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;
}
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;

	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 (IS_CAPTURE_ACTIVE(fh) != 0) {
			DEB_EE(("streaming capture is active\n"));
			return -EBUSY;
		}
		err = try_fmt(fh,f);
		if (0 != err)
			return err;
		fh->video_fmt = f->fmt.pix;
		DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat));
		return 0;
	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
		DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
		err = try_win(dev,&f->fmt.win);
		if (0 != err)
			return err;
		down(&dev->lock);
		fh->ov.win    = f->fmt.win;
		fh->ov.nclips = f->fmt.win.clipcount;
		if (fh->ov.nclips > 16)
			fh->ov.nclips = 16;
		if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) {
			up(&dev->lock);
			return -EFAULT;
		}

		/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
		fh->ov.fh = fh;

		up(&dev->lock);

		/* check if our current overlay is active */
		if (IS_OVERLAY_ACTIVE(fh) != 0) {
			saa7146_stop_preview(fh);
			saa7146_start_preview(fh);
		}
		return 0;
	default:
		DEB_D(("unknown format type '%d'\n",f->type));
		return -EINVAL;
	}
}
static void video_close(struct saa7146_dev *dev, struct file *file)
{
	struct saa7146_fh *fh = file->private_data;
	struct saa7146_vv *vv = dev->vv_data;
	struct videobuf_queue *q = &fh->video_q;

	if (IS_CAPTURE_ACTIVE(fh) != 0)
		video_end(fh, file);
	else if (IS_OVERLAY_ACTIVE(fh) != 0)
		saa7146_stop_preview(fh);

	videobuf_stop(q);
	/* hmm, why is this function declared void? */
}
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;
	int err;

	if (IS_CAPTURE_ACTIVE(fh) != 0) {
		err = video_end(fh, file);
	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
		err = saa7146_stop_preview(fh);
	}

	/* hmm, why is this function declared void? */
	/* return err */
}
Beispiel #6
0
static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
{
	struct saa7146_fh *fh = __fh;
	struct saa7146_dev *dev = fh->dev;
	struct saa7146_vv *vv = dev->vv_data;
	int err;

	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
	if (IS_CAPTURE_ACTIVE(fh) != 0) {
		DEB_EE(("streaming capture is active\n"));
		return -EBUSY;
	}
	err = vidioc_try_fmt_vid_cap(file, fh, f);
	if (0 != err)
		return err;
	fh->video_fmt = f->fmt.pix;
	DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
	return 0;
}
Beispiel #7
0
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;
	struct videobuf_queue *q = &fh->video_q;
	int err;

	if (IS_CAPTURE_ACTIVE(fh) != 0) {
		err = video_end(fh, file);
	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
		err = saa7146_stop_preview(fh);
	}

	// release all capture buffers
	mutex_lock(&q->lock);
	videobuf_read_stop(q);
	mutex_unlock(&q->lock);

	/* hmm, why is this function declared void? */
	/* return err */
}
static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
{
	struct saa7146_dev *dev = fh->dev;
	struct saa7146_vv *vv = dev->vv_data;

	const struct v4l2_queryctrl* ctrl;

	ctrl = ctrl_by_id(c->id);
	if (NULL == ctrl) {
		DEB_D(("unknown control %d\n",c->id));
		return -EINVAL;
	}

	down(&dev->lock);

	switch (ctrl->type) {
	case V4L2_CTRL_TYPE_BOOLEAN:
	case V4L2_CTRL_TYPE_MENU:
	case V4L2_CTRL_TYPE_INTEGER:
		if (c->value < ctrl->minimum)
			c->value = ctrl->minimum;
		if (c->value > ctrl->maximum)
			c->value = ctrl->maximum;
		break;
	default:
		/* nothing */;
	};

	switch (c->id) {
	case V4L2_CID_BRIGHTNESS: {
		u32 value = saa7146_read(dev, BCS_CTRL);
		value &= 0x00ffffff;
		value |= (c->value << 24);
		saa7146_write(dev, BCS_CTRL, value);
		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
		break;
	}
	case V4L2_CID_CONTRAST: {
		u32 value = saa7146_read(dev, BCS_CTRL);
		value &= 0xff00ffff;
		value |= (c->value << 16);
		saa7146_write(dev, BCS_CTRL, value);
		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
		break;
	}
	case V4L2_CID_SATURATION: {
		u32 value = saa7146_read(dev, BCS_CTRL);
		value &= 0xffffff00;
		value |= (c->value << 0);
		saa7146_write(dev, BCS_CTRL, value);
		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
		break;
	}
	case V4L2_CID_HFLIP:
		/* 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;
		break;
	case V4L2_CID_VFLIP:
		if (IS_CAPTURE_ACTIVE(fh) != 0) {
			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
			up(&dev->lock);
			return -EINVAL;
		}
		vv->vflip = c->value;
		break;
	default: {
		return -EINVAL;
	}
	}
	up(&dev->lock);

	if (IS_OVERLAY_ACTIVE(fh) != 0) {
		saa7146_stop_preview(fh);
		saa7146_start_preview(fh);
	}
	return 0;
}