Esempio n. 1
0
static int vpif_streamon(struct file *file, void *priv,
				enum v4l2_buf_type buftype)
{
	struct vpif_fh *fh = priv;
	struct channel_obj *ch = fh->channel;
	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
	struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
	struct vpif_params *vpif = &ch->vpifparams;
	struct vpif_display_config *vpif_config_data =
					vpif_dev->platform_data;
	unsigned long addr = 0;
	int ret = 0;

	if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		vpif_err("buffer type not supported\n");
		return -EINVAL;
	}

	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
		vpif_err("fh->io_allowed\n");
		return -EACCES;
	}

	/* If Streaming is already started, return error */
	if (common->started) {
		vpif_err("channel->started\n");
		return -EBUSY;
	}

	if ((ch->channel_id == VPIF_CHANNEL2_VIDEO
		&& oth_ch->common[VPIF_VIDEO_INDEX].started &&
		ch->vpifparams.std_info.ycmux_mode == 0)
		|| ((ch->channel_id == VPIF_CHANNEL3_VIDEO)
		&& (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
		vpif_err("other channel is using\n");
		return -EBUSY;
	}

	ret = vpif_check_format(ch, &common->fmt.fmt.pix);
	if (ret < 0)
		return ret;

	/* Call videobuf_streamon to start streaming in videobuf */
	ret = videobuf_streamon(&common->buffer_queue);
	if (ret < 0) {
		vpif_err("videobuf_streamon\n");
		return ret;
	}

	/* If buffer queue is empty, return error */
	if (list_empty(&common->dma_queue)) {
		vpif_err("buffer queue is empty\n");
		return -EIO;
	}

	/* Get the next frame from the buffer queue */
	common->next_frm = common->cur_frm =
			    list_entry(common->dma_queue.next,
				       struct videobuf_buffer, queue);

	list_del(&common->cur_frm->queue);
	/* Mark state of the current frame to active */
	common->cur_frm->state = VIDEOBUF_ACTIVE;

	/* Initialize field_id and started member */
	ch->field_id = 0;
	common->started = 1;
	if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		addr = common->cur_frm->boff;
		/* Calculate the offset for Y and C data  in the buffer */
		vpif_calculate_offsets(ch);

		if ((ch->vpifparams.std_info.frm_fmt &&
			((common->fmt.fmt.pix.field != V4L2_FIELD_NONE)
			&& (common->fmt.fmt.pix.field != V4L2_FIELD_ANY)))
			|| (!ch->vpifparams.std_info.frm_fmt
			&& (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
			vpif_err("conflict in field format and std format\n");
			return -EINVAL;
		}

		/* clock settings */
		ret =
		 vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
						ch->vpifparams.std_info.hd_sd);
		if (ret < 0) {
			vpif_err("can't set clock\n");
			return ret;
		}

		/* set the parameters and addresses */
		ret = vpif_set_video_params(vpif, ch->channel_id + 2);
		if (ret < 0)
			return ret;

		common->started = ret;
		vpif_config_addr(ch, ret);
		common->set_addr((addr + common->ytop_off),
				 (addr + common->ybtm_off),
				 (addr + common->ctop_off),
				 (addr + common->cbtm_off));

		/* Set interrupt for both the fields in VPIF
		   Register enable channel in VPIF register */
		if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
			channel2_intr_assert();
			channel2_intr_enable(1);
			enable_channel2(1);
		}

		if ((VPIF_CHANNEL3_VIDEO == ch->channel_id)
			|| (common->started == 2)) {
			channel3_intr_assert();
			channel3_intr_enable(1);
			enable_channel3(1);
		}
		channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
	}
	return ret;
}
Esempio n. 2
0
/**
 * vpif_streamon() - streamon handler
 * @file: file ptr
 * @priv: file handle
 * @buftype: v4l2 buffer type
 */
static int vpif_streamon(struct file *file, void *priv,
				enum v4l2_buf_type buftype)
{

	struct vpif_capture_config *config = vpif_dev->platform_data;
	struct vpif_fh *fh = priv;
	struct channel_obj *ch = fh->channel;
	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
	struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
	struct vpif_params *vpif;
	unsigned long addr = 0;
	int ret = 0;

	vpif_dbg(2, debug, "vpif_streamon\n");

	vpif = &ch->vpifparams;

	if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		vpif_dbg(1, debug, "buffer type not supported\n");
		return -EINVAL;
	}

	/* If file handle is not allowed IO, return error */
	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
		vpif_dbg(1, debug, "io not allowed\n");
		return -EACCES;
	}

	/* If Streaming is already started, return error */
	if (common->started) {
		vpif_dbg(1, debug, "channel->started\n");
		return -EBUSY;
	}

	if ((ch->channel_id == VPIF_CHANNEL0_VIDEO &&
	    oth_ch->common[VPIF_VIDEO_INDEX].started &&
	    vpif->std_info.ycmux_mode == 0) ||
	   ((ch->channel_id == VPIF_CHANNEL1_VIDEO) &&
	    (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
		vpif_dbg(1, debug, "other channel is being used\n");
		return -EBUSY;
	}

	ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0);
	if (ret)
		return ret;

	/* Enable streamon on the sub device */
	ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
				s_stream, 1);

	if (ret && (ret != -ENOIOCTLCMD)) {
		vpif_dbg(1, debug, "stream on failed in subdev\n");
		return ret;
	}

	/* Call videobuf_streamon to start streaming in videobuf */
	ret = videobuf_streamon(&common->buffer_queue);
	if (ret) {
		vpif_dbg(1, debug, "videobuf_streamon\n");
		return ret;
	}

	if (mutex_lock_interruptible(&common->lock)) {
		ret = -ERESTARTSYS;
		goto streamoff_exit;
	}

	/* If buffer queue is empty, return error */
	if (list_empty(&common->dma_queue)) {
		vpif_dbg(1, debug, "buffer queue is empty\n");
		ret = -EIO;
		goto exit;
	}

	/* Get the next frame from the buffer queue */
	common->cur_frm = list_entry(common->dma_queue.next,
				    struct videobuf_buffer, queue);
	common->next_frm = common->cur_frm;

	/* Remove buffer from the buffer queue */
	list_del(&common->cur_frm->queue);
	/* Mark state of the current frame to active */
	common->cur_frm->state = VIDEOBUF_ACTIVE;
	/* Initialize field_id and started member */
	ch->field_id = 0;
	common->started = 1;

	if (V4L2_MEMORY_USERPTR == common->memory)
		addr = common->cur_frm->boff;
	else
		addr = videobuf_to_dma_contig(common->cur_frm);

	/* Calculate the offset for Y and C data in the buffer */
	vpif_calculate_offsets(ch);

	if ((vpif->std_info.frm_fmt &&
	    ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) &&
	     (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) ||
	    (!vpif->std_info.frm_fmt &&
	     (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
		vpif_dbg(1, debug, "conflict in field format and std format\n");
		ret = -EINVAL;
		goto exit;
	}

	/* configure 1 or 2 channel mode */
	ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode);

	if (ret < 0) {
		vpif_dbg(1, debug, "can't set vpif channel mode\n");
		goto exit;
	}

	/* Call vpif_set_params function to set the parameters and addresses */
	ret = vpif_set_video_params(vpif, ch->channel_id);

	if (ret < 0) {
		vpif_dbg(1, debug, "can't set video params\n");
		goto exit;
	}

	common->started = ret;
	vpif_config_addr(ch, ret);

	common->set_addr(addr + common->ytop_off,
			 addr + common->ybtm_off,
			 addr + common->ctop_off,
			 addr + common->cbtm_off);

	/**
	 * Set interrupt for both the fields in VPIF Register enable channel in
	 * VPIF register
	 */
	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) {
		channel0_intr_assert();
		channel0_intr_enable(1);
		enable_channel0(1);
	}
	if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
	    (common->started == 2)) {
		channel1_intr_assert();
		channel1_intr_enable(1);
		enable_channel1(1);
	}
	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
	mutex_unlock(&common->lock);
	return ret;

exit:
	mutex_unlock(&common->lock);
streamoff_exit:
	ret = videobuf_streamoff(&common->buffer_queue);
	return ret;
}
static int vpif_streamon(struct file *file, void *priv,
				enum v4l2_buf_type buftype)
{

	struct vpif_capture_config *config = vpif_dev->platform_data;
	struct vpif_fh *fh = priv;
	struct channel_obj *ch = fh->channel;
	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
	struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
	struct vpif_params *vpif;
	unsigned long addr = 0;
	int ret = 0;

	vpif_dbg(2, debug, "vpif_streamon\n");

	vpif = &ch->vpifparams;

	if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		vpif_dbg(1, debug, "buffer type not supported\n");
		return -EINVAL;
	}

	
	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
		vpif_dbg(1, debug, "io not allowed\n");
		return -EACCES;
	}

	
	if (common->started) {
		vpif_dbg(1, debug, "channel->started\n");
		return -EBUSY;
	}

	if ((ch->channel_id == VPIF_CHANNEL0_VIDEO &&
	    oth_ch->common[VPIF_VIDEO_INDEX].started &&
	    vpif->std_info.ycmux_mode == 0) ||
	   ((ch->channel_id == VPIF_CHANNEL1_VIDEO) &&
	    (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
		vpif_dbg(1, debug, "other channel is being used\n");
		return -EBUSY;
	}

	ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0);
	if (ret)
		return ret;

	
	ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
				s_stream, 1);

	if (ret && (ret != -ENOIOCTLCMD)) {
		vpif_dbg(1, debug, "stream on failed in subdev\n");
		return ret;
	}

	
	ret = videobuf_streamon(&common->buffer_queue);
	if (ret) {
		vpif_dbg(1, debug, "videobuf_streamon\n");
		return ret;
	}

	
	if (list_empty(&common->dma_queue)) {
		vpif_dbg(1, debug, "buffer queue is empty\n");
		ret = -EIO;
		goto exit;
	}

	
	common->cur_frm = list_entry(common->dma_queue.next,
				    struct videobuf_buffer, queue);
	common->next_frm = common->cur_frm;

	
	list_del(&common->cur_frm->queue);
	
	common->cur_frm->state = VIDEOBUF_ACTIVE;
	
	ch->field_id = 0;
	common->started = 1;

	if (V4L2_MEMORY_USERPTR == common->memory)
		addr = common->cur_frm->boff;
	else
		addr = videobuf_to_dma_contig(common->cur_frm);

	
	vpif_calculate_offsets(ch);

	if ((vpif->std_info.frm_fmt &&
	    ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) &&
	     (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) ||
	    (!vpif->std_info.frm_fmt &&
	     (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
		vpif_dbg(1, debug, "conflict in field format and std format\n");
		ret = -EINVAL;
		goto exit;
	}

	
	ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode);

	if (ret < 0) {
		vpif_dbg(1, debug, "can't set vpif channel mode\n");
		goto exit;
	}

	
	ret = vpif_set_video_params(vpif, ch->channel_id);

	if (ret < 0) {
		vpif_dbg(1, debug, "can't set video params\n");
		goto exit;
	}

	common->started = ret;
	vpif_config_addr(ch, ret);

	common->set_addr(addr + common->ytop_off,
			 addr + common->ybtm_off,
			 addr + common->ctop_off,
			 addr + common->cbtm_off);

	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) {
		channel0_intr_assert();
		channel0_intr_enable(1);
		enable_channel0(1);
	}
	if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
	    (common->started == 2)) {
		channel1_intr_assert();
		channel1_intr_enable(1);
		enable_channel1(1);
	}
	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
	return ret;

exit:
	videobuf_streamoff(&common->buffer_queue);
	return ret;
}