brintos

brintos / linux-shallow public Read only

0
0
Text · 37.3 KiB · 76d8fa8 Raw
1405 lines · c
1/*2 * vpif-display - VPIF display driver3 * Display driver for TI DaVinci VPIF4 *5 * Copyright (C) 2009 Texas Instruments Incorporated - https://www.ti.com/6 * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com>7 *8 * This program is free software; you can redistribute it and/or9 * modify it under the terms of the GNU General Public License as10 * published by the Free Software Foundation version 2.11 *12 * This program is distributed .as is. WITHOUT ANY WARRANTY of any13 * kind, whether express or implied; without even the implied warranty14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the15 * GNU General Public License for more details.16 */17 18#include <linux/interrupt.h>19#include <linux/module.h>20#include <linux/platform_device.h>21#include <linux/slab.h>22 23#include <media/v4l2-ioctl.h>24 25#include "vpif.h"26#include "vpif_display.h"27 28MODULE_DESCRIPTION("TI DaVinci VPIF Display driver");29MODULE_LICENSE("GPL");30MODULE_VERSION(VPIF_DISPLAY_VERSION);31 32#define VPIF_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50)33 34#define vpif_err(fmt, arg...)	v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)35#define vpif_dbg(level, debug, fmt, arg...)	\36		v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)37 38static int debug = 1;39 40module_param(debug, int, 0644);41 42MODULE_PARM_DESC(debug, "Debug level 0-1");43 44#define VPIF_DRIVER_NAME	"vpif_display"45MODULE_ALIAS("platform:" VPIF_DRIVER_NAME);46 47/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */48static int ycmux_mode;49 50static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} };51 52static struct vpif_device vpif_obj = { {NULL} };53static struct device *vpif_dev;54static void vpif_calculate_offsets(struct channel_obj *ch);55static void vpif_config_addr(struct channel_obj *ch, int muxmode);56 57static inline58struct vpif_disp_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb)59{60	return container_of(vb, struct vpif_disp_buffer, vb);61}62 63/**64 * vpif_buffer_prepare :  callback function for buffer prepare65 * @vb: ptr to vb2_buffer66 *67 * This is the callback function for buffer prepare when vb2_qbuf()68 * function is called. The buffer is prepared and user space virtual address69 * or user address is converted into  physical address70 */71static int vpif_buffer_prepare(struct vb2_buffer *vb)72{73	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);74	struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);75	struct common_obj *common;76 77	common = &ch->common[VPIF_VIDEO_INDEX];78 79	vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage);80	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))81		return -EINVAL;82 83	vbuf->field = common->fmt.fmt.pix.field;84 85	if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {86		unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0);87 88		if (!ISALIGNED(addr + common->ytop_off) ||89			!ISALIGNED(addr + common->ybtm_off) ||90			!ISALIGNED(addr + common->ctop_off) ||91			!ISALIGNED(addr + common->cbtm_off)) {92			vpif_err("buffer offset not aligned to 8 bytes\n");93			return -EINVAL;94		}95	}96 97	return 0;98}99 100/**101 * vpif_buffer_queue_setup : Callback function for buffer setup.102 * @vq: vb2_queue ptr103 * @nbuffers: ptr to number of buffers requested by application104 * @nplanes: contains number of distinct video planes needed to hold a frame105 * @sizes: contains the size (in bytes) of each plane.106 * @alloc_devs: ptr to allocation context107 *108 * This callback function is called when reqbuf() is called to adjust109 * the buffer count and buffer size110 */111static int vpif_buffer_queue_setup(struct vb2_queue *vq,112				unsigned int *nbuffers, unsigned int *nplanes,113				unsigned int sizes[], struct device *alloc_devs[])114{115	struct channel_obj *ch = vb2_get_drv_priv(vq);116	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];117	unsigned size = common->fmt.fmt.pix.sizeimage;118	unsigned int q_num_bufs = vb2_get_num_buffers(vq);119 120	if (*nplanes) {121		if (sizes[0] < size)122			return -EINVAL;123		size = sizes[0];124	}125 126	if (q_num_bufs + *nbuffers < 3)127		*nbuffers = 3 - q_num_bufs;128 129	*nplanes = 1;130	sizes[0] = size;131 132	/* Calculate the offset for Y and C data  in the buffer */133	vpif_calculate_offsets(ch);134 135	return 0;136}137 138/**139 * vpif_buffer_queue : Callback function to add buffer to DMA queue140 * @vb: ptr to vb2_buffer141 *142 * This callback function queues the buffer to DMA engine143 */144static void vpif_buffer_queue(struct vb2_buffer *vb)145{146	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);147	struct vpif_disp_buffer *buf = to_vpif_buffer(vbuf);148	struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);149	struct common_obj *common;150	unsigned long flags;151 152	common = &ch->common[VPIF_VIDEO_INDEX];153 154	/* add the buffer to the DMA queue */155	spin_lock_irqsave(&common->irqlock, flags);156	list_add_tail(&buf->list, &common->dma_queue);157	spin_unlock_irqrestore(&common->irqlock, flags);158}159 160/**161 * vpif_start_streaming : Starts the DMA engine for streaming162 * @vq: ptr to vb2_buffer163 * @count: number of buffers164 */165static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)166{167	struct vpif_display_config *vpif_config_data =168					vpif_dev->platform_data;169	struct channel_obj *ch = vb2_get_drv_priv(vq);170	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];171	struct vpif_params *vpif = &ch->vpifparams;172	struct vpif_disp_buffer *buf, *tmp;173	unsigned long addr, flags;174	int ret;175 176	spin_lock_irqsave(&common->irqlock, flags);177 178	/* Initialize field_id */179	ch->field_id = 0;180 181	/* clock settings */182	if (vpif_config_data->set_clock) {183		ret = vpif_config_data->set_clock(ch->vpifparams.std_info.184		ycmux_mode, ch->vpifparams.std_info.hd_sd);185		if (ret < 0) {186			vpif_err("can't set clock\n");187			goto err;188		}189	}190 191	/* set the parameters and addresses */192	ret = vpif_set_video_params(vpif, ch->channel_id + 2);193	if (ret < 0)194		goto err;195 196	ycmux_mode = ret;197	vpif_config_addr(ch, ret);198	/* Get the next frame from the buffer queue */199	common->next_frm = common->cur_frm =200			    list_entry(common->dma_queue.next,201				       struct vpif_disp_buffer, list);202 203	list_del(&common->cur_frm->list);204	spin_unlock_irqrestore(&common->irqlock, flags);205 206	addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb.vb2_buf, 0);207	common->set_addr((addr + common->ytop_off),208			    (addr + common->ybtm_off),209			    (addr + common->ctop_off),210			    (addr + common->cbtm_off));211 212	/*213	 * Set interrupt for both the fields in VPIF214	 * Register enable channel in VPIF register215	 */216	channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;217	if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {218		channel2_intr_assert();219		channel2_intr_enable(1);220		enable_channel2(1);221		if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)222			channel2_clipping_enable(1);223	}224 225	if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) {226		channel3_intr_assert();227		channel3_intr_enable(1);228		enable_channel3(1);229		if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)230			channel3_clipping_enable(1);231	}232 233	return 0;234 235err:236	list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {237		list_del(&buf->list);238		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);239	}240	spin_unlock_irqrestore(&common->irqlock, flags);241 242	return ret;243}244 245/**246 * vpif_stop_streaming : Stop the DMA engine247 * @vq: ptr to vb2_queue248 *249 * This callback stops the DMA engine and any remaining buffers250 * in the DMA queue are released.251 */252static void vpif_stop_streaming(struct vb2_queue *vq)253{254	struct channel_obj *ch = vb2_get_drv_priv(vq);255	struct common_obj *common;256	unsigned long flags;257 258	common = &ch->common[VPIF_VIDEO_INDEX];259 260	/* Disable channel */261	if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {262		enable_channel2(0);263		channel2_intr_enable(0);264	}265	if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) {266		enable_channel3(0);267		channel3_intr_enable(0);268	}269 270	/* release all active buffers */271	spin_lock_irqsave(&common->irqlock, flags);272	if (common->cur_frm == common->next_frm) {273		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,274				VB2_BUF_STATE_ERROR);275	} else {276		if (common->cur_frm)277			vb2_buffer_done(&common->cur_frm->vb.vb2_buf,278					VB2_BUF_STATE_ERROR);279		if (common->next_frm)280			vb2_buffer_done(&common->next_frm->vb.vb2_buf,281					VB2_BUF_STATE_ERROR);282	}283 284	while (!list_empty(&common->dma_queue)) {285		common->next_frm = list_entry(common->dma_queue.next,286						struct vpif_disp_buffer, list);287		list_del(&common->next_frm->list);288		vb2_buffer_done(&common->next_frm->vb.vb2_buf,289				VB2_BUF_STATE_ERROR);290	}291	spin_unlock_irqrestore(&common->irqlock, flags);292}293 294static const struct vb2_ops video_qops = {295	.queue_setup		= vpif_buffer_queue_setup,296	.wait_prepare		= vb2_ops_wait_prepare,297	.wait_finish		= vb2_ops_wait_finish,298	.buf_prepare		= vpif_buffer_prepare,299	.start_streaming	= vpif_start_streaming,300	.stop_streaming		= vpif_stop_streaming,301	.buf_queue		= vpif_buffer_queue,302};303 304static void process_progressive_mode(struct common_obj *common)305{306	unsigned long addr;307 308	spin_lock(&common->irqlock);309	/* Get the next buffer from buffer queue */310	common->next_frm = list_entry(common->dma_queue.next,311				struct vpif_disp_buffer, list);312	/* Remove that buffer from the buffer queue */313	list_del(&common->next_frm->list);314	spin_unlock(&common->irqlock);315 316	/* Set top and bottom field addrs in VPIF registers */317	addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb.vb2_buf, 0);318	common->set_addr(addr + common->ytop_off,319				 addr + common->ybtm_off,320				 addr + common->ctop_off,321				 addr + common->cbtm_off);322}323 324static void process_interlaced_mode(int fid, struct common_obj *common)325{326	/* device field id and local field id are in sync */327	/* If this is even field */328	if (0 == fid) {329		if (common->cur_frm == common->next_frm)330			return;331 332		/* one frame is displayed If next frame is333		 *  available, release cur_frm and move on */334		/* Copy frame display time */335		common->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();336		/* Change status of the cur_frm */337		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,338					VB2_BUF_STATE_DONE);339		/* Make cur_frm pointing to next_frm */340		common->cur_frm = common->next_frm;341 342	} else if (1 == fid) {	/* odd field */343		spin_lock(&common->irqlock);344		if (list_empty(&common->dma_queue)345		    || (common->cur_frm != common->next_frm)) {346			spin_unlock(&common->irqlock);347			return;348		}349		spin_unlock(&common->irqlock);350		/* one field is displayed configure the next351		 * frame if it is available else hold on current352		 * frame */353		/* Get next from the buffer queue */354		process_progressive_mode(common);355	}356}357 358/*359 * vpif_channel_isr: It changes status of the displayed buffer, takes next360 * buffer from the queue and sets its address in VPIF registers361 */362static irqreturn_t vpif_channel_isr(int irq, void *dev_id)363{364	struct vpif_device *dev = &vpif_obj;365	struct channel_obj *ch;366	struct common_obj *common;367	int fid = -1, i;368	int channel_id;369 370	channel_id = *(int *)(dev_id);371	if (!vpif_intr_status(channel_id + 2))372		return IRQ_NONE;373 374	ch = dev->dev[channel_id];375	for (i = 0; i < VPIF_NUMOBJECTS; i++) {376		common = &ch->common[i];377		/* If streaming is started in this channel */378 379		if (1 == ch->vpifparams.std_info.frm_fmt) {380			spin_lock(&common->irqlock);381			if (list_empty(&common->dma_queue)) {382				spin_unlock(&common->irqlock);383				continue;384			}385			spin_unlock(&common->irqlock);386 387			/* Progressive mode */388			if (!channel_first_int[i][channel_id]) {389				/* Mark status of the cur_frm to390				 * done and unlock semaphore on it */391				common->cur_frm->vb.vb2_buf.timestamp =392						ktime_get_ns();393				vb2_buffer_done(&common->cur_frm->vb.vb2_buf,394						VB2_BUF_STATE_DONE);395				/* Make cur_frm pointing to next_frm */396				common->cur_frm = common->next_frm;397			}398 399			channel_first_int[i][channel_id] = 0;400			process_progressive_mode(common);401		} else {402			/* Interlaced mode */403			/* If it is first interrupt, ignore it */404 405			if (channel_first_int[i][channel_id]) {406				channel_first_int[i][channel_id] = 0;407				continue;408			}409 410			if (0 == i) {411				ch->field_id ^= 1;412				/* Get field id from VPIF registers */413				fid = vpif_channel_getfid(ch->channel_id + 2);414				/* If fid does not match with stored field id */415				if (fid != ch->field_id) {416					/* Make them in sync */417					if (0 == fid)418						ch->field_id = fid;419 420					return IRQ_HANDLED;421				}422			}423			process_interlaced_mode(fid, common);424		}425	}426 427	return IRQ_HANDLED;428}429 430static int vpif_update_std_info(struct channel_obj *ch)431{432	struct video_obj *vid_ch = &ch->video;433	struct vpif_params *vpifparams = &ch->vpifparams;434	struct vpif_channel_config_params *std_info = &vpifparams->std_info;435	const struct vpif_channel_config_params *config;436 437	int i;438 439	for (i = 0; i < vpif_ch_params_count; i++) {440		config = &vpif_ch_params[i];441		if (config->hd_sd == 0) {442			vpif_dbg(2, debug, "SD format\n");443			if (config->stdid & vid_ch->stdid) {444				memcpy(std_info, config, sizeof(*config));445				break;446			}447		}448	}449 450	if (i == vpif_ch_params_count) {451		vpif_dbg(1, debug, "Format not found\n");452		return -EINVAL;453	}454 455	return 0;456}457 458static int vpif_update_resolution(struct channel_obj *ch)459{460	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];461	struct video_obj *vid_ch = &ch->video;462	struct vpif_params *vpifparams = &ch->vpifparams;463	struct vpif_channel_config_params *std_info = &vpifparams->std_info;464 465	if (!vid_ch->stdid && !vid_ch->dv_timings.bt.height)466		return -EINVAL;467 468	if (vid_ch->stdid) {469		if (vpif_update_std_info(ch))470			return -EINVAL;471	}472 473	common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;474	common->fmt.fmt.pix.width = std_info->width;475	common->fmt.fmt.pix.height = std_info->height;476	vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n",477			common->fmt.fmt.pix.width, common->fmt.fmt.pix.height);478 479	/* Set height and width paramateres */480	common->height = std_info->height;481	common->width = std_info->width;482	common->fmt.fmt.pix.sizeimage = common->height * common->width * 2;483 484	if (vid_ch->stdid)485		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;486	else487		common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709;488 489	if (ch->vpifparams.std_info.frm_fmt)490		common->fmt.fmt.pix.field = V4L2_FIELD_NONE;491	else492		common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;493 494	return 0;495}496 497/*498 * vpif_calculate_offsets: This function calculates buffers offset for Y and C499 * in the top and bottom field500 */501static void vpif_calculate_offsets(struct channel_obj *ch)502{503	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];504	struct vpif_params *vpifparams = &ch->vpifparams;505	enum v4l2_field field = common->fmt.fmt.pix.field;506	struct video_obj *vid_ch = &ch->video;507	unsigned int hpitch, sizeimage;508 509	if (V4L2_FIELD_ANY == common->fmt.fmt.pix.field) {510		if (ch->vpifparams.std_info.frm_fmt)511			vid_ch->buf_field = V4L2_FIELD_NONE;512		else513			vid_ch->buf_field = V4L2_FIELD_INTERLACED;514	} else {515		vid_ch->buf_field = common->fmt.fmt.pix.field;516	}517 518	sizeimage = common->fmt.fmt.pix.sizeimage;519 520	hpitch = common->fmt.fmt.pix.bytesperline;521	if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||522	    (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {523		common->ytop_off = 0;524		common->ybtm_off = hpitch;525		common->ctop_off = sizeimage / 2;526		common->cbtm_off = sizeimage / 2 + hpitch;527	} else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) {528		common->ytop_off = 0;529		common->ybtm_off = sizeimage / 4;530		common->ctop_off = sizeimage / 2;531		common->cbtm_off = common->ctop_off + sizeimage / 4;532	} else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) {533		common->ybtm_off = 0;534		common->ytop_off = sizeimage / 4;535		common->cbtm_off = sizeimage / 2;536		common->ctop_off = common->cbtm_off + sizeimage / 4;537	}538 539	if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||540	    (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {541		vpifparams->video_params.storage_mode = 1;542	} else {543		vpifparams->video_params.storage_mode = 0;544	}545 546	if (ch->vpifparams.std_info.frm_fmt == 1) {547		vpifparams->video_params.hpitch =548		    common->fmt.fmt.pix.bytesperline;549	} else {550		if ((field == V4L2_FIELD_ANY) ||551			(field == V4L2_FIELD_INTERLACED))552			vpifparams->video_params.hpitch =553			    common->fmt.fmt.pix.bytesperline * 2;554		else555			vpifparams->video_params.hpitch =556			    common->fmt.fmt.pix.bytesperline;557	}558 559	ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid;560}561 562static void vpif_config_addr(struct channel_obj *ch, int muxmode)563{564	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];565 566	if (VPIF_CHANNEL3_VIDEO == ch->channel_id) {567		common->set_addr = ch3_set_video_buf_addr;568	} else {569		if (2 == muxmode)570			common->set_addr = ch2_set_video_buf_addr_yc_nmux;571		else572			common->set_addr = ch2_set_video_buf_addr;573	}574}575 576/* functions implementing ioctls */577/**578 * vpif_querycap() - QUERYCAP handler579 * @file: file ptr580 * @priv: file handle581 * @cap: ptr to v4l2_capability structure582 */583static int vpif_querycap(struct file *file, void  *priv,584				struct v4l2_capability *cap)585{586	struct vpif_display_config *config = vpif_dev->platform_data;587 588	strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver));589	strscpy(cap->card, config->card_name, sizeof(cap->card));590 591	return 0;592}593 594static int vpif_enum_fmt_vid_out(struct file *file, void  *priv,595					struct v4l2_fmtdesc *fmt)596{597	if (fmt->index != 0)598		return -EINVAL;599 600	/* Fill in the information about format */601	fmt->pixelformat = V4L2_PIX_FMT_YUV422P;602	return 0;603}604 605static int vpif_g_fmt_vid_out(struct file *file, void *priv,606				struct v4l2_format *fmt)607{608	struct video_device *vdev = video_devdata(file);609	struct channel_obj *ch = video_get_drvdata(vdev);610	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];611 612	/* Check the validity of the buffer type */613	if (common->fmt.type != fmt->type)614		return -EINVAL;615 616	if (vpif_update_resolution(ch))617		return -EINVAL;618	*fmt = common->fmt;619	return 0;620}621 622static int vpif_try_fmt_vid_out(struct file *file, void *priv,623				struct v4l2_format *fmt)624{625	struct video_device *vdev = video_devdata(file);626	struct channel_obj *ch = video_get_drvdata(vdev);627	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];628	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;629 630	/*631	 * to suppress v4l-compliance warnings silently correct632	 * the pixelformat633	 */634	if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P)635		pixfmt->pixelformat = common->fmt.fmt.pix.pixelformat;636 637	if (vpif_update_resolution(ch))638		return -EINVAL;639 640	pixfmt->colorspace = common->fmt.fmt.pix.colorspace;641	pixfmt->field = common->fmt.fmt.pix.field;642	pixfmt->bytesperline = common->fmt.fmt.pix.width;643	pixfmt->width = common->fmt.fmt.pix.width;644	pixfmt->height = common->fmt.fmt.pix.height;645	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;646 647	return 0;648}649 650static int vpif_s_fmt_vid_out(struct file *file, void *priv,651				struct v4l2_format *fmt)652{653	struct video_device *vdev = video_devdata(file);654	struct channel_obj *ch = video_get_drvdata(vdev);655	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];656	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;657	int ret;658 659	if (vb2_is_busy(&common->buffer_queue))660		return -EBUSY;661 662	ret = vpif_try_fmt_vid_out(file, priv, fmt);663	if (ret)664		return ret;665 666	/* store the pix format in the channel object */667	common->fmt.fmt.pix = *pixfmt;668 669	/* store the format in the channel object */670	common->fmt = *fmt;671	return 0;672}673 674static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)675{676	struct vpif_display_config *config = vpif_dev->platform_data;677	struct video_device *vdev = video_devdata(file);678	struct channel_obj *ch = video_get_drvdata(vdev);679	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];680	struct vpif_display_chan_config *chan_cfg;681	struct v4l2_output output;682	int ret;683 684	if (!config->chan_config[ch->channel_id].outputs)685		return -ENODATA;686 687	chan_cfg = &config->chan_config[ch->channel_id];688	output = chan_cfg->outputs[ch->output_idx].output;689	if (output.capabilities != V4L2_OUT_CAP_STD)690		return -ENODATA;691 692	if (vb2_is_busy(&common->buffer_queue))693		return -EBUSY;694 695 696	if (!(std_id & VPIF_V4L2_STD))697		return -EINVAL;698 699	/* Call encoder subdevice function to set the standard */700	ch->video.stdid = std_id;701	memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));702	/* Get the information about the standard */703	if (vpif_update_resolution(ch))704		return -EINVAL;705 706	common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width;707 708	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,709						s_std_output, std_id);710	if (ret < 0) {711		vpif_err("Failed to set output standard\n");712		return ret;713	}714 715	ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,716							s_std, std_id);717	if (ret < 0)718		vpif_err("Failed to set standard for sub devices\n");719	return ret;720}721 722static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)723{724	struct vpif_display_config *config = vpif_dev->platform_data;725	struct video_device *vdev = video_devdata(file);726	struct channel_obj *ch = video_get_drvdata(vdev);727	struct vpif_display_chan_config *chan_cfg;728	struct v4l2_output output;729 730	if (!config->chan_config[ch->channel_id].outputs)731		return -ENODATA;732 733	chan_cfg = &config->chan_config[ch->channel_id];734	output = chan_cfg->outputs[ch->output_idx].output;735	if (output.capabilities != V4L2_OUT_CAP_STD)736		return -ENODATA;737 738	*std = ch->video.stdid;739	return 0;740}741 742static int vpif_enum_output(struct file *file, void *fh,743				struct v4l2_output *output)744{745 746	struct vpif_display_config *config = vpif_dev->platform_data;747	struct video_device *vdev = video_devdata(file);748	struct channel_obj *ch = video_get_drvdata(vdev);749	struct vpif_display_chan_config *chan_cfg;750 751	chan_cfg = &config->chan_config[ch->channel_id];752	if (output->index >= chan_cfg->output_count) {753		vpif_dbg(1, debug, "Invalid output index\n");754		return -EINVAL;755	}756 757	*output = chan_cfg->outputs[output->index].output;758	return 0;759}760 761/**762 * vpif_output_to_subdev() - Maps output to sub device763 * @vpif_cfg: global config ptr764 * @chan_cfg: channel config ptr765 * @index: Given output index from application766 *767 * lookup the sub device information for a given output index.768 * we report all the output to application. output table also769 * has sub device name for the each output770 */771static int772vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,773		      struct vpif_display_chan_config *chan_cfg, int index)774{775	struct vpif_subdev_info *subdev_info;776	const char *subdev_name;777	int i;778 779	vpif_dbg(2, debug, "vpif_output_to_subdev\n");780 781	if (!chan_cfg->outputs)782		return -1;783 784	subdev_name = chan_cfg->outputs[index].subdev_name;785	if (!subdev_name)786		return -1;787 788	/* loop through the sub device list to get the sub device info */789	for (i = 0; i < vpif_cfg->subdev_count; i++) {790		subdev_info = &vpif_cfg->subdevinfo[i];791		if (!strcmp(subdev_info->name, subdev_name))792			return i;793	}794	return -1;795}796 797/**798 * vpif_set_output() - Select an output799 * @vpif_cfg: global config ptr800 * @ch: channel801 * @index: Given output index from application802 *803 * Select the given output.804 */805static int vpif_set_output(struct vpif_display_config *vpif_cfg,806		      struct channel_obj *ch, int index)807{808	struct vpif_display_chan_config *chan_cfg =809		&vpif_cfg->chan_config[ch->channel_id];810	struct v4l2_subdev *sd = NULL;811	u32 input = 0, output = 0;812	int sd_index;813	int ret;814 815	sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);816	if (sd_index >= 0)817		sd = vpif_obj.sd[sd_index];818 819	if (sd) {820		input = chan_cfg->outputs[index].input_route;821		output = chan_cfg->outputs[index].output_route;822		ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);823		if (ret < 0 && ret != -ENOIOCTLCMD) {824			vpif_err("Failed to set output\n");825			return ret;826		}827 828	}829	ch->output_idx = index;830	ch->sd = sd;831	if (chan_cfg->outputs)832		/* update tvnorms from the sub device output info */833		ch->video_dev.tvnorms = chan_cfg->outputs[index].output.std;834	return 0;835}836 837static int vpif_s_output(struct file *file, void *priv, unsigned int i)838{839	struct vpif_display_config *config = vpif_dev->platform_data;840	struct video_device *vdev = video_devdata(file);841	struct channel_obj *ch = video_get_drvdata(vdev);842	struct vpif_display_chan_config *chan_cfg;843	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];844 845	if (vb2_is_busy(&common->buffer_queue))846		return -EBUSY;847 848	chan_cfg = &config->chan_config[ch->channel_id];849 850	if (i >= chan_cfg->output_count)851		return -EINVAL;852 853	return vpif_set_output(config, ch, i);854}855 856static int vpif_g_output(struct file *file, void *priv, unsigned int *i)857{858	struct video_device *vdev = video_devdata(file);859	struct channel_obj *ch = video_get_drvdata(vdev);860 861	*i = ch->output_idx;862 863	return 0;864}865 866/**867 * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler868 * @file: file ptr869 * @priv: file handle870 * @timings: input timings871 */872static int873vpif_enum_dv_timings(struct file *file, void *priv,874		     struct v4l2_enum_dv_timings *timings)875{876	struct vpif_display_config *config = vpif_dev->platform_data;877	struct video_device *vdev = video_devdata(file);878	struct channel_obj *ch = video_get_drvdata(vdev);879	struct vpif_display_chan_config *chan_cfg;880	struct v4l2_output output;881	int ret;882 883	if (!config->chan_config[ch->channel_id].outputs)884		return -ENODATA;885 886	chan_cfg = &config->chan_config[ch->channel_id];887	output = chan_cfg->outputs[ch->output_idx].output;888	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS)889		return -ENODATA;890 891	timings->pad = 0;892 893	ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);894	if (ret == -ENOIOCTLCMD || ret == -ENODEV)895		return -EINVAL;896	return ret;897}898 899/**900 * vpif_s_dv_timings() - S_DV_TIMINGS handler901 * @file: file ptr902 * @priv: file handle903 * @timings: digital video timings904 */905static int vpif_s_dv_timings(struct file *file, void *priv,906		struct v4l2_dv_timings *timings)907{908	struct vpif_display_config *config = vpif_dev->platform_data;909	struct video_device *vdev = video_devdata(file);910	struct channel_obj *ch = video_get_drvdata(vdev);911	struct vpif_params *vpifparams = &ch->vpifparams;912	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];913	struct vpif_channel_config_params *std_info = &vpifparams->std_info;914	struct video_obj *vid_ch = &ch->video;915	struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt;916	struct vpif_display_chan_config *chan_cfg;917	struct v4l2_output output;918	int ret;919 920	if (!config->chan_config[ch->channel_id].outputs)921		return -ENODATA;922 923	chan_cfg = &config->chan_config[ch->channel_id];924	output = chan_cfg->outputs[ch->output_idx].output;925	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS)926		return -ENODATA;927 928	if (vb2_is_busy(&common->buffer_queue))929		return -EBUSY;930 931	if (timings->type != V4L2_DV_BT_656_1120) {932		vpif_dbg(2, debug, "Timing type not defined\n");933		return -EINVAL;934	}935 936	/* Configure subdevice timings, if any */937	ret = v4l2_subdev_call(ch->sd, pad, s_dv_timings, 0, timings);938	if (ret == -ENOIOCTLCMD || ret == -ENODEV)939		ret = 0;940	if (ret < 0) {941		vpif_dbg(2, debug, "Error setting custom DV timings\n");942		return ret;943	}944 945	if (!(timings->bt.width && timings->bt.height &&946				(timings->bt.hbackporch ||947				 timings->bt.hfrontporch ||948				 timings->bt.hsync) &&949				timings->bt.vfrontporch &&950				(timings->bt.vbackporch ||951				 timings->bt.vsync))) {952		vpif_dbg(2, debug, "Timings for width, height, horizontal back porch, horizontal sync, horizontal front porch, vertical back porch, vertical sync and vertical back porch must be defined\n");953		return -EINVAL;954	}955 956	vid_ch->dv_timings = *timings;957 958	/* Configure video port timings */959 960	std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8;961	std_info->sav2eav = bt->width;962 963	std_info->l1 = 1;964	std_info->l3 = bt->vsync + bt->vbackporch + 1;965 966	std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt);967	if (bt->interlaced) {968		if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {969			std_info->l5 = std_info->vsize/2 -970				(bt->vfrontporch - 1);971			std_info->l7 = std_info->vsize/2 + 1;972			std_info->l9 = std_info->l7 + bt->il_vsync +973				bt->il_vbackporch + 1;974			std_info->l11 = std_info->vsize -975				(bt->il_vfrontporch - 1);976		} else {977			vpif_dbg(2, debug, "Required timing values for interlaced BT format missing\n");978			return -EINVAL;979		}980	} else {981		std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);982	}983	strscpy(std_info->name, "Custom timings BT656/1120",984		sizeof(std_info->name));985	std_info->width = bt->width;986	std_info->height = bt->height;987	std_info->frm_fmt = bt->interlaced ? 0 : 1;988	std_info->ycmux_mode = 0;989	std_info->capture_format = 0;990	std_info->vbi_supported = 0;991	std_info->hd_sd = 1;992	std_info->stdid = 0;993	vid_ch->stdid = 0;994 995	return 0;996}997 998/**999 * vpif_g_dv_timings() - G_DV_TIMINGS handler1000 * @file: file ptr1001 * @priv: file handle1002 * @timings: digital video timings1003 */1004static int vpif_g_dv_timings(struct file *file, void *priv,1005		struct v4l2_dv_timings *timings)1006{1007	struct vpif_display_config *config = vpif_dev->platform_data;1008	struct video_device *vdev = video_devdata(file);1009	struct channel_obj *ch = video_get_drvdata(vdev);1010	struct vpif_display_chan_config *chan_cfg;1011	struct video_obj *vid_ch = &ch->video;1012	struct v4l2_output output;1013 1014	if (!config->chan_config[ch->channel_id].outputs)1015		goto error;1016 1017	chan_cfg = &config->chan_config[ch->channel_id];1018	output = chan_cfg->outputs[ch->output_idx].output;1019 1020	if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS)1021		goto error;1022 1023	*timings = vid_ch->dv_timings;1024 1025	return 0;1026error:1027	return -ENODATA;1028}1029 1030/*1031 * vpif_log_status() - Status information1032 * @file: file ptr1033 * @priv: file handle1034 *1035 * Returns zero.1036 */1037static int vpif_log_status(struct file *filep, void *priv)1038{1039	/* status for sub devices */1040	v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);1041 1042	return 0;1043}1044 1045/* vpif display ioctl operations */1046static const struct v4l2_ioctl_ops vpif_ioctl_ops = {1047	.vidioc_querycap		= vpif_querycap,1048	.vidioc_enum_fmt_vid_out	= vpif_enum_fmt_vid_out,1049	.vidioc_g_fmt_vid_out		= vpif_g_fmt_vid_out,1050	.vidioc_s_fmt_vid_out		= vpif_s_fmt_vid_out,1051	.vidioc_try_fmt_vid_out		= vpif_try_fmt_vid_out,1052 1053	.vidioc_reqbufs			= vb2_ioctl_reqbufs,1054	.vidioc_create_bufs		= vb2_ioctl_create_bufs,1055	.vidioc_querybuf		= vb2_ioctl_querybuf,1056	.vidioc_qbuf			= vb2_ioctl_qbuf,1057	.vidioc_dqbuf			= vb2_ioctl_dqbuf,1058	.vidioc_expbuf			= vb2_ioctl_expbuf,1059	.vidioc_streamon		= vb2_ioctl_streamon,1060	.vidioc_streamoff		= vb2_ioctl_streamoff,1061 1062	.vidioc_s_std			= vpif_s_std,1063	.vidioc_g_std			= vpif_g_std,1064 1065	.vidioc_enum_output		= vpif_enum_output,1066	.vidioc_s_output		= vpif_s_output,1067	.vidioc_g_output		= vpif_g_output,1068 1069	.vidioc_enum_dv_timings		= vpif_enum_dv_timings,1070	.vidioc_s_dv_timings		= vpif_s_dv_timings,1071	.vidioc_g_dv_timings		= vpif_g_dv_timings,1072 1073	.vidioc_log_status		= vpif_log_status,1074};1075 1076static const struct v4l2_file_operations vpif_fops = {1077	.owner		= THIS_MODULE,1078	.open		= v4l2_fh_open,1079	.release	= vb2_fop_release,1080	.unlocked_ioctl	= video_ioctl2,1081	.mmap		= vb2_fop_mmap,1082	.poll		= vb2_fop_poll1083};1084 1085/*Configure the channels, buffer sizei, request irq */1086static int initialize_vpif(void)1087{1088	int free_channel_objects_index;1089	int err, i, j;1090 1091	/* Allocate memory for six channel objects */1092	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {1093		vpif_obj.dev[i] =1094		    kzalloc(sizeof(struct channel_obj), GFP_KERNEL);1095		/* If memory allocation fails, return error */1096		if (!vpif_obj.dev[i]) {1097			free_channel_objects_index = i;1098			err = -ENOMEM;1099			goto vpif_init_free_channel_objects;1100		}1101	}1102 1103	return 0;1104 1105vpif_init_free_channel_objects:1106	for (j = 0; j < free_channel_objects_index; j++)1107		kfree(vpif_obj.dev[j]);1108	return err;1109}1110 1111static void free_vpif_objs(void)1112{1113	int i;1114 1115	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++)1116		kfree(vpif_obj.dev[i]);1117}1118 1119static int vpif_probe_complete(void)1120{1121	struct common_obj *common;1122	struct video_device *vdev;1123	struct channel_obj *ch;1124	struct vb2_queue *q;1125	int j, err, k;1126 1127	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {1128		ch = vpif_obj.dev[j];1129		/* Initialize field of the channel objects */1130		for (k = 0; k < VPIF_NUMOBJECTS; k++) {1131			common = &ch->common[k];1132			spin_lock_init(&common->irqlock);1133			mutex_init(&common->lock);1134			common->set_addr = NULL;1135			common->ytop_off = 0;1136			common->ybtm_off = 0;1137			common->ctop_off = 0;1138			common->cbtm_off = 0;1139			common->cur_frm = NULL;1140			common->next_frm = NULL;1141			memset(&common->fmt, 0, sizeof(common->fmt));1142		}1143		ch->initialized = 0;1144		if (vpif_obj.config->subdev_count)1145			ch->sd = vpif_obj.sd[0];1146		ch->channel_id = j;1147 1148		memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));1149 1150		ch->common[VPIF_VIDEO_INDEX].fmt.type =1151						V4L2_BUF_TYPE_VIDEO_OUTPUT;1152 1153		/* select output 0 */1154		err = vpif_set_output(vpif_obj.config, ch, 0);1155		if (err)1156			goto probe_out;1157 1158		/* set initial format */1159		ch->video.stdid = V4L2_STD_525_60;1160		memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));1161		vpif_update_resolution(ch);1162 1163		/* Initialize vb2 queue */1164		q = &common->buffer_queue;1165		q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;1166		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;1167		q->drv_priv = ch;1168		q->ops = &video_qops;1169		q->mem_ops = &vb2_dma_contig_memops;1170		q->buf_struct_size = sizeof(struct vpif_disp_buffer);1171		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;1172		q->min_queued_buffers = 1;1173		q->lock = &common->lock;1174		q->dev = vpif_dev;1175		err = vb2_queue_init(q);1176		if (err) {1177			vpif_err("vpif_display: vb2_queue_init() failed\n");1178			goto probe_out;1179		}1180 1181		INIT_LIST_HEAD(&common->dma_queue);1182 1183		/* register video device */1184		vpif_dbg(1, debug, "channel=%p,channel->video_dev=%p\n",1185			 ch, &ch->video_dev);1186 1187		/* Initialize the video_device structure */1188		vdev = &ch->video_dev;1189		strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));1190		vdev->release = video_device_release_empty;1191		vdev->fops = &vpif_fops;1192		vdev->ioctl_ops = &vpif_ioctl_ops;1193		vdev->v4l2_dev = &vpif_obj.v4l2_dev;1194		vdev->vfl_dir = VFL_DIR_TX;1195		vdev->queue = q;1196		vdev->lock = &common->lock;1197		vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;1198		video_set_drvdata(&ch->video_dev, ch);1199		err = video_register_device(vdev, VFL_TYPE_VIDEO,1200					    (j ? 3 : 2));1201		if (err < 0)1202			goto probe_out;1203	}1204 1205	return 0;1206 1207probe_out:1208	for (k = 0; k < j; k++) {1209		ch = vpif_obj.dev[k];1210		video_unregister_device(&ch->video_dev);1211	}1212	return err;1213}1214 1215/*1216 * vpif_probe: This function creates device entries by register itself to the1217 * V4L2 driver and initializes fields of each channel objects1218 */1219static __init int vpif_probe(struct platform_device *pdev)1220{1221	struct vpif_subdev_info *subdevdata;1222	struct i2c_adapter *i2c_adap;1223	int subdev_count;1224	int res_idx = 0;1225	int i, err;1226 1227	if (!pdev->dev.platform_data) {1228		dev_warn(&pdev->dev, "Missing platform data.  Giving up.\n");1229		return -EINVAL;1230	}1231 1232	vpif_dev = &pdev->dev;1233	err = initialize_vpif();1234 1235	if (err) {1236		v4l2_err(vpif_dev->driver, "Error initializing vpif\n");1237		return err;1238	}1239 1240	err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);1241	if (err) {1242		v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");1243		goto vpif_free;1244	}1245 1246	do {1247		int irq;1248 1249		err = platform_get_irq_optional(pdev, res_idx);1250		if (err < 0 && err != -ENXIO)1251			goto vpif_unregister;1252		if (err > 0)1253			irq = err;1254		else1255			break;1256 1257		err = devm_request_irq(&pdev->dev, irq, vpif_channel_isr,1258				       IRQF_SHARED, VPIF_DRIVER_NAME,1259				       (void *)(&vpif_obj.dev[res_idx]->channel_id));1260		if (err) {1261			vpif_err("VPIF IRQ request failed\n");1262			goto vpif_unregister;1263		}1264	} while (++res_idx);1265 1266	vpif_obj.config = pdev->dev.platform_data;1267	subdev_count = vpif_obj.config->subdev_count;1268	subdevdata = vpif_obj.config->subdevinfo;1269	vpif_obj.sd = kcalloc(subdev_count, sizeof(*vpif_obj.sd), GFP_KERNEL);1270	if (!vpif_obj.sd) {1271		err = -ENOMEM;1272		goto vpif_unregister;1273	}1274 1275	i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id);1276	for (i = 0; i < subdev_count; i++) {1277		vpif_obj.sd[i] =1278			v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,1279						  i2c_adap,1280						  &subdevdata[i].board_info,1281						  NULL);1282		if (!vpif_obj.sd[i]) {1283			vpif_err("Error registering v4l2 subdevice\n");1284			err = -ENODEV;1285			goto probe_subdev_out;1286		}1287 1288		vpif_obj.sd[i]->grp_id = 1 << i;1289	}1290	err = vpif_probe_complete();1291	if (err)1292		goto probe_subdev_out;1293 1294	return 0;1295 1296probe_subdev_out:1297	kfree(vpif_obj.sd);1298vpif_unregister:1299	v4l2_device_unregister(&vpif_obj.v4l2_dev);1300vpif_free:1301	free_vpif_objs();1302 1303	return err;1304}1305 1306/*1307 * vpif_remove: It un-register channels from V4L2 driver1308 */1309static void vpif_remove(struct platform_device *device)1310{1311	struct channel_obj *ch;1312	int i;1313 1314	v4l2_device_unregister(&vpif_obj.v4l2_dev);1315 1316	kfree(vpif_obj.sd);1317	/* un-register device */1318	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {1319		/* Get the pointer to the channel object */1320		ch = vpif_obj.dev[i];1321		/* Unregister video device */1322		video_unregister_device(&ch->video_dev);1323	}1324	free_vpif_objs();1325}1326 1327#ifdef CONFIG_PM_SLEEP1328static int vpif_suspend(struct device *dev)1329{1330	struct common_obj *common;1331	struct channel_obj *ch;1332	int i;1333 1334	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {1335		/* Get the pointer to the channel object */1336		ch = vpif_obj.dev[i];1337		common = &ch->common[VPIF_VIDEO_INDEX];1338 1339		if (!vb2_start_streaming_called(&common->buffer_queue))1340			continue;1341 1342		mutex_lock(&common->lock);1343		/* Disable channel */1344		if (ch->channel_id == VPIF_CHANNEL2_VIDEO) {1345			enable_channel2(0);1346			channel2_intr_enable(0);1347		}1348		if (ch->channel_id == VPIF_CHANNEL3_VIDEO ||1349			ycmux_mode == 2) {1350			enable_channel3(0);1351			channel3_intr_enable(0);1352		}1353		mutex_unlock(&common->lock);1354	}1355 1356	return 0;1357}1358 1359static int vpif_resume(struct device *dev)1360{1361 1362	struct common_obj *common;1363	struct channel_obj *ch;1364	int i;1365 1366	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {1367		/* Get the pointer to the channel object */1368		ch = vpif_obj.dev[i];1369		common = &ch->common[VPIF_VIDEO_INDEX];1370 1371		if (!vb2_start_streaming_called(&common->buffer_queue))1372			continue;1373 1374		mutex_lock(&common->lock);1375		/* Enable channel */1376		if (ch->channel_id == VPIF_CHANNEL2_VIDEO) {1377			enable_channel2(1);1378			channel2_intr_enable(1);1379		}1380		if (ch->channel_id == VPIF_CHANNEL3_VIDEO ||1381				ycmux_mode == 2) {1382			enable_channel3(1);1383			channel3_intr_enable(1);1384		}1385		mutex_unlock(&common->lock);1386	}1387 1388	return 0;1389}1390 1391#endif1392 1393static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume);1394 1395static __refdata struct platform_driver vpif_driver = {1396	.driver	= {1397			.name	= VPIF_DRIVER_NAME,1398			.pm	= &vpif_pm_ops,1399	},1400	.probe	= vpif_probe,1401	.remove_new = vpif_remove,1402};1403 1404module_platform_driver(vpif_driver);1405