diff options
Diffstat (limited to 'drivers/media/video/blackfin')
-rw-r--r-- | drivers/media/video/blackfin/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/video/blackfin/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/video/blackfin/bfin_capture.c | 1068 | ||||
-rw-r--r-- | drivers/media/video/blackfin/ppi.c | 271 |
4 files changed, 0 insertions, 1351 deletions
diff --git a/drivers/media/video/blackfin/Kconfig b/drivers/media/video/blackfin/Kconfig deleted file mode 100644 index ecd5323768b7..000000000000 --- a/drivers/media/video/blackfin/Kconfig +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | config VIDEO_BLACKFIN_CAPTURE | ||
2 | tristate "Blackfin Video Capture Driver" | ||
3 | depends on VIDEO_V4L2 && BLACKFIN && I2C | ||
4 | select VIDEOBUF2_DMA_CONTIG | ||
5 | help | ||
6 | V4L2 bridge driver for Blackfin video capture device. | ||
7 | Choose PPI or EPPI as its interface. | ||
8 | |||
9 | To compile this driver as a module, choose M here: the | ||
10 | module will be called bfin_video_capture. | ||
diff --git a/drivers/media/video/blackfin/Makefile b/drivers/media/video/blackfin/Makefile deleted file mode 100644 index aa3a0a216387..000000000000 --- a/drivers/media/video/blackfin/Makefile +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | bfin_video_capture-objs := bfin_capture.o ppi.o | ||
2 | obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o | ||
diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c deleted file mode 100644 index 1677623d8296..000000000000 --- a/drivers/media/video/blackfin/bfin_capture.c +++ /dev/null | |||
@@ -1,1068 +0,0 @@ | |||
1 | /* | ||
2 | * Analog Devices video capture driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/completion.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/time.h> | ||
33 | #include <linux/types.h> | ||
34 | |||
35 | #include <media/v4l2-chip-ident.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/v4l2-ctrls.h> | ||
38 | #include <media/v4l2-device.h> | ||
39 | #include <media/v4l2-ioctl.h> | ||
40 | #include <media/videobuf2-dma-contig.h> | ||
41 | |||
42 | #include <asm/dma.h> | ||
43 | |||
44 | #include <media/blackfin/bfin_capture.h> | ||
45 | #include <media/blackfin/ppi.h> | ||
46 | |||
47 | #define CAPTURE_DRV_NAME "bfin_capture" | ||
48 | #define BCAP_MIN_NUM_BUF 2 | ||
49 | |||
50 | struct bcap_format { | ||
51 | char *desc; | ||
52 | u32 pixelformat; | ||
53 | enum v4l2_mbus_pixelcode mbus_code; | ||
54 | int bpp; /* bits per pixel */ | ||
55 | }; | ||
56 | |||
57 | struct bcap_buffer { | ||
58 | struct vb2_buffer vb; | ||
59 | struct list_head list; | ||
60 | }; | ||
61 | |||
62 | struct bcap_device { | ||
63 | /* capture device instance */ | ||
64 | struct v4l2_device v4l2_dev; | ||
65 | /* v4l2 control handler */ | ||
66 | struct v4l2_ctrl_handler ctrl_handler; | ||
67 | /* device node data */ | ||
68 | struct video_device *video_dev; | ||
69 | /* sub device instance */ | ||
70 | struct v4l2_subdev *sd; | ||
71 | /* capture config */ | ||
72 | struct bfin_capture_config *cfg; | ||
73 | /* ppi interface */ | ||
74 | struct ppi_if *ppi; | ||
75 | /* current input */ | ||
76 | unsigned int cur_input; | ||
77 | /* current selected standard */ | ||
78 | v4l2_std_id std; | ||
79 | /* used to store pixel format */ | ||
80 | struct v4l2_pix_format fmt; | ||
81 | /* bits per pixel*/ | ||
82 | int bpp; | ||
83 | /* used to store sensor supported format */ | ||
84 | struct bcap_format *sensor_formats; | ||
85 | /* number of sensor formats array */ | ||
86 | int num_sensor_formats; | ||
87 | /* pointing to current video buffer */ | ||
88 | struct bcap_buffer *cur_frm; | ||
89 | /* pointing to next video buffer */ | ||
90 | struct bcap_buffer *next_frm; | ||
91 | /* buffer queue used in videobuf2 */ | ||
92 | struct vb2_queue buffer_queue; | ||
93 | /* allocator-specific contexts for each plane */ | ||
94 | struct vb2_alloc_ctx *alloc_ctx; | ||
95 | /* queue of filled frames */ | ||
96 | struct list_head dma_queue; | ||
97 | /* used in videobuf2 callback */ | ||
98 | spinlock_t lock; | ||
99 | /* used to access capture device */ | ||
100 | struct mutex mutex; | ||
101 | /* used to wait ppi to complete one transfer */ | ||
102 | struct completion comp; | ||
103 | /* prepare to stop */ | ||
104 | bool stop; | ||
105 | }; | ||
106 | |||
107 | struct bcap_fh { | ||
108 | struct v4l2_fh fh; | ||
109 | /* indicates whether this file handle is doing IO */ | ||
110 | bool io_allowed; | ||
111 | }; | ||
112 | |||
113 | static const struct bcap_format bcap_formats[] = { | ||
114 | { | ||
115 | .desc = "YCbCr 4:2:2 Interleaved UYVY", | ||
116 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
117 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
118 | .bpp = 16, | ||
119 | }, | ||
120 | { | ||
121 | .desc = "YCbCr 4:2:2 Interleaved YUYV", | ||
122 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
123 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
124 | .bpp = 16, | ||
125 | }, | ||
126 | { | ||
127 | .desc = "RGB 565", | ||
128 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
129 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
130 | .bpp = 16, | ||
131 | }, | ||
132 | { | ||
133 | .desc = "RGB 444", | ||
134 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
135 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | ||
136 | .bpp = 16, | ||
137 | }, | ||
138 | |||
139 | }; | ||
140 | #define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) | ||
141 | |||
142 | static irqreturn_t bcap_isr(int irq, void *dev_id); | ||
143 | |||
144 | static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) | ||
145 | { | ||
146 | return container_of(vb, struct bcap_buffer, vb); | ||
147 | } | ||
148 | |||
149 | static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) | ||
150 | { | ||
151 | enum v4l2_mbus_pixelcode code; | ||
152 | struct bcap_format *sf; | ||
153 | unsigned int num_formats = 0; | ||
154 | int i, j; | ||
155 | |||
156 | while (!v4l2_subdev_call(bcap_dev->sd, video, | ||
157 | enum_mbus_fmt, num_formats, &code)) | ||
158 | num_formats++; | ||
159 | if (!num_formats) | ||
160 | return -ENXIO; | ||
161 | |||
162 | sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL); | ||
163 | if (!sf) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | for (i = 0; i < num_formats; i++) { | ||
167 | v4l2_subdev_call(bcap_dev->sd, video, | ||
168 | enum_mbus_fmt, i, &code); | ||
169 | for (j = 0; j < BCAP_MAX_FMTS; j++) | ||
170 | if (code == bcap_formats[j].mbus_code) | ||
171 | break; | ||
172 | if (j == BCAP_MAX_FMTS) { | ||
173 | /* we don't allow this sensor working with our bridge */ | ||
174 | kfree(sf); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | sf[i] = bcap_formats[j]; | ||
178 | } | ||
179 | bcap_dev->sensor_formats = sf; | ||
180 | bcap_dev->num_sensor_formats = num_formats; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) | ||
185 | { | ||
186 | bcap_dev->num_sensor_formats = 0; | ||
187 | kfree(bcap_dev->sensor_formats); | ||
188 | bcap_dev->sensor_formats = NULL; | ||
189 | } | ||
190 | |||
191 | static int bcap_open(struct file *file) | ||
192 | { | ||
193 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
194 | struct video_device *vfd = bcap_dev->video_dev; | ||
195 | struct bcap_fh *bcap_fh; | ||
196 | |||
197 | if (!bcap_dev->sd) { | ||
198 | v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n"); | ||
199 | return -ENODEV; | ||
200 | } | ||
201 | |||
202 | bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); | ||
203 | if (!bcap_fh) { | ||
204 | v4l2_err(&bcap_dev->v4l2_dev, | ||
205 | "unable to allocate memory for file handle object\n"); | ||
206 | return -ENOMEM; | ||
207 | } | ||
208 | |||
209 | v4l2_fh_init(&bcap_fh->fh, vfd); | ||
210 | |||
211 | /* store pointer to v4l2_fh in private_data member of file */ | ||
212 | file->private_data = &bcap_fh->fh; | ||
213 | v4l2_fh_add(&bcap_fh->fh); | ||
214 | bcap_fh->io_allowed = false; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int bcap_release(struct file *file) | ||
219 | { | ||
220 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
221 | struct v4l2_fh *fh = file->private_data; | ||
222 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
223 | |||
224 | /* if this instance is doing IO */ | ||
225 | if (bcap_fh->io_allowed) | ||
226 | vb2_queue_release(&bcap_dev->buffer_queue); | ||
227 | |||
228 | file->private_data = NULL; | ||
229 | v4l2_fh_del(&bcap_fh->fh); | ||
230 | v4l2_fh_exit(&bcap_fh->fh); | ||
231 | kfree(bcap_fh); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int bcap_mmap(struct file *file, struct vm_area_struct *vma) | ||
236 | { | ||
237 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
238 | int ret; | ||
239 | |||
240 | if (mutex_lock_interruptible(&bcap_dev->mutex)) | ||
241 | return -ERESTARTSYS; | ||
242 | ret = vb2_mmap(&bcap_dev->buffer_queue, vma); | ||
243 | mutex_unlock(&bcap_dev->mutex); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | #ifndef CONFIG_MMU | ||
248 | static unsigned long bcap_get_unmapped_area(struct file *file, | ||
249 | unsigned long addr, | ||
250 | unsigned long len, | ||
251 | unsigned long pgoff, | ||
252 | unsigned long flags) | ||
253 | { | ||
254 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
255 | |||
256 | return vb2_get_unmapped_area(&bcap_dev->buffer_queue, | ||
257 | addr, | ||
258 | len, | ||
259 | pgoff, | ||
260 | flags); | ||
261 | } | ||
262 | #endif | ||
263 | |||
264 | static unsigned int bcap_poll(struct file *file, poll_table *wait) | ||
265 | { | ||
266 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
267 | unsigned int res; | ||
268 | |||
269 | mutex_lock(&bcap_dev->mutex); | ||
270 | res = vb2_poll(&bcap_dev->buffer_queue, file, wait); | ||
271 | mutex_unlock(&bcap_dev->mutex); | ||
272 | return res; | ||
273 | } | ||
274 | |||
275 | static int bcap_queue_setup(struct vb2_queue *vq, | ||
276 | const struct v4l2_format *fmt, | ||
277 | unsigned int *nbuffers, unsigned int *nplanes, | ||
278 | unsigned int sizes[], void *alloc_ctxs[]) | ||
279 | { | ||
280 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
281 | |||
282 | if (*nbuffers < BCAP_MIN_NUM_BUF) | ||
283 | *nbuffers = BCAP_MIN_NUM_BUF; | ||
284 | |||
285 | *nplanes = 1; | ||
286 | sizes[0] = bcap_dev->fmt.sizeimage; | ||
287 | alloc_ctxs[0] = bcap_dev->alloc_ctx; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int bcap_buffer_init(struct vb2_buffer *vb) | ||
293 | { | ||
294 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
295 | |||
296 | INIT_LIST_HEAD(&buf->list); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int bcap_buffer_prepare(struct vb2_buffer *vb) | ||
301 | { | ||
302 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
303 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
304 | unsigned long size; | ||
305 | |||
306 | size = bcap_dev->fmt.sizeimage; | ||
307 | if (vb2_plane_size(vb, 0) < size) { | ||
308 | v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", | ||
309 | vb2_plane_size(vb, 0), size); | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | vb2_set_plane_payload(&buf->vb, 0, size); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static void bcap_buffer_queue(struct vb2_buffer *vb) | ||
318 | { | ||
319 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
320 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
321 | unsigned long flags; | ||
322 | |||
323 | spin_lock_irqsave(&bcap_dev->lock, flags); | ||
324 | list_add_tail(&buf->list, &bcap_dev->dma_queue); | ||
325 | spin_unlock_irqrestore(&bcap_dev->lock, flags); | ||
326 | } | ||
327 | |||
328 | static void bcap_buffer_cleanup(struct vb2_buffer *vb) | ||
329 | { | ||
330 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
331 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
332 | unsigned long flags; | ||
333 | |||
334 | spin_lock_irqsave(&bcap_dev->lock, flags); | ||
335 | list_del_init(&buf->list); | ||
336 | spin_unlock_irqrestore(&bcap_dev->lock, flags); | ||
337 | } | ||
338 | |||
339 | static void bcap_lock(struct vb2_queue *vq) | ||
340 | { | ||
341 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
342 | mutex_lock(&bcap_dev->mutex); | ||
343 | } | ||
344 | |||
345 | static void bcap_unlock(struct vb2_queue *vq) | ||
346 | { | ||
347 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
348 | mutex_unlock(&bcap_dev->mutex); | ||
349 | } | ||
350 | |||
351 | static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
352 | { | ||
353 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
354 | struct ppi_if *ppi = bcap_dev->ppi; | ||
355 | struct ppi_params params; | ||
356 | int ret; | ||
357 | |||
358 | /* enable streamon on the sub device */ | ||
359 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); | ||
360 | if (ret && (ret != -ENOIOCTLCMD)) { | ||
361 | v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | /* set ppi params */ | ||
366 | params.width = bcap_dev->fmt.width; | ||
367 | params.height = bcap_dev->fmt.height; | ||
368 | params.bpp = bcap_dev->bpp; | ||
369 | params.ppi_control = bcap_dev->cfg->ppi_control; | ||
370 | params.int_mask = bcap_dev->cfg->int_mask; | ||
371 | params.blank_clocks = bcap_dev->cfg->blank_clocks; | ||
372 | ret = ppi->ops->set_params(ppi, ¶ms); | ||
373 | if (ret < 0) { | ||
374 | v4l2_err(&bcap_dev->v4l2_dev, | ||
375 | "Error in setting ppi params\n"); | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | /* attach ppi DMA irq handler */ | ||
380 | ret = ppi->ops->attach_irq(ppi, bcap_isr); | ||
381 | if (ret < 0) { | ||
382 | v4l2_err(&bcap_dev->v4l2_dev, | ||
383 | "Error in attaching interrupt handler\n"); | ||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | INIT_COMPLETION(bcap_dev->comp); | ||
388 | bcap_dev->stop = false; | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int bcap_stop_streaming(struct vb2_queue *vq) | ||
393 | { | ||
394 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
395 | struct ppi_if *ppi = bcap_dev->ppi; | ||
396 | int ret; | ||
397 | |||
398 | if (!vb2_is_streaming(vq)) | ||
399 | return 0; | ||
400 | |||
401 | bcap_dev->stop = true; | ||
402 | wait_for_completion(&bcap_dev->comp); | ||
403 | ppi->ops->stop(ppi); | ||
404 | ppi->ops->detach_irq(ppi); | ||
405 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); | ||
406 | if (ret && (ret != -ENOIOCTLCMD)) | ||
407 | v4l2_err(&bcap_dev->v4l2_dev, | ||
408 | "stream off failed in subdev\n"); | ||
409 | |||
410 | /* release all active buffers */ | ||
411 | while (!list_empty(&bcap_dev->dma_queue)) { | ||
412 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
413 | struct bcap_buffer, list); | ||
414 | list_del(&bcap_dev->next_frm->list); | ||
415 | vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); | ||
416 | } | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static struct vb2_ops bcap_video_qops = { | ||
421 | .queue_setup = bcap_queue_setup, | ||
422 | .buf_init = bcap_buffer_init, | ||
423 | .buf_prepare = bcap_buffer_prepare, | ||
424 | .buf_cleanup = bcap_buffer_cleanup, | ||
425 | .buf_queue = bcap_buffer_queue, | ||
426 | .wait_prepare = bcap_unlock, | ||
427 | .wait_finish = bcap_lock, | ||
428 | .start_streaming = bcap_start_streaming, | ||
429 | .stop_streaming = bcap_stop_streaming, | ||
430 | }; | ||
431 | |||
432 | static int bcap_reqbufs(struct file *file, void *priv, | ||
433 | struct v4l2_requestbuffers *req_buf) | ||
434 | { | ||
435 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
436 | struct vb2_queue *vq = &bcap_dev->buffer_queue; | ||
437 | struct v4l2_fh *fh = file->private_data; | ||
438 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
439 | |||
440 | if (vb2_is_busy(vq)) | ||
441 | return -EBUSY; | ||
442 | |||
443 | bcap_fh->io_allowed = true; | ||
444 | |||
445 | return vb2_reqbufs(vq, req_buf); | ||
446 | } | ||
447 | |||
448 | static int bcap_querybuf(struct file *file, void *priv, | ||
449 | struct v4l2_buffer *buf) | ||
450 | { | ||
451 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
452 | |||
453 | return vb2_querybuf(&bcap_dev->buffer_queue, buf); | ||
454 | } | ||
455 | |||
456 | static int bcap_qbuf(struct file *file, void *priv, | ||
457 | struct v4l2_buffer *buf) | ||
458 | { | ||
459 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
460 | struct v4l2_fh *fh = file->private_data; | ||
461 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
462 | |||
463 | if (!bcap_fh->io_allowed) | ||
464 | return -EBUSY; | ||
465 | |||
466 | return vb2_qbuf(&bcap_dev->buffer_queue, buf); | ||
467 | } | ||
468 | |||
469 | static int bcap_dqbuf(struct file *file, void *priv, | ||
470 | struct v4l2_buffer *buf) | ||
471 | { | ||
472 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
473 | struct v4l2_fh *fh = file->private_data; | ||
474 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
475 | |||
476 | if (!bcap_fh->io_allowed) | ||
477 | return -EBUSY; | ||
478 | |||
479 | return vb2_dqbuf(&bcap_dev->buffer_queue, | ||
480 | buf, file->f_flags & O_NONBLOCK); | ||
481 | } | ||
482 | |||
483 | static irqreturn_t bcap_isr(int irq, void *dev_id) | ||
484 | { | ||
485 | struct ppi_if *ppi = dev_id; | ||
486 | struct bcap_device *bcap_dev = ppi->priv; | ||
487 | struct timeval timevalue; | ||
488 | struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; | ||
489 | dma_addr_t addr; | ||
490 | |||
491 | spin_lock(&bcap_dev->lock); | ||
492 | |||
493 | if (bcap_dev->cur_frm != bcap_dev->next_frm) { | ||
494 | do_gettimeofday(&timevalue); | ||
495 | vb->v4l2_buf.timestamp = timevalue; | ||
496 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
497 | bcap_dev->cur_frm = bcap_dev->next_frm; | ||
498 | } | ||
499 | |||
500 | ppi->ops->stop(ppi); | ||
501 | |||
502 | if (bcap_dev->stop) { | ||
503 | complete(&bcap_dev->comp); | ||
504 | } else { | ||
505 | if (!list_empty(&bcap_dev->dma_queue)) { | ||
506 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
507 | struct bcap_buffer, list); | ||
508 | list_del(&bcap_dev->next_frm->list); | ||
509 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); | ||
510 | ppi->ops->update_addr(ppi, (unsigned long)addr); | ||
511 | } | ||
512 | ppi->ops->start(ppi); | ||
513 | } | ||
514 | |||
515 | spin_unlock(&bcap_dev->lock); | ||
516 | |||
517 | return IRQ_HANDLED; | ||
518 | } | ||
519 | |||
520 | static int bcap_streamon(struct file *file, void *priv, | ||
521 | enum v4l2_buf_type buf_type) | ||
522 | { | ||
523 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
524 | struct bcap_fh *fh = file->private_data; | ||
525 | struct ppi_if *ppi = bcap_dev->ppi; | ||
526 | dma_addr_t addr; | ||
527 | int ret; | ||
528 | |||
529 | if (!fh->io_allowed) | ||
530 | return -EBUSY; | ||
531 | |||
532 | /* call streamon to start streaming in videobuf */ | ||
533 | ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type); | ||
534 | if (ret) | ||
535 | return ret; | ||
536 | |||
537 | /* if dma queue is empty, return error */ | ||
538 | if (list_empty(&bcap_dev->dma_queue)) { | ||
539 | v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n"); | ||
540 | ret = -EINVAL; | ||
541 | goto err; | ||
542 | } | ||
543 | |||
544 | /* get the next frame from the dma queue */ | ||
545 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
546 | struct bcap_buffer, list); | ||
547 | bcap_dev->cur_frm = bcap_dev->next_frm; | ||
548 | /* remove buffer from the dma queue */ | ||
549 | list_del(&bcap_dev->cur_frm->list); | ||
550 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); | ||
551 | /* update DMA address */ | ||
552 | ppi->ops->update_addr(ppi, (unsigned long)addr); | ||
553 | /* enable ppi */ | ||
554 | ppi->ops->start(ppi); | ||
555 | |||
556 | return 0; | ||
557 | err: | ||
558 | vb2_streamoff(&bcap_dev->buffer_queue, buf_type); | ||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | static int bcap_streamoff(struct file *file, void *priv, | ||
563 | enum v4l2_buf_type buf_type) | ||
564 | { | ||
565 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
566 | struct bcap_fh *fh = file->private_data; | ||
567 | |||
568 | if (!fh->io_allowed) | ||
569 | return -EBUSY; | ||
570 | |||
571 | return vb2_streamoff(&bcap_dev->buffer_queue, buf_type); | ||
572 | } | ||
573 | |||
574 | static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) | ||
575 | { | ||
576 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
577 | |||
578 | return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); | ||
579 | } | ||
580 | |||
581 | static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) | ||
582 | { | ||
583 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
584 | |||
585 | *std = bcap_dev->std; | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) | ||
590 | { | ||
591 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
592 | int ret; | ||
593 | |||
594 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
595 | return -EBUSY; | ||
596 | |||
597 | ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | |||
601 | bcap_dev->std = *std; | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static int bcap_enum_input(struct file *file, void *priv, | ||
606 | struct v4l2_input *input) | ||
607 | { | ||
608 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
609 | struct bfin_capture_config *config = bcap_dev->cfg; | ||
610 | int ret; | ||
611 | u32 status; | ||
612 | |||
613 | if (input->index >= config->num_inputs) | ||
614 | return -EINVAL; | ||
615 | |||
616 | *input = config->inputs[input->index]; | ||
617 | /* get input status */ | ||
618 | ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); | ||
619 | if (!ret) | ||
620 | input->status = status; | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static int bcap_g_input(struct file *file, void *priv, unsigned int *index) | ||
625 | { | ||
626 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
627 | |||
628 | *index = bcap_dev->cur_input; | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int bcap_s_input(struct file *file, void *priv, unsigned int index) | ||
633 | { | ||
634 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
635 | struct bfin_capture_config *config = bcap_dev->cfg; | ||
636 | struct bcap_route *route; | ||
637 | int ret; | ||
638 | |||
639 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
640 | return -EBUSY; | ||
641 | |||
642 | if (index >= config->num_inputs) | ||
643 | return -EINVAL; | ||
644 | |||
645 | route = &config->routes[index]; | ||
646 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, | ||
647 | route->input, route->output, 0); | ||
648 | if ((ret < 0) && (ret != -ENOIOCTLCMD)) { | ||
649 | v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); | ||
650 | return ret; | ||
651 | } | ||
652 | bcap_dev->cur_input = index; | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static int bcap_try_format(struct bcap_device *bcap, | ||
657 | struct v4l2_pix_format *pixfmt, | ||
658 | enum v4l2_mbus_pixelcode *mbus_code, | ||
659 | int *bpp) | ||
660 | { | ||
661 | struct bcap_format *sf = bcap->sensor_formats; | ||
662 | struct bcap_format *fmt = NULL; | ||
663 | struct v4l2_mbus_framefmt mbus_fmt; | ||
664 | int ret, i; | ||
665 | |||
666 | for (i = 0; i < bcap->num_sensor_formats; i++) { | ||
667 | fmt = &sf[i]; | ||
668 | if (pixfmt->pixelformat == fmt->pixelformat) | ||
669 | break; | ||
670 | } | ||
671 | if (i == bcap->num_sensor_formats) | ||
672 | fmt = &sf[0]; | ||
673 | |||
674 | if (mbus_code) | ||
675 | *mbus_code = fmt->mbus_code; | ||
676 | if (bpp) | ||
677 | *bpp = fmt->bpp; | ||
678 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); | ||
679 | ret = v4l2_subdev_call(bcap->sd, video, | ||
680 | try_mbus_fmt, &mbus_fmt); | ||
681 | if (ret < 0) | ||
682 | return ret; | ||
683 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); | ||
684 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; | ||
685 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, | ||
690 | struct v4l2_fmtdesc *fmt) | ||
691 | { | ||
692 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
693 | struct bcap_format *sf = bcap_dev->sensor_formats; | ||
694 | |||
695 | if (fmt->index >= bcap_dev->num_sensor_formats) | ||
696 | return -EINVAL; | ||
697 | |||
698 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
699 | strlcpy(fmt->description, | ||
700 | sf[fmt->index].desc, | ||
701 | sizeof(fmt->description)); | ||
702 | fmt->pixelformat = sf[fmt->index].pixelformat; | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int bcap_try_fmt_vid_cap(struct file *file, void *priv, | ||
707 | struct v4l2_format *fmt) | ||
708 | { | ||
709 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
710 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
711 | |||
712 | return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); | ||
713 | } | ||
714 | |||
715 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, | ||
716 | struct v4l2_format *fmt) | ||
717 | { | ||
718 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
719 | |||
720 | fmt->fmt.pix = bcap_dev->fmt; | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | static int bcap_s_fmt_vid_cap(struct file *file, void *priv, | ||
725 | struct v4l2_format *fmt) | ||
726 | { | ||
727 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
728 | struct v4l2_mbus_framefmt mbus_fmt; | ||
729 | enum v4l2_mbus_pixelcode mbus_code; | ||
730 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
731 | int ret, bpp; | ||
732 | |||
733 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
734 | return -EBUSY; | ||
735 | |||
736 | /* see if format works */ | ||
737 | ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); | ||
738 | if (ret < 0) | ||
739 | return ret; | ||
740 | |||
741 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); | ||
742 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); | ||
743 | if (ret < 0) | ||
744 | return ret; | ||
745 | bcap_dev->fmt = *pixfmt; | ||
746 | bcap_dev->bpp = bpp; | ||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static int bcap_querycap(struct file *file, void *priv, | ||
751 | struct v4l2_capability *cap) | ||
752 | { | ||
753 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
754 | |||
755 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | ||
756 | strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); | ||
757 | strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); | ||
758 | strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int bcap_g_parm(struct file *file, void *fh, | ||
763 | struct v4l2_streamparm *a) | ||
764 | { | ||
765 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
766 | |||
767 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
768 | return -EINVAL; | ||
769 | return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); | ||
770 | } | ||
771 | |||
772 | static int bcap_s_parm(struct file *file, void *fh, | ||
773 | struct v4l2_streamparm *a) | ||
774 | { | ||
775 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
776 | |||
777 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
778 | return -EINVAL; | ||
779 | return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); | ||
780 | } | ||
781 | |||
782 | static int bcap_g_chip_ident(struct file *file, void *priv, | ||
783 | struct v4l2_dbg_chip_ident *chip) | ||
784 | { | ||
785 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
786 | |||
787 | chip->ident = V4L2_IDENT_NONE; | ||
788 | chip->revision = 0; | ||
789 | if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && | ||
790 | chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
791 | return -EINVAL; | ||
792 | |||
793 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
794 | g_chip_ident, chip); | ||
795 | } | ||
796 | |||
797 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
798 | static int bcap_dbg_g_register(struct file *file, void *priv, | ||
799 | struct v4l2_dbg_register *reg) | ||
800 | { | ||
801 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
802 | |||
803 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
804 | g_register, reg); | ||
805 | } | ||
806 | |||
807 | static int bcap_dbg_s_register(struct file *file, void *priv, | ||
808 | struct v4l2_dbg_register *reg) | ||
809 | { | ||
810 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
811 | |||
812 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
813 | s_register, reg); | ||
814 | } | ||
815 | #endif | ||
816 | |||
817 | static int bcap_log_status(struct file *file, void *priv) | ||
818 | { | ||
819 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
820 | /* status for sub devices */ | ||
821 | v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static const struct v4l2_ioctl_ops bcap_ioctl_ops = { | ||
826 | .vidioc_querycap = bcap_querycap, | ||
827 | .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, | ||
828 | .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, | ||
829 | .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, | ||
830 | .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, | ||
831 | .vidioc_enum_input = bcap_enum_input, | ||
832 | .vidioc_g_input = bcap_g_input, | ||
833 | .vidioc_s_input = bcap_s_input, | ||
834 | .vidioc_querystd = bcap_querystd, | ||
835 | .vidioc_s_std = bcap_s_std, | ||
836 | .vidioc_g_std = bcap_g_std, | ||
837 | .vidioc_reqbufs = bcap_reqbufs, | ||
838 | .vidioc_querybuf = bcap_querybuf, | ||
839 | .vidioc_qbuf = bcap_qbuf, | ||
840 | .vidioc_dqbuf = bcap_dqbuf, | ||
841 | .vidioc_streamon = bcap_streamon, | ||
842 | .vidioc_streamoff = bcap_streamoff, | ||
843 | .vidioc_g_parm = bcap_g_parm, | ||
844 | .vidioc_s_parm = bcap_s_parm, | ||
845 | .vidioc_g_chip_ident = bcap_g_chip_ident, | ||
846 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
847 | .vidioc_g_register = bcap_dbg_g_register, | ||
848 | .vidioc_s_register = bcap_dbg_s_register, | ||
849 | #endif | ||
850 | .vidioc_log_status = bcap_log_status, | ||
851 | }; | ||
852 | |||
853 | static struct v4l2_file_operations bcap_fops = { | ||
854 | .owner = THIS_MODULE, | ||
855 | .open = bcap_open, | ||
856 | .release = bcap_release, | ||
857 | .unlocked_ioctl = video_ioctl2, | ||
858 | .mmap = bcap_mmap, | ||
859 | #ifndef CONFIG_MMU | ||
860 | .get_unmapped_area = bcap_get_unmapped_area, | ||
861 | #endif | ||
862 | .poll = bcap_poll | ||
863 | }; | ||
864 | |||
865 | static int __devinit bcap_probe(struct platform_device *pdev) | ||
866 | { | ||
867 | struct bcap_device *bcap_dev; | ||
868 | struct video_device *vfd; | ||
869 | struct i2c_adapter *i2c_adap; | ||
870 | struct bfin_capture_config *config; | ||
871 | struct vb2_queue *q; | ||
872 | int ret; | ||
873 | |||
874 | config = pdev->dev.platform_data; | ||
875 | if (!config) { | ||
876 | v4l2_err(pdev->dev.driver, "Unable to get board config\n"); | ||
877 | return -ENODEV; | ||
878 | } | ||
879 | |||
880 | bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); | ||
881 | if (!bcap_dev) { | ||
882 | v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n"); | ||
883 | return -ENOMEM; | ||
884 | } | ||
885 | |||
886 | bcap_dev->cfg = config; | ||
887 | |||
888 | bcap_dev->ppi = ppi_create_instance(config->ppi_info); | ||
889 | if (!bcap_dev->ppi) { | ||
890 | v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); | ||
891 | ret = -ENODEV; | ||
892 | goto err_free_dev; | ||
893 | } | ||
894 | bcap_dev->ppi->priv = bcap_dev; | ||
895 | |||
896 | bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
897 | if (IS_ERR(bcap_dev->alloc_ctx)) { | ||
898 | ret = PTR_ERR(bcap_dev->alloc_ctx); | ||
899 | goto err_free_ppi; | ||
900 | } | ||
901 | |||
902 | vfd = video_device_alloc(); | ||
903 | if (!vfd) { | ||
904 | ret = -ENOMEM; | ||
905 | v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); | ||
906 | goto err_cleanup_ctx; | ||
907 | } | ||
908 | |||
909 | /* initialize field of video device */ | ||
910 | vfd->release = video_device_release; | ||
911 | vfd->fops = &bcap_fops; | ||
912 | vfd->ioctl_ops = &bcap_ioctl_ops; | ||
913 | vfd->tvnorms = 0; | ||
914 | vfd->v4l2_dev = &bcap_dev->v4l2_dev; | ||
915 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
916 | strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); | ||
917 | bcap_dev->video_dev = vfd; | ||
918 | |||
919 | ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); | ||
920 | if (ret) { | ||
921 | v4l2_err(pdev->dev.driver, | ||
922 | "Unable to register v4l2 device\n"); | ||
923 | goto err_release_vdev; | ||
924 | } | ||
925 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); | ||
926 | |||
927 | bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; | ||
928 | ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); | ||
929 | if (ret) { | ||
930 | v4l2_err(&bcap_dev->v4l2_dev, | ||
931 | "Unable to init control handler\n"); | ||
932 | goto err_unreg_v4l2; | ||
933 | } | ||
934 | |||
935 | spin_lock_init(&bcap_dev->lock); | ||
936 | /* initialize queue */ | ||
937 | q = &bcap_dev->buffer_queue; | ||
938 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
939 | q->io_modes = VB2_MMAP; | ||
940 | q->drv_priv = bcap_dev; | ||
941 | q->buf_struct_size = sizeof(struct bcap_buffer); | ||
942 | q->ops = &bcap_video_qops; | ||
943 | q->mem_ops = &vb2_dma_contig_memops; | ||
944 | |||
945 | vb2_queue_init(q); | ||
946 | |||
947 | mutex_init(&bcap_dev->mutex); | ||
948 | init_completion(&bcap_dev->comp); | ||
949 | |||
950 | /* init video dma queues */ | ||
951 | INIT_LIST_HEAD(&bcap_dev->dma_queue); | ||
952 | |||
953 | vfd->lock = &bcap_dev->mutex; | ||
954 | |||
955 | /* register video device */ | ||
956 | ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); | ||
957 | if (ret) { | ||
958 | v4l2_err(&bcap_dev->v4l2_dev, | ||
959 | "Unable to register video device\n"); | ||
960 | goto err_free_handler; | ||
961 | } | ||
962 | video_set_drvdata(bcap_dev->video_dev, bcap_dev); | ||
963 | v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", | ||
964 | video_device_node_name(vfd)); | ||
965 | |||
966 | /* load up the subdevice */ | ||
967 | i2c_adap = i2c_get_adapter(config->i2c_adapter_id); | ||
968 | if (!i2c_adap) { | ||
969 | v4l2_err(&bcap_dev->v4l2_dev, | ||
970 | "Unable to find i2c adapter\n"); | ||
971 | goto err_unreg_vdev; | ||
972 | |||
973 | } | ||
974 | bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, | ||
975 | i2c_adap, | ||
976 | &config->board_info, | ||
977 | NULL); | ||
978 | if (bcap_dev->sd) { | ||
979 | int i; | ||
980 | /* update tvnorms from the sub devices */ | ||
981 | for (i = 0; i < config->num_inputs; i++) | ||
982 | vfd->tvnorms |= config->inputs[i].std; | ||
983 | } else { | ||
984 | v4l2_err(&bcap_dev->v4l2_dev, | ||
985 | "Unable to register sub device\n"); | ||
986 | goto err_unreg_vdev; | ||
987 | } | ||
988 | |||
989 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); | ||
990 | |||
991 | /* now we can probe the default state */ | ||
992 | if (vfd->tvnorms) { | ||
993 | v4l2_std_id std; | ||
994 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); | ||
995 | if (ret) { | ||
996 | v4l2_err(&bcap_dev->v4l2_dev, | ||
997 | "Unable to get std\n"); | ||
998 | goto err_unreg_vdev; | ||
999 | } | ||
1000 | bcap_dev->std = std; | ||
1001 | } | ||
1002 | ret = bcap_init_sensor_formats(bcap_dev); | ||
1003 | if (ret) { | ||
1004 | v4l2_err(&bcap_dev->v4l2_dev, | ||
1005 | "Unable to create sensor formats table\n"); | ||
1006 | goto err_unreg_vdev; | ||
1007 | } | ||
1008 | return 0; | ||
1009 | err_unreg_vdev: | ||
1010 | video_unregister_device(bcap_dev->video_dev); | ||
1011 | bcap_dev->video_dev = NULL; | ||
1012 | err_free_handler: | ||
1013 | v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); | ||
1014 | err_unreg_v4l2: | ||
1015 | v4l2_device_unregister(&bcap_dev->v4l2_dev); | ||
1016 | err_release_vdev: | ||
1017 | if (bcap_dev->video_dev) | ||
1018 | video_device_release(bcap_dev->video_dev); | ||
1019 | err_cleanup_ctx: | ||
1020 | vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); | ||
1021 | err_free_ppi: | ||
1022 | ppi_delete_instance(bcap_dev->ppi); | ||
1023 | err_free_dev: | ||
1024 | kfree(bcap_dev); | ||
1025 | return ret; | ||
1026 | } | ||
1027 | |||
1028 | static int __devexit bcap_remove(struct platform_device *pdev) | ||
1029 | { | ||
1030 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
1031 | struct bcap_device *bcap_dev = container_of(v4l2_dev, | ||
1032 | struct bcap_device, v4l2_dev); | ||
1033 | |||
1034 | bcap_free_sensor_formats(bcap_dev); | ||
1035 | video_unregister_device(bcap_dev->video_dev); | ||
1036 | v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); | ||
1037 | v4l2_device_unregister(v4l2_dev); | ||
1038 | vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); | ||
1039 | ppi_delete_instance(bcap_dev->ppi); | ||
1040 | kfree(bcap_dev); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | static struct platform_driver bcap_driver = { | ||
1045 | .driver = { | ||
1046 | .name = CAPTURE_DRV_NAME, | ||
1047 | .owner = THIS_MODULE, | ||
1048 | }, | ||
1049 | .probe = bcap_probe, | ||
1050 | .remove = __devexit_p(bcap_remove), | ||
1051 | }; | ||
1052 | |||
1053 | static __init int bcap_init(void) | ||
1054 | { | ||
1055 | return platform_driver_register(&bcap_driver); | ||
1056 | } | ||
1057 | |||
1058 | static __exit void bcap_exit(void) | ||
1059 | { | ||
1060 | platform_driver_unregister(&bcap_driver); | ||
1061 | } | ||
1062 | |||
1063 | module_init(bcap_init); | ||
1064 | module_exit(bcap_exit); | ||
1065 | |||
1066 | MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); | ||
1067 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
1068 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/blackfin/ppi.c b/drivers/media/video/blackfin/ppi.c deleted file mode 100644 index d29592186b02..000000000000 --- a/drivers/media/video/blackfin/ppi.c +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
1 | /* | ||
2 | * ppi.c Analog Devices Parallel Peripheral Interface driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <asm/bfin_ppi.h> | ||
23 | #include <asm/blackfin.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/dma.h> | ||
26 | #include <asm/portmux.h> | ||
27 | |||
28 | #include <media/blackfin/ppi.h> | ||
29 | |||
30 | static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); | ||
31 | static void ppi_detach_irq(struct ppi_if *ppi); | ||
32 | static int ppi_start(struct ppi_if *ppi); | ||
33 | static int ppi_stop(struct ppi_if *ppi); | ||
34 | static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); | ||
35 | static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); | ||
36 | |||
37 | static const struct ppi_ops ppi_ops = { | ||
38 | .attach_irq = ppi_attach_irq, | ||
39 | .detach_irq = ppi_detach_irq, | ||
40 | .start = ppi_start, | ||
41 | .stop = ppi_stop, | ||
42 | .set_params = ppi_set_params, | ||
43 | .update_addr = ppi_update_addr, | ||
44 | }; | ||
45 | |||
46 | static irqreturn_t ppi_irq_err(int irq, void *dev_id) | ||
47 | { | ||
48 | struct ppi_if *ppi = dev_id; | ||
49 | const struct ppi_info *info = ppi->info; | ||
50 | |||
51 | switch (info->type) { | ||
52 | case PPI_TYPE_PPI: | ||
53 | { | ||
54 | struct bfin_ppi_regs *reg = info->base; | ||
55 | unsigned short status; | ||
56 | |||
57 | /* register on bf561 is cleared when read | ||
58 | * others are W1C | ||
59 | */ | ||
60 | status = bfin_read16(®->status); | ||
61 | bfin_write16(®->status, 0xff00); | ||
62 | break; | ||
63 | } | ||
64 | case PPI_TYPE_EPPI: | ||
65 | { | ||
66 | struct bfin_eppi_regs *reg = info->base; | ||
67 | bfin_write16(®->status, 0xffff); | ||
68 | break; | ||
69 | } | ||
70 | default: | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | return IRQ_HANDLED; | ||
75 | } | ||
76 | |||
77 | static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) | ||
78 | { | ||
79 | const struct ppi_info *info = ppi->info; | ||
80 | int ret; | ||
81 | |||
82 | ret = request_dma(info->dma_ch, "PPI_DMA"); | ||
83 | |||
84 | if (ret) { | ||
85 | pr_err("Unable to allocate DMA channel for PPI\n"); | ||
86 | return ret; | ||
87 | } | ||
88 | set_dma_callback(info->dma_ch, handler, ppi); | ||
89 | |||
90 | if (ppi->err_int) { | ||
91 | ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); | ||
92 | if (ret) { | ||
93 | pr_err("Unable to allocate IRQ for PPI\n"); | ||
94 | free_dma(info->dma_ch); | ||
95 | } | ||
96 | } | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static void ppi_detach_irq(struct ppi_if *ppi) | ||
101 | { | ||
102 | const struct ppi_info *info = ppi->info; | ||
103 | |||
104 | if (ppi->err_int) | ||
105 | free_irq(info->irq_err, ppi); | ||
106 | free_dma(info->dma_ch); | ||
107 | } | ||
108 | |||
109 | static int ppi_start(struct ppi_if *ppi) | ||
110 | { | ||
111 | const struct ppi_info *info = ppi->info; | ||
112 | |||
113 | /* enable DMA */ | ||
114 | enable_dma(info->dma_ch); | ||
115 | |||
116 | /* enable PPI */ | ||
117 | ppi->ppi_control |= PORT_EN; | ||
118 | switch (info->type) { | ||
119 | case PPI_TYPE_PPI: | ||
120 | { | ||
121 | struct bfin_ppi_regs *reg = info->base; | ||
122 | bfin_write16(®->control, ppi->ppi_control); | ||
123 | break; | ||
124 | } | ||
125 | case PPI_TYPE_EPPI: | ||
126 | { | ||
127 | struct bfin_eppi_regs *reg = info->base; | ||
128 | bfin_write32(®->control, ppi->ppi_control); | ||
129 | break; | ||
130 | } | ||
131 | default: | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | SSYNC(); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int ppi_stop(struct ppi_if *ppi) | ||
140 | { | ||
141 | const struct ppi_info *info = ppi->info; | ||
142 | |||
143 | /* disable PPI */ | ||
144 | ppi->ppi_control &= ~PORT_EN; | ||
145 | switch (info->type) { | ||
146 | case PPI_TYPE_PPI: | ||
147 | { | ||
148 | struct bfin_ppi_regs *reg = info->base; | ||
149 | bfin_write16(®->control, ppi->ppi_control); | ||
150 | break; | ||
151 | } | ||
152 | case PPI_TYPE_EPPI: | ||
153 | { | ||
154 | struct bfin_eppi_regs *reg = info->base; | ||
155 | bfin_write32(®->control, ppi->ppi_control); | ||
156 | break; | ||
157 | } | ||
158 | default: | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | /* disable DMA */ | ||
163 | clear_dma_irqstat(info->dma_ch); | ||
164 | disable_dma(info->dma_ch); | ||
165 | |||
166 | SSYNC(); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | ||
171 | { | ||
172 | const struct ppi_info *info = ppi->info; | ||
173 | int dma32 = 0; | ||
174 | int dma_config, bytes_per_line, lines_per_frame; | ||
175 | |||
176 | bytes_per_line = params->width * params->bpp / 8; | ||
177 | lines_per_frame = params->height; | ||
178 | if (params->int_mask == 0xFFFFFFFF) | ||
179 | ppi->err_int = false; | ||
180 | else | ||
181 | ppi->err_int = true; | ||
182 | |||
183 | dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); | ||
184 | ppi->ppi_control = params->ppi_control & ~PORT_EN; | ||
185 | switch (info->type) { | ||
186 | case PPI_TYPE_PPI: | ||
187 | { | ||
188 | struct bfin_ppi_regs *reg = info->base; | ||
189 | |||
190 | if (params->ppi_control & DMA32) | ||
191 | dma32 = 1; | ||
192 | |||
193 | bfin_write16(®->control, ppi->ppi_control); | ||
194 | bfin_write16(®->count, bytes_per_line - 1); | ||
195 | bfin_write16(®->frame, lines_per_frame); | ||
196 | break; | ||
197 | } | ||
198 | case PPI_TYPE_EPPI: | ||
199 | { | ||
200 | struct bfin_eppi_regs *reg = info->base; | ||
201 | |||
202 | if ((params->ppi_control & PACK_EN) | ||
203 | || (params->ppi_control & 0x38000) > DLEN_16) | ||
204 | dma32 = 1; | ||
205 | |||
206 | bfin_write32(®->control, ppi->ppi_control); | ||
207 | bfin_write16(®->line, bytes_per_line + params->blank_clocks); | ||
208 | bfin_write16(®->frame, lines_per_frame); | ||
209 | bfin_write16(®->hdelay, 0); | ||
210 | bfin_write16(®->vdelay, 0); | ||
211 | bfin_write16(®->hcount, bytes_per_line); | ||
212 | bfin_write16(®->vcount, lines_per_frame); | ||
213 | break; | ||
214 | } | ||
215 | default: | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | if (dma32) { | ||
220 | dma_config |= WDSIZE_32; | ||
221 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); | ||
222 | set_dma_x_modify(info->dma_ch, 4); | ||
223 | set_dma_y_modify(info->dma_ch, 4); | ||
224 | } else { | ||
225 | dma_config |= WDSIZE_16; | ||
226 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); | ||
227 | set_dma_x_modify(info->dma_ch, 2); | ||
228 | set_dma_y_modify(info->dma_ch, 2); | ||
229 | } | ||
230 | set_dma_y_count(info->dma_ch, lines_per_frame); | ||
231 | set_dma_config(info->dma_ch, dma_config); | ||
232 | |||
233 | SSYNC(); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) | ||
238 | { | ||
239 | set_dma_start_addr(ppi->info->dma_ch, addr); | ||
240 | } | ||
241 | |||
242 | struct ppi_if *ppi_create_instance(const struct ppi_info *info) | ||
243 | { | ||
244 | struct ppi_if *ppi; | ||
245 | |||
246 | if (!info || !info->pin_req) | ||
247 | return NULL; | ||
248 | |||
249 | if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { | ||
250 | pr_err("request peripheral failed\n"); | ||
251 | return NULL; | ||
252 | } | ||
253 | |||
254 | ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); | ||
255 | if (!ppi) { | ||
256 | peripheral_free_list(info->pin_req); | ||
257 | pr_err("unable to allocate memory for ppi handle\n"); | ||
258 | return NULL; | ||
259 | } | ||
260 | ppi->ops = &ppi_ops; | ||
261 | ppi->info = info; | ||
262 | |||
263 | pr_info("ppi probe success\n"); | ||
264 | return ppi; | ||
265 | } | ||
266 | |||
267 | void ppi_delete_instance(struct ppi_if *ppi) | ||
268 | { | ||
269 | peripheral_free_list(ppi->info->pin_req); | ||
270 | kfree(ppi); | ||
271 | } | ||