summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch2249
1 files changed, 2249 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
new file mode 100644
index 0000000000..22074be148
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
@@ -0,0 +1,2249 @@
1From 0edf5a50dc0164db5bc71b1a5d1aa8bb1838262c Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:03 +0200
4Subject: [PATCH] omap34xxcam: Add camera driver
5
6This is the camera driver for the OMAP 3 camera ISP and v4l2-int-device
7sensors, lenses and (led) flashes. There are a few connections to OMAP
83 left but after those have been broken this is hardware independent.
9Namely, the OMAP 3 ISP must offer a standard interface through
10v4l2_subdev (or v4l2-int-device) first.
11
12This driver has originated from the omap24xxcam camera driver written
13specifically for OMAP 2.
14
15TODO:
16
17- Convert to use v4l2_subdev instead of v4l2-int-device.
18
19Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20---
21 drivers/media/video/Kconfig | 9 +
22 drivers/media/video/Makefile | 2 +
23 drivers/media/video/omap34xxcam.c | 1966 +++++++++++++++++++++++++++++++++++++
24 drivers/media/video/omap34xxcam.h | 207 ++++
25 4 files changed, 2184 insertions(+), 0 deletions(-)
26 create mode 100644 drivers/media/video/omap34xxcam.c
27 create mode 100644 drivers/media/video/omap34xxcam.h
28
29diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
30index 19cf3b8..3cdb5a4 100644
31--- a/drivers/media/video/Kconfig
32+++ b/drivers/media/video/Kconfig
33@@ -711,6 +711,15 @@ config VIDEO_CAFE_CCIC
34 CMOS camera controller. This is the controller found on first-
35 generation OLPC systems.
36
37+config VIDEO_OMAP3
38+ tristate "OMAP 3 Camera support"
39+ select VIDEOBUF_GEN
40+ select VIDEOBUF_DMA_SG
41+ select OMAP_IOMMU
42+ depends on VIDEO_V4L2 && ARCH_OMAP34XX
43+ ---help---
44+ Driver for an OMAP 3 camera controller.
45+
46 config SOC_CAMERA
47 tristate "SoC camera support"
48 depends on VIDEO_V4L2 && HAS_DMA
49diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
50index e654270..74a684e 100644
51--- a/drivers/media/video/Makefile
52+++ b/drivers/media/video/Makefile
53@@ -108,6 +108,8 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
54
55 obj-y += isp/
56
57+obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o
58+
59 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
60
61 obj-$(CONFIG_USB_DABUSB) += dabusb.o
62diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
63new file mode 100644
64index 0000000..00fdbf2
65--- /dev/null
66+++ b/drivers/media/video/omap34xxcam.c
67@@ -0,0 +1,1966 @@
68+/*
69+ * omap34xxcam.c
70+ *
71+ * Copyright (C) 2006--2009 Nokia Corporation
72+ * Copyright (C) 2007--2009 Texas Instruments
73+ *
74+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
75+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
76+ *
77+ * Originally based on the OMAP 2 camera driver.
78+ *
79+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
80+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
81+ * Sergio Aguirre <saaguirre@ti.com>
82+ * Mohit Jalori
83+ * Sameer Venkatraman
84+ * Leonides Martinez
85+ *
86+ * This program is free software; you can redistribute it and/or
87+ * modify it under the terms of the GNU General Public License
88+ * version 2 as published by the Free Software Foundation.
89+ *
90+ * This program is distributed in the hope that it will be useful, but
91+ * WITHOUT ANY WARRANTY; without even the implied warranty of
92+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
93+ * General Public License for more details.
94+ *
95+ * You should have received a copy of the GNU General Public License
96+ * along with this program; if not, write to the Free Software
97+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
98+ * 02110-1301 USA
99+ *
100+ */
101+
102+#include <linux/io.h>
103+#include <linux/clk.h>
104+#include <linux/pci.h> /* needed for videobufs */
105+#include <linux/delay.h>
106+#include <linux/kernel.h>
107+#include <linux/interrupt.h>
108+#include <linux/videodev2.h>
109+#include <linux/version.h>
110+#include <linux/platform_device.h>
111+
112+#include <media/v4l2-common.h>
113+#include <media/v4l2-ioctl.h>
114+
115+#include "omap34xxcam.h"
116+#include "isp/isp.h"
117+#include "isp/ispmmu.h"
118+#include "isp/ispreg.h"
119+#include "isp/ispccdc.h"
120+#include "isp/isph3a.h"
121+#include "isp/isp_af.h"
122+#include "isp/isphist.h"
123+#include "isp/isppreview.h"
124+#include "isp/ispresizer.h"
125+
126+#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
127+
128+/* global variables */
129+static struct omap34xxcam_device *omap34xxcam;
130+
131+/*
132+ *
133+ * Sensor handling.
134+ *
135+ */
136+
137+/**
138+ * omap34xxcam_slave_power_set - set slave power state
139+ * @vdev: per-video device data structure
140+ * @power: new power state
141+ */
142+static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
143+ enum v4l2_power power,
144+ int mask)
145+{
146+ int rval = 0, i = 0;
147+
148+ BUG_ON(!mutex_is_locked(&vdev->mutex));
149+
150+#ifdef OMAP34XXCAM_POWEROFF_DELAY
151+ vdev->power_state_wish = -1;
152+#endif
153+
154+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
155+ if (vdev->slave[i] == v4l2_int_device_dummy())
156+ continue;
157+
158+ if (!(mask & (1 << i))
159+ || power == vdev->power_state[i])
160+ continue;
161+
162+ rval = vidioc_int_s_power(vdev->slave[i], power);
163+
164+ if (rval && power != V4L2_POWER_OFF) {
165+ power = V4L2_POWER_OFF;
166+ goto out;
167+ }
168+
169+ vdev->power_state[i] = power;
170+ }
171+
172+ return 0;
173+
174+out:
175+ for (i--; i >= 0; i--) {
176+ if (vdev->slave[i] == v4l2_int_device_dummy())
177+ continue;
178+
179+ if (!(mask & (1 << i)))
180+ continue;
181+
182+ vidioc_int_s_power(vdev->slave[i], power);
183+ vdev->power_state[i] = power;
184+ }
185+
186+ return rval;
187+}
188+
189+#ifdef OMAP34XXCAM_POWEROFF_DELAY
190+static void omap34xxcam_slave_power_work(struct work_struct *work)
191+{
192+ struct omap34xxcam_videodev *vdev =
193+ container_of(work, struct omap34xxcam_videodev, poweroff_work);
194+
195+ mutex_lock(&vdev->mutex);
196+
197+ if (vdev->power_state_wish != -1)
198+ omap34xxcam_slave_power_set(vdev, vdev->power_state_wish,
199+ vdev->power_state_mask);
200+
201+ mutex_unlock(&vdev->mutex);
202+}
203+
204+static void omap34xxcam_slave_power_timer(unsigned long ptr)
205+{
206+ struct omap34xxcam_videodev *vdev = (void *)ptr;
207+
208+ schedule_work(&vdev->poweroff_work);
209+}
210+
211+/**
212+ * omap34xxcam_slave_power_suggest - delayed power state change
213+ *
214+ * @vdev: per-video device data structure
215+ * @power: new power state
216+ */
217+static void omap34xxcam_slave_power_suggest(struct omap34xxcam_videodev *vdev,
218+ enum v4l2_power power,
219+ int mask)
220+{
221+ BUG_ON(!mutex_is_locked(&vdev->mutex));
222+
223+ del_timer(&vdev->poweroff_timer);
224+
225+ vdev->power_state_wish = power;
226+ vdev->power_state_mask = mask;
227+
228+ mod_timer(&vdev->poweroff_timer, jiffies + OMAP34XXCAM_POWEROFF_DELAY);
229+}
230+#else /* OMAP34XXCAM_POWEROFF_DELAY */
231+#define omap34xxcam_slave_power_suggest(a, b, c) do {} while (0)
232+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
233+
234+/**
235+ * omap34xxcam_update_vbq - Updates VBQ with completed input buffer
236+ * @vb: ptr. to standard V4L2 video buffer structure
237+ *
238+ * Updates video buffer queue with completed buffer passed as
239+ * input parameter. Also updates ISP H3A timestamp and field count
240+ * statistics.
241+ */
242+void omap34xxcam_vbq_complete(struct videobuf_buffer *vb, void *priv)
243+{
244+ struct omap34xxcam_fh *fh = priv;
245+
246+ do_gettimeofday(&vb->ts);
247+ vb->field_count = atomic_add_return(2, &fh->field_count);
248+
249+ wake_up(&vb->done);
250+}
251+
252+/**
253+ * omap34xxcam_vbq_setup - Calcs size and num of buffs allowed in queue
254+ * @vbq: ptr. to standard V4L2 video buffer queue structure
255+ * @cnt: ptr to location to hold the count of buffers to be in the queue
256+ * @size: ptr to location to hold the size of a frame
257+ *
258+ * Calculates the number of buffers of current image size that can be
259+ * supported by the available capture memory.
260+ */
261+static int omap34xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
262+ unsigned int *size)
263+{
264+ struct omap34xxcam_fh *fh = vbq->priv_data;
265+ struct omap34xxcam_videodev *vdev = fh->vdev;
266+
267+ if (*cnt <= 0)
268+ *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */
269+
270+ if (*cnt > VIDEO_MAX_FRAME)
271+ *cnt = VIDEO_MAX_FRAME;
272+
273+ *size = vdev->pix.sizeimage;
274+
275+ while (*size * *cnt > fh->vdev->vdev_sensor_config.capture_mem)
276+ (*cnt)--;
277+
278+ return isp_vbq_setup(vbq, cnt, size);
279+}
280+
281+/**
282+ * omap34xxcam_vbq_release - Free resources for input VBQ and VB
283+ * @vbq: ptr. to standard V4L2 video buffer queue structure
284+ * @vb: ptr to standard V4L2 video buffer structure
285+ *
286+ * Unmap and free all memory associated with input VBQ and VB, also
287+ * unmap the address in ISP MMU. Reset the VB state.
288+ */
289+static void omap34xxcam_vbq_release(struct videobuf_queue *vbq,
290+ struct videobuf_buffer *vb)
291+{
292+ if (!vbq->streaming) {
293+ isp_vbq_release(vbq, vb);
294+ videobuf_dma_unmap(vbq, videobuf_to_dma(vb));
295+ videobuf_dma_free(videobuf_to_dma(vb));
296+ vb->state = VIDEOBUF_NEEDS_INIT;
297+ }
298+ return;
299+}
300+
301+/**
302+ * omap34xxcam_vbq_prepare - V4L2 video ops buf_prepare handler
303+ * @vbq: ptr. to standard V4L2 video buffer queue structure
304+ * @vb: ptr to standard V4L2 video buffer structure
305+ * @field: standard V4L2 field enum
306+ *
307+ * Verifies there is sufficient locked memory for the requested
308+ * buffer, or if there is not, allocates, locks and initializes
309+ * it.
310+ */
311+static int omap34xxcam_vbq_prepare(struct videobuf_queue *vbq,
312+ struct videobuf_buffer *vb,
313+ enum v4l2_field field)
314+{
315+ struct omap34xxcam_fh *fh = vbq->priv_data;
316+ struct omap34xxcam_videodev *vdev = fh->vdev;
317+ int err = 0;
318+
319+ /*
320+ * Accessing pix here is okay since it's constant while
321+ * streaming is on (and we only get called then).
322+ */
323+ if (vb->baddr) {
324+ /* This is a userspace buffer. */
325+ if (vdev->pix.sizeimage > vb->bsize)
326+ /* The buffer isn't big enough. */
327+ return -EINVAL;
328+ } else {
329+ if (vb->state != VIDEOBUF_NEEDS_INIT
330+ && vdev->pix.sizeimage > vb->bsize)
331+ /*
332+ * We have a kernel bounce buffer that has
333+ * already been allocated.
334+ */
335+ omap34xxcam_vbq_release(vbq, vb);
336+ }
337+
338+ vb->size = vdev->pix.bytesperline * vdev->pix.height;
339+ vb->width = vdev->pix.width;
340+ vb->height = vdev->pix.height;
341+ vb->field = field;
342+
343+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
344+ err = videobuf_iolock(vbq, vb, NULL);
345+ if (!err) {
346+ /* isp_addr will be stored locally inside isp code */
347+ err = isp_vbq_prepare(vbq, vb, field);
348+ }
349+ }
350+
351+ if (!err)
352+ vb->state = VIDEOBUF_PREPARED;
353+ else
354+ omap34xxcam_vbq_release(vbq, vb);
355+
356+ return err;
357+}
358+
359+/**
360+ * omap34xxcam_vbq_queue - V4L2 video ops buf_queue handler
361+ * @vbq: ptr. to standard V4L2 video buffer queue structure
362+ * @vb: ptr to standard V4L2 video buffer structure
363+ *
364+ * Maps the video buffer to sgdma and through the isp, sets
365+ * the isp buffer done callback and sets the video buffer state
366+ * to active.
367+ */
368+static void omap34xxcam_vbq_queue(struct videobuf_queue *vbq,
369+ struct videobuf_buffer *vb)
370+{
371+ struct omap34xxcam_fh *fh = vbq->priv_data;
372+
373+ vb->state = VIDEOBUF_ACTIVE;
374+
375+ isp_buf_queue(vb, omap34xxcam_vbq_complete, (void *)fh);
376+}
377+
378+static struct videobuf_queue_ops omap34xxcam_vbq_ops = {
379+ .buf_setup = omap34xxcam_vbq_setup,
380+ .buf_prepare = omap34xxcam_vbq_prepare,
381+ .buf_queue = omap34xxcam_vbq_queue,
382+ .buf_release = omap34xxcam_vbq_release,
383+};
384+
385+/*
386+ *
387+ * IOCTL interface.
388+ *
389+ */
390+
391+/**
392+ * vidioc_querycap - V4L2 query capabilities IOCTL handler
393+ * @file: ptr. to system file structure
394+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
395+ * @cap: ptr to standard V4L2 capability structure
396+ *
397+ * Fill in the V4L2 capabliity structure for the camera device
398+ */
399+static int vidioc_querycap(struct file *file, void *fh,
400+ struct v4l2_capability *cap)
401+{
402+ struct omap34xxcam_fh *ofh = fh;
403+ struct omap34xxcam_videodev *vdev = ofh->vdev;
404+
405+ strlcpy(cap->driver, CAM_SHORT_NAME, sizeof(cap->driver));
406+ strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
407+ cap->version = OMAP34XXCAM_VERSION;
408+ if (vdev->vdev_sensor != v4l2_int_device_dummy())
409+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
410+
411+ return 0;
412+}
413+
414+/**
415+ * vidioc_enum_fmt_vid_cap - V4L2 enumerate format capabilities IOCTL handler
416+ * @file: ptr. to system file structure
417+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
418+ * @f: ptr to standard V4L2 format description structure
419+ *
420+ * Fills in enumerate format capabilities information for sensor (if SOC
421+ * sensor attached) or ISP (if raw sensor attached).
422+ */
423+static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
424+ struct v4l2_fmtdesc *f)
425+{
426+ struct omap34xxcam_fh *ofh = fh;
427+ struct omap34xxcam_videodev *vdev = ofh->vdev;
428+ int rval;
429+
430+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
431+ return -EINVAL;
432+
433+ if (vdev->vdev_sensor_config.sensor_isp)
434+ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, f);
435+ else
436+ rval = isp_enum_fmt_cap(f);
437+
438+ return rval;
439+}
440+
441+/**
442+ * vidioc_g_fmt_vid_cap - V4L2 get format capabilities IOCTL handler
443+ * @file: ptr. to system file structure
444+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
445+ * @f: ptr to standard V4L2 format structure
446+ *
447+ * Fills in format capabilities for sensor (if SOC sensor attached) or ISP
448+ * (if raw sensor attached).
449+ */
450+static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
451+ struct v4l2_format *f)
452+{
453+ struct omap34xxcam_fh *ofh = fh;
454+ struct omap34xxcam_videodev *vdev = ofh->vdev;
455+
456+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
457+ return -EINVAL;
458+
459+ mutex_lock(&vdev->mutex);
460+ f->fmt.pix = vdev->pix;
461+ mutex_unlock(&vdev->mutex);
462+
463+ return 0;
464+}
465+
466+static int try_pix_parm(struct omap34xxcam_videodev *vdev,
467+ struct v4l2_pix_format *best_pix_in,
468+ struct v4l2_pix_format *wanted_pix_out,
469+ struct v4l2_fract *best_ival)
470+{
471+ int fps;
472+ int fmtd_index;
473+ int rval;
474+ struct v4l2_pix_format best_pix_out;
475+
476+ if (best_ival->numerator == 0
477+ || best_ival->denominator == 0)
478+ *best_ival = vdev->vdev_sensor_config.ival_default;
479+
480+ fps = best_ival->denominator / best_ival->numerator;
481+
482+ best_ival->denominator = 0;
483+ best_pix_out.height = INT_MAX >> 1;
484+ best_pix_out.width = best_pix_out.height;
485+
486+ for (fmtd_index = 0; ; fmtd_index++) {
487+ int size_index;
488+ struct v4l2_fmtdesc fmtd;
489+
490+ fmtd.index = fmtd_index;
491+ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
492+ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, &fmtd);
493+ if (rval)
494+ break;
495+ dev_info(&vdev->vfd->dev, "trying fmt %8.8x (%d)\n",
496+ fmtd.pixelformat, fmtd_index);
497+ /*
498+ * Get supported resolutions.
499+ */
500+ for (size_index = 0; ; size_index++) {
501+ struct v4l2_frmsizeenum frms;
502+ struct v4l2_pix_format pix_tmp_in, pix_tmp_out;
503+ int ival_index;
504+
505+ frms.index = size_index;
506+ frms.pixel_format = fmtd.pixelformat;
507+
508+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor,
509+ &frms);
510+ if (rval)
511+ break;
512+
513+ pix_tmp_in.pixelformat = frms.pixel_format;
514+ pix_tmp_in.width = frms.discrete.width;
515+ pix_tmp_in.height = frms.discrete.height;
516+ pix_tmp_out = *wanted_pix_out;
517+ /* Don't do upscaling. */
518+ if (pix_tmp_out.width > pix_tmp_in.width)
519+ pix_tmp_out.width = pix_tmp_in.width;
520+ if (pix_tmp_out.height > pix_tmp_in.height)
521+ pix_tmp_out.height = pix_tmp_in.height;
522+ rval = isp_try_fmt_cap(&pix_tmp_in, &pix_tmp_out);
523+ if (rval)
524+ return rval;
525+
526+ dev_info(&vdev->vfd->dev, "this w %d\th %d\tfmt %8.8x\t"
527+ "-> w %d\th %d\t fmt %8.8x"
528+ "\twanted w %d\th %d\t fmt %8.8x\n",
529+ pix_tmp_in.width, pix_tmp_in.height,
530+ pix_tmp_in.pixelformat,
531+ pix_tmp_out.width, pix_tmp_out.height,
532+ pix_tmp_out.pixelformat,
533+ wanted_pix_out->width, wanted_pix_out->height,
534+ wanted_pix_out->pixelformat);
535+
536+#define IS_SMALLER_OR_EQUAL(pix1, pix2) \
537+ ((pix1)->width + (pix1)->height \
538+ < (pix2)->width + (pix2)->height)
539+#define SIZE_DIFF(pix1, pix2) \
540+ (abs((pix1)->width - (pix2)->width) \
541+ + abs((pix1)->height - (pix2)->height))
542+
543+ /*
544+ * Don't use modes that are farther from wanted size
545+ * that what we already got.
546+ */
547+ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
548+ > SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
549+ dev_info(&vdev->vfd->dev, "size diff bigger: "
550+ "w %d\th %d\tw %d\th %d\n",
551+ pix_tmp_out.width, pix_tmp_out.height,
552+ best_pix_out.width,
553+ best_pix_out.height);
554+ continue;
555+ }
556+
557+ /*
558+ * There's an input mode that can provide output
559+ * closer to wanted.
560+ */
561+ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
562+ < SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
563+ /* Force renegotation of fps etc. */
564+ best_ival->denominator = 0;
565+ dev_info(&vdev->vfd->dev, "renegotiate: "
566+ "w %d\th %d\tw %d\th %d\n",
567+ pix_tmp_out.width, pix_tmp_out.height,
568+ best_pix_out.width,
569+ best_pix_out.height);
570+ }
571+
572+ for (ival_index = 0; ; ival_index++) {
573+ struct v4l2_frmivalenum frmi;
574+
575+ frmi.index = ival_index;
576+ frmi.pixel_format = frms.pixel_format;
577+ frmi.width = frms.discrete.width;
578+ frmi.height = frms.discrete.height;
579+ /* FIXME: try to fix standard... */
580+ frmi.reserved[0] = 0xdeafbeef;
581+
582+ rval = vidioc_int_enum_frameintervals(
583+ vdev->vdev_sensor, &frmi);
584+ if (rval)
585+ break;
586+
587+ dev_info(&vdev->vfd->dev, "fps %d\n",
588+ frmi.discrete.denominator
589+ / frmi.discrete.numerator);
590+
591+ if (best_ival->denominator == 0)
592+ goto do_it_now;
593+
594+ /*
595+ * We aim to use maximum resolution
596+ * from the sensor, provided that the
597+ * fps is at least as close as on the
598+ * current mode.
599+ */
600+#define FPS_ABS_DIFF(fps, ival) abs(fps - (ival).denominator / (ival).numerator)
601+
602+ /* Select mode with closest fps. */
603+ if (FPS_ABS_DIFF(fps, frmi.discrete)
604+ < FPS_ABS_DIFF(fps, *best_ival)) {
605+ dev_info(&vdev->vfd->dev, "closer fps: "
606+ "fps %d\t fps %d\n",
607+ FPS_ABS_DIFF(fps,
608+ frmi.discrete),
609+ FPS_ABS_DIFF(fps, *best_ival));
610+ goto do_it_now;
611+ }
612+
613+ /*
614+ * Select bigger resolution if it's available
615+ * at same fps.
616+ */
617+ if (frmi.width + frmi.height
618+ > best_pix_in->width + best_pix_in->height
619+ && FPS_ABS_DIFF(fps, frmi.discrete)
620+ <= FPS_ABS_DIFF(fps, *best_ival)) {
621+ dev_info(&vdev->vfd->dev, "bigger res, "
622+ "same fps: "
623+ "w %d\th %d\tw %d\th %d\n",
624+ frmi.width, frmi.height,
625+ best_pix_in->width,
626+ best_pix_in->height);
627+ goto do_it_now;
628+ }
629+
630+ dev_info(&vdev->vfd->dev, "falling through\n");
631+
632+ continue;
633+
634+do_it_now:
635+ *best_ival = frmi.discrete;
636+ best_pix_out = pix_tmp_out;
637+ best_pix_in->width = frmi.width;
638+ best_pix_in->height = frmi.height;
639+ best_pix_in->pixelformat = frmi.pixel_format;
640+
641+ dev_info(&vdev->vfd->dev,
642+ "best_pix_in: w %d\th %d\tfmt %8.8x"
643+ "\tival %d/%d\n",
644+ best_pix_in->width,
645+ best_pix_in->height,
646+ best_pix_in->pixelformat,
647+ best_ival->numerator,
648+ best_ival->denominator);
649+ }
650+ }
651+ }
652+
653+ if (best_ival->denominator == 0)
654+ return -EINVAL;
655+
656+ *wanted_pix_out = best_pix_out;
657+
658+ dev_info(&vdev->vfd->dev, "w %d, h %d, fmt %8.8x -> w %d, h %d\n",
659+ best_pix_in->width, best_pix_in->height,
660+ best_pix_in->pixelformat,
661+ best_pix_out.width, best_pix_out.height);
662+
663+ return isp_try_fmt_cap(best_pix_in, wanted_pix_out);
664+}
665+
666+static int s_pix_parm(struct omap34xxcam_videodev *vdev,
667+ struct v4l2_pix_format *best_pix,
668+ struct v4l2_pix_format *pix,
669+ struct v4l2_fract *best_ival)
670+{
671+ struct v4l2_streamparm a;
672+ struct v4l2_format fmt;
673+ int rval;
674+
675+ rval = try_pix_parm(vdev, best_pix, pix, best_ival);
676+ if (rval)
677+ return rval;
678+
679+ rval = isp_s_fmt_cap(best_pix, pix);
680+ if (rval)
681+ return rval;
682+
683+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
684+ fmt.fmt.pix = *best_pix;
685+ rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &fmt);
686+ if (rval)
687+ return rval;
688+
689+ a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
690+ a.parm.capture.timeperframe = *best_ival;
691+ rval = vidioc_int_s_parm(vdev->vdev_sensor, &a);
692+
693+ return rval;
694+}
695+
696+/**
697+ * vidioc_s_fmt_vid_cap - V4L2 set format capabilities IOCTL handler
698+ * @file: ptr. to system file structure
699+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
700+ * @f: ptr to standard V4L2 format structure
701+ *
702+ * Attempts to set input format with the sensor driver (first) and then the
703+ * ISP. Returns the return code from vidioc_g_fmt_vid_cap().
704+ */
705+static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
706+ struct v4l2_format *f)
707+{
708+ struct omap34xxcam_fh *ofh = fh;
709+ struct omap34xxcam_videodev *vdev = ofh->vdev;
710+ struct v4l2_pix_format pix_tmp;
711+ struct v4l2_fract timeperframe;
712+ int rval;
713+
714+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
715+ return -EINVAL;
716+
717+ mutex_lock(&vdev->mutex);
718+ if (vdev->streaming) {
719+ rval = -EBUSY;
720+ goto out;
721+ }
722+
723+ vdev->want_pix = f->fmt.pix;
724+
725+ timeperframe = vdev->want_timeperframe;
726+
727+ rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
728+ if (!rval)
729+ vdev->pix = f->fmt.pix;
730+
731+out:
732+ mutex_unlock(&vdev->mutex);
733+
734+ return rval;
735+}
736+
737+/**
738+ * vidioc_try_fmt_vid_cap - V4L2 try format capabilities IOCTL handler
739+ * @file: ptr. to system file structure
740+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
741+ * @f: ptr to standard V4L2 format structure
742+ *
743+ * Checks if the given format is supported by the sensor driver and
744+ * by the ISP.
745+ */
746+static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
747+ struct v4l2_format *f)
748+{
749+ struct omap34xxcam_fh *ofh = fh;
750+ struct omap34xxcam_videodev *vdev = ofh->vdev;
751+ struct v4l2_pix_format pix_tmp;
752+ struct v4l2_fract timeperframe;
753+ int rval;
754+
755+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
756+ return -EINVAL;
757+
758+ mutex_lock(&vdev->mutex);
759+
760+ timeperframe = vdev->want_timeperframe;
761+
762+ rval = try_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
763+
764+ mutex_unlock(&vdev->mutex);
765+
766+ return rval;
767+}
768+
769+/**
770+ * vidioc_reqbufs - V4L2 request buffers IOCTL handler
771+ * @file: ptr. to system file structure
772+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
773+ * @b: ptr to standard V4L2 request buffers structure
774+ *
775+ * Attempts to get a buffer from the buffer queue associated with the
776+ * fh through the video buffer library API.
777+ */
778+static int vidioc_reqbufs(struct file *file, void *fh,
779+ struct v4l2_requestbuffers *b)
780+{
781+ struct omap34xxcam_fh *ofh = fh;
782+ struct omap34xxcam_videodev *vdev = ofh->vdev;
783+ int rval;
784+
785+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
786+ return -EINVAL;
787+
788+ mutex_lock(&vdev->mutex);
789+ if (vdev->streaming) {
790+ mutex_unlock(&vdev->mutex);
791+ return -EBUSY;
792+ }
793+
794+ rval = videobuf_reqbufs(&ofh->vbq, b);
795+
796+ mutex_unlock(&vdev->mutex);
797+
798+ /*
799+ * Either videobuf_reqbufs failed or the buffers are not
800+ * memory-mapped (which would need special attention).
801+ */
802+ if (rval < 0 || b->memory != V4L2_MEMORY_MMAP)
803+ goto out;
804+
805+out:
806+ return rval;
807+}
808+
809+/**
810+ * vidioc_querybuf - V4L2 query buffer IOCTL handler
811+ * @file: ptr. to system file structure
812+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
813+ * @b: ptr to standard V4L2 buffer structure
814+ *
815+ * Attempts to fill in the v4l2_buffer structure for the buffer queue
816+ * associated with the fh through the video buffer library API.
817+ */
818+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
819+{
820+ struct omap34xxcam_fh *ofh = fh;
821+
822+ return videobuf_querybuf(&ofh->vbq, b);
823+}
824+
825+/**
826+ * vidioc_qbuf - V4L2 queue buffer IOCTL handler
827+ * @file: ptr. to system file structure
828+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
829+ * @b: ptr to standard V4L2 buffer structure
830+ *
831+ * Attempts to queue the v4l2_buffer on the buffer queue
832+ * associated with the fh through the video buffer library API.
833+ */
834+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
835+{
836+ struct omap34xxcam_fh *ofh = fh;
837+
838+ return videobuf_qbuf(&ofh->vbq, b);
839+}
840+
841+/**
842+ * vidioc_dqbuf - V4L2 dequeue buffer IOCTL handler
843+ * @file: ptr. to system file structure
844+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
845+ * @b: ptr to standard V4L2 buffer structure
846+ *
847+ * Attempts to dequeue the v4l2_buffer from the buffer queue
848+ * associated with the fh through the video buffer library API. If the
849+ * buffer is a user space buffer, then this function will also requeue it,
850+ * as user does not expect to do this.
851+ */
852+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
853+{
854+ struct omap34xxcam_fh *ofh = fh;
855+ int rval;
856+
857+videobuf_dqbuf_again:
858+ rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
859+
860+ /*
861+ * This is a hack. We don't want to show -EIO to the user
862+ * space. Requeue the buffer and try again if we're not doing
863+ * this in non-blocking mode.
864+ */
865+ if (rval == -EIO) {
866+ videobuf_qbuf(&ofh->vbq, b);
867+ if (!(file->f_flags & O_NONBLOCK))
868+ goto videobuf_dqbuf_again;
869+ /*
870+ * We don't have a videobuf_buffer now --- maybe next
871+ * time...
872+ */
873+ rval = -EAGAIN;
874+ }
875+
876+ return rval;
877+}
878+
879+/**
880+ * vidioc_streamon - V4L2 streamon IOCTL handler
881+ * @file: ptr. to system file structure
882+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
883+ * @i: V4L2 buffer type
884+ *
885+ * Attempts to start streaming by enabling the sensor interface and turning
886+ * on video buffer streaming through the video buffer library API. Upon
887+ * success the function returns 0, otherwise an error code is returned.
888+ */
889+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
890+{
891+ struct omap34xxcam_fh *ofh = fh;
892+ struct omap34xxcam_videodev *vdev = ofh->vdev;
893+ int rval;
894+
895+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
896+ return -EINVAL;
897+
898+ mutex_lock(&vdev->mutex);
899+ if (vdev->streaming) {
900+ rval = -EBUSY;
901+ goto out;
902+ }
903+
904+ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
905+ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
906+ if (rval) {
907+ dev_dbg(&vdev->vfd->dev,
908+ "omap34xxcam_slave_power_set failed\n");
909+ goto out;
910+ }
911+
912+ rval = videobuf_streamon(&ofh->vbq);
913+ if (rval)
914+ omap34xxcam_slave_power_set(
915+ vdev, V4L2_POWER_OFF,
916+ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
917+ else
918+ vdev->streaming = file;
919+
920+out:
921+ mutex_unlock(&vdev->mutex);
922+
923+ return rval;
924+}
925+
926+/**
927+ * vidioc_streamoff - V4L2 streamoff IOCTL handler
928+ * @file: ptr. to system file structure
929+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
930+ * @i: V4L2 buffer type
931+ *
932+ * Attempts to stop streaming by flushing all scheduled work, waiting on
933+ * any queued buffers to complete and then stopping the ISP and turning
934+ * off video buffer streaming through the video buffer library API. Upon
935+ * success the function returns 0, otherwise an error code is returned.
936+ */
937+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
938+{
939+ struct omap34xxcam_fh *ofh = fh;
940+ struct omap34xxcam_videodev *vdev = ofh->vdev;
941+ struct videobuf_queue *q = &ofh->vbq;
942+ int rval;
943+
944+ mutex_lock(&vdev->mutex);
945+
946+ if (vdev->streaming == file)
947+ isp_stop();
948+
949+ rval = videobuf_streamoff(q);
950+ if (!rval) {
951+ vdev->streaming = NULL;
952+
953+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY,
954+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
955+ omap34xxcam_slave_power_suggest(vdev, V4L2_POWER_STANDBY,
956+ OMAP34XXCAM_SLAVE_POWER_LENS);
957+ }
958+
959+ mutex_unlock(&vdev->mutex);
960+
961+ return rval;
962+}
963+
964+/**
965+ * vidioc_enum_input - V4L2 enumerate input IOCTL handler
966+ * @file: ptr. to system file structure
967+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
968+ * @inp: V4L2 input type information structure
969+ *
970+ * Fills in v4l2_input structure. Returns 0.
971+ */
972+static int vidioc_enum_input(struct file *file, void *fh,
973+ struct v4l2_input *inp)
974+{
975+ if (inp->index > 0)
976+ return -EINVAL;
977+
978+ strlcpy(inp->name, "camera", sizeof(inp->name));
979+ inp->type = V4L2_INPUT_TYPE_CAMERA;
980+
981+ return 0;
982+}
983+
984+/**
985+ * vidioc_g_input - V4L2 get input IOCTL handler
986+ * @file: ptr. to system file structure
987+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
988+ * @i: address to hold index of input supported
989+ *
990+ * Sets index to 0.
991+ */
992+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
993+{
994+ *i = 0;
995+
996+ return 0;
997+}
998+
999+/**
1000+ * vidioc_s_input - V4L2 set input IOCTL handler
1001+ * @file: ptr. to system file structure
1002+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1003+ * @i: index of input selected
1004+ *
1005+ * 0 is only index supported.
1006+ */
1007+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
1008+{
1009+ if (i > 0)
1010+ return -EINVAL;
1011+
1012+ return 0;
1013+}
1014+
1015+/**
1016+ * vidioc_queryctrl - V4L2 query control IOCTL handler
1017+ * @file: ptr. to system file structure
1018+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1019+ * @a: standard V4L2 query control ioctl structure
1020+ *
1021+ * If the requested control is supported, returns the control information
1022+ * in the v4l2_queryctrl structure. Otherwise, returns -EINVAL if the
1023+ * control is not supported. If the sensor being used is a "smart sensor",
1024+ * this request is passed to the sensor driver, otherwise the ISP is
1025+ * queried and if it does not support the requested control, the request
1026+ * is forwarded to the "raw" sensor driver to see if it supports it.
1027+ */
1028+static int vidioc_queryctrl(struct file *file, void *fh,
1029+ struct v4l2_queryctrl *a)
1030+{
1031+ struct omap34xxcam_fh *ofh = fh;
1032+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1033+ struct v4l2_queryctrl a_tmp;
1034+ int best_slave = -1;
1035+ u32 best_ctrl = (u32)-1;
1036+ int i;
1037+
1038+ if (vdev->vdev_sensor_config.sensor_isp)
1039+ return vidioc_int_queryctrl(vdev->vdev_sensor, a);
1040+
1041+ /* No next flags: try slaves directly. */
1042+ if (!(a->id & V4L2_CTRL_FLAG_NEXT_CTRL)) {
1043+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1044+ if (!vidioc_int_queryctrl(vdev->slave[i], a))
1045+ return 0;
1046+ }
1047+ return isp_queryctrl(a);
1048+ }
1049+
1050+ /* Find slave with smallest next control id. */
1051+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1052+ a_tmp = *a;
1053+
1054+ if (vidioc_int_queryctrl(vdev->slave[i], &a_tmp))
1055+ continue;
1056+
1057+ if (a_tmp.id < best_ctrl) {
1058+ best_slave = i;
1059+ best_ctrl = a_tmp.id;
1060+ }
1061+ }
1062+
1063+ a_tmp = *a;
1064+ if (!isp_queryctrl(&a_tmp)) {
1065+ if (a_tmp.id < best_ctrl) {
1066+ *a = a_tmp;
1067+
1068+ return 0;
1069+ }
1070+ }
1071+
1072+ if (best_slave == -1)
1073+ return -EINVAL;
1074+
1075+ a->id = best_ctrl;
1076+ return vidioc_int_queryctrl(vdev->slave[best_slave], a);
1077+}
1078+
1079+/**
1080+ * vidioc_querymenu - V4L2 query menu IOCTL handler
1081+ * @file: ptr. to system file structure
1082+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1083+ * @a: standard V4L2 query menu ioctl structure
1084+ *
1085+ * If the requested control is supported, returns the menu information
1086+ * in the v4l2_querymenu structure. Otherwise, returns -EINVAL if the
1087+ * control is not supported or is not a menu. If the sensor being used
1088+ * is a "smart sensor", this request is passed to the sensor driver,
1089+ * otherwise the ISP is queried and if it does not support the requested
1090+ * menu control, the request is forwarded to the "raw" sensor driver to
1091+ * see if it supports it.
1092+ */
1093+static int vidioc_querymenu(struct file *file, void *fh,
1094+ struct v4l2_querymenu *a)
1095+{
1096+ struct omap34xxcam_fh *ofh = fh;
1097+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1098+ int i;
1099+
1100+ if (vdev->vdev_sensor_config.sensor_isp)
1101+ return vidioc_int_querymenu(vdev->vdev_sensor, a);
1102+
1103+ /* Try slaves directly. */
1104+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1105+ if (!vidioc_int_querymenu(vdev->slave[i], a))
1106+ return 0;
1107+ }
1108+ return isp_querymenu(a);
1109+}
1110+
1111+static int vidioc_g_ext_ctrls(struct file *file, void *fh,
1112+ struct v4l2_ext_controls *a)
1113+{
1114+ struct omap34xxcam_fh *ofh = fh;
1115+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1116+ int i, ctrl_idx, rval = 0;
1117+
1118+ mutex_lock(&vdev->mutex);
1119+
1120+ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
1121+ struct v4l2_control ctrl;
1122+
1123+ ctrl.id = a->controls[ctrl_idx].id;
1124+
1125+ if (vdev->vdev_sensor_config.sensor_isp) {
1126+ rval = vidioc_int_g_ctrl(vdev->vdev_sensor, &ctrl);
1127+ } else {
1128+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1129+ rval = vidioc_int_g_ctrl(vdev->slave[i], &ctrl);
1130+ if (!rval)
1131+ break;
1132+ }
1133+ }
1134+
1135+ if (rval)
1136+ rval = isp_g_ctrl(&ctrl);
1137+
1138+ if (rval) {
1139+ a->error_idx = ctrl_idx;
1140+ break;
1141+ }
1142+
1143+ a->controls[ctrl_idx].value = ctrl.value;
1144+ }
1145+
1146+ mutex_unlock(&vdev->mutex);
1147+
1148+ return rval;
1149+}
1150+
1151+static int vidioc_s_ext_ctrls(struct file *file, void *fh,
1152+ struct v4l2_ext_controls *a)
1153+{
1154+ struct omap34xxcam_fh *ofh = fh;
1155+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1156+ int i, ctrl_idx, rval = 0;
1157+
1158+ mutex_lock(&vdev->mutex);
1159+
1160+ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
1161+ struct v4l2_control ctrl;
1162+
1163+ ctrl.id = a->controls[ctrl_idx].id;
1164+ ctrl.value = a->controls[ctrl_idx].value;
1165+
1166+ if (vdev->vdev_sensor_config.sensor_isp) {
1167+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor, &ctrl);
1168+ } else {
1169+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1170+ rval = vidioc_int_s_ctrl(vdev->slave[i], &ctrl);
1171+ if (!rval)
1172+ break;
1173+ }
1174+ }
1175+
1176+ if (rval)
1177+ rval = isp_s_ctrl(&ctrl);
1178+
1179+ if (rval) {
1180+ a->error_idx = ctrl_idx;
1181+ break;
1182+ }
1183+
1184+ a->controls[ctrl_idx].value = ctrl.value;
1185+ }
1186+
1187+ mutex_unlock(&vdev->mutex);
1188+
1189+ return rval;
1190+}
1191+
1192+/**
1193+ * vidioc_g_parm - V4L2 get parameters IOCTL handler
1194+ * @file: ptr. to system file structure
1195+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1196+ * @a: standard V4L2 stream parameters structure
1197+ *
1198+ * If request is for video capture buffer type, handles request by
1199+ * forwarding to sensor driver.
1200+ */
1201+static int vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1202+{
1203+ struct omap34xxcam_fh *ofh = fh;
1204+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1205+ int rval;
1206+
1207+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1208+ return -EINVAL;
1209+
1210+ mutex_lock(&vdev->mutex);
1211+ rval = vidioc_int_g_parm(vdev->vdev_sensor, a);
1212+ mutex_unlock(&vdev->mutex);
1213+
1214+ return rval;
1215+}
1216+
1217+/**
1218+ * vidioc_s_parm - V4L2 set parameters IOCTL handler
1219+ * @file: ptr. to system file structure
1220+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1221+ * @a: standard V4L2 stream parameters structure
1222+ *
1223+ * If request is for video capture buffer type, handles request by
1224+ * first getting current stream parameters from sensor, then forwarding
1225+ * request to set new parameters to sensor driver. It then attempts to
1226+ * enable the sensor interface with the new parameters. If this fails, it
1227+ * reverts back to the previous parameters.
1228+ */
1229+static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1230+{
1231+ struct omap34xxcam_fh *ofh = fh;
1232+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1233+ struct v4l2_pix_format pix_tmp_sensor, pix_tmp;
1234+ int rval;
1235+
1236+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1237+ return -EINVAL;
1238+
1239+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1240+ return -EINVAL;
1241+
1242+ mutex_lock(&vdev->mutex);
1243+ if (vdev->streaming) {
1244+ rval = -EBUSY;
1245+ goto out;
1246+ }
1247+
1248+ vdev->want_timeperframe = a->parm.capture.timeperframe;
1249+
1250+ pix_tmp = vdev->want_pix;
1251+
1252+ rval = s_pix_parm(vdev, &pix_tmp_sensor, &pix_tmp,
1253+ &a->parm.capture.timeperframe);
1254+
1255+out:
1256+ mutex_unlock(&vdev->mutex);
1257+
1258+ return rval;
1259+}
1260+
1261+/**
1262+ * vidioc_cropcap - V4L2 crop capture IOCTL handler
1263+ * @file: ptr. to system file structure
1264+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1265+ * @a: standard V4L2 crop capture structure
1266+ *
1267+ * If using a "smart" sensor, just forwards request to the sensor driver,
1268+ * otherwise fills in the v4l2_cropcap values locally.
1269+ */
1270+static int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
1271+{
1272+ struct omap34xxcam_fh *ofh = fh;
1273+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1274+ struct v4l2_cropcap *cropcap = a;
1275+ int rval;
1276+
1277+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1278+ return -EINVAL;
1279+
1280+ mutex_lock(&vdev->mutex);
1281+
1282+ rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
1283+
1284+ if (rval && !vdev->vdev_sensor_config.sensor_isp) {
1285+ struct v4l2_format f;
1286+
1287+ /* cropcap failed, try to do this via g_fmt_cap */
1288+ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &f);
1289+ if (!rval) {
1290+ cropcap->bounds.top = 0;
1291+ cropcap->bounds.left = 0;
1292+ cropcap->bounds.width = f.fmt.pix.width;
1293+ cropcap->bounds.height = f.fmt.pix.height;
1294+ cropcap->defrect = cropcap->bounds;
1295+ cropcap->pixelaspect.numerator = 1;
1296+ cropcap->pixelaspect.denominator = 1;
1297+ }
1298+ }
1299+
1300+ mutex_unlock(&vdev->mutex);
1301+
1302+ return rval;
1303+}
1304+
1305+/**
1306+ * vidioc_g_crop - V4L2 get capture crop IOCTL handler
1307+ * @file: ptr. to system file structure
1308+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1309+ * @a: standard V4L2 crop structure
1310+ *
1311+ * If using a "smart" sensor, just forwards request to the sensor driver,
1312+ * otherwise calls the isp functions to fill in current crop values.
1313+ */
1314+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
1315+{
1316+ struct omap34xxcam_fh *ofh = fh;
1317+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1318+ int rval = 0;
1319+
1320+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1321+ return -EINVAL;
1322+
1323+ mutex_lock(&vdev->mutex);
1324+
1325+ if (vdev->vdev_sensor_config.sensor_isp)
1326+ rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
1327+ else
1328+ rval = isp_g_crop(a);
1329+
1330+ mutex_unlock(&vdev->mutex);
1331+
1332+ return rval;
1333+}
1334+
1335+/**
1336+ * vidioc_s_crop - V4L2 set capture crop IOCTL handler
1337+ * @file: ptr. to system file structure
1338+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1339+ * @a: standard V4L2 crop structure
1340+ *
1341+ * If using a "smart" sensor, just forwards request to the sensor driver,
1342+ * otherwise calls the isp functions to set the current crop values.
1343+ */
1344+static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
1345+{
1346+ struct omap34xxcam_fh *ofh = fh;
1347+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1348+ int rval = 0;
1349+
1350+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1351+ return -EINVAL;
1352+
1353+ mutex_lock(&vdev->mutex);
1354+
1355+ if (vdev->vdev_sensor_config.sensor_isp)
1356+ rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
1357+ else
1358+ rval = isp_s_crop(a, &vdev->pix);
1359+
1360+ mutex_unlock(&vdev->mutex);
1361+
1362+ return rval;
1363+}
1364+
1365+static int vidioc_enum_framesizes(struct file *file, void *fh,
1366+ struct v4l2_frmsizeenum *frms)
1367+{
1368+ struct omap34xxcam_fh *ofh = fh;
1369+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1370+ u32 pixel_format;
1371+ int rval;
1372+
1373+ mutex_lock(&vdev->mutex);
1374+
1375+ if (vdev->vdev_sensor_config.sensor_isp) {
1376+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
1377+ } else {
1378+ pixel_format = frms->pixel_format;
1379+ frms->pixel_format = -1; /* ISP does format conversion */
1380+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
1381+ frms->pixel_format = pixel_format;
1382+ }
1383+
1384+ mutex_unlock(&vdev->mutex);
1385+ return rval;
1386+}
1387+
1388+static int vidioc_enum_frameintervals(struct file *file, void *fh,
1389+ struct v4l2_frmivalenum *frmi)
1390+{
1391+ struct omap34xxcam_fh *ofh = fh;
1392+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1393+ u32 pixel_format;
1394+ int rval;
1395+
1396+ mutex_lock(&vdev->mutex);
1397+
1398+ if (vdev->vdev_sensor_config.sensor_isp) {
1399+ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
1400+ } else {
1401+ pixel_format = frmi->pixel_format;
1402+ frmi->pixel_format = -1; /* ISP does format conversion */
1403+ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
1404+ frmi->pixel_format = pixel_format;
1405+ }
1406+
1407+ mutex_unlock(&vdev->mutex);
1408+ return rval;
1409+}
1410+
1411+/**
1412+ * vidioc_default - private IOCTL handler
1413+ * @file: ptr. to system file structure
1414+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1415+ * @cmd: ioctl cmd value
1416+ * @arg: ioctl arg value
1417+ *
1418+ * If the sensor being used is a "smart sensor", this request is returned to
1419+ * caller with -EINVAL err code. Otherwise if the control id is the private
1420+ * VIDIOC_PRIVATE_ISP_AEWB_REQ to update the analog gain or exposure,
1421+ * then this request is forwared directly to the sensor to incorporate the
1422+ * feedback. The request is then passed on to the ISP private IOCTL handler,
1423+ * isp_handle_private()
1424+ */
1425+static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
1426+{
1427+ struct omap34xxcam_fh *ofh = file->private_data;
1428+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1429+ int rval;
1430+
1431+ if (vdev->vdev_sensor_config.sensor_isp) {
1432+ rval = -EINVAL;
1433+ } else {
1434+ switch (cmd) {
1435+ case VIDIOC_PRIVATE_ISP_AEWB_REQ:
1436+ {
1437+ /* Need to update sensor first */
1438+ struct isph3a_aewb_data *data;
1439+ struct v4l2_control vc;
1440+
1441+ data = (struct isph3a_aewb_data *) arg;
1442+ if (data->update & SET_EXPOSURE) {
1443+ dev_info(&vdev->vfd->dev, "using "
1444+ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
1445+ "exposure is deprecated!\n");
1446+ vc.id = V4L2_CID_EXPOSURE;
1447+ vc.value = data->shutter;
1448+ mutex_lock(&vdev->mutex);
1449+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
1450+ &vc);
1451+ mutex_unlock(&vdev->mutex);
1452+ if (rval)
1453+ goto out;
1454+ }
1455+ if (data->update & SET_ANALOG_GAIN) {
1456+ dev_info(&vdev->vfd->dev, "using "
1457+ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
1458+ "gain is deprecated!\n");
1459+ vc.id = V4L2_CID_GAIN;
1460+ vc.value = data->gain;
1461+ mutex_lock(&vdev->mutex);
1462+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
1463+ &vc);
1464+ mutex_unlock(&vdev->mutex);
1465+ if (rval)
1466+ goto out;
1467+ }
1468+ }
1469+ break;
1470+ case VIDIOC_PRIVATE_ISP_AF_REQ: {
1471+ /* Need to update lens first */
1472+ struct isp_af_data *data;
1473+ struct v4l2_control vc;
1474+
1475+ if (!vdev->vdev_lens) {
1476+ rval = -EINVAL;
1477+ goto out;
1478+ }
1479+ data = (struct isp_af_data *) arg;
1480+ if (data->update & LENS_DESIRED_POSITION) {
1481+ dev_info(&vdev->vfd->dev, "using "
1482+ "VIDIOC_PRIVATE_ISP_AF_REQ to set "
1483+ "lens position is deprecated!\n");
1484+ vc.id = V4L2_CID_FOCUS_ABSOLUTE;
1485+ vc.value = data->desired_lens_direction;
1486+ mutex_lock(&vdev->mutex);
1487+ rval = vidioc_int_s_ctrl(vdev->vdev_lens, &vc);
1488+ mutex_unlock(&vdev->mutex);
1489+ if (rval)
1490+ goto out;
1491+ }
1492+ }
1493+ break;
1494+ }
1495+
1496+ mutex_lock(&vdev->mutex);
1497+ rval = isp_handle_private(cmd, arg);
1498+ mutex_unlock(&vdev->mutex);
1499+ }
1500+out:
1501+ return rval;
1502+}
1503+
1504+/*
1505+ *
1506+ * File operations.
1507+ *
1508+ */
1509+
1510+/**
1511+ * omap34xxcam_poll - file operations poll handler
1512+ * @file: ptr. to system file structure
1513+ * @wait: system poll table structure
1514+ *
1515+ */
1516+static unsigned int omap34xxcam_poll(struct file *file,
1517+ struct poll_table_struct *wait)
1518+{
1519+ struct omap34xxcam_fh *fh = file->private_data;
1520+ struct omap34xxcam_videodev *vdev = fh->vdev;
1521+ struct videobuf_buffer *vb;
1522+
1523+ mutex_lock(&vdev->mutex);
1524+ if (vdev->streaming != file) {
1525+ mutex_unlock(&vdev->mutex);
1526+ return POLLERR;
1527+ }
1528+ mutex_unlock(&vdev->mutex);
1529+
1530+ mutex_lock(&fh->vbq.vb_lock);
1531+ if (list_empty(&fh->vbq.stream)) {
1532+ mutex_unlock(&fh->vbq.vb_lock);
1533+ return POLLERR;
1534+ }
1535+ vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream);
1536+ mutex_unlock(&fh->vbq.vb_lock);
1537+
1538+ poll_wait(file, &vb->done, wait);
1539+
1540+ if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR)
1541+ return POLLIN | POLLRDNORM;
1542+
1543+ return 0;
1544+}
1545+
1546+/**
1547+ * omap34xxcam_mmap - file operations mmap handler
1548+ * @file: ptr. to system file structure
1549+ * @vma: system virt. mem. area structure
1550+ *
1551+ * Maps a virtual memory area via the video buffer API
1552+ */
1553+static int omap34xxcam_mmap(struct file *file, struct vm_area_struct *vma)
1554+{
1555+ struct omap34xxcam_fh *fh = file->private_data;
1556+ return videobuf_mmap_mapper(&fh->vbq, vma);
1557+}
1558+
1559+/**
1560+ * omap34xxcam_open - file operations open handler
1561+ * @inode: ptr. to system inode structure
1562+ * @file: ptr. to system file structure
1563+ *
1564+ * Allocates and initializes the per-filehandle data (omap34xxcam_fh),
1565+ * enables the sensor, opens/initializes the ISP interface and the
1566+ * video buffer queue. Note that this function will allow multiple
1567+ * file handles to be open simultaneously, however only the first
1568+ * handle opened will initialize the ISP. It is the application
1569+ * responsibility to only use one handle for streaming and the others
1570+ * for control only.
1571+ * This function returns 0 upon success and -ENODEV upon error.
1572+ */
1573+static int omap34xxcam_open(struct file *file)
1574+{
1575+ int rval = 0;
1576+ struct omap34xxcam_videodev *vdev = NULL;
1577+ struct omap34xxcam_device *cam = omap34xxcam;
1578+ struct omap34xxcam_fh *fh;
1579+ struct v4l2_format format;
1580+ int i;
1581+
1582+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1583+ if (cam->vdevs[i].vfd
1584+ && cam->vdevs[i].vfd->minor ==
1585+ iminor(file->f_dentry->d_inode)) {
1586+ vdev = &cam->vdevs[i];
1587+ break;
1588+ }
1589+ }
1590+
1591+ if (!vdev || !vdev->vfd)
1592+ return -ENODEV;
1593+
1594+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1595+ if (fh == NULL)
1596+ return -ENOMEM;
1597+
1598+ mutex_lock(&vdev->mutex);
1599+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1600+ if (vdev->slave[i] != v4l2_int_device_dummy()
1601+ && !try_module_get(vdev->slave[i]->module)) {
1602+ mutex_unlock(&vdev->mutex);
1603+ dev_err(&vdev->vfd->dev, "can't try_module_get %s\n",
1604+ vdev->slave[i]->name);
1605+ rval = -ENODEV;
1606+ goto out_try_module_get;
1607+ }
1608+ }
1609+
1610+ if (atomic_inc_return(&vdev->users) == 1) {
1611+ rval = isp_get();
1612+ if (rval < 0) {
1613+ dev_err(&vdev->vfd->dev, "can't get isp\n");
1614+ goto out_isp_get;
1615+ }
1616+ if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
1617+ OMAP34XXCAM_SLAVE_POWER_ALL)) {
1618+ dev_err(&vdev->vfd->dev, "can't power up slaves\n");
1619+ rval = -EBUSY;
1620+ goto out_slave_power_set_standby;
1621+ }
1622+ omap34xxcam_slave_power_set(
1623+ vdev, V4L2_POWER_STANDBY,
1624+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
1625+ omap34xxcam_slave_power_suggest(
1626+ vdev, V4L2_POWER_STANDBY,
1627+ OMAP34XXCAM_SLAVE_POWER_LENS);
1628+ }
1629+
1630+ fh->vdev = vdev;
1631+
1632+ if (!vdev->pix.width
1633+ && vdev->vdev_sensor != v4l2_int_device_dummy()) {
1634+ memset(&format, 0, sizeof(format));
1635+ if (vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format)) {
1636+ dev_err(&vdev->vfd->dev,
1637+ "can't get current pix from sensor!\n");
1638+ goto out_vidioc_int_g_fmt_cap;
1639+ }
1640+ if (!vdev->vdev_sensor_config.sensor_isp) {
1641+ struct v4l2_pix_format pix = format.fmt.pix;
1642+ if (isp_s_fmt_cap(&pix, &format.fmt.pix)) {
1643+ dev_err(&vdev->vfd->dev,
1644+ "isp doesn't like the sensor!\n");
1645+ goto out_isp_s_fmt_cap;
1646+ }
1647+ }
1648+ vdev->pix = format.fmt.pix;
1649+ }
1650+
1651+ mutex_unlock(&vdev->mutex);
1652+
1653+ file->private_data = fh;
1654+
1655+ spin_lock_init(&fh->vbq_lock);
1656+
1657+ videobuf_queue_sg_init(&fh->vbq, &omap34xxcam_vbq_ops, NULL,
1658+ &fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
1659+ V4L2_FIELD_NONE,
1660+ sizeof(struct videobuf_buffer), fh);
1661+
1662+ return 0;
1663+
1664+out_isp_s_fmt_cap:
1665+out_vidioc_int_g_fmt_cap:
1666+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
1667+ OMAP34XXCAM_SLAVE_POWER_ALL);
1668+out_slave_power_set_standby:
1669+ isp_put();
1670+
1671+out_isp_get:
1672+ atomic_dec(&vdev->users);
1673+ mutex_unlock(&vdev->mutex);
1674+
1675+out_try_module_get:
1676+ for (i--; i >= 0; i--)
1677+ if (vdev->slave[i] != v4l2_int_device_dummy())
1678+ module_put(vdev->slave[i]->module);
1679+
1680+ kfree(fh);
1681+
1682+ return rval;
1683+}
1684+
1685+/**
1686+ * omap34xxcam_release - file operations release handler
1687+ * @inode: ptr. to system inode structure
1688+ * @file: ptr. to system file structure
1689+ *
1690+ * Complement of omap34xxcam_open. This function will flush any scheduled
1691+ * work, disable the sensor, close the ISP interface, stop the
1692+ * video buffer queue from streaming and free the per-filehandle data
1693+ * (omap34xxcam_fh). Note that because multiple open file handles
1694+ * are allowed, this function will only close the ISP and disable the
1695+ * sensor when the last open file handle (by count) is closed.
1696+ * This function returns 0.
1697+ */
1698+static int omap34xxcam_release(struct file *file)
1699+{
1700+ struct omap34xxcam_fh *fh = file->private_data;
1701+ struct omap34xxcam_videodev *vdev = fh->vdev;
1702+ int i;
1703+
1704+ mutex_lock(&vdev->mutex);
1705+ if (vdev->streaming == file) {
1706+ isp_stop();
1707+ videobuf_streamoff(&fh->vbq);
1708+ omap34xxcam_slave_power_set(
1709+ vdev, V4L2_POWER_STANDBY,
1710+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
1711+ omap34xxcam_slave_power_suggest(
1712+ vdev, V4L2_POWER_STANDBY,
1713+ OMAP34XXCAM_SLAVE_POWER_LENS);
1714+ vdev->streaming = NULL;
1715+ }
1716+
1717+ if (atomic_dec_return(&vdev->users) == 0) {
1718+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
1719+ OMAP34XXCAM_SLAVE_POWER_ALL);
1720+ isp_put();
1721+ }
1722+ mutex_unlock(&vdev->mutex);
1723+
1724+ file->private_data = NULL;
1725+
1726+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
1727+ if (vdev->slave[i] != v4l2_int_device_dummy())
1728+ module_put(vdev->slave[i]->module);
1729+
1730+ kfree(fh);
1731+
1732+ return 0;
1733+}
1734+
1735+static struct v4l2_file_operations omap34xxcam_fops = {
1736+ .owner = THIS_MODULE,
1737+ .unlocked_ioctl = video_ioctl2,
1738+ .poll = omap34xxcam_poll,
1739+ .mmap = omap34xxcam_mmap,
1740+ .open = omap34xxcam_open,
1741+ .release = omap34xxcam_release,
1742+};
1743+
1744+static void omap34xxcam_vfd_name_update(struct omap34xxcam_videodev *vdev)
1745+{
1746+ struct video_device *vfd = vdev->vfd;
1747+ int i;
1748+
1749+ strlcpy(vfd->name, CAM_SHORT_NAME, sizeof(vfd->name));
1750+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1751+ strlcat(vfd->name, "/", sizeof(vfd->name));
1752+ if (vdev->slave[i] == v4l2_int_device_dummy())
1753+ continue;
1754+ strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
1755+ }
1756+ dev_info(&vdev->vfd->dev, "video%d is now %s\n", vfd->num, vfd->name);
1757+}
1758+
1759+/**
1760+ * omap34xxcam_device_unregister - V4L2 detach handler
1761+ * @s: ptr. to standard V4L2 device information structure
1762+ *
1763+ * Detach sensor and unregister and release the video device.
1764+ */
1765+static void omap34xxcam_device_unregister(struct v4l2_int_device *s)
1766+{
1767+ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
1768+ struct omap34xxcam_hw_config hwc;
1769+
1770+ BUG_ON(vidioc_int_g_priv(s, &hwc) < 0);
1771+
1772+ mutex_lock(&vdev->mutex);
1773+
1774+ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy()) {
1775+ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
1776+ vdev->slaves--;
1777+ omap34xxcam_vfd_name_update(vdev);
1778+ }
1779+
1780+ if (vdev->slaves == 0 && vdev->vfd) {
1781+ if (vdev->vfd->minor == -1) {
1782+ /*
1783+ * The device was never registered, so release the
1784+ * video_device struct directly.
1785+ */
1786+ video_device_release(vdev->vfd);
1787+ } else {
1788+ /*
1789+ * The unregister function will release the
1790+ * video_device struct as well as
1791+ * unregistering it.
1792+ */
1793+ video_unregister_device(vdev->vfd);
1794+ }
1795+ vdev->vfd = NULL;
1796+ }
1797+
1798+ mutex_unlock(&vdev->mutex);
1799+}
1800+
1801+static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
1802+ .vidioc_querycap = vidioc_querycap,
1803+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1804+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1805+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1806+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1807+ .vidioc_reqbufs = vidioc_reqbufs,
1808+ .vidioc_querybuf = vidioc_querybuf,
1809+ .vidioc_qbuf = vidioc_qbuf,
1810+ .vidioc_dqbuf = vidioc_dqbuf,
1811+ .vidioc_streamon = vidioc_streamon,
1812+ .vidioc_streamoff = vidioc_streamoff,
1813+ .vidioc_enum_input = vidioc_enum_input,
1814+ .vidioc_g_input = vidioc_g_input,
1815+ .vidioc_s_input = vidioc_s_input,
1816+ .vidioc_queryctrl = vidioc_queryctrl,
1817+ .vidioc_querymenu = vidioc_querymenu,
1818+ .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1819+ .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1820+ .vidioc_g_parm = vidioc_g_parm,
1821+ .vidioc_s_parm = vidioc_s_parm,
1822+ .vidioc_cropcap = vidioc_cropcap,
1823+ .vidioc_g_crop = vidioc_g_crop,
1824+ .vidioc_s_crop = vidioc_s_crop,
1825+ .vidioc_enum_framesizes = vidioc_enum_framesizes,
1826+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
1827+ .vidioc_default = vidioc_default,
1828+};
1829+
1830+/**
1831+ * omap34xxcam_device_register - V4L2 attach handler
1832+ * @s: ptr. to standard V4L2 device information structure
1833+ *
1834+ * Allocates and initializes the V4L2 video_device structure, initializes
1835+ * the sensor, and finally
1836+ registers the device with V4L2 based on the
1837+ * video_device structure.
1838+ *
1839+ * Returns 0 on success, otherwise an appropriate error code on
1840+ * failure.
1841+ */
1842+static int omap34xxcam_device_register(struct v4l2_int_device *s)
1843+{
1844+ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
1845+ struct omap34xxcam_hw_config hwc;
1846+ int rval;
1847+
1848+ /* We need to check rval just once. The place is here. */
1849+ if (vidioc_int_g_priv(s, &hwc))
1850+ return -ENODEV;
1851+
1852+ if (vdev->index != hwc.dev_index)
1853+ return -ENODEV;
1854+
1855+ if (hwc.dev_type < 0 || hwc.dev_type > OMAP34XXCAM_SLAVE_FLASH)
1856+ return -EINVAL;
1857+
1858+ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy())
1859+ return -EBUSY;
1860+
1861+ mutex_lock(&vdev->mutex);
1862+ if (atomic_read(&vdev->users)) {
1863+ printk(KERN_ERR "%s: we're open (%d), can't register\n",
1864+ __func__, atomic_read(&vdev->users));
1865+ mutex_unlock(&vdev->mutex);
1866+ return -EBUSY;
1867+ }
1868+
1869+ vdev->slaves++;
1870+ vdev->slave[hwc.dev_type] = s;
1871+ vdev->slave_config[hwc.dev_type] = hwc;
1872+
1873+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
1874+ rval = isp_get();
1875+ if (rval < 0) {
1876+ printk(KERN_ERR "%s: can't get ISP, "
1877+ "sensor init failed\n", __func__);
1878+ goto err;
1879+ }
1880+ }
1881+ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
1882+ 1 << hwc.dev_type);
1883+ if (rval)
1884+ goto err_omap34xxcam_slave_power_set;
1885+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
1886+ struct v4l2_format format;
1887+
1888+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1889+ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
1890+ if (rval)
1891+ rval = -EBUSY;
1892+
1893+ vdev->want_pix = format.fmt.pix;
1894+ }
1895+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF, 1 << hwc.dev_type);
1896+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
1897+ isp_put();
1898+
1899+ if (rval)
1900+ goto err;
1901+
1902+ /* Are we the first slave? */
1903+ if (vdev->slaves == 1) {
1904+ /* initialize the video_device struct */
1905+ vdev->vfd = video_device_alloc();
1906+ if (!vdev->vfd) {
1907+ printk(KERN_ERR "%s: could not allocate "
1908+ "video device struct\n", __func__);
1909+ rval = -ENOMEM;
1910+ goto err;
1911+ }
1912+ vdev->vfd->release = video_device_release;
1913+ vdev->vfd->minor = -1;
1914+ vdev->vfd->fops = &omap34xxcam_fops;
1915+ vdev->vfd->ioctl_ops = &omap34xxcam_ioctl_ops;
1916+ video_set_drvdata(vdev->vfd, vdev);
1917+
1918+ if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
1919+ hwc.dev_minor) < 0) {
1920+ printk(KERN_ERR "%s: could not register V4L device\n",
1921+ __func__);
1922+ vdev->vfd->minor = -1;
1923+ rval = -EBUSY;
1924+ goto err;
1925+ }
1926+ }
1927+
1928+ omap34xxcam_vfd_name_update(vdev);
1929+
1930+ mutex_unlock(&vdev->mutex);
1931+
1932+ return 0;
1933+
1934+err_omap34xxcam_slave_power_set:
1935+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
1936+ isp_put();
1937+
1938+err:
1939+ if (s == vdev->slave[hwc.dev_type]) {
1940+ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
1941+ vdev->slaves--;
1942+ }
1943+
1944+ mutex_unlock(&vdev->mutex);
1945+ omap34xxcam_device_unregister(s);
1946+
1947+ return rval;
1948+}
1949+
1950+static struct v4l2_int_master omap34xxcam_master = {
1951+ .attach = omap34xxcam_device_register,
1952+ .detach = omap34xxcam_device_unregister,
1953+};
1954+
1955+/*
1956+ *
1957+ * Module initialisation and deinitialisation
1958+ *
1959+ */
1960+
1961+static void omap34xxcam_exit(void)
1962+{
1963+ struct omap34xxcam_device *cam = omap34xxcam;
1964+ int i;
1965+
1966+ if (!cam)
1967+ return;
1968+
1969+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1970+ if (cam->vdevs[i].cam == NULL)
1971+ continue;
1972+
1973+ v4l2_int_device_unregister(&cam->vdevs[i].master);
1974+ cam->vdevs[i].cam = NULL;
1975+ }
1976+
1977+ omap34xxcam = NULL;
1978+
1979+ kfree(cam);
1980+}
1981+
1982+static int __init omap34xxcam_init(void)
1983+{
1984+ struct omap34xxcam_device *cam;
1985+ int i;
1986+
1987+ cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1988+ if (!cam) {
1989+ printk(KERN_ERR "%s: could not allocate memory\n", __func__);
1990+ return -ENOMEM;
1991+ }
1992+
1993+ omap34xxcam = cam;
1994+
1995+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1996+ struct omap34xxcam_videodev *vdev = &cam->vdevs[i];
1997+ struct v4l2_int_device *m = &vdev->master;
1998+
1999+ m->module = THIS_MODULE;
2000+ strlcpy(m->name, CAM_NAME, sizeof(m->name));
2001+ m->type = v4l2_int_type_master;
2002+ m->u.master = &omap34xxcam_master;
2003+ m->priv = vdev;
2004+
2005+ mutex_init(&vdev->mutex);
2006+ vdev->index = i;
2007+ vdev->cam = cam;
2008+ vdev->vdev_sensor =
2009+ vdev->vdev_lens =
2010+ vdev->vdev_flash = v4l2_int_device_dummy();
2011+#ifdef OMAP34XXCAM_POWEROFF_DELAY
2012+ setup_timer(&vdev->poweroff_timer,
2013+ omap34xxcam_slave_power_timer, (unsigned long)vdev);
2014+ INIT_WORK(&vdev->poweroff_work, omap34xxcam_slave_power_work);
2015+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
2016+
2017+ if (v4l2_int_device_register(m))
2018+ goto err;
2019+ }
2020+
2021+ return 0;
2022+
2023+err:
2024+ omap34xxcam_exit();
2025+ return -ENODEV;
2026+}
2027+
2028+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
2029+MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
2030+MODULE_LICENSE("GPL");
2031+
2032+late_initcall(omap34xxcam_init);
2033+module_exit(omap34xxcam_exit);
2034diff --git a/drivers/media/video/omap34xxcam.h b/drivers/media/video/omap34xxcam.h
2035new file mode 100644
2036index 0000000..9859d15
2037--- /dev/null
2038+++ b/drivers/media/video/omap34xxcam.h
2039@@ -0,0 +1,207 @@
2040+/*
2041+ * omap34xxcam.h
2042+ *
2043+ * Copyright (C) 2006--2009 Nokia Corporation
2044+ * Copyright (C) 2007--2009 Texas Instruments
2045+ *
2046+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
2047+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2048+ *
2049+ * Originally based on the OMAP 2 camera driver.
2050+ *
2051+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
2052+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2053+ * Sergio Aguirre <saaguirre@ti.com>
2054+ * Mohit Jalori
2055+ * Sameer Venkatraman
2056+ * Leonides Martinez
2057+ *
2058+ * This program is free software; you can redistribute it and/or
2059+ * modify it under the terms of the GNU General Public License
2060+ * version 2 as published by the Free Software Foundation.
2061+ *
2062+ * This program is distributed in the hope that it will be useful, but
2063+ * WITHOUT ANY WARRANTY; without even the implied warranty of
2064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2065+ * General Public License for more details.
2066+ *
2067+ * You should have received a copy of the GNU General Public License
2068+ * along with this program; if not, write to the Free Software
2069+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
2070+ * 02110-1301 USA
2071+ *
2072+ */
2073+
2074+#ifndef OMAP34XXCAM_H
2075+#define OMAP34XXCAM_H
2076+
2077+#include <media/v4l2-int-device.h>
2078+#include "isp/isp.h"
2079+
2080+#define CAM_NAME "omap34xxcam"
2081+#define CAM_SHORT_NAME "omap3"
2082+
2083+#define OMAP_ISP_AF (1 << 4)
2084+#define OMAP_ISP_HIST (1 << 5)
2085+#define OMAP34XXCAM_XCLK_NONE -1
2086+#define OMAP34XXCAM_XCLK_A 0
2087+#define OMAP34XXCAM_XCLK_B 1
2088+
2089+#define OMAP34XXCAM_SLAVE_SENSOR 0
2090+#define OMAP34XXCAM_SLAVE_LENS 1
2091+#define OMAP34XXCAM_SLAVE_FLASH 2 /* This is the last slave! */
2092+
2093+/* mask for omap34xxcam_slave_power_set */
2094+#define OMAP34XXCAM_SLAVE_POWER_SENSOR (1 << OMAP34XXCAM_SLAVE_SENSOR)
2095+#define OMAP34XXCAM_SLAVE_POWER_LENS (1 << OMAP34XXCAM_SLAVE_LENS)
2096+#define OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS \
2097+ (OMAP34XXCAM_SLAVE_POWER_SENSOR | OMAP34XXCAM_SLAVE_POWER_LENS)
2098+#define OMAP34XXCAM_SLAVE_POWER_FLASH (1 << OMAP34XXCAM_SLAVE_FLASH)
2099+#define OMAP34XXCAM_SLAVE_POWER_ALL -1
2100+
2101+#define OMAP34XXCAM_VIDEODEVS 4
2102+
2103+/* #define OMAP34XXCAM_POWEROFF_DELAY (2 * HZ) */
2104+
2105+struct omap34xxcam_device;
2106+struct omap34xxcam_videodev;
2107+
2108+struct omap34xxcam_sensor_config {
2109+ int xclk;
2110+ int sensor_isp;
2111+ u32 capture_mem;
2112+ struct v4l2_fract ival_default;
2113+};
2114+
2115+struct omap34xxcam_lens_config {
2116+};
2117+
2118+struct omap34xxcam_flash_config {
2119+};
2120+
2121+/**
2122+ * struct omap34xxcam_hw_config - struct for vidioc_int_g_priv ioctl
2123+ * @xclk: OMAP34XXCAM_XCLK_A or OMAP34XXCAM_XCLK_B
2124+ * @sensor_isp: Is sensor smart/SOC or raw
2125+ * @s_pix_sparm: Access function to set pix and sparm.
2126+ * Pix will override sparm
2127+ */
2128+struct omap34xxcam_hw_config {
2129+ int dev_index; /* Index in omap34xxcam_sensors */
2130+ int dev_minor; /* Video device minor number */
2131+ int dev_type; /* OMAP34XXCAM_SLAVE_* */
2132+ union {
2133+ struct omap34xxcam_sensor_config sensor;
2134+ struct omap34xxcam_lens_config lens;
2135+ struct omap34xxcam_flash_config flash;
2136+ } u;
2137+};
2138+
2139+/**
2140+ * struct omap34xxcam_videodev - per /dev/video* structure
2141+ * @mutex: serialises access to this structure
2142+ * @cam: pointer to cam hw structure
2143+ * @master: we are v4l2_int_device master
2144+ * @sensor: sensor device
2145+ * @lens: lens device
2146+ * @flash: flash device
2147+ * @slaves: how many slaves we have at the moment
2148+ * @vfd: our video device
2149+ * @capture_mem: maximum kernel-allocated capture memory
2150+ * @if_u: sensor interface stuff
2151+ * @index: index of this structure in cam->vdevs
2152+ * @users: how many users we have
2153+ * @power_state: Current power state
2154+ * @power_state_wish: New power state when poweroff_timer expires
2155+ * @power_state_mask: Bitmask of devices to set the new power state
2156+ * @poweroff_timer: Timer for dispatching poweroff_work
2157+ * @poweroff_work: Work for slave power state change
2158+ * @sensor_config: ISP-speicific sensor configuration
2159+ * @lens_config: ISP-speicific lens configuration
2160+ * @flash_config: ISP-speicific flash configuration
2161+ * @want_timeperframe: Desired timeperframe
2162+ * @want_pix: Desired pix
2163+ * @pix: Current pix
2164+ * @streaming: streaming file handle, if streaming is enabled
2165+ */
2166+struct omap34xxcam_videodev {
2167+ struct mutex mutex; /* serialises access to this structure */
2168+
2169+ struct omap34xxcam_device *cam;
2170+ struct v4l2_int_device master;
2171+
2172+#define vdev_sensor slave[OMAP34XXCAM_SLAVE_SENSOR]
2173+#define vdev_lens slave[OMAP34XXCAM_SLAVE_LENS]
2174+#define vdev_flash slave[OMAP34XXCAM_SLAVE_FLASH]
2175+ struct v4l2_int_device *slave[OMAP34XXCAM_SLAVE_FLASH + 1];
2176+
2177+ /* number of slaves attached */
2178+ int slaves;
2179+
2180+ /*** video device parameters ***/
2181+ struct video_device *vfd;
2182+ int capture_mem;
2183+
2184+ /*** general driver state information ***/
2185+ int index;
2186+ atomic_t users;
2187+ enum v4l2_power power_state[OMAP34XXCAM_SLAVE_FLASH + 1];
2188+#ifdef OMAP34XXCAM_POWEROFF_DELAY
2189+ enum v4l2_power power_state_wish;
2190+ int power_state_mask;
2191+ struct timer_list poweroff_timer;
2192+ struct work_struct poweroff_work;
2193+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
2194+
2195+#define vdev_sensor_config slave_config[OMAP34XXCAM_SLAVE_SENSOR].u.sensor
2196+#define vdev_lens_config slave_config[OMAP34XXCAM_SLAVE_LENS].u.lens
2197+#define vdev_flash_config slave_config[OMAP34XXCAM_SLAVE_FLASH].u.flash
2198+ struct omap34xxcam_hw_config slave_config[OMAP34XXCAM_SLAVE_FLASH + 1];
2199+
2200+ /*** capture data ***/
2201+ struct file *streaming;
2202+ struct v4l2_fract want_timeperframe;
2203+ struct v4l2_pix_format want_pix;
2204+ spinlock_t pix_lock;
2205+ struct v4l2_pix_format pix;
2206+};
2207+
2208+/**
2209+ * struct omap34xxcam_device - per-device data structure
2210+ * @mutex: mutex serialises access to this structure
2211+ * @sgdma_in_queue: Number or sgdma requests in scatter-gather queue,
2212+ * protected by the lock above.
2213+ * @sgdma: ISP sgdma subsystem information structure
2214+ * @dma_notify: DMA notify flag
2215+ * @dev: device structure
2216+ * @vdevs: /dev/video specific structures
2217+ * @fck: camera module fck clock information
2218+ * @ick: camera module ick clock information
2219+ */
2220+struct omap34xxcam_device {
2221+ struct mutex mutex; /* serialises access to this structure */
2222+
2223+ /*** interfaces and device ***/
2224+ struct omap34xxcam_videodev vdevs[OMAP34XXCAM_VIDEODEVS];
2225+
2226+ /*** camera module clocks ***/
2227+ struct clk *fck;
2228+ struct clk *ick;
2229+ bool sensor_if_enabled;
2230+};
2231+
2232+/**
2233+ * struct omap34xxcam_fh - per-filehandle data structure
2234+ * @vbq_lock: spinlock for the videobuf queue
2235+ * @vbq: V4L2 video buffer queue structure
2236+ * @field_count: field counter for videobuf_buffer
2237+ * @vdev: our /dev/video specific structure
2238+ */
2239+struct omap34xxcam_fh {
2240+ spinlock_t vbq_lock; /* spinlock for the videobuf queue */
2241+ struct videobuf_queue vbq;
2242+ atomic_t field_count;
2243+ struct omap34xxcam_videodev *vdev;
2244+};
2245+
2246+#endif /* ifndef OMAP34XXCAM_H */
2247--
22481.5.6.5
2249