aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/fimc-capture.c
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2010-10-07 09:06:16 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:55:47 -0400
commit5f3cc4474cdeab3ee44962fd752baec24e8fecec (patch)
tree5c0255cb2c8f531a2b139f700a210c855dea19aa /drivers/media/video/s5p-fimc/fimc-capture.c
parent28f06ff4b75a309d9255567b3a15b6a5bf63747d (diff)
[media] s5p-fimc: Add camera capture support
Add a video device driver per each FIMC entity to support the camera capture input mode. Video capture node is registered only if CCD sensor data is provided through driver's platfrom data and board setup code. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-capture.c')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c819
1 files changed, 819 insertions, 0 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
new file mode 100644
index 000000000000..e8f13d3e2df1
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -0,0 +1,819 @@
1/*
2 * Samsung S5P SoC series camera interface (camera capture) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd
5 * Author: Sylwester Nawrocki, <s.nawrocki@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/version.h>
15#include <linux/types.h>
16#include <linux/errno.h>
17#include <linux/bug.h>
18#include <linux/interrupt.h>
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/list.h>
22#include <linux/slab.h>
23#include <linux/clk.h>
24#include <linux/i2c.h>
25
26#include <linux/videodev2.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-ioctl.h>
29#include <media/v4l2-mem2mem.h>
30#include <media/videobuf-core.h>
31#include <media/videobuf-dma-contig.h>
32
33#include "fimc-core.h"
34
35static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
36 struct s3c_fimc_isp_info *isp_info)
37{
38 struct i2c_adapter *i2c_adap;
39 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
40 struct v4l2_subdev *sd = NULL;
41
42 i2c_adap = i2c_get_adapter(isp_info->i2c_bus_num);
43 if (!i2c_adap)
44 return ERR_PTR(-ENOMEM);
45
46 sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
47 MODULE_NAME, isp_info->board_info, NULL);
48 if (!sd) {
49 v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
50 return NULL;
51 }
52
53 v4l2_info(&vid_cap->v4l2_dev, "subdevice %s registered successfuly\n",
54 isp_info->board_info->type);
55
56 return sd;
57}
58
59static void fimc_subdev_unregister(struct fimc_dev *fimc)
60{
61 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
62 struct i2c_client *client;
63
64 if (vid_cap->input_index < 0)
65 return; /* Subdevice already released or not registered. */
66
67 if (vid_cap->sd) {
68 v4l2_device_unregister_subdev(vid_cap->sd);
69 client = v4l2_get_subdevdata(vid_cap->sd);
70 i2c_unregister_device(client);
71 i2c_put_adapter(client->adapter);
72 vid_cap->sd = NULL;
73 }
74
75 vid_cap->input_index = -1;
76}
77
78/**
79 * fimc_subdev_attach - attach v4l2_subdev to camera host interface
80 *
81 * @fimc: FIMC device information
82 * @index: index to the array of available subdevices,
83 * -1 for full array search or non negative value
84 * to select specific subdevice
85 */
86static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
87{
88 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
89 struct s3c_platform_fimc *pdata = fimc->pdata;
90 struct s3c_fimc_isp_info *isp_info;
91 struct v4l2_subdev *sd;
92 int i;
93
94 for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i) {
95 isp_info = pdata->isp_info[i];
96
97 if (!isp_info || (index >= 0 && i != index))
98 continue;
99
100 sd = fimc_subdev_register(fimc, isp_info);
101 if (sd) {
102 vid_cap->sd = sd;
103 vid_cap->input_index = i;
104
105 return 0;
106 }
107 }
108
109 vid_cap->input_index = -1;
110 vid_cap->sd = NULL;
111 v4l2_err(&vid_cap->v4l2_dev, "fimc%d: sensor attach failed\n",
112 fimc->id);
113 return -ENODEV;
114}
115
116static int fimc_isp_subdev_init(struct fimc_dev *fimc, int index)
117{
118 struct s3c_fimc_isp_info *isp_info;
119 int ret;
120
121 ret = fimc_subdev_attach(fimc, index);
122 if (ret)
123 return ret;
124
125 isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
126 ret = fimc_hw_set_camera_polarity(fimc, isp_info);
127 if (!ret) {
128 ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
129 s_power, 1);
130 if (!ret)
131 return ret;
132 }
133
134 fimc_subdev_unregister(fimc);
135 err("ISP initialization failed: %d", ret);
136 return ret;
137}
138
139/*
140 * At least one buffer on the pending_buf_q queue is required.
141 * Locking: The caller holds fimc->slock spinlock.
142 */
143int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
144 struct fimc_vid_buffer *fimc_vb)
145{
146 struct fimc_vid_cap *cap = &fimc->vid_cap;
147 struct fimc_ctx *ctx = cap->ctx;
148 int ret = 0;
149
150 BUG_ON(!fimc || !fimc_vb);
151
152 ret = fimc_prepare_addr(ctx, fimc_vb, &ctx->d_frame,
153 &fimc_vb->paddr);
154 if (ret)
155 return ret;
156
157 if (test_bit(ST_CAPT_STREAM, &fimc->state)) {
158 fimc_pending_queue_add(cap, fimc_vb);
159 } else {
160 /* Setup the buffer directly for processing. */
161 int buf_id = (cap->reqbufs_count == 1) ? -1 : cap->buf_index;
162 fimc_hw_set_output_addr(fimc, &fimc_vb->paddr, buf_id);
163
164 fimc_vb->index = cap->buf_index;
165 active_queue_add(cap, fimc_vb);
166
167 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
168 cap->buf_index = 0;
169 }
170 return ret;
171}
172
173static int fimc_stop_capture(struct fimc_dev *fimc)
174{
175 unsigned long flags;
176 struct fimc_vid_cap *cap;
177 int ret;
178
179 cap = &fimc->vid_cap;
180
181 if (!fimc_capture_active(fimc))
182 return 0;
183
184 spin_lock_irqsave(&fimc->slock, flags);
185 set_bit(ST_CAPT_SHUT, &fimc->state);
186 fimc_deactivate_capture(fimc);
187 spin_unlock_irqrestore(&fimc->slock, flags);
188
189 wait_event_timeout(fimc->irq_queue,
190 test_bit(ST_CAPT_SHUT, &fimc->state),
191 FIMC_SHUTDOWN_TIMEOUT);
192
193 ret = v4l2_subdev_call(cap->sd, video, s_stream, 0);
194 if (ret)
195 v4l2_err(&fimc->vid_cap.v4l2_dev, "s_stream(0) failed\n");
196
197 spin_lock_irqsave(&fimc->slock, flags);
198 fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
199 1 << ST_CAPT_STREAM);
200
201 fimc->vid_cap.active_buf_cnt = 0;
202 spin_unlock_irqrestore(&fimc->slock, flags);
203
204 dbg("state: 0x%lx", fimc->state);
205 return 0;
206}
207
208static int fimc_capture_open(struct file *file)
209{
210 struct fimc_dev *fimc = video_drvdata(file);
211 int ret = 0;
212
213 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
214
215 /* Return if the corresponding video mem2mem node is already opened. */
216 if (fimc_m2m_active(fimc))
217 return -EBUSY;
218
219 if (mutex_lock_interruptible(&fimc->lock))
220 return -ERESTARTSYS;
221
222 if (++fimc->vid_cap.refcnt == 1) {
223 ret = fimc_isp_subdev_init(fimc, -1);
224 if (ret) {
225 fimc->vid_cap.refcnt--;
226 ret = -EIO;
227 }
228 }
229
230 file->private_data = fimc->vid_cap.ctx;
231
232 mutex_unlock(&fimc->lock);
233 return ret;
234}
235
236static int fimc_capture_close(struct file *file)
237{
238 struct fimc_dev *fimc = video_drvdata(file);
239
240 if (mutex_lock_interruptible(&fimc->lock))
241 return -ERESTARTSYS;
242
243 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
244
245 if (--fimc->vid_cap.refcnt == 0) {
246 fimc_stop_capture(fimc);
247
248 videobuf_stop(&fimc->vid_cap.vbq);
249 videobuf_mmap_free(&fimc->vid_cap.vbq);
250
251 v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");
252 v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
253 fimc_subdev_unregister(fimc);
254 }
255
256 mutex_unlock(&fimc->lock);
257 return 0;
258}
259
260static unsigned int fimc_capture_poll(struct file *file,
261 struct poll_table_struct *wait)
262{
263 struct fimc_ctx *ctx = file->private_data;
264 struct fimc_dev *fimc = ctx->fimc_dev;
265 struct fimc_vid_cap *cap = &fimc->vid_cap;
266 int ret;
267
268 if (mutex_lock_interruptible(&fimc->lock))
269 return POLLERR;
270
271 ret = videobuf_poll_stream(file, &cap->vbq, wait);
272 mutex_unlock(&fimc->lock);
273
274 return ret;
275}
276
277static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma)
278{
279 struct fimc_ctx *ctx = file->private_data;
280 struct fimc_dev *fimc = ctx->fimc_dev;
281 struct fimc_vid_cap *cap = &fimc->vid_cap;
282 int ret;
283
284 if (mutex_lock_interruptible(&fimc->lock))
285 return -ERESTARTSYS;
286
287 ret = videobuf_mmap_mapper(&cap->vbq, vma);
288 mutex_unlock(&fimc->lock);
289
290 return ret;
291}
292
293/* video device file operations */
294static const struct v4l2_file_operations fimc_capture_fops = {
295 .owner = THIS_MODULE,
296 .open = fimc_capture_open,
297 .release = fimc_capture_close,
298 .poll = fimc_capture_poll,
299 .unlocked_ioctl = video_ioctl2,
300 .mmap = fimc_capture_mmap,
301};
302
303static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
304 struct v4l2_capability *cap)
305{
306 struct fimc_ctx *ctx = file->private_data;
307 struct fimc_dev *fimc = ctx->fimc_dev;
308
309 strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
310 strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
311 cap->bus_info[0] = 0;
312 cap->version = KERNEL_VERSION(1, 0, 0);
313 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
314
315 return 0;
316}
317
318/* Synchronize formats of the camera interface input and attached sensor. */
319static int sync_capture_fmt(struct fimc_ctx *ctx)
320{
321 struct fimc_frame *frame = &ctx->s_frame;
322 struct fimc_dev *fimc = ctx->fimc_dev;
323 struct v4l2_mbus_framefmt *fmt = &fimc->vid_cap.fmt;
324 int ret;
325
326 fmt->width = ctx->d_frame.o_width;
327 fmt->height = ctx->d_frame.o_height;
328
329 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_mbus_fmt, fmt);
330 if (ret == -ENOIOCTLCMD) {
331 err("s_mbus_fmt failed");
332 return ret;
333 }
334 dbg("w: %d, h: %d, code= %d", fmt->width, fmt->height, fmt->code);
335
336 frame->fmt = find_mbus_format(fmt, FMT_FLAGS_CAM);
337 if (!frame->fmt) {
338 err("fimc source format not found\n");
339 return -EINVAL;
340 }
341
342 frame->f_width = fmt->width;
343 frame->f_height = fmt->height;
344 frame->width = fmt->width;
345 frame->height = fmt->height;
346 frame->o_width = fmt->width;
347 frame->o_height = fmt->height;
348 frame->offs_h = 0;
349 frame->offs_v = 0;
350
351 return 0;
352}
353
354static int fimc_cap_s_fmt(struct file *file, void *priv,
355 struct v4l2_format *f)
356{
357 struct fimc_ctx *ctx = priv;
358 struct fimc_dev *fimc = ctx->fimc_dev;
359 struct fimc_frame *frame;
360 struct v4l2_pix_format *pix;
361 int ret;
362
363 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
364 return -EINVAL;
365
366 ret = fimc_vidioc_try_fmt(file, priv, f);
367 if (ret)
368 return ret;
369
370 if (mutex_lock_interruptible(&fimc->lock))
371 return -ERESTARTSYS;
372
373 if (fimc_capture_active(fimc)) {
374 ret = -EBUSY;
375 goto sf_unlock;
376 }
377
378 frame = &ctx->d_frame;
379
380 pix = &f->fmt.pix;
381 frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM);
382 if (!frame->fmt) {
383 err("fimc target format not found\n");
384 ret = -EINVAL;
385 goto sf_unlock;
386 }
387
388 /* Output DMA frame pixel size and offsets. */
389 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
390 frame->f_height = pix->height;
391 frame->width = pix->width;
392 frame->height = pix->height;
393 frame->o_width = pix->width;
394 frame->o_height = pix->height;
395 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
396 frame->offs_h = 0;
397 frame->offs_v = 0;
398
399 ret = sync_capture_fmt(ctx);
400
401 ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT);
402
403sf_unlock:
404 mutex_unlock(&fimc->lock);
405 return ret;
406}
407
408static int fimc_cap_enum_input(struct file *file, void *priv,
409 struct v4l2_input *i)
410{
411 struct fimc_ctx *ctx = priv;
412 struct s3c_platform_fimc *pldata = ctx->fimc_dev->pdata;
413 struct s3c_fimc_isp_info *isp_info;
414
415 if (i->index >= FIMC_MAX_CAMIF_CLIENTS)
416 return -EINVAL;
417
418 isp_info = pldata->isp_info[i->index];
419 if (isp_info == NULL)
420 return -EINVAL;
421
422 i->type = V4L2_INPUT_TYPE_CAMERA;
423 strncpy(i->name, isp_info->board_info->type, 32);
424 return 0;
425}
426
427static int fimc_cap_s_input(struct file *file, void *priv,
428 unsigned int i)
429{
430 struct fimc_ctx *ctx = priv;
431 struct fimc_dev *fimc = ctx->fimc_dev;
432 struct s3c_platform_fimc *pdata = fimc->pdata;
433 int ret;
434
435 if (fimc_capture_active(ctx->fimc_dev))
436 return -EBUSY;
437
438 if (mutex_lock_interruptible(&fimc->lock))
439 return -ERESTARTSYS;
440
441 if (i >= FIMC_MAX_CAMIF_CLIENTS || !pdata->isp_info[i]) {
442 ret = -EINVAL;
443 goto si_unlock;
444 }
445
446 if (fimc->vid_cap.sd) {
447 ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
448 if (ret)
449 err("s_power failed: %d", ret);
450 }
451
452 /* Release the attached sensor subdevice. */
453 fimc_subdev_unregister(fimc);
454
455 ret = fimc_isp_subdev_init(fimc, i);
456
457si_unlock:
458 mutex_unlock(&fimc->lock);
459 return ret;
460}
461
462static int fimc_cap_g_input(struct file *file, void *priv,
463 unsigned int *i)
464{
465 struct fimc_ctx *ctx = priv;
466 struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
467
468 *i = cap->input_index;
469 return 0;
470}
471
472static int fimc_cap_streamon(struct file *file, void *priv,
473 enum v4l2_buf_type type)
474{
475 struct s3c_fimc_isp_info *isp_info;
476 struct fimc_ctx *ctx = priv;
477 struct fimc_dev *fimc = ctx->fimc_dev;
478 int ret = -EBUSY;
479
480 if (mutex_lock_interruptible(&fimc->lock))
481 return -ERESTARTSYS;
482
483 if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
484 goto s_unlock;
485
486 if (!(ctx->state & FIMC_DST_FMT)) {
487 v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
488 ret = -EINVAL;
489 goto s_unlock;
490 }
491
492 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
493 if (ret && ret != -ENOIOCTLCMD)
494 goto s_unlock;
495
496 ret = fimc_prepare_config(ctx, ctx->state);
497 if (ret)
498 goto s_unlock;
499
500 isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
501 fimc_hw_set_camera_type(fimc, isp_info);
502 fimc_hw_set_camera_source(fimc, isp_info);
503 fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
504
505 if (ctx->state & FIMC_PARAMS) {
506 ret = fimc_set_scaler_info(ctx);
507 if (ret) {
508 err("Scaler setup error");
509 goto s_unlock;
510 }
511 fimc_hw_set_input_path(ctx);
512 fimc_hw_set_scaler(ctx);
513 fimc_hw_set_target_format(ctx);
514 fimc_hw_set_rotation(ctx);
515 fimc_hw_set_effect(ctx);
516 }
517
518 fimc_hw_set_output_path(ctx);
519 fimc_hw_set_out_dma(ctx);
520
521 INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
522 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
523 fimc->vid_cap.active_buf_cnt = 0;
524 fimc->vid_cap.frame_count = 0;
525
526 set_bit(ST_CAPT_PEND, &fimc->state);
527 ret = videobuf_streamon(&fimc->vid_cap.vbq);
528
529s_unlock:
530 mutex_unlock(&fimc->lock);
531 return ret;
532}
533
534static int fimc_cap_streamoff(struct file *file, void *priv,
535 enum v4l2_buf_type type)
536{
537 struct fimc_ctx *ctx = priv;
538 struct fimc_dev *fimc = ctx->fimc_dev;
539 struct fimc_vid_cap *cap = &fimc->vid_cap;
540 unsigned long flags;
541 int ret;
542
543 spin_lock_irqsave(&fimc->slock, flags);
544 if (!fimc_capture_running(fimc) && !fimc_capture_pending(fimc)) {
545 spin_unlock_irqrestore(&fimc->slock, flags);
546 dbg("state: 0x%lx", fimc->state);
547 return -EINVAL;
548 }
549 spin_unlock_irqrestore(&fimc->slock, flags);
550
551 if (mutex_lock_interruptible(&fimc->lock))
552 return -ERESTARTSYS;
553
554 fimc_stop_capture(fimc);
555 ret = videobuf_streamoff(&cap->vbq);
556 mutex_unlock(&fimc->lock);
557 return ret;
558}
559
560static int fimc_cap_reqbufs(struct file *file, void *priv,
561 struct v4l2_requestbuffers *reqbufs)
562{
563 struct fimc_ctx *ctx = priv;
564 struct fimc_dev *fimc = ctx->fimc_dev;
565 struct fimc_vid_cap *cap = &fimc->vid_cap;
566 int ret;
567
568 if (fimc_capture_active(ctx->fimc_dev))
569 return -EBUSY;
570
571 if (mutex_lock_interruptible(&fimc->lock))
572 return -ERESTARTSYS;
573
574 ret = videobuf_reqbufs(&cap->vbq, reqbufs);
575 if (!ret)
576 cap->reqbufs_count = reqbufs->count;
577
578 mutex_unlock(&fimc->lock);
579 return ret;
580}
581
582static int fimc_cap_querybuf(struct file *file, void *priv,
583 struct v4l2_buffer *buf)
584{
585 struct fimc_ctx *ctx = priv;
586 struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
587
588 if (fimc_capture_active(ctx->fimc_dev))
589 return -EBUSY;
590
591 return videobuf_querybuf(&cap->vbq, buf);
592}
593
594static int fimc_cap_qbuf(struct file *file, void *priv,
595 struct v4l2_buffer *buf)
596{
597 struct fimc_ctx *ctx = priv;
598 struct fimc_dev *fimc = ctx->fimc_dev;
599 struct fimc_vid_cap *cap = &fimc->vid_cap;
600 int ret;
601
602 if (mutex_lock_interruptible(&fimc->lock))
603 return -ERESTARTSYS;
604
605 ret = videobuf_qbuf(&cap->vbq, buf);
606
607 mutex_unlock(&fimc->lock);
608 return ret;
609}
610
611static int fimc_cap_dqbuf(struct file *file, void *priv,
612 struct v4l2_buffer *buf)
613{
614 struct fimc_ctx *ctx = priv;
615 int ret;
616
617 if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
618 return -ERESTARTSYS;
619
620 ret = videobuf_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
621 file->f_flags & O_NONBLOCK);
622
623 mutex_unlock(&ctx->fimc_dev->lock);
624 return ret;
625}
626
627static int fimc_cap_s_ctrl(struct file *file, void *priv,
628 struct v4l2_control *ctrl)
629{
630 struct fimc_ctx *ctx = priv;
631 int ret = -EINVAL;
632
633 if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
634 return -ERESTARTSYS;
635
636 /* Allow any controls but 90/270 rotation while streaming */
637 if (!fimc_capture_active(ctx->fimc_dev) ||
638 ctrl->id != V4L2_CID_ROTATE ||
639 (ctrl->value != 90 && ctrl->value != 270)) {
640 ret = check_ctrl_val(ctx, ctrl);
641 if (!ret) {
642 ret = fimc_s_ctrl(ctx, ctrl);
643 if (!ret)
644 ctx->state |= FIMC_PARAMS;
645 }
646 }
647 if (ret == -EINVAL)
648 ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
649 core, s_ctrl, ctrl);
650
651 mutex_unlock(&ctx->fimc_dev->lock);
652 return ret;
653}
654
655static int fimc_cap_s_crop(struct file *file, void *fh,
656 struct v4l2_crop *cr)
657{
658 struct fimc_frame *f;
659 struct fimc_ctx *ctx = file->private_data;
660 struct fimc_dev *fimc = ctx->fimc_dev;
661 int ret = -EINVAL;
662
663 if (fimc_capture_active(fimc))
664 return -EBUSY;
665
666 ret = fimc_try_crop(ctx, cr);
667 if (ret)
668 return ret;
669
670 if (mutex_lock_interruptible(&fimc->lock))
671 return -ERESTARTSYS;
672
673 if (!(ctx->state & FIMC_DST_FMT)) {
674 v4l2_err(&fimc->vid_cap.v4l2_dev,
675 "Capture color format not set\n");
676 goto sc_unlock;
677 }
678
679 f = &ctx->s_frame;
680 /* Check for the pixel scaling ratio when cropping input image. */
681 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
682 if (ret) {
683 v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range");
684 } else {
685 ret = 0;
686 f->offs_h = cr->c.left;
687 f->offs_v = cr->c.top;
688 f->width = cr->c.width;
689 f->height = cr->c.height;
690 }
691
692sc_unlock:
693 mutex_unlock(&fimc->lock);
694 return ret;
695}
696
697
698static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
699 .vidioc_querycap = fimc_vidioc_querycap_capture,
700
701 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt,
702 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt,
703 .vidioc_s_fmt_vid_cap = fimc_cap_s_fmt,
704 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt,
705
706 .vidioc_reqbufs = fimc_cap_reqbufs,
707 .vidioc_querybuf = fimc_cap_querybuf,
708
709 .vidioc_qbuf = fimc_cap_qbuf,
710 .vidioc_dqbuf = fimc_cap_dqbuf,
711
712 .vidioc_streamon = fimc_cap_streamon,
713 .vidioc_streamoff = fimc_cap_streamoff,
714
715 .vidioc_queryctrl = fimc_vidioc_queryctrl,
716 .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
717 .vidioc_s_ctrl = fimc_cap_s_ctrl,
718
719 .vidioc_g_crop = fimc_vidioc_g_crop,
720 .vidioc_s_crop = fimc_cap_s_crop,
721 .vidioc_cropcap = fimc_vidioc_cropcap,
722
723 .vidioc_enum_input = fimc_cap_enum_input,
724 .vidioc_s_input = fimc_cap_s_input,
725 .vidioc_g_input = fimc_cap_g_input,
726};
727
728int fimc_register_capture_device(struct fimc_dev *fimc)
729{
730 struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
731 struct video_device *vfd;
732 struct fimc_vid_cap *vid_cap;
733 struct fimc_ctx *ctx;
734 struct v4l2_format f;
735 int ret;
736
737 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
738 if (!ctx)
739 return -ENOMEM;
740
741 ctx->fimc_dev = fimc;
742 ctx->in_path = FIMC_CAMERA;
743 ctx->out_path = FIMC_DMA;
744 ctx->state = FIMC_CTX_CAP;
745
746 f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
747 ctx->d_frame.fmt = find_format(&f, FMT_FLAGS_M2M);
748
749 if (!v4l2_dev->name[0])
750 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
751 "%s.capture", dev_name(&fimc->pdev->dev));
752
753 ret = v4l2_device_register(NULL, v4l2_dev);
754 if (ret)
755 goto err_info;
756
757 vfd = video_device_alloc();
758 if (!vfd) {
759 v4l2_err(v4l2_dev, "Failed to allocate video device\n");
760 goto err_v4l2_reg;
761 }
762
763 snprintf(vfd->name, sizeof(vfd->name), "%s:cap",
764 dev_name(&fimc->pdev->dev));
765
766 vfd->fops = &fimc_capture_fops;
767 vfd->ioctl_ops = &fimc_capture_ioctl_ops;
768 vfd->minor = -1;
769 vfd->release = video_device_release;
770 video_set_drvdata(vfd, fimc);
771
772 vid_cap = &fimc->vid_cap;
773 vid_cap->vfd = vfd;
774 vid_cap->active_buf_cnt = 0;
775 vid_cap->reqbufs_count = 0;
776 vid_cap->refcnt = 0;
777 /* The default color format for image sensor. */
778 vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
779
780 INIT_LIST_HEAD(&vid_cap->pending_buf_q);
781 INIT_LIST_HEAD(&vid_cap->active_buf_q);
782 spin_lock_init(&ctx->slock);
783 vid_cap->ctx = ctx;
784
785 videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
786 vid_cap->v4l2_dev.dev, &fimc->irqlock,
787 V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
788 sizeof(struct fimc_vid_buffer), (void *)ctx);
789
790 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
791 if (ret) {
792 v4l2_err(v4l2_dev, "Failed to register video device\n");
793 goto err_vd_reg;
794 }
795
796 v4l2_info(v4l2_dev,
797 "FIMC capture driver registered as /dev/video%d\n",
798 vfd->num);
799
800 return 0;
801
802err_vd_reg:
803 video_device_release(vfd);
804err_v4l2_reg:
805 v4l2_device_unregister(v4l2_dev);
806err_info:
807 dev_err(&fimc->pdev->dev, "failed to install\n");
808 return ret;
809}
810
811void fimc_unregister_capture_device(struct fimc_dev *fimc)
812{
813 struct fimc_vid_cap *capture = &fimc->vid_cap;
814
815 if (capture->vfd)
816 video_unregister_device(capture->vfd);
817
818 kfree(capture->ctx);
819}