diff options
Diffstat (limited to 'drivers/media/platform/davinci')
| -rw-r--r-- | drivers/media/platform/davinci/vpbe_display.c | 82 | ||||
| -rw-r--r-- | drivers/media/platform/davinci/vpfe_capture.c | 21 | ||||
| -rw-r--r-- | drivers/media/platform/davinci/vpif_capture.c | 1155 | ||||
| -rw-r--r-- | drivers/media/platform/davinci/vpif_capture.h | 28 | ||||
| -rw-r--r-- | drivers/media/platform/davinci/vpif_display.c | 1241 | ||||
| -rw-r--r-- | drivers/media/platform/davinci/vpif_display.h | 44 | 
6 files changed, 759 insertions, 1812 deletions
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 04609cc6eba..bf5eff99452 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -341,14 +341,8 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)  {  	struct vpbe_fh *fh = vb2_get_drv_priv(vq);  	struct vpbe_layer *layer = fh->layer; -	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;  	int ret; -	/* If buffer queue is empty, return error */ -	if (list_empty(&layer->dma_queue)) { -		v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n"); -		return -EINVAL; -	}  	/* Get the next frame from the buffer queue */  	layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,  				struct vpbe_disp_buffer, list); @@ -361,8 +355,17 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)  	/* Set parameters in OSD and VENC */  	ret = vpbe_set_osd_display_params(fh->disp_dev, layer); -	if (ret < 0) +	if (ret < 0) { +		struct vpbe_disp_buffer *buf, *tmp; + +		vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_QUEUED); +		list_for_each_entry_safe(buf, tmp, &layer->dma_queue, list) { +			list_del(&buf->list); +			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); +		} +  		return ret; +	}  	/*  	 * if request format is yuv420 semiplanar, need to @@ -374,23 +377,36 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)  	return ret;  } -static int vpbe_stop_streaming(struct vb2_queue *vq) +static void vpbe_stop_streaming(struct vb2_queue *vq)  {  	struct vpbe_fh *fh = vb2_get_drv_priv(vq);  	struct vpbe_layer *layer = fh->layer; +	struct vpbe_display *disp = fh->disp_dev; +	unsigned long flags;  	if (!vb2_is_streaming(vq)) -		return 0; +		return;  	/* release all active buffers */ +	spin_lock_irqsave(&disp->dma_queue_lock, flags); +	if (layer->cur_frm == layer->next_frm) { +		vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR); +	} else { +		if (layer->cur_frm != NULL) +			vb2_buffer_done(&layer->cur_frm->vb, +					VB2_BUF_STATE_ERROR); +		if (layer->next_frm != NULL) +			vb2_buffer_done(&layer->next_frm->vb, +					VB2_BUF_STATE_ERROR); +	} +  	while (!list_empty(&layer->dma_queue)) {  		layer->next_frm = list_entry(layer->dma_queue.next,  						struct vpbe_disp_buffer, list);  		list_del(&layer->next_frm->list);  		vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);  	} - -	return 0; +	spin_unlock_irqrestore(&disp->dma_queue_lock, flags);  }  static struct vb2_ops video_qops = { @@ -672,29 +688,6 @@ static int vpbe_try_format(struct vpbe_display *disp_dev,  	return 0;  } -static int vpbe_display_g_priority(struct file *file, void *priv, -				enum v4l2_priority *p) -{ -	struct vpbe_fh *fh = file->private_data; -	struct vpbe_layer *layer = fh->layer; - -	*p = v4l2_prio_max(&layer->prio); - -	return 0; -} - -static int vpbe_display_s_priority(struct file *file, void *priv, -				enum v4l2_priority p) -{ -	struct vpbe_fh *fh = file->private_data; -	struct vpbe_layer *layer = fh->layer; -	int ret; - -	ret = v4l2_prio_change(&layer->prio, &fh->prio, p); - -	return ret; -} -  static int vpbe_display_querycap(struct file *file, void  *priv,  			       struct v4l2_capability *cap)  { @@ -1415,7 +1408,8 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,  	q->ops = &video_qops;  	q->mem_ops = &vb2_dma_contig_memops;  	q->buf_struct_size = sizeof(struct vpbe_disp_buffer); -	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +	q->min_buffers_needed = 1;  	ret = vb2_queue_init(q);  	if (ret) { @@ -1483,6 +1477,7 @@ static int vpbe_display_open(struct file *file)  {  	struct vpbe_fh *fh = NULL;  	struct vpbe_layer *layer = video_drvdata(file); +	struct video_device *vdev = video_devdata(file);  	struct vpbe_display *disp_dev = layer->disp_dev;  	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;  	struct osd_state *osd_device = disp_dev->osd_device; @@ -1495,6 +1490,7 @@ static int vpbe_display_open(struct file *file)  			"unable to allocate memory for file handle object\n");  		return -ENOMEM;  	} +	v4l2_fh_init(&fh->fh, vdev);  	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,  			"vpbe display open plane = %d\n",  			layer->device_id); @@ -1523,9 +1519,7 @@ static int vpbe_display_open(struct file *file)  	layer->usrs++;  	/* Set io_allowed member to false */  	fh->io_allowed = 0; -	/* Initialize priority of this instance to default priority */ -	fh->prio = V4L2_PRIORITY_UNSET; -	v4l2_prio_open(&layer->prio, &fh->prio); +	v4l2_fh_add(&fh->fh);  	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,  			"vpbe display device opened successfully\n");  	return 0; @@ -1580,8 +1574,9 @@ static int vpbe_display_release(struct file *file)  		osd_device->ops.release_layer(osd_device,  				layer->layer_info.id);  	} -	/* Close the priority */ -	v4l2_prio_close(&layer->prio, fh->prio); + +	v4l2_fh_del(&fh->fh); +	v4l2_fh_exit(&fh->fh);  	file->private_data = NULL;  	mutex_unlock(&layer->opslock); @@ -1609,8 +1604,6 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {  	.vidioc_cropcap		 = vpbe_display_cropcap,  	.vidioc_g_crop		 = vpbe_display_g_crop,  	.vidioc_s_crop		 = vpbe_display_s_crop, -	.vidioc_g_priority	 = vpbe_display_g_priority, -	.vidioc_s_priority	 = vpbe_display_s_priority,  	.vidioc_s_std		 = vpbe_display_s_std,  	.vidioc_g_std		 = vpbe_display_g_std,  	.vidioc_enum_output	 = vpbe_display_enum_output, @@ -1690,8 +1683,6 @@ static int init_vpbe_layer(int i, struct vpbe_display *disp_dev,  	vpbe_display_layer->layer_info.id =  		((i == VPBE_DISPLAY_DEVICE_0) ? WIN_VID0 : WIN_VID1); -	/* Initialize prio member of layer object */ -	v4l2_prio_init(&vpbe_display_layer->prio);  	return 0;  } @@ -1718,6 +1709,7 @@ static int register_device(struct vpbe_layer *vpbe_display_layer,  	vpbe_display_layer->disp_dev = disp_dev;  	/* set the driver data in platform device */  	platform_set_drvdata(pdev, disp_dev); +	set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags);  	video_set_drvdata(&vpbe_display_layer->video_dev,  			  vpbe_display_layer); @@ -1785,7 +1777,7 @@ static int vpbe_display_probe(struct platform_device *pdev)  	}  	irq = res->start; -	err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED, +	err = devm_request_irq(&pdev->dev, irq, venc_isr, 0,  			       VPBE_DISPLAY_DRIVER, disp_dev);  	if (err) {  		v4l2_err(&disp_dev->vpbe_dev->v4l2_dev, diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 93609091cb2..a51bda2fb63 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -498,6 +498,7 @@ unlock:  static int vpfe_open(struct file *file)  {  	struct vpfe_device *vpfe_dev = video_drvdata(file); +	struct video_device *vdev = video_devdata(file);  	struct vpfe_fh *fh;  	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n"); @@ -517,6 +518,7 @@ static int vpfe_open(struct file *file)  	/* store pointer to fh in private_data member of file */  	file->private_data = fh;  	fh->vpfe_dev = vpfe_dev; +	v4l2_fh_init(&fh->fh, vdev);  	mutex_lock(&vpfe_dev->lock);  	/* If decoder is not initialized. initialize it */  	if (!vpfe_dev->initialized) { @@ -529,9 +531,7 @@ static int vpfe_open(struct file *file)  	vpfe_dev->usrs++;  	/* Set io_allowed member to false */  	fh->io_allowed = 0; -	/* Initialize priority of this instance to default priority */ -	fh->prio = V4L2_PRIORITY_UNSET; -	v4l2_prio_open(&vpfe_dev->prio, &fh->prio); +	v4l2_fh_add(&fh->fh);  	mutex_unlock(&vpfe_dev->lock);  	return 0;  } @@ -688,7 +688,7 @@ static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)  	frame_format = ccdc_dev->hw_ops.get_frame_format();  	if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {  		return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr, -				    IRQF_DISABLED, "vpfe_capture1", +				    0, "vpfe_capture1",  				    vpfe_dev);  	}  	return 0; @@ -734,12 +734,14 @@ static int vpfe_release(struct file *file)  		}  		vpfe_dev->io_usrs = 0;  		vpfe_dev->numbuffers = config_params.numbuffers; +		videobuf_stop(&vpfe_dev->buffer_queue); +		videobuf_mmap_free(&vpfe_dev->buffer_queue);  	}  	/* Decrement device usrs counter */  	vpfe_dev->usrs--; -	/* Close the priority */ -	v4l2_prio_close(&vpfe_dev->prio, fh->prio); +	v4l2_fh_del(&fh->fh); +	v4l2_fh_exit(&fh->fh);  	/* If this is the last file handle */  	if (!vpfe_dev->usrs) {  		vpfe_dev->initialized = 0; @@ -1215,7 +1217,7 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)  	}  	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, -					 core, s_std, std_id); +					 video, s_std, std_id);  	if (ret < 0) {  		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");  		goto unlock_out; @@ -1863,7 +1865,7 @@ static int vpfe_probe(struct platform_device *pdev)  	}  	vpfe_dev->ccdc_irq1 = res1->start; -	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, +	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, 0,  			  "vpfe_capture0", vpfe_dev);  	if (0 != ret) { @@ -1908,14 +1910,13 @@ static int vpfe_probe(struct platform_device *pdev)  	/* Initialize field of the device objects */  	vpfe_dev->numbuffers = config_params.numbuffers; -	/* Initialize prio member of device object */ -	v4l2_prio_init(&vpfe_dev->prio);  	/* register video device */  	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,  		"trying to register vpfe device.\n");  	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,  		"video_dev=%x\n", (int)&vpfe_dev->video_dev);  	vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +	set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags);  	ret = video_register_device(vpfe_dev->video_dev,  				    VFL_TYPE_GRABBER, -1); diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 1089834a4ef..1e4ec697fb1 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1,5 +1,6 @@  /*   * Copyright (C) 2009 Texas Instruments Inc + * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -65,14 +66,26 @@ static struct vpif_config_params config_params = {  	.channel_bufsize[1] = 720 * 576 * 2,  }; +#define VPIF_DRIVER_NAME	"vpif_capture" +  /* global variables */  static struct vpif_device vpif_obj = { {NULL} };  static struct device *vpif_dev;  static void vpif_calculate_offsets(struct channel_obj *ch);  static void vpif_config_addr(struct channel_obj *ch, int muxmode); +static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} }; + +/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ +static int ycmux_mode; + +static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb) +{ +	return container_of(vb, struct vpif_cap_buffer, vb); +} +  /** - * buffer_prepare :  callback function for buffer prepare + * vpif_buffer_prepare :  callback function for buffer prepare   * @vb: ptr to vb2_buffer   *   * This is the callback function for buffer prepare when vb2_qbuf() @@ -81,10 +94,8 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode);   */  static int vpif_buffer_prepare(struct vb2_buffer *vb)  { -	/* Get the file handle object and channel object */ -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue);  	struct vb2_queue *q = vb->vb2_queue; -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(q);  	struct common_obj *common;  	unsigned long addr; @@ -92,26 +103,22 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)  	common = &ch->common[VPIF_VIDEO_INDEX]; -	if (vb->state != VB2_BUF_STATE_ACTIVE && -		vb->state != VB2_BUF_STATE_PREPARED) { -		vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); -		if (vb2_plane_vaddr(vb, 0) && -		vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) -			goto exit; -		addr = vb2_dma_contig_plane_dma_addr(vb, 0); +	vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); +	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) +		return -EINVAL; -		if (q->streaming) { -			if (!IS_ALIGNED((addr + common->ytop_off), 8) || -				!IS_ALIGNED((addr + common->ybtm_off), 8) || -				!IS_ALIGNED((addr + common->ctop_off), 8) || -				!IS_ALIGNED((addr + common->cbtm_off), 8)) -				goto exit; -		} +	vb->v4l2_buf.field = common->fmt.fmt.pix.field; + +	addr = vb2_dma_contig_plane_dma_addr(vb, 0); +	if (!IS_ALIGNED((addr + common->ytop_off), 8) || +		!IS_ALIGNED((addr + common->ybtm_off), 8) || +		!IS_ALIGNED((addr + common->ctop_off), 8) || +		!IS_ALIGNED((addr + common->cbtm_off), 8)) { +		vpif_dbg(1, debug, "offset is not aligned\n"); +		return -EINVAL;  	} +  	return 0; -exit: -	vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n"); -	return -EINVAL;  }  /** @@ -131,49 +138,26 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,  				unsigned int *nbuffers, unsigned int *nplanes,  				unsigned int sizes[], void *alloc_ctxs[])  { -	/* Get the file handle object and channel object */ -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common; -	unsigned long size;  	common = &ch->common[VPIF_VIDEO_INDEX];  	vpif_dbg(2, debug, "vpif_buffer_setup\n"); -	/* If memory type is not mmap, return */ -	if (V4L2_MEMORY_MMAP == common->memory) { -		/* Calculate the size of the buffer */ -		size = config_params.channel_bufsize[ch->channel_id]; -		/* -		 * Checking if the buffer size exceeds the available buffer -		 * ycmux_mode = 0 means 1 channel mode HD and -		 * ycmux_mode = 1 means 2 channels mode SD -		 */ -		if (ch->vpifparams.std_info.ycmux_mode == 0) { -			if (config_params.video_limit[ch->channel_id]) -				while (size * *nbuffers > -					(config_params.video_limit[0] -						+ config_params.video_limit[1])) -					(*nbuffers)--; -		} else { -			if (config_params.video_limit[ch->channel_id]) -				while (size * *nbuffers > -				config_params.video_limit[ch->channel_id]) -					(*nbuffers)--; -		} - -	} else { -		size = common->fmt.fmt.pix.sizeimage; -	} +	if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) +		return -EINVAL; -	if (*nbuffers < config_params.min_numbuffers) -		*nbuffers = config_params.min_numbuffers; +	if (vq->num_buffers + *nbuffers < 3) +		*nbuffers = 3 - vq->num_buffers;  	*nplanes = 1; -	sizes[0] = size; +	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage;  	alloc_ctxs[0] = common->alloc_ctx; +	/* Calculate the offset for Y and C data in the buffer */ +	vpif_calculate_offsets(ch); +  	return 0;  } @@ -183,11 +167,8 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq,   */  static void vpif_buffer_queue(struct vb2_buffer *vb)  { -	/* Get the file handle object and channel object */ -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); -	struct channel_obj *ch = fh->channel; -	struct vpif_cap_buffer *buf = container_of(vb, -				struct vpif_cap_buffer, vb); +	struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); +	struct vpif_cap_buffer *buf = to_vpif_buffer(vb);  	struct common_obj *common;  	unsigned long flags; @@ -202,108 +183,25 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)  }  /** - * vpif_buf_cleanup : Callback function to free buffer + * vpif_start_streaming : Starts the DMA engine for streaming   * @vb: ptr to vb2_buffer - * - * This function is called from the videobuf2 layer to free memory - * allocated to  the buffers + * @count: number of buffers   */ -static void vpif_buf_cleanup(struct vb2_buffer *vb) -{ -	/* Get the file handle object and channel object */ -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); -	struct vpif_cap_buffer *buf = container_of(vb, -					struct vpif_cap_buffer, vb); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; -	unsigned long flags; - -	common = &ch->common[VPIF_VIDEO_INDEX]; - -	spin_lock_irqsave(&common->irqlock, flags); -	if (vb->state == VB2_BUF_STATE_ACTIVE) -		list_del_init(&buf->list); -	spin_unlock_irqrestore(&common->irqlock, flags); - -} - -static void vpif_wait_prepare(struct vb2_queue *vq) -{ -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; - -	common = &ch->common[VPIF_VIDEO_INDEX]; -	mutex_unlock(&common->lock); -} - -static void vpif_wait_finish(struct vb2_queue *vq) -{ -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; - -	common = &ch->common[VPIF_VIDEO_INDEX]; -	mutex_lock(&common->lock); -} - -static int vpif_buffer_init(struct vb2_buffer *vb) -{ -	struct vpif_cap_buffer *buf = container_of(vb, -					struct vpif_cap_buffer, vb); - -	INIT_LIST_HEAD(&buf->list); - -	return 0; -} - -static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = -	{ {1, 1} }; -  static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  {  	struct vpif_capture_config *vpif_config_data =  					vpif_dev->platform_data; -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct vpif_params *vpif = &ch->vpifparams; -	unsigned long addr = 0; -	unsigned long flags; +	struct vpif_cap_buffer *buf, *tmp; +	unsigned long addr, flags;  	int ret; -	/* If buffer queue is empty, return error */  	spin_lock_irqsave(&common->irqlock, flags); -	if (list_empty(&common->dma_queue)) { -		spin_unlock_irqrestore(&common->irqlock, flags); -		vpif_dbg(1, debug, "buffer queue is empty\n"); -		return -EIO; -	} -	/* Get the next frame from the buffer queue */ -	common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, -				    struct vpif_cap_buffer, list); -	/* Remove buffer from the buffer queue */ -	list_del(&common->cur_frm->list); -	spin_unlock_irqrestore(&common->irqlock, flags); -	/* Mark state of the current frame to active */ -	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; -	/* Initialize field_id and started member */ +	/* Initialize field_id */  	ch->field_id = 0; -	common->started = 1; -	addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); - -	/* 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"); -		return -EINVAL; -	}  	/* configure 1 or 2 channel mode */  	if (vpif_config_data->setup_input_channel_mode) { @@ -311,21 +209,37 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  			setup_input_channel_mode(vpif->std_info.ycmux_mode);  		if (ret < 0) {  			vpif_dbg(1, debug, "can't set vpif channel mode\n"); -			return ret; +			goto err;  		}  	} +	ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); +	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { +		vpif_dbg(1, debug, "stream on failed in subdev\n"); +		goto err; +	} +  	/* 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"); -		return ret; +		goto err;  	} -	common->started = ret; +	ycmux_mode = ret;  	vpif_config_addr(ch, ret); +	/* Get the next frame from the buffer queue */ +	common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, +				    struct vpif_cap_buffer, list); +	/* Remove buffer from the buffer queue */ +	list_del(&common->cur_frm->list); +	spin_unlock_irqrestore(&common->irqlock, flags); +	/* Mark state of the current frame to active */ +	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + +	addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); +  	common->set_addr(addr + common->ytop_off,  			 addr + common->ybtm_off,  			 addr + common->ctop_off, @@ -336,36 +250,76 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  	 * VPIF register  	 */  	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; -	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { +	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)) { +	if (VPIF_CHANNEL1_VIDEO == ch->channel_id || +		ycmux_mode == 2) {  		channel1_intr_assert();  		channel1_intr_enable(1);  		enable_channel1(1);  	}  	return 0; + +err: +	list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { +		list_del(&buf->list); +		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); +	} +	spin_unlock_irqrestore(&common->irqlock, flags); + +	return ret;  } -/* abort streaming and wait for last buffer */ -static int vpif_stop_streaming(struct vb2_queue *vq) +/** + * vpif_stop_streaming : Stop the DMA engine + * @vq: ptr to vb2_queue + * + * This callback stops the DMA engine and any remaining buffers + * in the DMA queue are released. + */ +static void vpif_stop_streaming(struct vb2_queue *vq)  { -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common;  	unsigned long flags; - -	if (!vb2_is_streaming(vq)) -		return 0; +	int ret;  	common = &ch->common[VPIF_VIDEO_INDEX]; +	/* Disable channel as per its device type and channel id */ +	if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { +		enable_channel0(0); +		channel0_intr_enable(0); +	} +	if (VPIF_CHANNEL1_VIDEO == ch->channel_id || +		ycmux_mode == 2) { +		enable_channel1(0); +		channel1_intr_enable(0); +	} + +	ycmux_mode = 0; + +	ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); +	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) +		vpif_dbg(1, debug, "stream off failed in subdev\n"); +  	/* release all active buffers */  	spin_lock_irqsave(&common->irqlock, flags); +	if (common->cur_frm == common->next_frm) { +		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); +	} else { +		if (common->cur_frm != NULL) +			vb2_buffer_done(&common->cur_frm->vb, +					VB2_BUF_STATE_ERROR); +		if (common->next_frm != NULL) +			vb2_buffer_done(&common->next_frm->vb, +					VB2_BUF_STATE_ERROR); +	} +  	while (!list_empty(&common->dma_queue)) {  		common->next_frm = list_entry(common->dma_queue.next,  						struct vpif_cap_buffer, list); @@ -373,19 +327,13 @@ static int vpif_stop_streaming(struct vb2_queue *vq)  		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);  	}  	spin_unlock_irqrestore(&common->irqlock, flags); - -	return 0;  }  static struct vb2_ops video_qops = {  	.queue_setup		= vpif_buffer_queue_setup, -	.wait_prepare		= vpif_wait_prepare, -	.wait_finish		= vpif_wait_finish, -	.buf_init		= vpif_buffer_init,  	.buf_prepare		= vpif_buffer_prepare,  	.start_streaming	= vpif_start_streaming,  	.stop_streaming		= vpif_stop_streaming, -	.buf_cleanup		= vpif_buf_cleanup,  	.buf_queue		= vpif_buffer_queue,  }; @@ -462,9 +410,6 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)  	for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) {  		common = &ch->common[i];  		/* skip If streaming is not started in this channel */ -		if (0 == common->started) -			continue; -  		/* Check the field format */  		if (1 == ch->vpifparams.std_info.frm_fmt) {  			/* Progressive mode */ @@ -666,11 +611,6 @@ static void vpif_config_format(struct channel_obj *ch)  	vpif_dbg(2, debug, "vpif_config_format\n");  	common->fmt.fmt.pix.field = V4L2_FIELD_ANY; -	if (config_params.numbuffers[ch->channel_id] == 0) -		common->memory = V4L2_MEMORY_USERPTR; -	else -		common->memory = V4L2_MEMORY_MMAP; -  	common->fmt.fmt.pix.sizeimage  	    = config_params.channel_bufsize[ch->channel_id]; @@ -820,425 +760,6 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode)  }  /** - * vpif_mmap : It is used to map kernel space buffers into user spaces - * @filep: file pointer - * @vma: ptr to vm_area_struct - */ -static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) -{ -	/* Get the channel object and file handle object */ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); -	int ret; - -	vpif_dbg(2, debug, "vpif_mmap\n"); - -	if (mutex_lock_interruptible(&common->lock)) -		return -ERESTARTSYS; -	ret = vb2_mmap(&common->buffer_queue, vma); -	mutex_unlock(&common->lock); -	return ret; -} - -/** - * vpif_poll: It is used for select/poll system call - * @filep: file pointer - * @wait: poll table to wait - */ -static unsigned int vpif_poll(struct file *filep, poll_table * wait) -{ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *channel = fh->channel; -	struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]); -	unsigned int res = 0; - -	vpif_dbg(2, debug, "vpif_poll\n"); - -	if (common->started) { -		mutex_lock(&common->lock); -		res = vb2_poll(&common->buffer_queue, filep, wait); -		mutex_unlock(&common->lock); -	} -	return res; -} - -/** - * vpif_open : vpif open handler - * @filep: file ptr - * - * It creates object of file handle structure and stores it in private_data - * member of filepointer - */ -static int vpif_open(struct file *filep) -{ -	struct video_device *vdev = video_devdata(filep); -	struct common_obj *common; -	struct video_obj *vid_ch; -	struct channel_obj *ch; -	struct vpif_fh *fh; - -	vpif_dbg(2, debug, "vpif_open\n"); - -	ch = video_get_drvdata(vdev); - -	vid_ch = &ch->video; -	common = &ch->common[VPIF_VIDEO_INDEX]; - -	/* Allocate memory for the file handle object */ -	fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); -	if (NULL == fh) { -		vpif_err("unable to allocate memory for file handle object\n"); -		return -ENOMEM; -	} - -	if (mutex_lock_interruptible(&common->lock)) { -		kfree(fh); -		return -ERESTARTSYS; -	} -	/* store pointer to fh in private_data member of filep */ -	filep->private_data = fh; -	fh->channel = ch; -	fh->initialized = 0; -	/* If decoder is not initialized. initialize it */ -	if (!ch->initialized) { -		fh->initialized = 1; -		ch->initialized = 1; -		memset(&(ch->vpifparams), 0, sizeof(struct vpif_params)); -	} -	/* Increment channel usrs counter */ -	ch->usrs++; -	/* Set io_allowed member to false */ -	fh->io_allowed[VPIF_VIDEO_INDEX] = 0; -	/* Initialize priority of this instance to default priority */ -	fh->prio = V4L2_PRIORITY_UNSET; -	v4l2_prio_open(&ch->prio, &fh->prio); -	mutex_unlock(&common->lock); -	return 0; -} - -/** - * vpif_release : function to clean up file close - * @filep: file pointer - * - * This function deletes buffer queue, frees the buffers and the vpif file - * handle - */ -static int vpif_release(struct file *filep) -{ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; - -	vpif_dbg(2, debug, "vpif_release\n"); - -	common = &ch->common[VPIF_VIDEO_INDEX]; - -	mutex_lock(&common->lock); -	/* if this instance is doing IO */ -	if (fh->io_allowed[VPIF_VIDEO_INDEX]) { -		/* Reset io_usrs member of channel object */ -		common->io_usrs = 0; -		/* Disable channel as per its device type and channel id */ -		if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { -			enable_channel0(0); -			channel0_intr_enable(0); -		} -		if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || -		    (2 == common->started)) { -			enable_channel1(0); -			channel1_intr_enable(0); -		} -		common->started = 0; -		/* Free buffers allocated */ -		vb2_queue_release(&common->buffer_queue); -		vb2_dma_contig_cleanup_ctx(common->alloc_ctx); -	} - -	/* Decrement channel usrs counter */ -	ch->usrs--; - -	/* Close the priority */ -	v4l2_prio_close(&ch->prio, fh->prio); - -	if (fh->initialized) -		ch->initialized = 0; - -	mutex_unlock(&common->lock); -	filep->private_data = NULL; -	kfree(fh); -	return 0; -} - -/** - * vpif_reqbufs() - request buffer handler - * @file: file ptr - * @priv: file handle - * @reqbuf: request buffer structure ptr - */ -static int vpif_reqbufs(struct file *file, void *priv, -			struct v4l2_requestbuffers *reqbuf) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; -	u8 index = 0; -	struct vb2_queue *q; -	int ret; - -	vpif_dbg(2, debug, "vpif_reqbufs\n"); - -	/** -	 * This file handle has not initialized the channel, -	 * It is not allowed to do settings -	 */ -	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) -	    || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_dbg(1, debug, "Channel Busy\n"); -			return -EBUSY; -		} -	} - -	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type || !vpif_dev) -		return -EINVAL; - -	index = VPIF_VIDEO_INDEX; - -	common = &ch->common[index]; - -	if (0 != common->io_usrs) -		return -EBUSY; - -	/* Initialize videobuf2 queue as per the buffer type */ -	common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); -	if (IS_ERR(common->alloc_ctx)) { -		vpif_err("Failed to get the context\n"); -		return PTR_ERR(common->alloc_ctx); -	} -	q = &common->buffer_queue; -	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -	q->io_modes = VB2_MMAP | VB2_USERPTR; -	q->drv_priv = fh; -	q->ops = &video_qops; -	q->mem_ops = &vb2_dma_contig_memops; -	q->buf_struct_size = sizeof(struct vpif_cap_buffer); -	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - -	ret = vb2_queue_init(q); -	if (ret) { -		vpif_err("vpif_capture: vb2_queue_init() failed\n"); -		vb2_dma_contig_cleanup_ctx(common->alloc_ctx); -		return ret; -	} -	/* Set io allowed member of file handle to TRUE */ -	fh->io_allowed[index] = 1; -	/* Increment io usrs member of channel object to 1 */ -	common->io_usrs = 1; -	/* Store type of memory requested in channel object */ -	common->memory = reqbuf->memory; -	INIT_LIST_HEAD(&common->dma_queue); - -	/* Allocate buffers */ -	return vb2_reqbufs(&common->buffer_queue, reqbuf); -} - -/** - * vpif_querybuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_querybuf(struct file *file, void *priv, -				struct v4l2_buffer *buf) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	vpif_dbg(2, debug, "vpif_querybuf\n"); - -	if (common->fmt.type != buf->type) -		return -EINVAL; - -	if (common->memory != V4L2_MEMORY_MMAP) { -		vpif_dbg(1, debug, "Invalid memory\n"); -		return -EINVAL; -	} - -	return vb2_querybuf(&common->buffer_queue, buf); -} - -/** - * vpif_qbuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	struct v4l2_buffer tbuf = *buf; - -	vpif_dbg(2, debug, "vpif_qbuf\n"); - -	if (common->fmt.type != tbuf.type) { -		vpif_err("invalid buffer type\n"); -		return -EINVAL; -	} - -	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { -		vpif_err("fh io not allowed\n"); -		return -EACCES; -	} - -	return vb2_qbuf(&common->buffer_queue, buf); -} - -/** - * vpif_dqbuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	vpif_dbg(2, debug, "vpif_dqbuf\n"); - -	return vb2_dqbuf(&common->buffer_queue, buf, -			 (file->f_flags & O_NONBLOCK)); -} - -/** - * 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_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; -	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(ch->sd, video, s_stream, 1); - -	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { -		vpif_dbg(1, debug, "stream on failed in subdev\n"); -		return ret; -	} - -	/* Call vb2_streamon to start streaming in videobuf2 */ -	ret = vb2_streamon(&common->buffer_queue, buftype); -	if (ret) { -		vpif_dbg(1, debug, "vb2_streamon\n"); -		return ret; -	} - -	return ret; -} - -/** - * vpif_streamoff() - streamoff handler - * @file: file ptr - * @priv: file handle - * @buftype: v4l2 buffer type - */ -static int vpif_streamoff(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]; -	int ret; - -	vpif_dbg(2, debug, "vpif_streamoff\n"); - -	if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -		vpif_dbg(1, debug, "buffer type not supported\n"); -		return -EINVAL; -	} - -	/* If io is allowed for this file handle, return error */ -	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { -		vpif_dbg(1, debug, "io not allowed\n"); -		return -EACCES; -	} - -	/* If streaming is not started, return error */ -	if (!common->started) { -		vpif_dbg(1, debug, "channel->started\n"); -		return -EINVAL; -	} - -	/* disable channel */ -	if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { -		enable_channel0(0); -		channel0_intr_enable(0); -	} else { -		enable_channel1(0); -		channel1_intr_enable(0); -	} - -	common->started = 0; - -	ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); - -	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) -		vpif_dbg(1, debug, "stream off failed in subdev\n"); - -	return vb2_streamoff(&common->buffer_queue, buftype); -} - -/**   * vpif_input_to_subdev() - Maps input to sub device   * @vpif_cfg - global config ptr   * @chan_cfg - channel config ptr @@ -1341,8 +862,8 @@ static int vpif_set_input(   */  static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	int ret = 0;  	vpif_dbg(2, debug, "vpif_querystd\n"); @@ -1368,11 +889,22 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)   */  static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input;  	vpif_dbg(2, debug, "vpif_g_std\n"); +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_STD) +		return -ENODATA; +  	*std = ch->video.stdid;  	return 0;  } @@ -1385,31 +917,26 @@ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)   */  static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	int ret = 0; +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input; +	int ret;  	vpif_dbg(2, debug, "vpif_s_std\n"); -	if (common->started) { -		vpif_err("streaming in progress\n"); -		return -EBUSY; -	} - -	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || -	    (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_dbg(1, debug, "Channel Busy\n"); -			return -EBUSY; -		} -	} +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; -	ret = v4l2_prio_check(&ch->prio, fh->prio); -	if (0 != ret) -		return ret; +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_STD) +		return -ENODATA; -	fh->initialized = 1; +	if (vb2_is_busy(&common->buffer_queue)) +		return -EBUSY;  	/* Call encoder subdevice function to set the standard */  	ch->video.stdid = std_id; @@ -1425,7 +952,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  	vpif_config_format(ch);  	/* set standard in the sub device */ -	ret = v4l2_subdev_call(ch->sd, core, s_std, std_id); +	ret = v4l2_subdev_call(ch->sd, video, s_std, std_id);  	if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {  		vpif_dbg(1, debug, "Failed to set standard for sub devices\n");  		return ret; @@ -1444,9 +971,9 @@ static int vpif_enum_input(struct file *file, void *priv,  {  	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct vpif_capture_chan_config *chan_cfg; -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel;  	chan_cfg = &config->chan_config[ch->channel_id]; @@ -1468,8 +995,8 @@ static int vpif_enum_input(struct file *file, void *priv,   */  static int vpif_g_input(struct file *file, void *priv, unsigned int *index)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	*index = ch->input_idx;  	return 0; @@ -1484,35 +1011,19 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index)  static int vpif_s_input(struct file *file, void *priv, unsigned int index)  {  	struct vpif_capture_config *config = vpif_dev->platform_data; -	struct vpif_capture_chan_config *chan_cfg; -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	int ret; +	struct vpif_capture_chan_config *chan_cfg;  	chan_cfg = &config->chan_config[ch->channel_id];  	if (index >= chan_cfg->input_count)  		return -EINVAL; -	if (common->started) { -		vpif_err("Streaming in progress\n"); +	if (vb2_is_busy(&common->buffer_queue))  		return -EBUSY; -	} - -	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || -	    (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_dbg(1, debug, "Channel Busy\n"); -			return -EBUSY; -		} -	} - -	ret = v4l2_prio_check(&ch->prio, fh->prio); -	if (0 != ret) -		return ret; -	fh->initialized = 1;  	return vpif_set_input(config, ch, index);  } @@ -1525,8 +1036,8 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)  static int vpif_enum_fmt_vid_cap(struct file *file, void  *priv,  					struct v4l2_fmtdesc *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	if (fmt->index != 0) {  		vpif_dbg(1, debug, "Invalid format index\n"); @@ -1555,8 +1066,8 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void  *priv,  static int vpif_try_fmt_vid_cap(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;  	return vpif_check_format(ch, pixfmt, 1); @@ -1572,8 +1083,8 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv,  static int vpif_g_fmt_vid_cap(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	/* Check the validity of the buffer type */ @@ -1594,33 +1105,16 @@ static int vpif_g_fmt_vid_cap(struct file *file, void *priv,  static int vpif_s_fmt_vid_cap(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct v4l2_pix_format *pixfmt;  	int ret = 0;  	vpif_dbg(2, debug, "%s\n", __func__); -	/* If streaming is started, return error */ -	if (common->started) { -		vpif_dbg(1, debug, "Streaming is started\n"); +	if (vb2_is_busy(&common->buffer_queue))  		return -EBUSY; -	} - -	if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || -	    (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_dbg(1, debug, "Channel Busy\n"); -			return -EBUSY; -		} -	} - -	ret = v4l2_prio_check(&ch->prio, fh->prio); -	if (0 != ret) -		return ret; - -	fh->initialized = 1;  	pixfmt = &fmt->fmt.pix;  	/* Check for valid field format */ @@ -1646,7 +1140,7 @@ static int vpif_querycap(struct file *file, void  *priv,  	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;  	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; -	snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); +	strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));  	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",  		 dev_name(vpif_dev));  	strlcpy(cap->card, config->card_name, sizeof(cap->card)); @@ -1655,61 +1149,6 @@ static int vpif_querycap(struct file *file, void  *priv,  }  /** - * vpif_g_priority() - get priority handler - * @file: file ptr - * @priv: file handle - * @prio: ptr to v4l2_priority structure - */ -static int vpif_g_priority(struct file *file, void *priv, -			   enum v4l2_priority *prio) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; - -	*prio = v4l2_prio_max(&ch->prio); - -	return 0; -} - -/** - * vpif_s_priority() - set priority handler - * @file: file ptr - * @priv: file handle - * @prio: ptr to v4l2_priority structure - */ -static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; - -	return v4l2_prio_change(&ch->prio, &fh->prio, p); -} - -/** - * vpif_cropcap() - cropcap handler - * @file: file ptr - * @priv: file handle - * @crop: ptr to v4l2_cropcap structure - */ -static int vpif_cropcap(struct file *file, void *priv, -			struct v4l2_cropcap *crop) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != crop->type) -		return -EINVAL; - -	crop->bounds.left = 0; -	crop->bounds.top = 0; -	crop->bounds.height = common->height; -	crop->bounds.width = common->width; -	crop->defrect = crop->bounds; -	return 0; -} - -/**   * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler   * @file: file ptr   * @priv: file handle @@ -1719,13 +1158,27 @@ static int  vpif_enum_dv_timings(struct file *file, void *priv,  		     struct v4l2_enum_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input;  	int ret; -	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) +		return -ENODATA; + +	timings->pad = 0; + +	ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);  	if (ret == -ENOIOCTLCMD || ret == -ENODEV)  		return -EINVAL; +  	return ret;  } @@ -1739,13 +1192,25 @@ static int  vpif_query_dv_timings(struct file *file, void *priv,  		      struct v4l2_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input;  	int ret; +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) +		return -ENODATA; +  	ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);  	if (ret == -ENOIOCTLCMD || ret == -ENODEV)  		return -ENODATA; +  	return ret;  } @@ -1758,19 +1223,34 @@ vpif_query_dv_timings(struct file *file, void *priv,  static int vpif_s_dv_timings(struct file *file, void *priv,  		struct v4l2_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct vpif_params *vpifparams = &ch->vpifparams;  	struct vpif_channel_config_params *std_info = &vpifparams->std_info; +	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct video_obj *vid_ch = &ch->video;  	struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input;  	int ret; +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) +		return -ENODATA; +  	if (timings->type != V4L2_DV_BT_656_1120) {  		vpif_dbg(2, debug, "Timing type not defined\n");  		return -EINVAL;  	} +	if (vb2_is_busy(&common->buffer_queue)) +		return -EBUSY; +  	/* Configure subdevice timings, if any */  	ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);  	if (ret == -ENOIOCTLCMD || ret == -ENODEV) @@ -1846,9 +1326,20 @@ static int vpif_s_dv_timings(struct file *file, void *priv,  static int vpif_g_dv_timings(struct file *file, void *priv,  		struct v4l2_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_capture_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct video_obj *vid_ch = &ch->video; +	struct vpif_capture_chan_config *chan_cfg; +	struct v4l2_input input; + +	if (config->chan_config[ch->channel_id].inputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	input = chan_cfg->inputs[ch->input_idx].input; +	if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) +		return -ENODATA;  	*timings = vid_ch->dv_timings; @@ -1872,49 +1363,45 @@ static int vpif_log_status(struct file *filep, void *priv)  /* vpif capture ioctl operations */  static const struct v4l2_ioctl_ops vpif_ioctl_ops = { -	.vidioc_querycap        	= vpif_querycap, -	.vidioc_g_priority		= vpif_g_priority, -	.vidioc_s_priority		= vpif_s_priority, +	.vidioc_querycap		= vpif_querycap,  	.vidioc_enum_fmt_vid_cap	= vpif_enum_fmt_vid_cap, -	.vidioc_g_fmt_vid_cap  		= vpif_g_fmt_vid_cap, +	.vidioc_g_fmt_vid_cap		= vpif_g_fmt_vid_cap,  	.vidioc_s_fmt_vid_cap		= vpif_s_fmt_vid_cap,  	.vidioc_try_fmt_vid_cap		= vpif_try_fmt_vid_cap, +  	.vidioc_enum_input		= vpif_enum_input,  	.vidioc_s_input			= vpif_s_input,  	.vidioc_g_input			= vpif_g_input, -	.vidioc_reqbufs         	= vpif_reqbufs, -	.vidioc_querybuf        	= vpif_querybuf, + +	.vidioc_reqbufs			= vb2_ioctl_reqbufs, +	.vidioc_create_bufs		= vb2_ioctl_create_bufs, +	.vidioc_querybuf		= vb2_ioctl_querybuf, +	.vidioc_qbuf			= vb2_ioctl_qbuf, +	.vidioc_dqbuf			= vb2_ioctl_dqbuf, +	.vidioc_expbuf			= vb2_ioctl_expbuf, +	.vidioc_streamon		= vb2_ioctl_streamon, +	.vidioc_streamoff		= vb2_ioctl_streamoff, +  	.vidioc_querystd		= vpif_querystd, -	.vidioc_s_std           	= vpif_s_std, +	.vidioc_s_std			= vpif_s_std,  	.vidioc_g_std			= vpif_g_std, -	.vidioc_qbuf            	= vpif_qbuf, -	.vidioc_dqbuf           	= vpif_dqbuf, -	.vidioc_streamon        	= vpif_streamon, -	.vidioc_streamoff       	= vpif_streamoff, -	.vidioc_cropcap         	= vpif_cropcap, -	.vidioc_enum_dv_timings         = vpif_enum_dv_timings, -	.vidioc_query_dv_timings        = vpif_query_dv_timings, -	.vidioc_s_dv_timings            = vpif_s_dv_timings, -	.vidioc_g_dv_timings            = vpif_g_dv_timings, + +	.vidioc_enum_dv_timings		= vpif_enum_dv_timings, +	.vidioc_query_dv_timings	= vpif_query_dv_timings, +	.vidioc_s_dv_timings		= vpif_s_dv_timings, +	.vidioc_g_dv_timings		= vpif_g_dv_timings, +  	.vidioc_log_status		= vpif_log_status,  };  /* vpif file operations */  static struct v4l2_file_operations vpif_fops = {  	.owner = THIS_MODULE, -	.open = vpif_open, -	.release = vpif_release, +	.open = v4l2_fh_open, +	.release = vb2_fop_release,  	.unlocked_ioctl = video_ioctl2, -	.mmap = vpif_mmap, -	.poll = vpif_poll -}; - -/* vpif video template */ -static struct video_device vpif_video_template = { -	.name		= "vpif", -	.fops		= &vpif_fops, -	.minor		= -1, -	.ioctl_ops	= &vpif_ioctl_ops, +	.mmap = vb2_fop_mmap, +	.poll = vb2_fop_poll  };  /** @@ -1992,7 +1479,9 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier,  static int vpif_probe_complete(void)  {  	struct common_obj *common; +	struct video_device *vdev;  	struct channel_obj *ch; +	struct vb2_queue *q;  	int i, j, err, k;  	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { @@ -2001,17 +1490,52 @@ static int vpif_probe_complete(void)  		common = &(ch->common[VPIF_VIDEO_INDEX]);  		spin_lock_init(&common->irqlock);  		mutex_init(&common->lock); -		ch->video_dev->lock = &common->lock; -		/* Initialize prio member of channel object */ -		v4l2_prio_init(&ch->prio); -		video_set_drvdata(ch->video_dev, ch);  		/* select input 0 */  		err = vpif_set_input(vpif_obj.config, ch, 0);  		if (err)  			goto probe_out; -		err = video_register_device(ch->video_dev, +		/* Initialize vb2 queue */ +		q = &common->buffer_queue; +		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; +		q->drv_priv = ch; +		q->ops = &video_qops; +		q->mem_ops = &vb2_dma_contig_memops; +		q->buf_struct_size = sizeof(struct vpif_cap_buffer); +		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +		q->min_buffers_needed = 1; +		q->lock = &common->lock; + +		err = vb2_queue_init(q); +		if (err) { +			vpif_err("vpif_capture: vb2_queue_init() failed\n"); +			goto probe_out; +		} + +		common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); +		if (IS_ERR(common->alloc_ctx)) { +			vpif_err("Failed to get the context\n"); +			err = PTR_ERR(common->alloc_ctx); +			goto probe_out; +		} + +		INIT_LIST_HEAD(&common->dma_queue); + +		/* Initialize the video_device structure */ +		vdev = ch->video_dev; +		strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); +		vdev->release = video_device_release; +		vdev->fops = &vpif_fops; +		vdev->ioctl_ops = &vpif_ioctl_ops; +		vdev->v4l2_dev = &vpif_obj.v4l2_dev; +		vdev->vfl_dir = VFL_DIR_RX; +		vdev->queue = q; +		vdev->lock = &common->lock; +		set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); +		video_set_drvdata(ch->video_dev, ch); +		err = video_register_device(vdev,  					    VFL_TYPE_GRABBER, (j ? 1 : 0));  		if (err)  			goto probe_out; @@ -2024,6 +1548,8 @@ probe_out:  	for (k = 0; k < j; k++) {  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[k]; +		common = &ch->common[k]; +		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);  		/* Unregister video device */  		video_unregister_device(ch->video_dev);  	} @@ -2060,7 +1586,6 @@ static __init int vpif_probe(struct platform_device *pdev)  	struct video_device *vfd;  	struct resource *res;  	int subdev_count; -	size_t size;  	vpif_dev = &pdev->dev; @@ -2078,7 +1603,7 @@ static __init int vpif_probe(struct platform_device *pdev)  	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {  		err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, -					IRQF_SHARED, "VPIF_Capture", +					IRQF_SHARED, VPIF_DRIVER_NAME,  					(void *)(&vpif_obj.dev[res_idx]->  					channel_id));  		if (err) { @@ -2102,34 +1627,10 @@ static __init int vpif_probe(struct platform_device *pdev)  			goto vpif_unregister;  		} -		/* Initialize field of video device */ -		*vfd = vpif_video_template; -		vfd->v4l2_dev = &vpif_obj.v4l2_dev; -		vfd->release = video_device_release; -		snprintf(vfd->name, sizeof(vfd->name), -			 "VPIF_Capture_DRIVER_V%s", -			 VPIF_CAPTURE_VERSION);  		/* Set video_dev to the video device */  		ch->video_dev = vfd;  	} -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (res) { -		size = resource_size(res); -		/* The resources are divided into two equal memory and when we -		 * have HD output we can add them together -		 */ -		for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { -			ch = vpif_obj.dev[j]; -			ch->channel_id = j; -			/* only enabled if second resource exists */ -			config_params.video_limit[ch->channel_id] = 0; -			if (size) -				config_params.video_limit[ch->channel_id] = -									size/2; -		} -	} -  	vpif_obj.config = pdev->dev.platform_data;  	subdev_count = vpif_obj.config->subdev_count; @@ -2154,7 +1655,7 @@ static __init int vpif_probe(struct platform_device *pdev)  			if (!vpif_obj.sd[i]) {  				vpif_err("Error registering v4l2 subdevice\n"); -				err = -ENOMEM; +				err = -ENODEV;  				goto probe_subdev_out;  			}  			v4l2_info(&vpif_obj.v4l2_dev, @@ -2202,6 +1703,7 @@ vpif_unregister:   */  static int vpif_remove(struct platform_device *device)  { +	struct common_obj *common;  	struct channel_obj *ch;  	int i; @@ -2212,6 +1714,8 @@ static int vpif_remove(struct platform_device *device)  	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i]; +		common = &ch->common[i]; +		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);  		/* Unregister video device */  		video_unregister_device(ch->video_dev);  		kfree(vpif_obj.dev[i]); @@ -2219,7 +1723,7 @@ static int vpif_remove(struct platform_device *device)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  /**   * vpif_suspend: vpif device suspend   */ @@ -2234,18 +1738,20 @@ static int vpif_suspend(struct device *dev)  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i];  		common = &ch->common[VPIF_VIDEO_INDEX]; + +		if (!vb2_is_streaming(&common->buffer_queue)) +			continue; +  		mutex_lock(&common->lock); -		if (ch->usrs && common->io_usrs) { -			/* Disable channel */ -			if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { -				enable_channel0(0); -				channel0_intr_enable(0); -			} -			if (ch->channel_id == VPIF_CHANNEL1_VIDEO || -			    common->started == 2) { -				enable_channel1(0); -				channel1_intr_enable(0); -			} +		/* Disable channel */ +		if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { +			enable_channel0(0); +			channel0_intr_enable(0); +		} +		if (ch->channel_id == VPIF_CHANNEL1_VIDEO || +			ycmux_mode == 2) { +			enable_channel1(0); +			channel1_intr_enable(0);  		}  		mutex_unlock(&common->lock);  	} @@ -2266,40 +1772,35 @@ static int vpif_resume(struct device *dev)  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i];  		common = &ch->common[VPIF_VIDEO_INDEX]; + +		if (!vb2_is_streaming(&common->buffer_queue)) +			continue; +  		mutex_lock(&common->lock); -		if (ch->usrs && common->io_usrs) { -			/* Disable channel */ -			if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { -				enable_channel0(1); -				channel0_intr_enable(1); -			} -			if (ch->channel_id == VPIF_CHANNEL1_VIDEO || -			    common->started == 2) { -				enable_channel1(1); -				channel1_intr_enable(1); -			} +		/* Enable channel */ +		if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { +			enable_channel0(1); +			channel0_intr_enable(1); +		} +		if (ch->channel_id == VPIF_CHANNEL1_VIDEO || +			ycmux_mode == 2) { +			enable_channel1(1); +			channel1_intr_enable(1);  		}  		mutex_unlock(&common->lock);  	}  	return 0;  } - -static const struct dev_pm_ops vpif_dev_pm_ops = { -	.suspend = vpif_suspend, -	.resume = vpif_resume, -}; - -#define vpif_pm_ops (&vpif_dev_pm_ops) -#else -#define vpif_pm_ops NULL  #endif +static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); +  static __refdata struct platform_driver vpif_driver = {  	.driver	= { -		.name	= "vpif_capture", +		.name	= VPIF_DRIVER_NAME,  		.owner	= THIS_MODULE, -		.pm	= vpif_pm_ops, +		.pm	= &vpif_pm_ops,  	},  	.probe = vpif_probe,  	.remove = vpif_remove, diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 5a29d9a0cae..1ee17824f48 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -19,8 +19,6 @@  #ifndef VPIF_CAPTURE_H  #define VPIF_CAPTURE_H -#ifdef __KERNEL__ -  /* Header files */  #include <media/videobuf2-dma-contig.h>  #include <media/v4l2-device.h> @@ -63,11 +61,6 @@ struct common_obj {  	struct vpif_cap_buffer *cur_frm;  	/* Pointer pointing to current v4l2_buffer */  	struct vpif_cap_buffer *next_frm; -	/* -	 * This field keeps track of type of buffer exchange mechanism -	 * user has selected -	 */ -	enum v4l2_memory memory;  	/* Used to store pixel format */  	struct v4l2_format fmt;  	/* Buffer queue used in video-buf */ @@ -80,10 +73,6 @@ struct common_obj {  	spinlock_t irqlock;  	/* lock used to access this structure */  	struct mutex lock; -	/* number of users performing IO */ -	u32 io_usrs; -	/* Indicates whether streaming started */ -	u8 started;  	/* Function pointer to set the addresses */  	void (*set_addr) (unsigned long, unsigned long, unsigned long,  			  unsigned long); @@ -104,10 +93,6 @@ struct common_obj {  struct channel_obj {  	/* Identifies video device for this channel */  	struct video_device *video_dev; -	/* Used to keep track of state of the priority */ -	struct v4l2_prio_state prio; -	/* number of open instances of the channel */ -	int usrs;  	/* Indicates id of the field which is being displayed */  	u32 field_id;  	/* flag to indicate whether decoder is initialized */ @@ -126,18 +111,6 @@ struct channel_obj {  	struct video_obj video;  }; -/* File handle structure */ -struct vpif_fh { -	/* pointer to channel object for opened device */ -	struct channel_obj *channel; -	/* Indicates whether this file handle is doing IO */ -	u8 io_allowed[VPIF_NUMBER_OF_OBJECTS]; -	/* Used to keep track priority of this instance */ -	enum v4l2_priority prio; -	/* Used to indicate channel is initialize or not */ -	u8 initialized; -}; -  struct vpif_device {  	struct v4l2_device v4l2_dev;  	struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; @@ -157,5 +130,4 @@ struct vpif_config_params {  	u8 max_device_type;  }; -#endif				/* End of __KERNEL__ */  #endif				/* VPIF_CAPTURE_H */ diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index c31bcf129a5..b431b58f39e 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -3,6 +3,7 @@   * Display driver for TI DaVinci VPIF   *   * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com>   *   * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License as @@ -35,129 +36,110 @@ MODULE_VERSION(VPIF_DISPLAY_VERSION);  		v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)  static int debug = 1; -static u32 ch2_numbuffers = 3; -static u32 ch3_numbuffers = 3; -static u32 ch2_bufsize = 1920 * 1080 * 2; -static u32 ch3_bufsize = 720 * 576 * 2;  module_param(debug, int, 0644); -module_param(ch2_numbuffers, uint, S_IRUGO); -module_param(ch3_numbuffers, uint, S_IRUGO); -module_param(ch2_bufsize, uint, S_IRUGO); -module_param(ch3_bufsize, uint, S_IRUGO);  MODULE_PARM_DESC(debug, "Debug level 0-1"); -MODULE_PARM_DESC(ch2_numbuffers, "Channel2 buffer count (default:3)"); -MODULE_PARM_DESC(ch3_numbuffers, "Channel3 buffer count (default:3)"); -MODULE_PARM_DESC(ch2_bufsize, "Channel2 buffer size (default:1920 x 1080 x 2)"); -MODULE_PARM_DESC(ch3_bufsize, "Channel3 buffer size (default:720 x 576 x 2)"); - -static struct vpif_config_params config_params = { -	.min_numbuffers		= 3, -	.numbuffers[0]		= 3, -	.numbuffers[1]		= 3, -	.min_bufsize[0]		= 720 * 480 * 2, -	.min_bufsize[1]		= 720 * 480 * 2, -	.channel_bufsize[0]	= 1920 * 1080 * 2, -	.channel_bufsize[1]	= 720 * 576 * 2, -}; + +#define VPIF_DRIVER_NAME	"vpif_display" + +/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ +static int ycmux_mode; + +static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} };  static struct vpif_device vpif_obj = { {NULL} };  static struct device *vpif_dev;  static void vpif_calculate_offsets(struct channel_obj *ch);  static void vpif_config_addr(struct channel_obj *ch, int muxmode); -/* - * buffer_prepare: This is the callback function called from vb2_qbuf() - * function the buffer is prepared and user space virtual address is converted - * into physical address +static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb) +{ +	return container_of(vb, struct vpif_disp_buffer, vb); +} + +/** + * vpif_buffer_prepare :  callback function for buffer prepare + * @vb: ptr to vb2_buffer + * + * This is the callback function for buffer prepare when vb2_qbuf() + * function is called. The buffer is prepared and user space virtual address + * or user address is converted into  physical address   */  static int vpif_buffer_prepare(struct vb2_buffer *vb)  { -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); -	struct vb2_queue *q = vb->vb2_queue; +	struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);  	struct common_obj *common; -	unsigned long addr; - -	common = &fh->channel->common[VPIF_VIDEO_INDEX]; -	if (vb->state != VB2_BUF_STATE_ACTIVE && -		vb->state != VB2_BUF_STATE_PREPARED) { -		vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); -		if (vb2_plane_vaddr(vb, 0) && -		vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) -			goto buf_align_exit; - -		addr = vb2_dma_contig_plane_dma_addr(vb, 0); -		if (q->streaming && -			(V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { -			if (!ISALIGNED(addr + common->ytop_off) || + +	common = &ch->common[VPIF_VIDEO_INDEX]; + +	vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); +	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) +		return -EINVAL; + +	vb->v4l2_buf.field = common->fmt.fmt.pix.field; + +	if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { +		unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0); + +		if (!ISALIGNED(addr + common->ytop_off) ||  			!ISALIGNED(addr + common->ybtm_off) ||  			!ISALIGNED(addr + common->ctop_off) || -			!ISALIGNED(addr + common->cbtm_off)) -				goto buf_align_exit; +			!ISALIGNED(addr + common->cbtm_off)) { +			vpif_err("buffer offset not aligned to 8 bytes\n"); +			return -EINVAL;  		}  	} -	return 0; -buf_align_exit: -	vpif_err("buffer offset not aligned to 8 bytes\n"); -	return -EINVAL; +	return 0;  } -/* - * vpif_buffer_queue_setup: This function allocates memory for the buffers +/** + * vpif_buffer_queue_setup : Callback function for buffer setup. + * @vq: vb2_queue ptr + * @fmt: v4l2 format + * @nbuffers: ptr to number of buffers requested by application + * @nplanes:: contains number of distinct video planes needed to hold a frame + * @sizes[]: contains the size (in bytes) of each plane. + * @alloc_ctxs: ptr to allocation context + * + * This callback function is called when reqbuf() is called to adjust + * the buffer count and buffer size   */  static int vpif_buffer_queue_setup(struct vb2_queue *vq,  				const struct v4l2_format *fmt,  				unsigned int *nbuffers, unsigned int *nplanes,  				unsigned int sizes[], void *alloc_ctxs[])  { -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	unsigned long size; - -	if (V4L2_MEMORY_MMAP == common->memory) { -		size = config_params.channel_bufsize[ch->channel_id]; -		/* -		* Checking if the buffer size exceeds the available buffer -		* ycmux_mode = 0 means 1 channel mode HD and -		* ycmux_mode = 1 means 2 channels mode SD -		*/ -		if (ch->vpifparams.std_info.ycmux_mode == 0) { -			if (config_params.video_limit[ch->channel_id]) -				while (size * *nbuffers > -					(config_params.video_limit[0] -						+ config_params.video_limit[1])) -					(*nbuffers)--; -		} else { -			if (config_params.video_limit[ch->channel_id]) -				while (size * *nbuffers > -				config_params.video_limit[ch->channel_id]) -					(*nbuffers)--; -		} -	} else { -		size = common->fmt.fmt.pix.sizeimage; -	} -	if (*nbuffers < config_params.min_numbuffers) -			*nbuffers = config_params.min_numbuffers; +	if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) +		return -EINVAL; + +	if (vq->num_buffers + *nbuffers < 3) +		*nbuffers = 3 - vq->num_buffers;  	*nplanes = 1; -	sizes[0] = size; +	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage;  	alloc_ctxs[0] = common->alloc_ctx; + +	/* Calculate the offset for Y and C data  in the buffer */ +	vpif_calculate_offsets(ch); +  	return 0;  } -/* - * vpif_buffer_queue: This function adds the buffer to DMA queue +/** + * vpif_buffer_queue : Callback function to add buffer to DMA queue + * @vb: ptr to vb2_buffer + * + * This callback fucntion queues the buffer to DMA engine   */  static void vpif_buffer_queue(struct vb2_buffer *vb)  { -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); -	struct vpif_disp_buffer *buf = container_of(vb, -				struct vpif_disp_buffer, vb); -	struct channel_obj *ch = fh->channel; +	struct vpif_disp_buffer *buf = to_vpif_buffer(vb); +	struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);  	struct common_obj *common;  	unsigned long flags; @@ -169,104 +151,26 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)  	spin_unlock_irqrestore(&common->irqlock, flags);  } -/* - * vpif_buf_cleanup: This function is called from the videobuf2 layer to - * free memory allocated to the buffers +/** + * vpif_start_streaming : Starts the DMA engine for streaming + * @vb: ptr to vb2_buffer + * @count: number of buffers   */ -static void vpif_buf_cleanup(struct vb2_buffer *vb) -{ -	struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); -	struct vpif_disp_buffer *buf = container_of(vb, -					struct vpif_disp_buffer, vb); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; -	unsigned long flags; - -	common = &ch->common[VPIF_VIDEO_INDEX]; - -	spin_lock_irqsave(&common->irqlock, flags); -	if (vb->state == VB2_BUF_STATE_ACTIVE) -		list_del_init(&buf->list); -	spin_unlock_irqrestore(&common->irqlock, flags); -} - -static void vpif_wait_prepare(struct vb2_queue *vq) -{ -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; - -	common = &ch->common[VPIF_VIDEO_INDEX]; -	mutex_unlock(&common->lock); -} - -static void vpif_wait_finish(struct vb2_queue *vq) -{ -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; - -	common = &ch->common[VPIF_VIDEO_INDEX]; -	mutex_lock(&common->lock); -} - -static int vpif_buffer_init(struct vb2_buffer *vb) -{ -	struct vpif_disp_buffer *buf = container_of(vb, -					struct vpif_disp_buffer, vb); - -	INIT_LIST_HEAD(&buf->list); - -	return 0; -} - -static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; -  static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  {  	struct vpif_display_config *vpif_config_data =  					vpif_dev->platform_data; -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct vpif_params *vpif = &ch->vpifparams; -	unsigned long addr = 0; -	unsigned long flags; +	struct vpif_disp_buffer *buf, *tmp; +	unsigned long addr, flags;  	int ret; -	/* If buffer queue is empty, return error */  	spin_lock_irqsave(&common->irqlock, flags); -	if (list_empty(&common->dma_queue)) { -		spin_unlock_irqrestore(&common->irqlock, flags); -		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 vpif_disp_buffer, list); - -	list_del(&common->cur_frm->list); -	spin_unlock_irqrestore(&common->irqlock, flags); -	/* Mark state of the current frame to active */ -	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; - -	/* Initialize field_id and started member */ +	/* Initialize field_id */  	ch->field_id = 0; -	common->started = 1; -	addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); -	/* 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 */  	if (vpif_config_data->set_clock) { @@ -274,24 +178,37 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  		ycmux_mode, ch->vpifparams.std_info.hd_sd);  		if (ret < 0) {  			vpif_err("can't set clock\n"); -			return ret; +			goto err;  		}  	}  	/* set the parameters and addresses */  	ret = vpif_set_video_params(vpif, ch->channel_id + 2);  	if (ret < 0) -		return ret; +		goto err; -	common->started = ret; +	ycmux_mode = ret;  	vpif_config_addr(ch, ret); +	/* Get the next frame from the buffer queue */ +	common->next_frm = common->cur_frm = +			    list_entry(common->dma_queue.next, +				       struct vpif_disp_buffer, list); + +	list_del(&common->cur_frm->list); +	spin_unlock_irqrestore(&common->irqlock, flags); +	/* Mark state of the current frame to active */ +	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + +	addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0);  	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 */ +	/* +	 * Set interrupt for both the fields in VPIF +	 * Register enable channel in VPIF register +	 */  	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;  	if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {  		channel2_intr_assert(); @@ -301,8 +218,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  			channel2_clipping_enable(1);  	} -	if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) -		|| (common->started == 2)) { +	if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) {  		channel3_intr_assert();  		channel3_intr_enable(1);  		enable_channel3(1); @@ -311,23 +227,55 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)  	}  	return 0; + +err: +	list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { +		list_del(&buf->list); +		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); +	} +	spin_unlock_irqrestore(&common->irqlock, flags); + +	return ret;  } -/* abort streaming and wait for last buffer */ -static int vpif_stop_streaming(struct vb2_queue *vq) +/** + * vpif_stop_streaming : Stop the DMA engine + * @vq: ptr to vb2_queue + * + * This callback stops the DMA engine and any remaining buffers + * in the DMA queue are released. + */ +static void vpif_stop_streaming(struct vb2_queue *vq)  { -	struct vpif_fh *fh = vb2_get_drv_priv(vq); -	struct channel_obj *ch = fh->channel; +	struct channel_obj *ch = vb2_get_drv_priv(vq);  	struct common_obj *common;  	unsigned long flags; -	if (!vb2_is_streaming(vq)) -		return 0; -  	common = &ch->common[VPIF_VIDEO_INDEX]; +	/* Disable channel */ +	if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { +		enable_channel2(0); +		channel2_intr_enable(0); +	} +	if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) { +		enable_channel3(0); +		channel3_intr_enable(0); +	} +  	/* release all active buffers */  	spin_lock_irqsave(&common->irqlock, flags); +	if (common->cur_frm == common->next_frm) { +		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR); +	} else { +		if (common->cur_frm != NULL) +			vb2_buffer_done(&common->cur_frm->vb, +					VB2_BUF_STATE_ERROR); +		if (common->next_frm != NULL) +			vb2_buffer_done(&common->next_frm->vb, +					VB2_BUF_STATE_ERROR); +	} +  	while (!list_empty(&common->dma_queue)) {  		common->next_frm = list_entry(common->dma_queue.next,  						struct vpif_disp_buffer, list); @@ -335,19 +283,15 @@ static int vpif_stop_streaming(struct vb2_queue *vq)  		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);  	}  	spin_unlock_irqrestore(&common->irqlock, flags); - -	return 0;  }  static struct vb2_ops video_qops = {  	.queue_setup		= vpif_buffer_queue_setup, -	.wait_prepare		= vpif_wait_prepare, -	.wait_finish		= vpif_wait_finish, -	.buf_init		= vpif_buffer_init, +	.wait_prepare		= vb2_ops_wait_prepare, +	.wait_finish		= vb2_ops_wait_finish,  	.buf_prepare		= vpif_buffer_prepare,  	.start_streaming	= vpif_start_streaming,  	.stop_streaming		= vpif_stop_streaming, -	.buf_cleanup		= vpif_buf_cleanup,  	.buf_queue		= vpif_buffer_queue,  }; @@ -429,8 +373,6 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)  	for (i = 0; i < VPIF_NUMOBJECTS; i++) {  		common = &ch->common[i];  		/* If streaming is started in this channel */ -		if (0 == common->started) -			continue;  		if (1 == ch->vpifparams.std_info.frm_fmt) {  			spin_lock(&common->irqlock); @@ -526,6 +468,7 @@ static int vpif_update_resolution(struct channel_obj *ch)  			return -EINVAL;  	} +	common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;  	common->fmt.fmt.pix.width = std_info->width;  	common->fmt.fmt.pix.height = std_info->height;  	vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n", @@ -534,6 +477,17 @@ static int vpif_update_resolution(struct channel_obj *ch)  	/* Set height and width paramateres */  	common->height = std_info->height;  	common->width = std_info->width; +	common->fmt.fmt.pix.sizeimage = common->height * common->width * 2; + +	if (vid_ch->stdid) +		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; +	else +		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + +	if (ch->vpifparams.std_info.frm_fmt) +		common->fmt.fmt.pix.field = V4L2_FIELD_NONE; +	else +		common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;  	return 0;  } @@ -604,70 +558,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch)  	ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid;  } -static void vpif_config_format(struct channel_obj *ch) -{ -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	common->fmt.fmt.pix.field = V4L2_FIELD_ANY; -	if (config_params.numbuffers[ch->channel_id] == 0) -		common->memory = V4L2_MEMORY_USERPTR; -	else -		common->memory = V4L2_MEMORY_MMAP; - -	common->fmt.fmt.pix.sizeimage = -			config_params.channel_bufsize[ch->channel_id]; -	common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; -	common->fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -} - -static int vpif_check_format(struct channel_obj *ch, -			     struct v4l2_pix_format *pixfmt) -{ -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	enum v4l2_field field = pixfmt->field; -	u32 sizeimage, hpitch, vpitch; - -	if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) -		goto invalid_fmt_exit; - -	if (!(VPIF_VALID_FIELD(field))) -		goto invalid_fmt_exit; - -	if (pixfmt->bytesperline <= 0) -		goto invalid_pitch_exit; - -	sizeimage = pixfmt->sizeimage; - -	if (vpif_update_resolution(ch)) -		return -EINVAL; - -	hpitch = pixfmt->bytesperline; -	vpitch = sizeimage / (hpitch * 2); - -	/* Check for valid value of pitch */ -	if ((hpitch < ch->vpifparams.std_info.width) || -	    (vpitch < ch->vpifparams.std_info.height)) -		goto invalid_pitch_exit; - -	/* Check for 8 byte alignment */ -	if (!ISALIGNED(hpitch)) { -		vpif_err("invalid pitch alignment\n"); -		return -EINVAL; -	} -	pixfmt->width = common->fmt.fmt.pix.width; -	pixfmt->height = common->fmt.fmt.pix.height; - -	return 0; - -invalid_fmt_exit: -	vpif_err("invalid field format\n"); -	return -EINVAL; - -invalid_pitch_exit: -	vpif_err("invalid pitch\n"); -	return -EINVAL; -} -  static void vpif_config_addr(struct channel_obj *ch, int muxmode)  {  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; @@ -682,139 +572,6 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode)  	}  } -/* - * vpif_mmap: It is used to map kernel space buffers into user spaces - */ -static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) -{ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); -	int ret; - -	vpif_dbg(2, debug, "vpif_mmap\n"); - -	if (mutex_lock_interruptible(&common->lock)) -		return -ERESTARTSYS; -	ret = vb2_mmap(&common->buffer_queue, vma); -	mutex_unlock(&common->lock); -	return ret; -} - -/* - * vpif_poll: It is used for select/poll system call - */ -static unsigned int vpif_poll(struct file *filep, poll_table *wait) -{ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	unsigned int res = 0; - -	if (common->started) { -		mutex_lock(&common->lock); -		res = vb2_poll(&common->buffer_queue, filep, wait); -		mutex_unlock(&common->lock); -	} - -	return res; -} - -/* - * vpif_open: It creates object of file handle structure and stores it in - * private_data member of filepointer - */ -static int vpif_open(struct file *filep) -{ -	struct video_device *vdev = video_devdata(filep); -	struct channel_obj *ch = video_get_drvdata(vdev); -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	struct vpif_fh *fh; - -	/* Allocate memory for the file handle object */ -	fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); -	if (fh == NULL) { -		vpif_err("unable to allocate memory for file handle object\n"); -		return -ENOMEM; -	} - -	if (mutex_lock_interruptible(&common->lock)) { -		kfree(fh); -		return -ERESTARTSYS; -	} -	/* store pointer to fh in private_data member of filep */ -	filep->private_data = fh; -	fh->channel = ch; -	fh->initialized = 0; -	if (!ch->initialized) { -		fh->initialized = 1; -		ch->initialized = 1; -		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); -	} - -	/* Increment channel usrs counter */ -	atomic_inc(&ch->usrs); -	/* Set io_allowed[VPIF_VIDEO_INDEX] member to false */ -	fh->io_allowed[VPIF_VIDEO_INDEX] = 0; -	/* Initialize priority of this instance to default priority */ -	fh->prio = V4L2_PRIORITY_UNSET; -	v4l2_prio_open(&ch->prio, &fh->prio); -	mutex_unlock(&common->lock); - -	return 0; -} - -/* - * vpif_release: This function deletes buffer queue, frees the buffers and - * the vpif file handle - */ -static int vpif_release(struct file *filep) -{ -	struct vpif_fh *fh = filep->private_data; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	mutex_lock(&common->lock); -	/* if this instance is doing IO */ -	if (fh->io_allowed[VPIF_VIDEO_INDEX]) { -		/* Reset io_usrs member of channel object */ -		common->io_usrs = 0; -		/* Disable channel */ -		if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { -			enable_channel2(0); -			channel2_intr_enable(0); -		} -		if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || -		    (2 == common->started)) { -			enable_channel3(0); -			channel3_intr_enable(0); -		} -		common->started = 0; - -		/* Free buffers allocated */ -		vb2_queue_release(&common->buffer_queue); -		vb2_dma_contig_cleanup_ctx(common->alloc_ctx); - -		common->numbuffers = -		    config_params.numbuffers[ch->channel_id]; -	} - -	/* Decrement channel usrs counter */ -	atomic_dec(&ch->usrs); -	/* If this file handle has initialize encoder device, reset it */ -	if (fh->initialized) -		ch->initialized = 0; - -	/* Close the priority */ -	v4l2_prio_close(&ch->prio, fh->prio); -	filep->private_data = NULL; -	fh->initialized = 0; -	mutex_unlock(&common->lock); -	kfree(fh); - -	return 0; -} -  /* functions implementing ioctls */  /**   * vpif_querycap() - QUERYCAP handler @@ -829,7 +586,7 @@ static int vpif_querycap(struct file *file, void  *priv,  	cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;  	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; -	snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); +	strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));  	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",  		 dev_name(vpif_dev));  	strlcpy(cap->card, config->card_name, sizeof(cap->card)); @@ -840,24 +597,22 @@ static int vpif_querycap(struct file *file, void  *priv,  static int vpif_enum_fmt_vid_out(struct file *file, void  *priv,  					struct v4l2_fmtdesc *fmt)  { -	if (fmt->index != 0) { -		vpif_err("Invalid format index\n"); +	if (fmt->index != 0)  		return -EINVAL; -	}  	/* Fill in the information about format */  	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;  	strcpy(fmt->description, "YCbCr4:2:2 YC Planar");  	fmt->pixelformat = V4L2_PIX_FMT_YUV422P; - +	fmt->flags = 0;  	return 0;  }  static int vpif_g_fmt_vid_out(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	/* Check the validity of the buffer type */ @@ -870,192 +625,84 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv,  	return 0;  } -static int vpif_s_fmt_vid_out(struct file *file, void *priv, +static int vpif_try_fmt_vid_out(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct v4l2_pix_format *pixfmt; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	int ret = 0; - -	if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) -	    || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_dbg(1, debug, "Channel Busy\n"); -			return -EBUSY; -		} +	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; -		/* Check for the priority */ -		ret = v4l2_prio_check(&ch->prio, fh->prio); -		if (0 != ret) -			return ret; -		fh->initialized = 1; -	} +	/* +	 * to supress v4l-compliance warnings silently correct +	 * the pixelformat +	 */ +	if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) +		pixfmt->pixelformat = common->fmt.fmt.pix.pixelformat; -	if (common->started) { -		vpif_dbg(1, debug, "Streaming in progress\n"); -		return -EBUSY; -	} +	if (vpif_update_resolution(ch)) +		return -EINVAL; -	pixfmt = &fmt->fmt.pix; -	/* Check for valid field format */ -	ret = vpif_check_format(ch, pixfmt); -	if (ret) -		return ret; +	pixfmt->colorspace = common->fmt.fmt.pix.colorspace; +	pixfmt->field = common->fmt.fmt.pix.field; +	pixfmt->bytesperline = common->fmt.fmt.pix.width; +	pixfmt->width = common->fmt.fmt.pix.width; +	pixfmt->height = common->fmt.fmt.pix.height; +	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; +	pixfmt->priv = 0; -	/* store the pix format in the channel object */ -	common->fmt.fmt.pix = *pixfmt; -	/* store the format in the channel object */ -	common->fmt = *fmt;  	return 0;  } -static int vpif_try_fmt_vid_out(struct file *file, void *priv, +static int vpif_s_fmt_vid_out(struct file *file, void *priv,  				struct v4l2_format *fmt)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; -	int ret = 0; - -	ret = vpif_check_format(ch, pixfmt); -	if (ret) { -		*pixfmt = common->fmt.fmt.pix; -		pixfmt->sizeimage = pixfmt->width * pixfmt->height * 2; -	} - -	return ret; -} - -static int vpif_reqbufs(struct file *file, void *priv, -			struct v4l2_requestbuffers *reqbuf) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common; -	enum v4l2_field field; -	struct vb2_queue *q; -	u8 index = 0;  	int ret; -	/* This file handle has not initialized the channel, -	   It is not allowed to do settings */ -	if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) -	    || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { -		if (!fh->initialized) { -			vpif_err("Channel Busy\n"); -			return -EBUSY; -		} -	} - -	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != reqbuf->type) -		return -EINVAL; - -	index = VPIF_VIDEO_INDEX; - -	common = &ch->common[index]; - -	if (common->fmt.type != reqbuf->type || !vpif_dev) -		return -EINVAL; -	if (0 != common->io_usrs) +	if (vb2_is_busy(&common->buffer_queue))  		return -EBUSY; -	if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { -		if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY) -			field = V4L2_FIELD_INTERLACED; -		else -			field = common->fmt.fmt.pix.field; -	} else { -		field = V4L2_VBI_INTERLACED; -	} -	/* Initialize videobuf2 queue as per the buffer type */ -	common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); -	if (IS_ERR(common->alloc_ctx)) { -		vpif_err("Failed to get the context\n"); -		return PTR_ERR(common->alloc_ctx); -	} -	q = &common->buffer_queue; -	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -	q->io_modes = VB2_MMAP | VB2_USERPTR; -	q->drv_priv = fh; -	q->ops = &video_qops; -	q->mem_ops = &vb2_dma_contig_memops; -	q->buf_struct_size = sizeof(struct vpif_disp_buffer); -	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - -	ret = vb2_queue_init(q); -	if (ret) { -		vpif_err("vpif_display: vb2_queue_init() failed\n"); -		vb2_dma_contig_cleanup_ctx(common->alloc_ctx); +	ret = vpif_try_fmt_vid_out(file, priv, fmt); +	if (ret)  		return ret; -	} -	/* Set io allowed member of file handle to TRUE */ -	fh->io_allowed[index] = 1; -	/* Increment io usrs member of channel object to 1 */ -	common->io_usrs = 1; -	/* Store type of memory requested in channel object */ -	common->memory = reqbuf->memory; -	INIT_LIST_HEAD(&common->dma_queue); -	/* Allocate buffers */ -	return vb2_reqbufs(&common->buffer_queue, reqbuf); -} -static int vpif_querybuf(struct file *file, void *priv, -				struct v4l2_buffer *tbuf) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	if (common->fmt.type != tbuf->type) -		return -EINVAL; +	/* store the pix format in the channel object */ +	common->fmt.fmt.pix = *pixfmt; -	return vb2_querybuf(&common->buffer_queue, tbuf); +	/* store the format in the channel object */ +	common->fmt = *fmt; +	return 0;  } -static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  { -	struct vpif_fh *fh = NULL; -	struct channel_obj *ch = NULL; -	struct common_obj *common = NULL; - -	if (!buf || !priv) -		return -EINVAL; - -	fh = priv; -	ch = fh->channel; -	if (!ch) -		return -EINVAL; +	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; +	struct vpif_display_chan_config *chan_cfg; +	struct v4l2_output output; +	int ret; -	common = &(ch->common[VPIF_VIDEO_INDEX]); -	if (common->fmt.type != buf->type) -		return -EINVAL; +	if (config->chan_config[ch->channel_id].outputs == NULL) +		return -ENODATA; -	if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { -		vpif_err("fh->io_allowed\n"); -		return -EACCES; -	} +	chan_cfg = &config->chan_config[ch->channel_id]; +	output = chan_cfg->outputs[ch->output_idx].output; +	if (output.capabilities != V4L2_OUT_CAP_STD) +		return -ENODATA; -	return vb2_qbuf(&common->buffer_queue, buf); -} +	if (vb2_is_busy(&common->buffer_queue)) +		return -EBUSY; -static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	int ret = 0;  	if (!(std_id & VPIF_V4L2_STD))  		return -EINVAL; -	if (common->started) { -		vpif_err("streaming in progress\n"); -		return -EBUSY; -	} -  	/* Call encoder subdevice function to set the standard */  	ch->video.stdid = std_id;  	memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); @@ -1063,16 +710,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  	if (vpif_update_resolution(ch))  		return -EINVAL; -	if ((ch->vpifparams.std_info.width * -		ch->vpifparams.std_info.height * 2) > -		config_params.channel_bufsize[ch->channel_id]) { -		vpif_err("invalid std for this size\n"); -		return -EINVAL; -	} -  	common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width; -	/* Configure the default format information */ -	vpif_config_format(ch);  	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,  						s_std_output, std_id); @@ -1081,7 +719,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  		return ret;  	} -	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core, +	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,  							s_std, std_id);  	if (ret < 0)  		vpif_err("Failed to set standard for sub devices\n"); @@ -1090,132 +728,21 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)  static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; - -	*std = ch->video.stdid; -	return 0; -} - -static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - -	return vb2_dqbuf(&common->buffer_queue, p, -					(file->f_flags & O_NONBLOCK)); -} - -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]; -	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 vb2_streamon to start streaming in videobuf2 */ -	ret = vb2_streamon(&common->buffer_queue, buftype); -	if (ret < 0) { -		vpif_err("vb2_streamon\n"); -		return ret; -	} - -	return ret; -} - -static int vpif_streamoff(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 vpif_display_config *vpif_config_data = -					vpif_dev->platform_data; - -	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 (!common->started) { -		vpif_err("channel->started\n"); -		return -EINVAL; -	} - -	if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { -		/* disable channel */ -		if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { -			if (vpif_config_data-> -				chan_config[VPIF_CHANNEL2_VIDEO].clip_en) -				channel2_clipping_enable(0); -			enable_channel2(0); -			channel2_intr_enable(0); -		} -		if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || -					(2 == common->started)) { -			if (vpif_config_data-> -				chan_config[VPIF_CHANNEL3_VIDEO].clip_en) -				channel3_clipping_enable(0); -			enable_channel3(0); -			channel3_intr_enable(0); -		} -	} - -	common->started = 0; -	return vb2_streamoff(&common->buffer_queue, buftype); -} +	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_display_chan_config *chan_cfg; +	struct v4l2_output output; -static int vpif_cropcap(struct file *file, void *priv, -			struct v4l2_cropcap *crop) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; -	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; -	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != crop->type) -		return -EINVAL; +	if (config->chan_config[ch->channel_id].outputs == NULL) +		return -ENODATA; -	crop->bounds.left = crop->bounds.top = 0; -	crop->defrect.left = crop->defrect.top = 0; -	crop->defrect.height = crop->bounds.height = common->height; -	crop->defrect.width = crop->bounds.width = common->width; +	chan_cfg = &config->chan_config[ch->channel_id]; +	output = chan_cfg->outputs[ch->output_idx].output; +	if (output.capabilities != V4L2_OUT_CAP_STD) +		return -ENODATA; +	*std = ch->video.stdid;  	return 0;  } @@ -1224,9 +751,9 @@ static int vpif_enum_output(struct file *file, void *fh,  {  	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct vpif_display_chan_config *chan_cfg; -	struct vpif_fh *vpif_handler = fh; -	struct channel_obj *ch = vpif_handler->channel;  	chan_cfg = &config->chan_config[ch->channel_id];  	if (output->index >= chan_cfg->output_count) { @@ -1320,52 +847,32 @@ static int vpif_set_output(struct vpif_display_config *vpif_cfg,  static int vpif_s_output(struct file *file, void *priv, unsigned int i)  {  	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct vpif_display_chan_config *chan_cfg; -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel;  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; +	if (vb2_is_busy(&common->buffer_queue)) +		return -EBUSY; +  	chan_cfg = &config->chan_config[ch->channel_id];  	if (i >= chan_cfg->output_count)  		return -EINVAL; -	if (common->started) { -		vpif_err("Streaming in progress\n"); -		return -EBUSY; -	} -  	return vpif_set_output(config, ch, i);  }  static int vpif_g_output(struct file *file, void *priv, unsigned int *i)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	*i = ch->output_idx;  	return 0;  } -static int vpif_g_priority(struct file *file, void *priv, enum v4l2_priority *p) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; - -	*p = v4l2_prio_max(&ch->prio); - -	return 0; -} - -static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) -{ -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; - -	return v4l2_prio_change(&ch->prio, &fh->prio, p); -} -  /**   * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler   * @file: file ptr @@ -1376,11 +883,24 @@ static int  vpif_enum_dv_timings(struct file *file, void *priv,  		     struct v4l2_enum_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_display_chan_config *chan_cfg; +	struct v4l2_output output;  	int ret; -	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); +	if (config->chan_config[ch->channel_id].outputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	output = chan_cfg->outputs[ch->output_idx].output; +	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) +		return -ENODATA; + +	timings->pad = 0; + +	ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);  	if (ret == -ENOIOCTLCMD || ret == -ENODEV)  		return -EINVAL;  	return ret; @@ -1395,14 +915,29 @@ vpif_enum_dv_timings(struct file *file, void *priv,  static int vpif_s_dv_timings(struct file *file, void *priv,  		struct v4l2_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev);  	struct vpif_params *vpifparams = &ch->vpifparams; +	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];  	struct vpif_channel_config_params *std_info = &vpifparams->std_info;  	struct video_obj *vid_ch = &ch->video;  	struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; +	struct vpif_display_chan_config *chan_cfg; +	struct v4l2_output output;  	int ret; +	if (config->chan_config[ch->channel_id].outputs == NULL) +		return -ENODATA; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	output = chan_cfg->outputs[ch->output_idx].output; +	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) +		return -ENODATA; + +	if (vb2_is_busy(&common->buffer_queue)) +		return -EBUSY; +  	if (timings->type != V4L2_DV_BT_656_1120) {  		vpif_dbg(2, debug, "Timing type not defined\n");  		return -EINVAL; @@ -1484,13 +1019,27 @@ static int vpif_s_dv_timings(struct file *file, void *priv,  static int vpif_g_dv_timings(struct file *file, void *priv,  		struct v4l2_dv_timings *timings)  { -	struct vpif_fh *fh = priv; -	struct channel_obj *ch = fh->channel; +	struct vpif_display_config *config = vpif_dev->platform_data; +	struct video_device *vdev = video_devdata(file); +	struct channel_obj *ch = video_get_drvdata(vdev); +	struct vpif_display_chan_config *chan_cfg;  	struct video_obj *vid_ch = &ch->video; +	struct v4l2_output output; + +	if (config->chan_config[ch->channel_id].outputs == NULL) +		goto error; + +	chan_cfg = &config->chan_config[ch->channel_id]; +	output = chan_cfg->outputs[ch->output_idx].output; + +	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) +		goto error;  	*timings = vid_ch->dv_timings;  	return 0; +error: +	return -ENODATA;  }  /* @@ -1510,83 +1059,49 @@ static int vpif_log_status(struct file *filep, void *priv)  /* vpif display ioctl operations */  static const struct v4l2_ioctl_ops vpif_ioctl_ops = { -	.vidioc_querycap        	= vpif_querycap, -	.vidioc_g_priority		= vpif_g_priority, -	.vidioc_s_priority		= vpif_s_priority, +	.vidioc_querycap		= vpif_querycap,  	.vidioc_enum_fmt_vid_out	= vpif_enum_fmt_vid_out, -	.vidioc_g_fmt_vid_out  		= vpif_g_fmt_vid_out, -	.vidioc_s_fmt_vid_out   	= vpif_s_fmt_vid_out, -	.vidioc_try_fmt_vid_out 	= vpif_try_fmt_vid_out, -	.vidioc_reqbufs         	= vpif_reqbufs, -	.vidioc_querybuf        	= vpif_querybuf, -	.vidioc_qbuf            	= vpif_qbuf, -	.vidioc_dqbuf           	= vpif_dqbuf, -	.vidioc_streamon        	= vpif_streamon, -	.vidioc_streamoff       	= vpif_streamoff, -	.vidioc_s_std           	= vpif_s_std, +	.vidioc_g_fmt_vid_out		= vpif_g_fmt_vid_out, +	.vidioc_s_fmt_vid_out		= vpif_s_fmt_vid_out, +	.vidioc_try_fmt_vid_out		= vpif_try_fmt_vid_out, + +	.vidioc_reqbufs			= vb2_ioctl_reqbufs, +	.vidioc_create_bufs		= vb2_ioctl_create_bufs, +	.vidioc_querybuf		= vb2_ioctl_querybuf, +	.vidioc_qbuf			= vb2_ioctl_qbuf, +	.vidioc_dqbuf			= vb2_ioctl_dqbuf, +	.vidioc_expbuf			= vb2_ioctl_expbuf, +	.vidioc_streamon		= vb2_ioctl_streamon, +	.vidioc_streamoff		= vb2_ioctl_streamoff, + +	.vidioc_s_std			= vpif_s_std,  	.vidioc_g_std			= vpif_g_std, +  	.vidioc_enum_output		= vpif_enum_output,  	.vidioc_s_output		= vpif_s_output,  	.vidioc_g_output		= vpif_g_output, -	.vidioc_cropcap         	= vpif_cropcap, -	.vidioc_enum_dv_timings         = vpif_enum_dv_timings, -	.vidioc_s_dv_timings            = vpif_s_dv_timings, -	.vidioc_g_dv_timings            = vpif_g_dv_timings, + +	.vidioc_enum_dv_timings		= vpif_enum_dv_timings, +	.vidioc_s_dv_timings		= vpif_s_dv_timings, +	.vidioc_g_dv_timings		= vpif_g_dv_timings, +  	.vidioc_log_status		= vpif_log_status,  };  static const struct v4l2_file_operations vpif_fops = {  	.owner		= THIS_MODULE, -	.open		= vpif_open, -	.release	= vpif_release, +	.open		= v4l2_fh_open, +	.release	= vb2_fop_release,  	.unlocked_ioctl	= video_ioctl2, -	.mmap		= vpif_mmap, -	.poll		= vpif_poll -}; - -static struct video_device vpif_video_template = { -	.name		= "vpif", -	.fops		= &vpif_fops, -	.ioctl_ops	= &vpif_ioctl_ops, +	.mmap		= vb2_fop_mmap, +	.poll		= vb2_fop_poll  };  /*Configure the channels, buffer sizei, request irq */  static int initialize_vpif(void)  {  	int free_channel_objects_index; -	int free_buffer_channel_index; -	int free_buffer_index; -	int err = 0, i, j; - -	/* Default number of buffers should be 3 */ -	if ((ch2_numbuffers > 0) && -	    (ch2_numbuffers < config_params.min_numbuffers)) -		ch2_numbuffers = config_params.min_numbuffers; -	if ((ch3_numbuffers > 0) && -	    (ch3_numbuffers < config_params.min_numbuffers)) -		ch3_numbuffers = config_params.min_numbuffers; - -	/* Set buffer size to min buffers size if invalid buffer size is -	 * given */ -	if (ch2_bufsize < config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]) -		ch2_bufsize = -		    config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]; -	if (ch3_bufsize < config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]) -		ch3_bufsize = -		    config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]; - -	config_params.numbuffers[VPIF_CHANNEL2_VIDEO] = ch2_numbuffers; - -	if (ch2_numbuffers) { -		config_params.channel_bufsize[VPIF_CHANNEL2_VIDEO] = -							ch2_bufsize; -	} -	config_params.numbuffers[VPIF_CHANNEL3_VIDEO] = ch3_numbuffers; - -	if (ch3_numbuffers) { -		config_params.channel_bufsize[VPIF_CHANNEL3_VIDEO] = -							ch3_bufsize; -	} +	int err, i, j;  	/* Allocate memory for six channel objects */  	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { @@ -1600,10 +1115,6 @@ static int initialize_vpif(void)  		}  	} -	free_channel_objects_index = VPIF_DISPLAY_MAX_DEVICES; -	free_buffer_channel_index = VPIF_DISPLAY_NUM_CHANNELS; -	free_buffer_index = config_params.numbuffers[i - 1]; -  	return 0;  vpif_init_free_channel_objects: @@ -1632,21 +1143,18 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier,  static int vpif_probe_complete(void)  {  	struct common_obj *common; +	struct video_device *vdev;  	struct channel_obj *ch; +	struct vb2_queue *q;  	int j, err, k;  	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {  		ch = vpif_obj.dev[j];  		/* Initialize field of the channel objects */ -		atomic_set(&ch->usrs, 0);  		for (k = 0; k < VPIF_NUMOBJECTS; k++) { -			ch->common[k].numbuffers = 0;  			common = &ch->common[k]; -			common->io_usrs = 0; -			common->started = 0;  			spin_lock_init(&common->irqlock);  			mutex_init(&common->lock); -			common->numbuffers = 0;  			common->set_addr = NULL;  			common->ytop_off = 0;  			common->ybtm_off = 0; @@ -1655,38 +1163,71 @@ static int vpif_probe_complete(void)  			common->cur_frm = NULL;  			common->next_frm = NULL;  			memset(&common->fmt, 0, sizeof(common->fmt)); -			common->numbuffers = config_params.numbuffers[k];  		}  		ch->initialized = 0;  		if (vpif_obj.config->subdev_count)  			ch->sd = vpif_obj.sd[0];  		ch->channel_id = j; -		if (j < 2) -			ch->common[VPIF_VIDEO_INDEX].numbuffers = -			    config_params.numbuffers[ch->channel_id]; -		else -			ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;  		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); -		/* Initialize prio member of channel object */ -		v4l2_prio_init(&ch->prio);  		ch->common[VPIF_VIDEO_INDEX].fmt.type =  						V4L2_BUF_TYPE_VIDEO_OUTPUT; -		ch->video_dev->lock = &common->lock; -		video_set_drvdata(ch->video_dev, ch);  		/* select output 0 */  		err = vpif_set_output(vpif_obj.config, ch, 0);  		if (err)  			goto probe_out; +		/* set initial format */ +		ch->video.stdid = V4L2_STD_525_60; +		memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); +		vpif_update_resolution(ch); + +		/* Initialize vb2 queue */ +		q = &common->buffer_queue; +		q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; +		q->drv_priv = ch; +		q->ops = &video_qops; +		q->mem_ops = &vb2_dma_contig_memops; +		q->buf_struct_size = sizeof(struct vpif_disp_buffer); +		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +		q->min_buffers_needed = 1; +		q->lock = &common->lock; +		err = vb2_queue_init(q); +		if (err) { +			vpif_err("vpif_display: vb2_queue_init() failed\n"); +			goto probe_out; +		} + +		common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); +		if (IS_ERR(common->alloc_ctx)) { +			vpif_err("Failed to get the context\n"); +			err = PTR_ERR(common->alloc_ctx); +			goto probe_out; +		} + +		INIT_LIST_HEAD(&common->dma_queue); +  		/* register video device */  		vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",  			 (int)ch, (int)&ch->video_dev); -		err = video_register_device(ch->video_dev, -					  VFL_TYPE_GRABBER, (j ? 3 : 2)); +		/* Initialize the video_device structure */ +		vdev = ch->video_dev; +		strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); +		vdev->release = video_device_release; +		vdev->fops = &vpif_fops; +		vdev->ioctl_ops = &vpif_ioctl_ops; +		vdev->v4l2_dev = &vpif_obj.v4l2_dev; +		vdev->vfl_dir = VFL_DIR_TX; +		vdev->queue = q; +		vdev->lock = &common->lock; +		set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); +		video_set_drvdata(ch->video_dev, ch); +		err = video_register_device(vdev, VFL_TYPE_GRABBER, +					    (j ? 3 : 2));  		if (err < 0)  			goto probe_out;  	} @@ -1696,6 +1237,8 @@ static int vpif_probe_complete(void)  probe_out:  	for (k = 0; k < j; k++) {  		ch = vpif_obj.dev[k]; +		common = &ch->common[k]; +		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);  		video_unregister_device(ch->video_dev);  		video_device_release(ch->video_dev);  		ch->video_dev = NULL; @@ -1722,7 +1265,6 @@ static __init int vpif_probe(struct platform_device *pdev)  	struct video_device *vfd;  	struct resource *res;  	int subdev_count; -	size_t size;  	vpif_dev = &pdev->dev;  	err = initialize_vpif(); @@ -1740,7 +1282,7 @@ static __init int vpif_probe(struct platform_device *pdev)  	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {  		err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, -					IRQF_SHARED, "VPIF_Display", +					IRQF_SHARED, VPIF_DRIVER_NAME,  					(void *)(&vpif_obj.dev[res_idx]->  					channel_id));  		if (err) { @@ -1766,36 +1308,10 @@ static __init int vpif_probe(struct platform_device *pdev)  			goto vpif_unregister;  		} -		/* Initialize field of video device */ -		*vfd = vpif_video_template; -		vfd->v4l2_dev = &vpif_obj.v4l2_dev; -		vfd->release = video_device_release; -		vfd->vfl_dir = VFL_DIR_TX; -		snprintf(vfd->name, sizeof(vfd->name), -			 "VPIF_Display_DRIVER_V%s", -			 VPIF_DISPLAY_VERSION); -  		/* Set video_dev to the video device */  		ch->video_dev = vfd;  	} -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (res) { -		size = resource_size(res); -		/* The resources are divided into two equal memory and when -		 * we have HD output we can add them together -		 */ -		for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { -			ch = vpif_obj.dev[j]; -			ch->channel_id = j; - -			/* only enabled if second resource exists */ -			config_params.video_limit[ch->channel_id] = 0; -			if (size) -				config_params.video_limit[ch->channel_id] = -									size/2; -		} -	}  	vpif_obj.config = pdev->dev.platform_data;  	subdev_count = vpif_obj.config->subdev_count;  	subdevdata = vpif_obj.config->subdevinfo; @@ -1861,6 +1377,7 @@ vpif_unregister:   */  static int vpif_remove(struct platform_device *device)  { +	struct common_obj *common;  	struct channel_obj *ch;  	int i; @@ -1871,6 +1388,8 @@ static int vpif_remove(struct platform_device *device)  	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i]; +		common = &ch->common[i]; +		vb2_dma_contig_cleanup_ctx(common->alloc_ctx);  		/* Unregister video device */  		video_unregister_device(ch->video_dev); @@ -1881,7 +1400,7 @@ static int vpif_remove(struct platform_device *device)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int vpif_suspend(struct device *dev)  {  	struct common_obj *common; @@ -1892,18 +1411,20 @@ static int vpif_suspend(struct device *dev)  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i];  		common = &ch->common[VPIF_VIDEO_INDEX]; + +		if (!vb2_is_streaming(&common->buffer_queue)) +			continue; +  		mutex_lock(&common->lock); -		if (atomic_read(&ch->usrs) && common->io_usrs) { -			/* Disable channel */ -			if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { -				enable_channel2(0); -				channel2_intr_enable(0); -			} -			if (ch->channel_id == VPIF_CHANNEL3_VIDEO || -					common->started == 2) { -				enable_channel3(0); -				channel3_intr_enable(0); -			} +		/* Disable channel */ +		if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { +			enable_channel2(0); +			channel2_intr_enable(0); +		} +		if (ch->channel_id == VPIF_CHANNEL3_VIDEO || +			ycmux_mode == 2) { +			enable_channel3(0); +			channel3_intr_enable(0);  		}  		mutex_unlock(&common->lock);  	} @@ -1922,18 +1443,20 @@ static int vpif_resume(struct device *dev)  		/* Get the pointer to the channel object */  		ch = vpif_obj.dev[i];  		common = &ch->common[VPIF_VIDEO_INDEX]; + +		if (!vb2_is_streaming(&common->buffer_queue)) +			continue; +  		mutex_lock(&common->lock); -		if (atomic_read(&ch->usrs) && common->io_usrs) { -			/* Enable channel */ -			if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { -				enable_channel2(1); -				channel2_intr_enable(1); -			} -			if (ch->channel_id == VPIF_CHANNEL3_VIDEO || -					common->started == 2) { -				enable_channel3(1); -				channel3_intr_enable(1); -			} +		/* Enable channel */ +		if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { +			enable_channel2(1); +			channel2_intr_enable(1); +		} +		if (ch->channel_id == VPIF_CHANNEL3_VIDEO || +				ycmux_mode == 2) { +			enable_channel3(1); +			channel3_intr_enable(1);  		}  		mutex_unlock(&common->lock);  	} @@ -1941,21 +1464,15 @@ static int vpif_resume(struct device *dev)  	return 0;  } -static const struct dev_pm_ops vpif_pm = { -	.suspend        = vpif_suspend, -	.resume         = vpif_resume, -}; - -#define vpif_pm_ops (&vpif_pm) -#else -#define vpif_pm_ops NULL  #endif +static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); +  static __refdata struct platform_driver vpif_driver = {  	.driver	= { -			.name	= "vpif_display", +			.name	= VPIF_DRIVER_NAME,  			.owner	= THIS_MODULE, -			.pm	= vpif_pm_ops, +			.pm	= &vpif_pm_ops,  	},  	.probe	= vpif_probe,  	.remove	= vpif_remove, diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index 4d0485b99a8..7b21a760767 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -13,8 +13,8 @@   * GNU General Public License for more details.   */ -#ifndef DAVINCIHD_DISPLAY_H -#define DAVINCIHD_DISPLAY_H +#ifndef VPIF_DISPLAY_H +#define VPIF_DISPLAY_H  /* Header files */  #include <media/videobuf2-dma-contig.h> @@ -67,17 +67,10 @@ struct vpif_disp_buffer {  };  struct common_obj { -	/* Buffer specific parameters */ -	u8 *fbuffers[VIDEO_MAX_FRAME];		/* List of buffer pointers for -						 * storing frames */ -	u32 numbuffers;				/* number of buffers */  	struct vpif_disp_buffer *cur_frm;	/* Pointer pointing to current  						 * vb2_buffer */  	struct vpif_disp_buffer *next_frm;	/* Pointer pointing to next  						 * vb2_buffer */ -	enum v4l2_memory memory;		/* This field keeps track of -						 * type of buffer exchange -						 * method user has selected */  	struct v4l2_format fmt;			/* Used to store the format */  	struct vb2_queue buffer_queue;		/* Buffer queue used in  						 * video-buf */ @@ -90,10 +83,6 @@ struct common_obj {  	/* channel specific parameters */  	struct mutex lock;			/* lock used to access this  						 * structure */ -	u32 io_usrs;				/* number of users performing -						 * IO */ -	u8 started;				/* Indicates whether streaming -						 * started */  	u32 ytop_off;				/* offset of Y top from the  						 * starting of the buffer */  	u32 ybtm_off;				/* offset of Y bottom from the @@ -103,7 +92,7 @@ struct common_obj {  	u32 cbtm_off;				/* offset of C bottom from the  						 * starting of the buffer */  	/* Function pointer to set the addresses */ -	void (*set_addr) (unsigned long, unsigned long, +	void (*set_addr)(unsigned long, unsigned long,  				unsigned long, unsigned long);  	u32 height;  	u32 width; @@ -113,10 +102,6 @@ struct channel_obj {  	/* V4l2 specific parameters */  	struct video_device *video_dev;	/* Identifies video device for  					 * this channel */ -	struct v4l2_prio_state prio;	/* Used to keep track of state of -					 * the priority */ -	atomic_t usrs;			/* number of open instances of -					 * the channel */  	u32 field_id;			/* Indicates id of the field  					 * which is being displayed */  	u8 initialized;			/* flag to indicate whether @@ -130,19 +115,6 @@ struct channel_obj {  	struct video_obj video;  }; -/* File handle structure */ -struct vpif_fh { -	struct channel_obj *channel;	/* pointer to channel object for -					 * opened device */ -	u8 io_allowed[VPIF_NUMOBJECTS];	/* Indicates whether this file handle -					 * is doing IO */ -	enum v4l2_priority prio;	/* Used to keep track priority of -					 * this instance */ -	u8 initialized;			/* Used to keep track of whether this -					 * file handle has initialized -					 * channel or not */ -}; -  /* vpif device structure */  struct vpif_device {  	struct v4l2_device v4l2_dev; @@ -152,12 +124,4 @@ struct vpif_device {  	struct vpif_display_config *config;  }; -struct vpif_config_params { -	u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; -	u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; -	u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS]; -	u32 video_limit[VPIF_DISPLAY_NUM_CHANNELS]; -	u8 min_numbuffers; -}; - -#endif				/* DAVINCIHD_DISPLAY_H */ +#endif				/* VPIF_DISPLAY_H */  | 
