blob: 6c5ff0f0d75f9f106cb665dc1ff23b2c20618222 [file] [log] [blame]
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001/*
2 * Copyright (C) 2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * TODO : add support for VBI & HBI data service
19 * add static buffer allocation
20 */
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030021
Lad, Prabhakar012eef72013-04-19 05:53:29 -030022#include <linux/module.h>
23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26
Lad, Prabhakar012eef72013-04-19 05:53:29 -030027#include <media/v4l2-ioctl.h>
28
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030029#include "vpif.h"
Lad, Prabhakar012eef72013-04-19 05:53:29 -030030#include "vpif_capture.h"
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030031
32MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver");
33MODULE_LICENSE("GPL");
Mauro Carvalho Chehab64dc3c12011-06-25 11:28:37 -030034MODULE_VERSION(VPIF_CAPTURE_VERSION);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030035
36#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)
37#define vpif_dbg(level, debug, fmt, arg...) \
38 v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
39
40static int debug = 1;
41static u32 ch0_numbuffers = 3;
42static u32 ch1_numbuffers = 3;
43static u32 ch0_bufsize = 1920 * 1080 * 2;
44static u32 ch1_bufsize = 720 * 576 * 2;
45
46module_param(debug, int, 0644);
47module_param(ch0_numbuffers, uint, S_IRUGO);
48module_param(ch1_numbuffers, uint, S_IRUGO);
49module_param(ch0_bufsize, uint, S_IRUGO);
50module_param(ch1_bufsize, uint, S_IRUGO);
51
52MODULE_PARM_DESC(debug, "Debug level 0-1");
53MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)");
54MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)");
55MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)");
56MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)");
57
58static struct vpif_config_params config_params = {
59 .min_numbuffers = 3,
60 .numbuffers[0] = 3,
61 .numbuffers[1] = 3,
62 .min_bufsize[0] = 720 * 480 * 2,
63 .min_bufsize[1] = 720 * 480 * 2,
64 .channel_bufsize[0] = 1920 * 1080 * 2,
65 .channel_bufsize[1] = 720 * 576 * 2,
66};
67
68/* global variables */
69static struct vpif_device vpif_obj = { {NULL} };
70static struct device *vpif_dev;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -030071static void vpif_calculate_offsets(struct channel_obj *ch);
72static void vpif_config_addr(struct channel_obj *ch, int muxmode);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030073
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -030074static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} };
75
76static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb)
77{
78 return container_of(vb, struct vpif_cap_buffer, vb);
79}
80
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030081/**
82 * buffer_prepare : callback function for buffer prepare
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -030083 * @vb: ptr to vb2_buffer
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030084 *
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -030085 * This is the callback function for buffer prepare when vb2_qbuf()
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030086 * function is called. The buffer is prepared and user space virtual address
87 * or user address is converted into physical address
88 */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -030089static int vpif_buffer_prepare(struct vb2_buffer *vb)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030090{
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -030091 struct vb2_queue *q = vb->vb2_queue;
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -030092 struct channel_obj *ch = vb2_get_drv_priv(q);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030093 struct common_obj *common;
94 unsigned long addr;
95
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -030096 vpif_dbg(2, debug, "vpif_buffer_prepare\n");
97
98 common = &ch->common[VPIF_VIDEO_INDEX];
99
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300100 if (vb->state != VB2_BUF_STATE_ACTIVE &&
101 vb->state != VB2_BUF_STATE_PREPARED) {
102 vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage);
103 if (vb2_plane_vaddr(vb, 0) &&
104 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
105 goto exit;
106 addr = vb2_dma_contig_plane_dma_addr(vb, 0);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300107
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300108 if (q->streaming) {
109 if (!IS_ALIGNED((addr + common->ytop_off), 8) ||
110 !IS_ALIGNED((addr + common->ybtm_off), 8) ||
111 !IS_ALIGNED((addr + common->ctop_off), 8) ||
112 !IS_ALIGNED((addr + common->cbtm_off), 8))
113 goto exit;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300114 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300115 }
116 return 0;
117exit:
118 vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n");
119 return -EINVAL;
120}
121
122/**
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300123 * vpif_buffer_queue_setup : Callback function for buffer setup.
124 * @vq: vb2_queue ptr
125 * @fmt: v4l2 format
126 * @nbuffers: ptr to number of buffers requested by application
127 * @nplanes:: contains number of distinct video planes needed to hold a frame
128 * @sizes[]: contains the size (in bytes) of each plane.
129 * @alloc_ctxs: ptr to allocation context
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300130 *
131 * This callback function is called when reqbuf() is called to adjust
132 * the buffer count and buffer size
133 */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300134static int vpif_buffer_queue_setup(struct vb2_queue *vq,
135 const struct v4l2_format *fmt,
136 unsigned int *nbuffers, unsigned int *nplanes,
137 unsigned int sizes[], void *alloc_ctxs[])
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300138{
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -0300139 struct channel_obj *ch = vb2_get_drv_priv(vq);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300140 struct common_obj *common;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300141 unsigned long size;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300142
143 common = &ch->common[VPIF_VIDEO_INDEX];
144
145 vpif_dbg(2, debug, "vpif_buffer_setup\n");
146
147 /* If memory type is not mmap, return */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300148 if (V4L2_MEMORY_MMAP == common->memory) {
149 /* Calculate the size of the buffer */
150 size = config_params.channel_bufsize[ch->channel_id];
151 /*
152 * Checking if the buffer size exceeds the available buffer
153 * ycmux_mode = 0 means 1 channel mode HD and
154 * ycmux_mode = 1 means 2 channels mode SD
155 */
156 if (ch->vpifparams.std_info.ycmux_mode == 0) {
157 if (config_params.video_limit[ch->channel_id])
158 while (size * *nbuffers >
159 (config_params.video_limit[0]
Manjunath Hadli764af392012-04-13 04:49:34 -0300160 + config_params.video_limit[1]))
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300161 (*nbuffers)--;
162 } else {
163 if (config_params.video_limit[ch->channel_id])
164 while (size * *nbuffers >
Manjunath Hadli764af392012-04-13 04:49:34 -0300165 config_params.video_limit[ch->channel_id])
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300166 (*nbuffers)--;
167 }
168
169 } else {
170 size = common->fmt.fmt.pix.sizeimage;
Manjunath Hadli764af392012-04-13 04:49:34 -0300171 }
172
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300173 if (*nbuffers < config_params.min_numbuffers)
174 *nbuffers = config_params.min_numbuffers;
175
176 *nplanes = 1;
177 sizes[0] = size;
178 alloc_ctxs[0] = common->alloc_ctx;
179
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300180 return 0;
181}
182
183/**
184 * vpif_buffer_queue : Callback function to add buffer to DMA queue
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300185 * @vb: ptr to vb2_buffer
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300186 */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300187static void vpif_buffer_queue(struct vb2_buffer *vb)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300188{
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -0300189 struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue);
190 struct vpif_cap_buffer *buf = to_vpif_buffer(vb);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300191 struct common_obj *common;
Hans Verkuilaec96832012-11-16 12:03:06 -0300192 unsigned long flags;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300193
194 common = &ch->common[VPIF_VIDEO_INDEX];
195
196 vpif_dbg(2, debug, "vpif_buffer_queue\n");
197
Hans Verkuilaec96832012-11-16 12:03:06 -0300198 spin_lock_irqsave(&common->irqlock, flags);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300199 /* add the buffer to the DMA queue */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300200 list_add_tail(&buf->list, &common->dma_queue);
Hans Verkuilaec96832012-11-16 12:03:06 -0300201 spin_unlock_irqrestore(&common->irqlock, flags);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300202}
203
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300204static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
205{
206 struct vpif_capture_config *vpif_config_data =
207 vpif_dev->platform_data;
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -0300208 struct channel_obj *ch = vb2_get_drv_priv(vq);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300209 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
210 struct vpif_params *vpif = &ch->vpifparams;
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300211 struct vpif_cap_buffer *buf, *tmp;
212 unsigned long addr, flags;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300213 int ret;
214
Hans Verkuilaec96832012-11-16 12:03:06 -0300215 spin_lock_irqsave(&common->irqlock, flags);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300216
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300217 /* Initialize field_id and started member */
218 ch->field_id = 0;
219 common->started = 1;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300220
221 /* Calculate the offset for Y and C data in the buffer */
222 vpif_calculate_offsets(ch);
223
224 if ((vpif->std_info.frm_fmt &&
225 ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) &&
226 (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) ||
227 (!vpif->std_info.frm_fmt &&
228 (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
229 vpif_dbg(1, debug, "conflict in field format and std format\n");
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300230 ret = -EINVAL;
231 goto err;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300232 }
233
234 /* configure 1 or 2 channel mode */
Lad, Prabhakarf4ad8d72012-09-27 02:33:12 -0300235 if (vpif_config_data->setup_input_channel_mode) {
236 ret = vpif_config_data->
237 setup_input_channel_mode(vpif->std_info.ycmux_mode);
238 if (ret < 0) {
239 vpif_dbg(1, debug, "can't set vpif channel mode\n");
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300240 goto err;
Lad, Prabhakarf4ad8d72012-09-27 02:33:12 -0300241 }
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300242 }
243
244 /* Call vpif_set_params function to set the parameters and addresses */
245 ret = vpif_set_video_params(vpif, ch->channel_id);
246
247 if (ret < 0) {
248 vpif_dbg(1, debug, "can't set video params\n");
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300249 goto err;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300250 }
251
252 common->started = ret;
253 vpif_config_addr(ch, ret);
254
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300255 /* Get the next frame from the buffer queue */
256 common->cur_frm = common->next_frm = list_entry(common->dma_queue.next,
257 struct vpif_cap_buffer, list);
258 /* Remove buffer from the buffer queue */
259 list_del(&common->cur_frm->list);
260 spin_unlock_irqrestore(&common->irqlock, flags);
261 /* Mark state of the current frame to active */
262 common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
263
264 addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0);
265
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300266 common->set_addr(addr + common->ytop_off,
267 addr + common->ybtm_off,
268 addr + common->ctop_off,
269 addr + common->cbtm_off);
270
271 /**
272 * Set interrupt for both the fields in VPIF Register enable channel in
273 * VPIF register
274 */
Lad, Prabhakar9e184042012-09-14 10:22:24 -0300275 channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300276 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) {
277 channel0_intr_assert();
278 channel0_intr_enable(1);
279 enable_channel0(1);
280 }
281 if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
282 (common->started == 2)) {
283 channel1_intr_assert();
284 channel1_intr_enable(1);
285 enable_channel1(1);
286 }
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300287
288 return 0;
Lad, Prabhakarbebd8d12014-05-16 10:33:35 -0300289
290err:
291 list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {
292 list_del(&buf->list);
293 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
294 }
295
296 return ret;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300297}
298
299/* abort streaming and wait for last buffer */
Hans Verkuile37559b2014-04-17 02:47:21 -0300300static void vpif_stop_streaming(struct vb2_queue *vq)
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300301{
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -0300302 struct channel_obj *ch = vb2_get_drv_priv(vq);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300303 struct common_obj *common;
Hans Verkuilaec96832012-11-16 12:03:06 -0300304 unsigned long flags;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300305
306 if (!vb2_is_streaming(vq))
Hans Verkuile37559b2014-04-17 02:47:21 -0300307 return;
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300308
309 common = &ch->common[VPIF_VIDEO_INDEX];
310
Lad, Prabhakare6ba3db2014-03-22 08:03:07 -0300311 /* Disable channel as per its device type and channel id */
312 if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
313 enable_channel0(0);
314 channel0_intr_enable(0);
315 }
316 if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
317 (2 == common->started)) {
318 enable_channel1(0);
319 channel1_intr_enable(0);
320 }
321 common->started = 0;
322
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300323 /* release all active buffers */
Hans Verkuilaec96832012-11-16 12:03:06 -0300324 spin_lock_irqsave(&common->irqlock, flags);
Lad, Prabhakare6ba3db2014-03-22 08:03:07 -0300325 if (common->cur_frm == common->next_frm) {
326 vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
327 } else {
328 if (common->cur_frm != NULL)
329 vb2_buffer_done(&common->cur_frm->vb,
330 VB2_BUF_STATE_ERROR);
331 if (common->next_frm != NULL)
332 vb2_buffer_done(&common->next_frm->vb,
333 VB2_BUF_STATE_ERROR);
334 }
335
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300336 while (!list_empty(&common->dma_queue)) {
337 common->next_frm = list_entry(common->dma_queue.next,
338 struct vpif_cap_buffer, list);
339 list_del(&common->next_frm->list);
340 vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
341 }
Hans Verkuilaec96832012-11-16 12:03:06 -0300342 spin_unlock_irqrestore(&common->irqlock, flags);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300343}
344
345static struct vb2_ops video_qops = {
346 .queue_setup = vpif_buffer_queue_setup,
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300347 .buf_prepare = vpif_buffer_prepare,
348 .start_streaming = vpif_start_streaming,
349 .stop_streaming = vpif_stop_streaming,
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300350 .buf_queue = vpif_buffer_queue,
351};
352
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300353/**
354 * vpif_process_buffer_complete: process a completed buffer
355 * @common: ptr to common channel object
356 *
357 * This function time stamp the buffer and mark it as DONE. It also
358 * wake up any process waiting on the QUEUE and set the next buffer
359 * as current
360 */
361static void vpif_process_buffer_complete(struct common_obj *common)
362{
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300363 v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300364 vb2_buffer_done(&common->cur_frm->vb,
365 VB2_BUF_STATE_DONE);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300366 /* Make curFrm pointing to nextFrm */
367 common->cur_frm = common->next_frm;
368}
369
370/**
371 * vpif_schedule_next_buffer: set next buffer address for capture
372 * @common : ptr to common channel object
373 *
374 * This function will get next buffer from the dma queue and
375 * set the buffer address in the vpif register for capture.
376 * the buffer is marked active
377 */
378static void vpif_schedule_next_buffer(struct common_obj *common)
379{
380 unsigned long addr = 0;
381
Hans Verkuilaec96832012-11-16 12:03:06 -0300382 spin_lock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300383 common->next_frm = list_entry(common->dma_queue.next,
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300384 struct vpif_cap_buffer, list);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300385 /* Remove that buffer from the buffer queue */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300386 list_del(&common->next_frm->list);
Hans Verkuilaec96832012-11-16 12:03:06 -0300387 spin_unlock(&common->irqlock);
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300388 common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
389 addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300390
391 /* Set top and bottom field addresses in VPIF registers */
392 common->set_addr(addr + common->ytop_off,
393 addr + common->ybtm_off,
394 addr + common->ctop_off,
395 addr + common->cbtm_off);
396}
397
398/**
399 * vpif_channel_isr : ISR handler for vpif capture
400 * @irq: irq number
401 * @dev_id: dev_id ptr
402 *
403 * It changes status of the captured buffer, takes next buffer from the queue
Mats Randgaard2c0ddd12010-12-16 12:17:45 -0300404 * and sets its address in VPIF registers
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300405 */
406static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
407{
408 struct vpif_device *dev = &vpif_obj;
409 struct common_obj *common;
410 struct channel_obj *ch;
411 enum v4l2_field field;
412 int channel_id = 0;
413 int fid = -1, i;
414
415 channel_id = *(int *)(dev_id);
Manjunath Hadlib1fc4232012-04-13 04:43:10 -0300416 if (!vpif_intr_status(channel_id))
417 return IRQ_NONE;
418
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300419 ch = dev->dev[channel_id];
420
421 field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field;
422
423 for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) {
424 common = &ch->common[i];
425 /* skip If streaming is not started in this channel */
426 if (0 == common->started)
427 continue;
428
429 /* Check the field format */
430 if (1 == ch->vpifparams.std_info.frm_fmt) {
431 /* Progressive mode */
Hans Verkuilaec96832012-11-16 12:03:06 -0300432 spin_lock(&common->irqlock);
433 if (list_empty(&common->dma_queue)) {
434 spin_unlock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300435 continue;
Hans Verkuilaec96832012-11-16 12:03:06 -0300436 }
437 spin_unlock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300438
439 if (!channel_first_int[i][channel_id])
440 vpif_process_buffer_complete(common);
441
442 channel_first_int[i][channel_id] = 0;
443
444 vpif_schedule_next_buffer(common);
445
446
447 channel_first_int[i][channel_id] = 0;
448 } else {
449 /**
450 * Interlaced mode. If it is first interrupt, ignore
451 * it
452 */
453 if (channel_first_int[i][channel_id]) {
454 channel_first_int[i][channel_id] = 0;
455 continue;
456 }
457 if (0 == i) {
458 ch->field_id ^= 1;
459 /* Get field id from VPIF registers */
460 fid = vpif_channel_getfid(ch->channel_id);
461 if (fid != ch->field_id) {
462 /**
463 * If field id does not match stored
464 * field id, make them in sync
465 */
466 if (0 == fid)
467 ch->field_id = fid;
468 return IRQ_HANDLED;
469 }
470 }
471 /* device field id and local field id are in sync */
472 if (0 == fid) {
473 /* this is even field */
474 if (common->cur_frm == common->next_frm)
475 continue;
476
477 /* mark the current buffer as done */
478 vpif_process_buffer_complete(common);
479 } else if (1 == fid) {
480 /* odd field */
Hans Verkuilaec96832012-11-16 12:03:06 -0300481 spin_lock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300482 if (list_empty(&common->dma_queue) ||
Hans Verkuilaec96832012-11-16 12:03:06 -0300483 (common->cur_frm != common->next_frm)) {
484 spin_unlock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300485 continue;
Hans Verkuilaec96832012-11-16 12:03:06 -0300486 }
487 spin_unlock(&common->irqlock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300488
489 vpif_schedule_next_buffer(common);
490 }
491 }
492 }
493 return IRQ_HANDLED;
494}
495
496/**
497 * vpif_update_std_info() - update standard related info
498 * @ch: ptr to channel object
499 *
500 * For a given standard selected by application, update values
501 * in the device data structures
502 */
503static int vpif_update_std_info(struct channel_obj *ch)
504{
505 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
506 struct vpif_params *vpifparams = &ch->vpifparams;
507 const struct vpif_channel_config_params *config;
Mats Randgaard2c0ddd12010-12-16 12:17:45 -0300508 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300509 struct video_obj *vid_ch = &ch->video;
510 int index;
511
512 vpif_dbg(2, debug, "vpif_update_std_info\n");
513
Mats Randgaardaa444402010-12-16 12:17:42 -0300514 for (index = 0; index < vpif_ch_params_count; index++) {
Lad, Prabhakarced9b212013-03-20 01:28:27 -0300515 config = &vpif_ch_params[index];
Mats Randgaard40c8bce2010-12-16 12:17:43 -0300516 if (config->hd_sd == 0) {
517 vpif_dbg(2, debug, "SD format\n");
518 if (config->stdid & vid_ch->stdid) {
519 memcpy(std_info, config, sizeof(*config));
520 break;
521 }
522 } else {
523 vpif_dbg(2, debug, "HD format\n");
Hans Verkuil0598c172012-09-18 07:18:47 -0300524 if (!memcmp(&config->dv_timings, &vid_ch->dv_timings,
525 sizeof(vid_ch->dv_timings))) {
Mats Randgaard40c8bce2010-12-16 12:17:43 -0300526 memcpy(std_info, config, sizeof(*config));
527 break;
528 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300529 }
530 }
531
532 /* standard not found */
Mats Randgaardaa444402010-12-16 12:17:42 -0300533 if (index == vpif_ch_params_count)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300534 return -EINVAL;
535
536 common->fmt.fmt.pix.width = std_info->width;
537 common->width = std_info->width;
538 common->fmt.fmt.pix.height = std_info->height;
539 common->height = std_info->height;
540 common->fmt.fmt.pix.bytesperline = std_info->width;
541 vpifparams->video_params.hpitch = std_info->width;
542 vpifparams->video_params.storage_mode = std_info->frm_fmt;
Mats Randgaard2c0ddd12010-12-16 12:17:45 -0300543
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300544 return 0;
545}
546
547/**
548 * vpif_calculate_offsets : This function calculates buffers offsets
549 * @ch : ptr to channel object
550 *
551 * This function calculates buffer offsets for Y and C in the top and
552 * bottom field
553 */
554static void vpif_calculate_offsets(struct channel_obj *ch)
555{
556 unsigned int hpitch, vpitch, sizeimage;
557 struct video_obj *vid_ch = &(ch->video);
558 struct vpif_params *vpifparams = &ch->vpifparams;
559 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
560 enum v4l2_field field = common->fmt.fmt.pix.field;
561
562 vpif_dbg(2, debug, "vpif_calculate_offsets\n");
563
564 if (V4L2_FIELD_ANY == field) {
565 if (vpifparams->std_info.frm_fmt)
566 vid_ch->buf_field = V4L2_FIELD_NONE;
567 else
568 vid_ch->buf_field = V4L2_FIELD_INTERLACED;
569 } else
570 vid_ch->buf_field = common->fmt.fmt.pix.field;
571
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300572 sizeimage = common->fmt.fmt.pix.sizeimage;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300573
574 hpitch = common->fmt.fmt.pix.bytesperline;
575 vpitch = sizeimage / (hpitch * 2);
576
577 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
578 (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {
579 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
580 common->ytop_off = 0;
581 common->ybtm_off = hpitch;
582 common->ctop_off = sizeimage / 2;
583 common->cbtm_off = sizeimage / 2 + hpitch;
584 } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) {
585 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
586 common->ytop_off = 0;
587 common->ybtm_off = sizeimage / 4;
588 common->ctop_off = sizeimage / 2;
589 common->cbtm_off = common->ctop_off + sizeimage / 4;
590 } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) {
591 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
592 common->ybtm_off = 0;
593 common->ytop_off = sizeimage / 4;
594 common->cbtm_off = sizeimage / 2;
595 common->ctop_off = common->cbtm_off + sizeimage / 4;
596 }
597 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
598 (V4L2_FIELD_INTERLACED == vid_ch->buf_field))
599 vpifparams->video_params.storage_mode = 1;
600 else
601 vpifparams->video_params.storage_mode = 0;
602
603 if (1 == vpifparams->std_info.frm_fmt)
604 vpifparams->video_params.hpitch =
605 common->fmt.fmt.pix.bytesperline;
606 else {
607 if ((field == V4L2_FIELD_ANY)
608 || (field == V4L2_FIELD_INTERLACED))
609 vpifparams->video_params.hpitch =
610 common->fmt.fmt.pix.bytesperline * 2;
611 else
612 vpifparams->video_params.hpitch =
613 common->fmt.fmt.pix.bytesperline;
614 }
615
616 ch->vpifparams.video_params.stdid = vpifparams->std_info.stdid;
617}
618
619/**
620 * vpif_config_format: configure default frame format in the device
621 * ch : ptr to channel object
622 */
623static void vpif_config_format(struct channel_obj *ch)
624{
625 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
626
627 vpif_dbg(2, debug, "vpif_config_format\n");
628
629 common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
630 if (config_params.numbuffers[ch->channel_id] == 0)
631 common->memory = V4L2_MEMORY_USERPTR;
632 else
633 common->memory = V4L2_MEMORY_MMAP;
634
635 common->fmt.fmt.pix.sizeimage
636 = config_params.channel_bufsize[ch->channel_id];
637
638 if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
639 common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
640 else
641 common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
642 common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
643}
644
645/**
646 * vpif_get_default_field() - Get default field type based on interface
647 * @vpif_params - ptr to vpif params
648 */
649static inline enum v4l2_field vpif_get_default_field(
650 struct vpif_interface *iface)
651{
652 return (iface->if_type == VPIF_IF_RAW_BAYER) ? V4L2_FIELD_NONE :
653 V4L2_FIELD_INTERLACED;
654}
655
656/**
657 * vpif_check_format() - check given pixel format for compatibility
658 * @ch - channel ptr
659 * @pixfmt - Given pixel format
660 * @update - update the values as per hardware requirement
661 *
662 * Check the application pixel format for S_FMT and update the input
663 * values as per hardware limits for TRY_FMT. The default pixel and
664 * field format is selected based on interface type.
665 */
666static int vpif_check_format(struct channel_obj *ch,
667 struct v4l2_pix_format *pixfmt,
668 int update)
669{
670 struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
671 struct vpif_params *vpif_params = &ch->vpifparams;
672 enum v4l2_field field = pixfmt->field;
673 u32 sizeimage, hpitch, vpitch;
674 int ret = -EINVAL;
675
676 vpif_dbg(2, debug, "vpif_check_format\n");
677 /**
678 * first check for the pixel format. If if_type is Raw bayer,
679 * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only
680 * V4L2_PIX_FMT_YUV422P is supported
681 */
682 if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
683 if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) {
684 if (!update) {
685 vpif_dbg(2, debug, "invalid pix format\n");
686 goto exit;
687 }
688 pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
689 }
690 } else {
691 if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) {
692 if (!update) {
693 vpif_dbg(2, debug, "invalid pixel format\n");
694 goto exit;
695 }
696 pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
697 }
698 }
699
700 if (!(VPIF_VALID_FIELD(field))) {
701 if (!update) {
702 vpif_dbg(2, debug, "invalid field format\n");
703 goto exit;
704 }
705 /**
706 * By default use FIELD_NONE for RAW Bayer capture
707 * and FIELD_INTERLACED for other interfaces
708 */
709 field = vpif_get_default_field(&vpif_params->iface);
710 } else if (field == V4L2_FIELD_ANY)
711 /* unsupported field. Use default */
712 field = vpif_get_default_field(&vpif_params->iface);
713
714 /* validate the hpitch */
715 hpitch = pixfmt->bytesperline;
716 if (hpitch < vpif_params->std_info.width) {
717 if (!update) {
718 vpif_dbg(2, debug, "invalid hpitch\n");
719 goto exit;
720 }
721 hpitch = vpif_params->std_info.width;
722 }
723
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300724 sizeimage = pixfmt->sizeimage;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300725
726 vpitch = sizeimage / (hpitch * 2);
727
728 /* validate the vpitch */
729 if (vpitch < vpif_params->std_info.height) {
730 if (!update) {
731 vpif_dbg(2, debug, "Invalid vpitch\n");
732 goto exit;
733 }
734 vpitch = vpif_params->std_info.height;
735 }
736
737 /* Check for 8 byte alignment */
738 if (!ALIGN(hpitch, 8)) {
739 if (!update) {
740 vpif_dbg(2, debug, "invalid pitch alignment\n");
741 goto exit;
742 }
743 /* adjust to next 8 byte boundary */
744 hpitch = (((hpitch + 7) / 8) * 8);
745 }
746 /* if update is set, modify the bytesperline and sizeimage */
747 if (update) {
748 pixfmt->bytesperline = hpitch;
749 pixfmt->sizeimage = hpitch * vpitch * 2;
750 }
751 /**
752 * Image width and height is always based on current standard width and
753 * height
754 */
755 pixfmt->width = common->fmt.fmt.pix.width;
756 pixfmt->height = common->fmt.fmt.pix.height;
757 return 0;
758exit:
759 return ret;
760}
761
762/**
763 * vpif_config_addr() - function to configure buffer address in vpif
764 * @ch - channel ptr
765 * @muxmode - channel mux mode
766 */
767static void vpif_config_addr(struct channel_obj *ch, int muxmode)
768{
769 struct common_obj *common;
770
771 vpif_dbg(2, debug, "vpif_config_addr\n");
772
773 common = &(ch->common[VPIF_VIDEO_INDEX]);
774
775 if (VPIF_CHANNEL1_VIDEO == ch->channel_id)
776 common->set_addr = ch1_set_videobuf_addr;
777 else if (2 == muxmode)
778 common->set_addr = ch0_set_videobuf_addr_yc_nmux;
779 else
780 common->set_addr = ch0_set_videobuf_addr;
781}
782
783/**
Dror Cohen6f45b1b2012-07-10 05:43:22 -0300784 * vpif_mmap : It is used to map kernel space buffers into user spaces
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300785 * @filep: file pointer
786 * @vma: ptr to vm_area_struct
787 */
788static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
789{
790 /* Get the channel object and file handle object */
791 struct vpif_fh *fh = filep->private_data;
792 struct channel_obj *ch = fh->channel;
793 struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
Hans Verkuil72246792012-07-31 03:48:31 -0300794 int ret;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300795
796 vpif_dbg(2, debug, "vpif_mmap\n");
797
Hans Verkuil72246792012-07-31 03:48:31 -0300798 if (mutex_lock_interruptible(&common->lock))
799 return -ERESTARTSYS;
800 ret = vb2_mmap(&common->buffer_queue, vma);
801 mutex_unlock(&common->lock);
802 return ret;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300803}
804
805/**
806 * vpif_poll: It is used for select/poll system call
807 * @filep: file pointer
808 * @wait: poll table to wait
809 */
810static unsigned int vpif_poll(struct file *filep, poll_table * wait)
811{
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300812 struct vpif_fh *fh = filep->private_data;
813 struct channel_obj *channel = fh->channel;
814 struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]);
Hans Verkuil72246792012-07-31 03:48:31 -0300815 unsigned int res = 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300816
817 vpif_dbg(2, debug, "vpif_poll\n");
818
Hans Verkuil72246792012-07-31 03:48:31 -0300819 if (common->started) {
820 mutex_lock(&common->lock);
821 res = vb2_poll(&common->buffer_queue, filep, wait);
822 mutex_unlock(&common->lock);
823 }
824 return res;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300825}
826
827/**
828 * vpif_open : vpif open handler
829 * @filep: file ptr
830 *
831 * It creates object of file handle structure and stores it in private_data
832 * member of filepointer
833 */
834static int vpif_open(struct file *filep)
835{
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300836 struct video_device *vdev = video_devdata(filep);
837 struct common_obj *common;
838 struct video_obj *vid_ch;
839 struct channel_obj *ch;
840 struct vpif_fh *fh;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300841
842 vpif_dbg(2, debug, "vpif_open\n");
843
844 ch = video_get_drvdata(vdev);
845
846 vid_ch = &ch->video;
847 common = &ch->common[VPIF_VIDEO_INDEX];
848
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300849 /* Allocate memory for the file handle object */
Mats Randgaard1f8766b2010-08-30 10:30:37 -0300850 fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300851 if (NULL == fh) {
852 vpif_err("unable to allocate memory for file handle object\n");
Hans Verkuil46656af2011-01-04 06:51:35 -0300853 return -ENOMEM;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300854 }
855
Hans Verkuil72246792012-07-31 03:48:31 -0300856 if (mutex_lock_interruptible(&common->lock)) {
857 kfree(fh);
858 return -ERESTARTSYS;
859 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300860 /* store pointer to fh in private_data member of filep */
861 filep->private_data = fh;
862 fh->channel = ch;
863 fh->initialized = 0;
864 /* If decoder is not initialized. initialize it */
865 if (!ch->initialized) {
866 fh->initialized = 1;
867 ch->initialized = 1;
868 memset(&(ch->vpifparams), 0, sizeof(struct vpif_params));
869 }
870 /* Increment channel usrs counter */
871 ch->usrs++;
872 /* Set io_allowed member to false */
873 fh->io_allowed[VPIF_VIDEO_INDEX] = 0;
874 /* Initialize priority of this instance to default priority */
875 fh->prio = V4L2_PRIORITY_UNSET;
876 v4l2_prio_open(&ch->prio, &fh->prio);
Hans Verkuil72246792012-07-31 03:48:31 -0300877 mutex_unlock(&common->lock);
Hans Verkuil46656af2011-01-04 06:51:35 -0300878 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300879}
880
881/**
882 * vpif_release : function to clean up file close
883 * @filep: file pointer
884 *
Dror Cohen6f45b1b2012-07-10 05:43:22 -0300885 * This function deletes buffer queue, frees the buffers and the vpif file
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300886 * handle
887 */
888static int vpif_release(struct file *filep)
889{
890 struct vpif_fh *fh = filep->private_data;
891 struct channel_obj *ch = fh->channel;
892 struct common_obj *common;
893
894 vpif_dbg(2, debug, "vpif_release\n");
895
896 common = &ch->common[VPIF_VIDEO_INDEX];
897
Hans Verkuil72246792012-07-31 03:48:31 -0300898 mutex_lock(&common->lock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300899 /* if this instance is doing IO */
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -0300900 if (fh->io_allowed[VPIF_VIDEO_INDEX])
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300901 /* Reset io_usrs member of channel object */
902 common->io_usrs = 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300903
904 /* Decrement channel usrs counter */
905 ch->usrs--;
906
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300907 /* Close the priority */
Hans Verkuilffb48772010-05-01 08:03:24 -0300908 v4l2_prio_close(&ch->prio, fh->prio);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300909
910 if (fh->initialized)
911 ch->initialized = 0;
912
Hans Verkuil72246792012-07-31 03:48:31 -0300913 mutex_unlock(&common->lock);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300914 filep->private_data = NULL;
915 kfree(fh);
916 return 0;
917}
918
919/**
920 * vpif_reqbufs() - request buffer handler
921 * @file: file ptr
922 * @priv: file handle
923 * @reqbuf: request buffer structure ptr
924 */
925static int vpif_reqbufs(struct file *file, void *priv,
926 struct v4l2_requestbuffers *reqbuf)
927{
928 struct vpif_fh *fh = priv;
929 struct channel_obj *ch = fh->channel;
930 struct common_obj *common;
931 u8 index = 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300932
933 vpif_dbg(2, debug, "vpif_reqbufs\n");
934
935 /**
936 * This file handle has not initialized the channel,
937 * It is not allowed to do settings
938 */
939 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)
940 || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
941 if (!fh->initialized) {
942 vpif_dbg(1, debug, "Channel Busy\n");
943 return -EBUSY;
944 }
945 }
946
Manjunath Hadli764af392012-04-13 04:49:34 -0300947 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type || !vpif_dev)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300948 return -EINVAL;
949
950 index = VPIF_VIDEO_INDEX;
951
952 common = &ch->common[index];
953
Hans Verkuil46656af2011-01-04 06:51:35 -0300954 if (0 != common->io_usrs)
955 return -EBUSY;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300956
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300957 /* Set io allowed member of file handle to TRUE */
958 fh->io_allowed[index] = 1;
959 /* Increment io usrs member of channel object to 1 */
960 common->io_usrs = 1;
961 /* Store type of memory requested in channel object */
962 common->memory = reqbuf->memory;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300963
964 /* Allocate buffers */
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300965 return vb2_reqbufs(&common->buffer_queue, reqbuf);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300966}
967
968/**
969 * vpif_querybuf() - query buffer handler
970 * @file: file ptr
971 * @priv: file handle
972 * @buf: v4l2 buffer structure ptr
973 */
974static int vpif_querybuf(struct file *file, void *priv,
975 struct v4l2_buffer *buf)
976{
977 struct vpif_fh *fh = priv;
978 struct channel_obj *ch = fh->channel;
979 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
980
981 vpif_dbg(2, debug, "vpif_querybuf\n");
982
983 if (common->fmt.type != buf->type)
984 return -EINVAL;
985
986 if (common->memory != V4L2_MEMORY_MMAP) {
987 vpif_dbg(1, debug, "Invalid memory\n");
988 return -EINVAL;
989 }
990
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -0300991 return vb2_querybuf(&common->buffer_queue, buf);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -0300992}
993
994/**
995 * vpif_qbuf() - query buffer handler
996 * @file: file ptr
997 * @priv: file handle
998 * @buf: v4l2 buffer structure ptr
999 */
1000static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1001{
1002
1003 struct vpif_fh *fh = priv;
1004 struct channel_obj *ch = fh->channel;
1005 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1006 struct v4l2_buffer tbuf = *buf;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001007
1008 vpif_dbg(2, debug, "vpif_qbuf\n");
1009
1010 if (common->fmt.type != tbuf.type) {
1011 vpif_err("invalid buffer type\n");
1012 return -EINVAL;
1013 }
1014
1015 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001016 vpif_err("fh io not allowed\n");
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001017 return -EACCES;
1018 }
1019
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001020 return vb2_qbuf(&common->buffer_queue, buf);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001021}
1022
1023/**
1024 * vpif_dqbuf() - query buffer handler
1025 * @file: file ptr
1026 * @priv: file handle
1027 * @buf: v4l2 buffer structure ptr
1028 */
1029static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1030{
1031 struct vpif_fh *fh = priv;
1032 struct channel_obj *ch = fh->channel;
1033 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1034
1035 vpif_dbg(2, debug, "vpif_dqbuf\n");
1036
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001037 return vb2_dqbuf(&common->buffer_queue, buf,
1038 (file->f_flags & O_NONBLOCK));
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001039}
1040
1041/**
1042 * vpif_streamon() - streamon handler
1043 * @file: file ptr
1044 * @priv: file handle
1045 * @buftype: v4l2 buffer type
1046 */
1047static int vpif_streamon(struct file *file, void *priv,
1048 enum v4l2_buf_type buftype)
1049{
1050
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001051 struct vpif_fh *fh = priv;
1052 struct channel_obj *ch = fh->channel;
1053 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1054 struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
1055 struct vpif_params *vpif;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001056 int ret = 0;
1057
1058 vpif_dbg(2, debug, "vpif_streamon\n");
1059
1060 vpif = &ch->vpifparams;
1061
1062 if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1063 vpif_dbg(1, debug, "buffer type not supported\n");
1064 return -EINVAL;
1065 }
1066
1067 /* If file handle is not allowed IO, return error */
1068 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1069 vpif_dbg(1, debug, "io not allowed\n");
1070 return -EACCES;
1071 }
1072
1073 /* If Streaming is already started, return error */
1074 if (common->started) {
1075 vpif_dbg(1, debug, "channel->started\n");
1076 return -EBUSY;
1077 }
1078
1079 if ((ch->channel_id == VPIF_CHANNEL0_VIDEO &&
1080 oth_ch->common[VPIF_VIDEO_INDEX].started &&
1081 vpif->std_info.ycmux_mode == 0) ||
1082 ((ch->channel_id == VPIF_CHANNEL1_VIDEO) &&
1083 (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
1084 vpif_dbg(1, debug, "other channel is being used\n");
1085 return -EBUSY;
1086 }
1087
1088 ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0);
1089 if (ret)
1090 return ret;
1091
1092 /* Enable streamon on the sub device */
Hans Verkuil178cce12012-09-20 09:06:30 -03001093 ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001094
Hans Verkuil178cce12012-09-20 09:06:30 -03001095 if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001096 vpif_dbg(1, debug, "stream on failed in subdev\n");
1097 return ret;
1098 }
1099
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001100 /* Call vb2_streamon to start streaming in videobuf2 */
1101 ret = vb2_streamon(&common->buffer_queue, buftype);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001102 if (ret) {
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001103 vpif_dbg(1, debug, "vb2_streamon\n");
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001104 return ret;
1105 }
1106
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001107 return ret;
1108}
1109
1110/**
1111 * vpif_streamoff() - streamoff handler
1112 * @file: file ptr
1113 * @priv: file handle
1114 * @buftype: v4l2 buffer type
1115 */
1116static int vpif_streamoff(struct file *file, void *priv,
1117 enum v4l2_buf_type buftype)
1118{
1119
1120 struct vpif_fh *fh = priv;
1121 struct channel_obj *ch = fh->channel;
1122 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1123 int ret;
1124
1125 vpif_dbg(2, debug, "vpif_streamoff\n");
1126
1127 if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1128 vpif_dbg(1, debug, "buffer type not supported\n");
1129 return -EINVAL;
1130 }
1131
1132 /* If io is allowed for this file handle, return error */
1133 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1134 vpif_dbg(1, debug, "io not allowed\n");
1135 return -EACCES;
1136 }
1137
1138 /* If streaming is not started, return error */
1139 if (!common->started) {
1140 vpif_dbg(1, debug, "channel->started\n");
1141 return -EINVAL;
1142 }
1143
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001144 /* disable channel */
1145 if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
1146 enable_channel0(0);
1147 channel0_intr_enable(0);
1148 } else {
1149 enable_channel1(0);
1150 channel1_intr_enable(0);
1151 }
1152
1153 common->started = 0;
1154
Hans Verkuil178cce12012-09-20 09:06:30 -03001155 ret = v4l2_subdev_call(ch->sd, video, s_stream, 0);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001156
Hans Verkuil178cce12012-09-20 09:06:30 -03001157 if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001158 vpif_dbg(1, debug, "stream off failed in subdev\n");
1159
Lad, Prabhakar60aa38d2012-06-28 09:28:05 -03001160 return vb2_streamoff(&common->buffer_queue, buftype);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001161}
1162
1163/**
Hans Verkuil178cce12012-09-20 09:06:30 -03001164 * vpif_input_to_subdev() - Maps input to sub device
1165 * @vpif_cfg - global config ptr
1166 * @chan_cfg - channel config ptr
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001167 * @input_index - Given input index from application
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001168 *
1169 * lookup the sub device information for a given input index.
1170 * we report all the inputs to application. inputs table also
1171 * has sub device name for the each input
1172 */
Hans Verkuil178cce12012-09-20 09:06:30 -03001173static int vpif_input_to_subdev(
1174 struct vpif_capture_config *vpif_cfg,
1175 struct vpif_capture_chan_config *chan_cfg,
1176 int input_index)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001177{
Hans Verkuil178cce12012-09-20 09:06:30 -03001178 struct vpif_subdev_info *subdev_info;
1179 const char *subdev_name;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001180 int i;
1181
Hans Verkuil178cce12012-09-20 09:06:30 -03001182 vpif_dbg(2, debug, "vpif_input_to_subdev\n");
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001183
Hans Verkuil178cce12012-09-20 09:06:30 -03001184 subdev_name = chan_cfg->inputs[input_index].subdev_name;
1185 if (subdev_name == NULL)
1186 return -1;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001187
1188 /* loop through the sub device list to get the sub device info */
1189 for (i = 0; i < vpif_cfg->subdev_count; i++) {
1190 subdev_info = &vpif_cfg->subdev_info[i];
1191 if (!strcmp(subdev_info->name, subdev_name))
Hans Verkuil178cce12012-09-20 09:06:30 -03001192 return i;
1193 }
1194 return -1;
1195}
1196
1197/**
1198 * vpif_set_input() - Select an input
1199 * @vpif_cfg - global config ptr
1200 * @ch - channel
1201 * @_index - Given input index from application
1202 *
1203 * Select the given input.
1204 */
1205static int vpif_set_input(
1206 struct vpif_capture_config *vpif_cfg,
1207 struct channel_obj *ch,
1208 int index)
1209{
1210 struct vpif_capture_chan_config *chan_cfg =
1211 &vpif_cfg->chan_config[ch->channel_id];
1212 struct vpif_subdev_info *subdev_info = NULL;
1213 struct v4l2_subdev *sd = NULL;
1214 u32 input = 0, output = 0;
1215 int sd_index;
1216 int ret;
1217
1218 sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index);
1219 if (sd_index >= 0) {
1220 sd = vpif_obj.sd[sd_index];
1221 subdev_info = &vpif_cfg->subdev_info[sd_index];
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001222 }
1223
Hans Verkuil178cce12012-09-20 09:06:30 -03001224 /* first setup input path from sub device to vpif */
1225 if (sd && vpif_cfg->setup_input_path) {
1226 ret = vpif_cfg->setup_input_path(ch->channel_id,
1227 subdev_info->name);
1228 if (ret < 0) {
1229 vpif_dbg(1, debug, "couldn't setup input path for the" \
1230 " sub device %s, for input index %d\n",
1231 subdev_info->name, index);
1232 return ret;
1233 }
1234 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001235
Hans Verkuil178cce12012-09-20 09:06:30 -03001236 if (sd) {
1237 input = chan_cfg->inputs[index].input_route;
1238 output = chan_cfg->inputs[index].output_route;
1239 ret = v4l2_subdev_call(sd, video, s_routing,
1240 input, output, 0);
1241 if (ret < 0 && ret != -ENOIOCTLCMD) {
1242 vpif_dbg(1, debug, "Failed to set input\n");
1243 return ret;
1244 }
1245 }
1246 ch->input_idx = index;
1247 ch->sd = sd;
1248 /* copy interface parameters to vpif */
Hans Verkuil0d4f35f2012-09-20 09:06:32 -03001249 ch->vpifparams.iface = chan_cfg->vpif_if;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001250
Hans Verkuil178cce12012-09-20 09:06:30 -03001251 /* update tvnorms from the sub device input info */
1252 ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
1253 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001254}
1255
1256/**
1257 * vpif_querystd() - querystd handler
1258 * @file: file ptr
1259 * @priv: file handle
1260 * @std_id: ptr to std id
1261 *
1262 * This function is called to detect standard at the selected input
1263 */
1264static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
1265{
1266 struct vpif_fh *fh = priv;
1267 struct channel_obj *ch = fh->channel;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001268 int ret = 0;
1269
1270 vpif_dbg(2, debug, "vpif_querystd\n");
1271
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001272 /* Call querystd function of decoder device */
Hans Verkuil178cce12012-09-20 09:06:30 -03001273 ret = v4l2_subdev_call(ch->sd, video, querystd, std_id);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001274
Hans Verkuil178cce12012-09-20 09:06:30 -03001275 if (ret == -ENOIOCTLCMD || ret == -ENODEV)
1276 return -ENODATA;
1277 if (ret) {
1278 vpif_dbg(1, debug, "Failed to query standard for sub devices\n");
1279 return ret;
1280 }
1281
1282 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001283}
1284
1285/**
1286 * vpif_g_std() - get STD handler
1287 * @file: file ptr
1288 * @priv: file handle
1289 * @std_id: ptr to std id
1290 */
1291static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)
1292{
1293 struct vpif_fh *fh = priv;
1294 struct channel_obj *ch = fh->channel;
1295
1296 vpif_dbg(2, debug, "vpif_g_std\n");
1297
1298 *std = ch->video.stdid;
1299 return 0;
1300}
1301
1302/**
1303 * vpif_s_std() - set STD handler
1304 * @file: file ptr
1305 * @priv: file handle
1306 * @std_id: ptr to std id
1307 */
Hans Verkuil314527a2013-03-15 06:10:40 -03001308static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001309{
1310 struct vpif_fh *fh = priv;
1311 struct channel_obj *ch = fh->channel;
1312 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1313 int ret = 0;
1314
1315 vpif_dbg(2, debug, "vpif_s_std\n");
1316
1317 if (common->started) {
1318 vpif_err("streaming in progress\n");
1319 return -EBUSY;
1320 }
1321
1322 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1323 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1324 if (!fh->initialized) {
1325 vpif_dbg(1, debug, "Channel Busy\n");
1326 return -EBUSY;
1327 }
1328 }
1329
Hans Verkuilffb48772010-05-01 08:03:24 -03001330 ret = v4l2_prio_check(&ch->prio, fh->prio);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001331 if (0 != ret)
1332 return ret;
1333
1334 fh->initialized = 1;
1335
1336 /* Call encoder subdevice function to set the standard */
Hans Verkuil314527a2013-03-15 06:10:40 -03001337 ch->video.stdid = std_id;
Hans Verkuil0598c172012-09-18 07:18:47 -03001338 memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001339
1340 /* Get the information about the standard */
1341 if (vpif_update_std_info(ch)) {
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001342 vpif_err("Error getting the standard info\n");
Hans Verkuil46656af2011-01-04 06:51:35 -03001343 return -EINVAL;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001344 }
1345
1346 /* Configure the default format information */
1347 vpif_config_format(ch);
1348
1349 /* set standard in the sub device */
Hans Verkuil314527a2013-03-15 06:10:40 -03001350 ret = v4l2_subdev_call(ch->sd, core, s_std, std_id);
Hans Verkuil178cce12012-09-20 09:06:30 -03001351 if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001352 vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
Hans Verkuil178cce12012-09-20 09:06:30 -03001353 return ret;
1354 }
1355 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001356}
1357
1358/**
1359 * vpif_enum_input() - ENUMINPUT handler
1360 * @file: file ptr
1361 * @priv: file handle
1362 * @input: ptr to input structure
1363 */
1364static int vpif_enum_input(struct file *file, void *priv,
1365 struct v4l2_input *input)
1366{
1367
1368 struct vpif_capture_config *config = vpif_dev->platform_data;
1369 struct vpif_capture_chan_config *chan_cfg;
1370 struct vpif_fh *fh = priv;
1371 struct channel_obj *ch = fh->channel;
1372
1373 chan_cfg = &config->chan_config[ch->channel_id];
1374
1375 if (input->index >= chan_cfg->input_count) {
1376 vpif_dbg(1, debug, "Invalid input index\n");
1377 return -EINVAL;
1378 }
1379
1380 memcpy(input, &chan_cfg->inputs[input->index].input,
1381 sizeof(*input));
1382 return 0;
1383}
1384
1385/**
1386 * vpif_g_input() - Get INPUT handler
1387 * @file: file ptr
1388 * @priv: file handle
1389 * @index: ptr to input index
1390 */
1391static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
1392{
1393 struct vpif_fh *fh = priv;
1394 struct channel_obj *ch = fh->channel;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001395
Hans Verkuil6f47c6c2012-09-20 09:06:22 -03001396 *index = ch->input_idx;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001397 return 0;
1398}
1399
1400/**
1401 * vpif_s_input() - Set INPUT handler
1402 * @file: file ptr
1403 * @priv: file handle
1404 * @index: input index
1405 */
1406static int vpif_s_input(struct file *file, void *priv, unsigned int index)
1407{
1408 struct vpif_capture_config *config = vpif_dev->platform_data;
1409 struct vpif_capture_chan_config *chan_cfg;
1410 struct vpif_fh *fh = priv;
1411 struct channel_obj *ch = fh->channel;
1412 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
Hans Verkuil178cce12012-09-20 09:06:30 -03001413 int ret;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001414
1415 chan_cfg = &config->chan_config[ch->channel_id];
1416
Hans Verkuil7aaad132012-09-20 09:06:25 -03001417 if (index >= chan_cfg->input_count)
1418 return -EINVAL;
1419
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001420 if (common->started) {
1421 vpif_err("Streaming in progress\n");
1422 return -EBUSY;
1423 }
1424
1425 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1426 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1427 if (!fh->initialized) {
1428 vpif_dbg(1, debug, "Channel Busy\n");
1429 return -EBUSY;
1430 }
1431 }
1432
Hans Verkuilffb48772010-05-01 08:03:24 -03001433 ret = v4l2_prio_check(&ch->prio, fh->prio);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001434 if (0 != ret)
1435 return ret;
1436
1437 fh->initialized = 1;
Hans Verkuil178cce12012-09-20 09:06:30 -03001438 return vpif_set_input(config, ch, index);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001439}
1440
1441/**
1442 * vpif_enum_fmt_vid_cap() - ENUM_FMT handler
1443 * @file: file ptr
1444 * @priv: file handle
1445 * @index: input index
1446 */
1447static int vpif_enum_fmt_vid_cap(struct file *file, void *priv,
1448 struct v4l2_fmtdesc *fmt)
1449{
1450 struct vpif_fh *fh = priv;
1451 struct channel_obj *ch = fh->channel;
1452
1453 if (fmt->index != 0) {
1454 vpif_dbg(1, debug, "Invalid format index\n");
1455 return -EINVAL;
1456 }
1457
1458 /* Fill in the information about format */
1459 if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) {
1460 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1461 strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb");
1462 fmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
1463 } else {
1464 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1465 strcpy(fmt->description, "YCbCr4:2:2 YC Planar");
1466 fmt->pixelformat = V4L2_PIX_FMT_YUV422P;
1467 }
1468 return 0;
1469}
1470
1471/**
1472 * vpif_try_fmt_vid_cap() - TRY_FMT handler
1473 * @file: file ptr
1474 * @priv: file handle
1475 * @fmt: ptr to v4l2 format structure
1476 */
1477static int vpif_try_fmt_vid_cap(struct file *file, void *priv,
1478 struct v4l2_format *fmt)
1479{
1480 struct vpif_fh *fh = priv;
1481 struct channel_obj *ch = fh->channel;
1482 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
1483
1484 return vpif_check_format(ch, pixfmt, 1);
1485}
1486
1487
1488/**
1489 * vpif_g_fmt_vid_cap() - Set INPUT handler
1490 * @file: file ptr
1491 * @priv: file handle
1492 * @fmt: ptr to v4l2 format structure
1493 */
1494static int vpif_g_fmt_vid_cap(struct file *file, void *priv,
1495 struct v4l2_format *fmt)
1496{
1497 struct vpif_fh *fh = priv;
1498 struct channel_obj *ch = fh->channel;
1499 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1500
1501 /* Check the validity of the buffer type */
1502 if (common->fmt.type != fmt->type)
1503 return -EINVAL;
1504
1505 /* Fill in the information about format */
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001506 *fmt = common->fmt;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001507 return 0;
1508}
1509
1510/**
1511 * vpif_s_fmt_vid_cap() - Set FMT handler
1512 * @file: file ptr
1513 * @priv: file handle
1514 * @fmt: ptr to v4l2 format structure
1515 */
1516static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
1517 struct v4l2_format *fmt)
1518{
1519 struct vpif_fh *fh = priv;
1520 struct channel_obj *ch = fh->channel;
1521 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1522 struct v4l2_pix_format *pixfmt;
1523 int ret = 0;
1524
Mats Randgaard2c0ddd12010-12-16 12:17:45 -03001525 vpif_dbg(2, debug, "%s\n", __func__);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001526
1527 /* If streaming is started, return error */
1528 if (common->started) {
1529 vpif_dbg(1, debug, "Streaming is started\n");
1530 return -EBUSY;
1531 }
1532
1533 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1534 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1535 if (!fh->initialized) {
1536 vpif_dbg(1, debug, "Channel Busy\n");
1537 return -EBUSY;
1538 }
1539 }
1540
Hans Verkuilffb48772010-05-01 08:03:24 -03001541 ret = v4l2_prio_check(&ch->prio, fh->prio);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001542 if (0 != ret)
1543 return ret;
1544
1545 fh->initialized = 1;
1546
1547 pixfmt = &fmt->fmt.pix;
1548 /* Check for valid field format */
1549 ret = vpif_check_format(ch, pixfmt, 0);
1550
1551 if (ret)
1552 return ret;
1553 /* store the format in the channel object */
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001554 common->fmt = *fmt;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001555 return 0;
1556}
1557
1558/**
1559 * vpif_querycap() - QUERYCAP handler
1560 * @file: file ptr
1561 * @priv: file handle
1562 * @cap: ptr to v4l2_capability structure
1563 */
1564static int vpif_querycap(struct file *file, void *priv,
1565 struct v4l2_capability *cap)
1566{
1567 struct vpif_capture_config *config = vpif_dev->platform_data;
1568
Lad, Prabhakar626d533f2012-09-25 11:21:55 -03001569 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1570 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1571 snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
1572 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1573 dev_name(vpif_dev));
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001574 strlcpy(cap->card, config->card_name, sizeof(cap->card));
1575
1576 return 0;
1577}
1578
1579/**
1580 * vpif_g_priority() - get priority handler
1581 * @file: file ptr
1582 * @priv: file handle
1583 * @prio: ptr to v4l2_priority structure
1584 */
1585static int vpif_g_priority(struct file *file, void *priv,
1586 enum v4l2_priority *prio)
1587{
1588 struct vpif_fh *fh = priv;
1589 struct channel_obj *ch = fh->channel;
1590
1591 *prio = v4l2_prio_max(&ch->prio);
1592
1593 return 0;
1594}
1595
1596/**
1597 * vpif_s_priority() - set priority handler
1598 * @file: file ptr
1599 * @priv: file handle
1600 * @prio: ptr to v4l2_priority structure
1601 */
1602static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p)
1603{
1604 struct vpif_fh *fh = priv;
1605 struct channel_obj *ch = fh->channel;
1606
1607 return v4l2_prio_change(&ch->prio, &fh->prio, p);
1608}
1609
1610/**
1611 * vpif_cropcap() - cropcap handler
1612 * @file: file ptr
1613 * @priv: file handle
1614 * @crop: ptr to v4l2_cropcap structure
1615 */
1616static int vpif_cropcap(struct file *file, void *priv,
1617 struct v4l2_cropcap *crop)
1618{
1619 struct vpif_fh *fh = priv;
1620 struct channel_obj *ch = fh->channel;
1621 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1622
1623 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != crop->type)
1624 return -EINVAL;
1625
1626 crop->bounds.left = 0;
1627 crop->bounds.top = 0;
1628 crop->bounds.height = common->height;
1629 crop->bounds.width = common->width;
1630 crop->defrect = crop->bounds;
1631 return 0;
1632}
1633
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001634/**
Hans Verkuil0598c172012-09-18 07:18:47 -03001635 * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001636 * @file: file ptr
1637 * @priv: file handle
Hans Verkuil0598c172012-09-18 07:18:47 -03001638 * @timings: input timings
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001639 */
Hans Verkuil0598c172012-09-18 07:18:47 -03001640static int
1641vpif_enum_dv_timings(struct file *file, void *priv,
1642 struct v4l2_enum_dv_timings *timings)
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001643{
1644 struct vpif_fh *fh = priv;
1645 struct channel_obj *ch = fh->channel;
Hans Verkuil178cce12012-09-20 09:06:30 -03001646 int ret;
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001647
Hans Verkuil178cce12012-09-20 09:06:30 -03001648 ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
Wei Yongjune070f1b2012-10-30 09:45:00 -03001649 if (ret == -ENOIOCTLCMD || ret == -ENODEV)
Hans Verkuil178cce12012-09-20 09:06:30 -03001650 return -EINVAL;
1651 return ret;
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001652}
1653
1654/**
Hans Verkuil0598c172012-09-18 07:18:47 -03001655 * vpif_query_dv_timings() - QUERY_DV_TIMINGS handler
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001656 * @file: file ptr
1657 * @priv: file handle
Hans Verkuil0598c172012-09-18 07:18:47 -03001658 * @timings: input timings
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001659 */
Hans Verkuil0598c172012-09-18 07:18:47 -03001660static int
1661vpif_query_dv_timings(struct file *file, void *priv,
1662 struct v4l2_dv_timings *timings)
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001663{
1664 struct vpif_fh *fh = priv;
1665 struct channel_obj *ch = fh->channel;
Hans Verkuil178cce12012-09-20 09:06:30 -03001666 int ret;
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001667
Hans Verkuil178cce12012-09-20 09:06:30 -03001668 ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
Wei Yongjune070f1b2012-10-30 09:45:00 -03001669 if (ret == -ENOIOCTLCMD || ret == -ENODEV)
Hans Verkuil178cce12012-09-20 09:06:30 -03001670 return -ENODATA;
1671 return ret;
Mats Randgaard40c8bce2010-12-16 12:17:43 -03001672}
1673
Mats Randgaardc027e162010-12-16 12:17:44 -03001674/**
1675 * vpif_s_dv_timings() - S_DV_TIMINGS handler
1676 * @file: file ptr
1677 * @priv: file handle
1678 * @timings: digital video timings
1679 */
1680static int vpif_s_dv_timings(struct file *file, void *priv,
1681 struct v4l2_dv_timings *timings)
1682{
1683 struct vpif_fh *fh = priv;
1684 struct channel_obj *ch = fh->channel;
1685 struct vpif_params *vpifparams = &ch->vpifparams;
1686 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
1687 struct video_obj *vid_ch = &ch->video;
Hans Verkuil0598c172012-09-18 07:18:47 -03001688 struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt;
Mats Randgaardc027e162010-12-16 12:17:44 -03001689 int ret;
1690
1691 if (timings->type != V4L2_DV_BT_656_1120) {
1692 vpif_dbg(2, debug, "Timing type not defined\n");
1693 return -EINVAL;
1694 }
1695
1696 /* Configure subdevice timings, if any */
Hans Verkuil178cce12012-09-20 09:06:30 -03001697 ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
1698 if (ret == -ENOIOCTLCMD || ret == -ENODEV)
1699 ret = 0;
Mats Randgaardc027e162010-12-16 12:17:44 -03001700 if (ret < 0) {
1701 vpif_dbg(2, debug, "Error setting custom DV timings\n");
1702 return ret;
1703 }
1704
1705 if (!(timings->bt.width && timings->bt.height &&
1706 (timings->bt.hbackporch ||
1707 timings->bt.hfrontporch ||
1708 timings->bt.hsync) &&
1709 timings->bt.vfrontporch &&
1710 (timings->bt.vbackporch ||
1711 timings->bt.vsync))) {
1712 vpif_dbg(2, debug, "Timings for width, height, "
1713 "horizontal back porch, horizontal sync, "
1714 "horizontal front porch, vertical back porch, "
1715 "vertical sync and vertical back porch "
1716 "must be defined\n");
1717 return -EINVAL;
1718 }
1719
Hans Verkuil0598c172012-09-18 07:18:47 -03001720 vid_ch->dv_timings = *timings;
Mats Randgaardc027e162010-12-16 12:17:44 -03001721
1722 /* Configure video port timings */
1723
Hans Verkuile3655262013-07-29 08:41:00 -03001724 std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8;
Mats Randgaardc027e162010-12-16 12:17:44 -03001725 std_info->sav2eav = bt->width;
1726
1727 std_info->l1 = 1;
1728 std_info->l3 = bt->vsync + bt->vbackporch + 1;
1729
Hans Verkuile3655262013-07-29 08:41:00 -03001730 std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt);
Mats Randgaardc027e162010-12-16 12:17:44 -03001731 if (bt->interlaced) {
1732 if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
Mats Randgaardc027e162010-12-16 12:17:44 -03001733 std_info->l5 = std_info->vsize/2 -
1734 (bt->vfrontporch - 1);
1735 std_info->l7 = std_info->vsize/2 + 1;
1736 std_info->l9 = std_info->l7 + bt->il_vsync +
1737 bt->il_vbackporch + 1;
1738 std_info->l11 = std_info->vsize -
1739 (bt->il_vfrontporch - 1);
1740 } else {
1741 vpif_dbg(2, debug, "Required timing values for "
1742 "interlaced BT format missing\n");
1743 return -EINVAL;
1744 }
1745 } else {
Mats Randgaardc027e162010-12-16 12:17:44 -03001746 std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
1747 }
1748 strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME);
1749 std_info->width = bt->width;
1750 std_info->height = bt->height;
1751 std_info->frm_fmt = bt->interlaced ? 0 : 1;
1752 std_info->ycmux_mode = 0;
1753 std_info->capture_format = 0;
1754 std_info->vbi_supported = 0;
1755 std_info->hd_sd = 1;
1756 std_info->stdid = 0;
Mats Randgaardc027e162010-12-16 12:17:44 -03001757
1758 vid_ch->stdid = 0;
Mats Randgaardc027e162010-12-16 12:17:44 -03001759 return 0;
1760}
1761
1762/**
1763 * vpif_g_dv_timings() - G_DV_TIMINGS handler
1764 * @file: file ptr
1765 * @priv: file handle
1766 * @timings: digital video timings
1767 */
1768static int vpif_g_dv_timings(struct file *file, void *priv,
1769 struct v4l2_dv_timings *timings)
1770{
1771 struct vpif_fh *fh = priv;
1772 struct channel_obj *ch = fh->channel;
1773 struct video_obj *vid_ch = &ch->video;
Mats Randgaardc027e162010-12-16 12:17:44 -03001774
Hans Verkuil0598c172012-09-18 07:18:47 -03001775 *timings = vid_ch->dv_timings;
Mats Randgaardc027e162010-12-16 12:17:44 -03001776
1777 return 0;
1778}
1779
Mats Randgaard7036d6a2010-12-16 12:17:41 -03001780/*
Mats Randgaard7036d6a2010-12-16 12:17:41 -03001781 * vpif_log_status() - Status information
1782 * @file: file ptr
1783 * @priv: file handle
1784 *
1785 * Returns zero.
1786 */
1787static int vpif_log_status(struct file *filep, void *priv)
1788{
1789 /* status for sub devices */
1790 v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
1791
1792 return 0;
1793}
1794
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001795/* vpif capture ioctl operations */
1796static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
1797 .vidioc_querycap = vpif_querycap,
1798 .vidioc_g_priority = vpif_g_priority,
1799 .vidioc_s_priority = vpif_s_priority,
1800 .vidioc_enum_fmt_vid_cap = vpif_enum_fmt_vid_cap,
1801 .vidioc_g_fmt_vid_cap = vpif_g_fmt_vid_cap,
1802 .vidioc_s_fmt_vid_cap = vpif_s_fmt_vid_cap,
1803 .vidioc_try_fmt_vid_cap = vpif_try_fmt_vid_cap,
1804 .vidioc_enum_input = vpif_enum_input,
1805 .vidioc_s_input = vpif_s_input,
1806 .vidioc_g_input = vpif_g_input,
1807 .vidioc_reqbufs = vpif_reqbufs,
1808 .vidioc_querybuf = vpif_querybuf,
1809 .vidioc_querystd = vpif_querystd,
1810 .vidioc_s_std = vpif_s_std,
1811 .vidioc_g_std = vpif_g_std,
1812 .vidioc_qbuf = vpif_qbuf,
1813 .vidioc_dqbuf = vpif_dqbuf,
1814 .vidioc_streamon = vpif_streamon,
1815 .vidioc_streamoff = vpif_streamoff,
1816 .vidioc_cropcap = vpif_cropcap,
Hans Verkuil0598c172012-09-18 07:18:47 -03001817 .vidioc_enum_dv_timings = vpif_enum_dv_timings,
1818 .vidioc_query_dv_timings = vpif_query_dv_timings,
Mats Randgaardc027e162010-12-16 12:17:44 -03001819 .vidioc_s_dv_timings = vpif_s_dv_timings,
1820 .vidioc_g_dv_timings = vpif_g_dv_timings,
Mats Randgaard7036d6a2010-12-16 12:17:41 -03001821 .vidioc_log_status = vpif_log_status,
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001822};
1823
1824/* vpif file operations */
1825static struct v4l2_file_operations vpif_fops = {
1826 .owner = THIS_MODULE,
1827 .open = vpif_open,
1828 .release = vpif_release,
Hans Verkuil46656af2011-01-04 06:51:35 -03001829 .unlocked_ioctl = video_ioctl2,
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001830 .mmap = vpif_mmap,
1831 .poll = vpif_poll
1832};
1833
1834/* vpif video template */
1835static struct video_device vpif_video_template = {
1836 .name = "vpif",
1837 .fops = &vpif_fops,
1838 .minor = -1,
1839 .ioctl_ops = &vpif_ioctl_ops,
1840};
1841
1842/**
1843 * initialize_vpif() - Initialize vpif data structures
1844 *
1845 * Allocate memory for data structures and initialize them
1846 */
1847static int initialize_vpif(void)
1848{
1849 int err = 0, i, j;
1850 int free_channel_objects_index;
1851
1852 /* Default number of buffers should be 3 */
1853 if ((ch0_numbuffers > 0) &&
1854 (ch0_numbuffers < config_params.min_numbuffers))
1855 ch0_numbuffers = config_params.min_numbuffers;
1856 if ((ch1_numbuffers > 0) &&
1857 (ch1_numbuffers < config_params.min_numbuffers))
1858 ch1_numbuffers = config_params.min_numbuffers;
1859
1860 /* Set buffer size to min buffers size if it is invalid */
1861 if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
1862 ch0_bufsize =
1863 config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
1864 if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
1865 ch1_bufsize =
1866 config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
1867
1868 config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers;
1869 config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers;
1870 if (ch0_numbuffers) {
1871 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
1872 = ch0_bufsize;
1873 }
1874 if (ch1_numbuffers) {
1875 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
1876 = ch1_bufsize;
1877 }
1878
1879 /* Allocate memory for six channel objects */
1880 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
1881 vpif_obj.dev[i] =
1882 kzalloc(sizeof(*vpif_obj.dev[i]), GFP_KERNEL);
1883 /* If memory allocation fails, return error */
1884 if (!vpif_obj.dev[i]) {
1885 free_channel_objects_index = i;
1886 err = -ENOMEM;
1887 goto vpif_init_free_channel_objects;
1888 }
1889 }
1890 return 0;
1891
1892vpif_init_free_channel_objects:
1893 for (j = 0; j < free_channel_objects_index; j++)
1894 kfree(vpif_obj.dev[j]);
1895 return err;
1896}
1897
Lad, Prabhakar873229e2013-06-25 11:17:34 -03001898static int vpif_async_bound(struct v4l2_async_notifier *notifier,
1899 struct v4l2_subdev *subdev,
1900 struct v4l2_async_subdev *asd)
1901{
1902 int i;
1903
1904 for (i = 0; i < vpif_obj.config->subdev_count; i++)
1905 if (!strcmp(vpif_obj.config->subdev_info[i].name,
1906 subdev->name)) {
1907 vpif_obj.sd[i] = subdev;
1908 return 0;
1909 }
1910
1911 return -EINVAL;
1912}
1913
1914static int vpif_probe_complete(void)
1915{
1916 struct common_obj *common;
1917 struct channel_obj *ch;
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03001918 struct vb2_queue *q;
Lad, Prabhakar873229e2013-06-25 11:17:34 -03001919 int i, j, err, k;
1920
1921 for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
1922 ch = vpif_obj.dev[j];
1923 ch->channel_id = j;
1924 common = &(ch->common[VPIF_VIDEO_INDEX]);
1925 spin_lock_init(&common->irqlock);
1926 mutex_init(&common->lock);
1927 ch->video_dev->lock = &common->lock;
1928 /* Initialize prio member of channel object */
1929 v4l2_prio_init(&ch->prio);
1930 video_set_drvdata(ch->video_dev, ch);
1931
1932 /* select input 0 */
1933 err = vpif_set_input(vpif_obj.config, ch, 0);
1934 if (err)
1935 goto probe_out;
1936
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03001937 /* Initialize vb2 queue */
1938 q = &common->buffer_queue;
1939 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1940 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1941 q->drv_priv = ch;
1942 q->ops = &video_qops;
1943 q->mem_ops = &vb2_dma_contig_memops;
1944 q->buf_struct_size = sizeof(struct vpif_cap_buffer);
1945 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1946 q->min_buffers_needed = 1;
Lad, Prabhakar999ba692014-05-16 10:33:33 -03001947 q->lock = &common->lock;
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03001948
1949 err = vb2_queue_init(q);
1950 if (err) {
1951 vpif_err("vpif_capture: vb2_queue_init() failed\n");
1952 goto probe_out;
1953 }
1954
1955 common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
1956 if (IS_ERR(common->alloc_ctx)) {
1957 vpif_err("Failed to get the context\n");
1958 err = PTR_ERR(common->alloc_ctx);
1959 goto probe_out;
1960 }
1961
1962 INIT_LIST_HEAD(&common->dma_queue);
1963
Lad, Prabhakar873229e2013-06-25 11:17:34 -03001964 err = video_register_device(ch->video_dev,
1965 VFL_TYPE_GRABBER, (j ? 1 : 0));
1966 if (err)
1967 goto probe_out;
1968 }
1969
1970 v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
1971 return 0;
1972
1973probe_out:
1974 for (k = 0; k < j; k++) {
1975 /* Get the pointer to the channel object */
1976 ch = vpif_obj.dev[k];
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03001977 common = &ch->common[k];
1978 vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
Lad, Prabhakar873229e2013-06-25 11:17:34 -03001979 /* Unregister video device */
1980 video_unregister_device(ch->video_dev);
1981 }
1982 kfree(vpif_obj.sd);
1983 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
1984 ch = vpif_obj.dev[i];
1985 /* Note: does nothing if ch->video_dev == NULL */
1986 video_device_release(ch->video_dev);
1987 }
1988 v4l2_device_unregister(&vpif_obj.v4l2_dev);
1989
1990 return err;
1991}
1992
1993static int vpif_async_complete(struct v4l2_async_notifier *notifier)
1994{
1995 return vpif_probe_complete();
1996}
1997
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03001998/**
1999 * vpif_probe : This function probes the vpif capture driver
2000 * @pdev: platform device pointer
2001 *
2002 * This creates device entries by register itself to the V4L2 driver and
2003 * initializes fields of each channel objects
2004 */
2005static __init int vpif_probe(struct platform_device *pdev)
2006{
2007 struct vpif_subdev_info *subdevdata;
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002008 int i, j, err;
Hans Verkuil5be452c2012-09-20 09:06:29 -03002009 int res_idx = 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002010 struct i2c_adapter *i2c_adap;
2011 struct channel_obj *ch;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002012 struct video_device *vfd;
2013 struct resource *res;
2014 int subdev_count;
Manjunath Hadli764af392012-04-13 04:49:34 -03002015 size_t size;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002016
2017 vpif_dev = &pdev->dev;
2018
2019 err = initialize_vpif();
2020 if (err) {
2021 v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
2022 return err;
2023 }
2024
Hans Verkuild2f7a1a2011-12-13 05:44:42 -03002025 err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
2026 if (err) {
2027 v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
2028 return err;
2029 }
2030
Hans Verkuil5be452c2012-09-20 09:06:29 -03002031 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
Lad, Prabhakara76a0b32013-06-17 11:20:47 -03002032 err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr,
2033 IRQF_SHARED, "VPIF_Capture",
2034 (void *)(&vpif_obj.dev[res_idx]->
2035 channel_id));
2036 if (err) {
2037 err = -EINVAL;
2038 goto vpif_unregister;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002039 }
Hans Verkuil5be452c2012-09-20 09:06:29 -03002040 res_idx++;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002041 }
2042
2043 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2044 /* Get the pointer to the channel object */
2045 ch = vpif_obj.dev[i];
2046 /* Allocate memory for video device */
2047 vfd = video_device_alloc();
2048 if (NULL == vfd) {
2049 for (j = 0; j < i; j++) {
2050 ch = vpif_obj.dev[j];
2051 video_device_release(ch->video_dev);
2052 }
2053 err = -ENOMEM;
Lad, Prabhakarb2de4f22013-06-17 11:20:46 -03002054 goto vpif_unregister;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002055 }
2056
2057 /* Initialize field of video device */
2058 *vfd = vpif_video_template;
2059 vfd->v4l2_dev = &vpif_obj.v4l2_dev;
2060 vfd->release = video_device_release;
2061 snprintf(vfd->name, sizeof(vfd->name),
Manjunath Hadli0a631722012-04-13 04:44:00 -03002062 "VPIF_Capture_DRIVER_V%s",
Mauro Carvalho Chehab64dc3c12011-06-25 11:28:37 -03002063 VPIF_CAPTURE_VERSION);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002064 /* Set video_dev to the video device */
2065 ch->video_dev = vfd;
2066 }
2067
Manjunath Hadli764af392012-04-13 04:49:34 -03002068 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2069 if (res) {
2070 size = resource_size(res);
2071 /* The resources are divided into two equal memory and when we
2072 * have HD output we can add them together
2073 */
2074 for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
2075 ch = vpif_obj.dev[j];
2076 ch->channel_id = j;
2077 /* only enabled if second resource exists */
2078 config_params.video_limit[ch->channel_id] = 0;
2079 if (size)
2080 config_params.video_limit[ch->channel_id] =
2081 size/2;
2082 }
2083 }
2084
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002085 vpif_obj.config = pdev->dev.platform_data;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002086
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002087 subdev_count = vpif_obj.config->subdev_count;
Mats Randgaard1f8766b2010-08-30 10:30:37 -03002088 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002089 GFP_KERNEL);
2090 if (vpif_obj.sd == NULL) {
2091 vpif_err("unable to allocate memory for subdevice pointers\n");
2092 err = -ENOMEM;
Hans Verkuil5be452c2012-09-20 09:06:29 -03002093 goto vpif_sd_error;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002094 }
2095
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002096 if (!vpif_obj.config->asd_sizes) {
2097 i2c_adap = i2c_get_adapter(1);
2098 for (i = 0; i < subdev_count; i++) {
2099 subdevdata = &vpif_obj.config->subdev_info[i];
2100 vpif_obj.sd[i] =
2101 v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
2102 i2c_adap,
2103 &subdevdata->
2104 board_info,
2105 NULL);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002106
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002107 if (!vpif_obj.sd[i]) {
2108 vpif_err("Error registering v4l2 subdevice\n");
Wei Yongjun2fcd9dc2013-09-02 05:06:10 -03002109 err = -ENODEV;
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002110 goto probe_subdev_out;
2111 }
2112 v4l2_info(&vpif_obj.v4l2_dev,
2113 "registered sub device %s\n",
2114 subdevdata->name);
2115 }
2116 vpif_probe_complete();
2117 } else {
Sylwester Nawrockie8419d02013-07-19 12:31:10 -03002118 vpif_obj.notifier.subdevs = vpif_obj.config->asd;
Lad, Prabhakar873229e2013-06-25 11:17:34 -03002119 vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
2120 vpif_obj.notifier.bound = vpif_async_bound;
2121 vpif_obj.notifier.complete = vpif_async_complete;
2122 err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
2123 &vpif_obj.notifier);
2124 if (err) {
2125 vpif_err("Error registering async notifier\n");
2126 err = -EINVAL;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002127 goto probe_subdev_out;
2128 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002129 }
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002130
2131 return 0;
2132
Hans Verkuilb65814e2012-09-20 09:06:26 -03002133probe_subdev_out:
2134 /* free sub devices memory */
2135 kfree(vpif_obj.sd);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002136
Hans Verkuil5be452c2012-09-20 09:06:29 -03002137vpif_sd_error:
2138 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2139 ch = vpif_obj.dev[i];
2140 /* Note: does nothing if ch->video_dev == NULL */
2141 video_device_release(ch->video_dev);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002142 }
Lad, Prabhakarb2de4f22013-06-17 11:20:46 -03002143vpif_unregister:
Hans Verkuild2f7a1a2011-12-13 05:44:42 -03002144 v4l2_device_unregister(&vpif_obj.v4l2_dev);
Lad, Prabhakarb2de4f22013-06-17 11:20:46 -03002145
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002146 return err;
2147}
2148
2149/**
2150 * vpif_remove() - driver remove handler
2151 * @device: ptr to platform device structure
2152 *
2153 * The vidoe device is unregistered
2154 */
2155static int vpif_remove(struct platform_device *device)
2156{
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03002157 struct common_obj *common;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002158 struct channel_obj *ch;
Lad, Prabhakarb2de4f22013-06-17 11:20:46 -03002159 int i;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002160
2161 v4l2_device_unregister(&vpif_obj.v4l2_dev);
2162
Lad, Prabhakar410ca602013-06-17 11:20:44 -03002163 kfree(vpif_obj.sd);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002164 /* un-register device */
2165 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2166 /* Get the pointer to the channel object */
2167 ch = vpif_obj.dev[i];
Lad, Prabhakarfa09acc2014-05-16 10:33:31 -03002168 common = &ch->common[i];
2169 vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002170 /* Unregister video device */
2171 video_unregister_device(ch->video_dev);
Lad, Prabhakar410ca602013-06-17 11:20:44 -03002172 kfree(vpif_obj.dev[i]);
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002173 }
2174 return 0;
2175}
2176
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002177#ifdef CONFIG_PM
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002178/**
2179 * vpif_suspend: vpif device suspend
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002180 */
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002181static int vpif_suspend(struct device *dev)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002182{
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002183
2184 struct common_obj *common;
2185 struct channel_obj *ch;
2186 int i;
2187
2188 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2189 /* Get the pointer to the channel object */
2190 ch = vpif_obj.dev[i];
2191 common = &ch->common[VPIF_VIDEO_INDEX];
2192 mutex_lock(&common->lock);
2193 if (ch->usrs && common->io_usrs) {
2194 /* Disable channel */
2195 if (ch->channel_id == VPIF_CHANNEL0_VIDEO) {
2196 enable_channel0(0);
2197 channel0_intr_enable(0);
2198 }
2199 if (ch->channel_id == VPIF_CHANNEL1_VIDEO ||
2200 common->started == 2) {
2201 enable_channel1(0);
2202 channel1_intr_enable(0);
2203 }
2204 }
2205 mutex_unlock(&common->lock);
2206 }
2207
2208 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002209}
2210
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002211/*
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002212 * vpif_resume: vpif device suspend
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002213 */
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002214static int vpif_resume(struct device *dev)
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002215{
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002216 struct common_obj *common;
2217 struct channel_obj *ch;
2218 int i;
2219
2220 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2221 /* Get the pointer to the channel object */
2222 ch = vpif_obj.dev[i];
2223 common = &ch->common[VPIF_VIDEO_INDEX];
2224 mutex_lock(&common->lock);
2225 if (ch->usrs && common->io_usrs) {
2226 /* Disable channel */
2227 if (ch->channel_id == VPIF_CHANNEL0_VIDEO) {
2228 enable_channel0(1);
2229 channel0_intr_enable(1);
2230 }
2231 if (ch->channel_id == VPIF_CHANNEL1_VIDEO ||
2232 common->started == 2) {
2233 enable_channel1(1);
2234 channel1_intr_enable(1);
2235 }
2236 }
2237 mutex_unlock(&common->lock);
2238 }
2239
2240 return 0;
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002241}
2242
Alexey Dobriyan47145212009-12-14 18:00:08 -08002243static const struct dev_pm_ops vpif_dev_pm_ops = {
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002244 .suspend = vpif_suspend,
2245 .resume = vpif_resume,
2246};
2247
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002248#define vpif_pm_ops (&vpif_dev_pm_ops)
2249#else
2250#define vpif_pm_ops NULL
2251#endif
2252
Mats Randgaardffa1b392010-08-30 10:30:36 -03002253static __refdata struct platform_driver vpif_driver = {
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002254 .driver = {
2255 .name = "vpif_capture",
2256 .owner = THIS_MODULE,
Manjunath Hadli3d5946d2012-04-13 04:50:55 -03002257 .pm = vpif_pm_ops,
Muralidharan Karicheri6ffefff2009-09-16 14:31:10 -03002258 },
2259 .probe = vpif_probe,
2260 .remove = vpif_remove,
2261};
2262
Lad, Prabhakarfe424b22013-06-17 11:20:45 -03002263module_platform_driver(vpif_driver);