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:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
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