summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.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/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.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/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch2915
1 files changed, 2915 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch
new file mode 100644
index 0000000000..f796ce8346
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch
@@ -0,0 +1,2915 @@
1From 3041daa54b49bcb6ab444c7b9e14bc6a1ade6236 Mon Sep 17 00:00:00 2001
2From: Vaibhav Hiremath <hvaibhav@ti.com>
3Date: Fri, 13 Feb 2009 14:44:20 +0530
4Subject: [PATCH 1/2] Resizer and Previewer driver added to commit
5
6The Resizer and Previewer driver added to the commit
7from the patch submitted by Sergio on 12 Dec 2008.
8
9The new WTBU code base and Nokia fixes package doesn't contain
10standalone resizer driver support.
11
12Following major changes done -
13
14 - Added stand-alone resizer driver support
15 in isp.c file.
16 - Seperate Kconfig file created
17 - hardware access of resizer module fixed as per new
18 isp.c
19
20Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
21---
22 drivers/media/video/Kconfig | 5 +-
23 drivers/media/video/isp/Kconfig | 16 +
24 drivers/media/video/isp/Makefile | 7 +
25 drivers/media/video/isp/isp.c | 12 +
26 drivers/media/video/isp/ispmmu.c | 1 +
27 drivers/media/video/isp/omap_previewer.c | 825 +++++++++++++++
28 drivers/media/video/isp/omap_previewer.h | 162 +++
29 drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++
30 include/linux/omap_resizer.h | 136 +++
31 9 files changed, 2794 insertions(+), 4 deletions(-)
32 create mode 100644 drivers/media/video/isp/Kconfig
33 create mode 100644 drivers/media/video/isp/omap_previewer.c
34 create mode 100644 drivers/media/video/isp/omap_previewer.h
35 create mode 100644 drivers/media/video/isp/omap_resizer.c
36 create mode 100644 include/linux/omap_resizer.h
37
38diff --git a/drivers/media/video/isp/Kconfig b/drivers/media/video/isp/Kconfig
39new file mode 100644
40index 0000000..acda63b
41--- /dev/null
42+++ b/drivers/media/video/isp/Kconfig
43@@ -0,0 +1,16 @@
44+# Kconfig for OMAP3 ISP driver
45+
46+config VIDEO_OMAP3_ISP
47+ tristate
48+ select VIDEOBUF_GEN
49+ select VIDEOBUF_DMA_SG
50+
51+config VIDEO_OMAP34XX_ISP_PREVIEWER
52+ tristate "OMAP ISP Previewer"
53+ depends on !ARCH_OMAP3410
54+ select VIDEO_OMAP3_ISP
55+
56+config VIDEO_OMAP34XX_ISP_RESIZER
57+ tristate "OMAP ISP Resizer"
58+ depends on !ARCH_OMAP3410
59+ select VIDEO_OMAP3_ISP
60diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
61index 0f9301c..ed10a51 100644
62--- a/drivers/media/video/isp/Makefile
63+++ b/drivers/media/video/isp/Makefile
64@@ -7,6 +7,13 @@ else
65 isp-mod-objs += \
66 isp.o ispccdc.o ispmmu.o \
67 isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
68+
69+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER) += \
70+ omap_previewer.o
71+
72+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
73+ omap_resizer.o
74+
75 endif
76
77 obj-$(CONFIG_VIDEO_OMAP3_ISP) += isp-mod.o
78diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
79index 6034a56..09a1792 100644
80--- a/drivers/media/video/isp/isp.c
81+++ b/drivers/media/video/isp/isp.c
82@@ -521,6 +521,13 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
83 OMAP3_ISP_IOMEM_MAIN,
84 ISP_IRQ0ENABLE);
85 break;
86+ case CBK_RESZ_DONE:
87+ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
88+ ISP_IRQ0STATUS);
89+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE) |
90+ IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
91+ ISP_IRQ0ENABLE);
92+ break;
93 default:
94 break;
95 }
96@@ -996,6 +1003,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
97 if (!ispresizer_busy())
98 ispresizer_config_shadow_registers();
99 isp_buf_process(bufs);
100+ } else {
101+ if (irqdis->isp_callbk[CBK_RESZ_DONE])
102+ irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE,
103+ irqdis->isp_callbk_arg1[CBK_RESZ_DONE],
104+ irqdis->isp_callbk_arg2[CBK_RESZ_DONE]);
105 }
106 }
107
108diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
109index 076aea1..b943d5b 100644
110--- a/drivers/media/video/isp/ispmmu.c
111+++ b/drivers/media/video/isp/ispmmu.c
112@@ -289,6 +289,7 @@ int ispmmu_get_mapeable_space(void)
113 return (L2P_TABLE_NR - no_of_l2p_alloted) * ISPMMU_TTB_ENTRIES_NR *
114 ISPMMU_L2D_ENTRIES_NR;
115 }
116+EXPORT_SYMBOL_GPL(ispmmu_get_mapeable_space);
117
118 /**
119 * ispmmu_map - Map a physically contiguous buffer to ISP space.
120diff --git a/drivers/media/video/isp/omap_previewer.c b/drivers/media/video/isp/omap_previewer.c
121new file mode 100644
122index 0000000..634a056
123--- /dev/null
124+++ b/drivers/media/video/isp/omap_previewer.c
125@@ -0,0 +1,825 @@
126+/*
127+ * drivers/media/video/isp/omap_previewer.c
128+ *
129+ * Wrapper for Preview module in TI's OMAP3430 ISP
130+ *
131+ * Copyright (C) 2008 Texas Instruments, Inc.
132+ *
133+ * Contributors:
134+ * Leonides Martinez <leonides.martinez@ti.com>
135+ * Sergio Aguirre <saaguirre@ti.com>
136+ *
137+ * This package is free software; you can redistribute it and/or modify
138+ * it under the terms of the GNU General Public License version 2 as
139+ * published by the Free Software Foundation.
140+ *
141+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
142+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
143+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
144+ */
145+
146+#include <linux/mutex.h>
147+#include <linux/cdev.h>
148+#include <linux/device.h>
149+#include <linux/delay.h>
150+#include <linux/fs.h>
151+#include <linux/mm.h>
152+#include <linux/module.h>
153+#include <linux/platform_device.h>
154+#include <linux/uaccess.h>
155+#include <linux/io.h>
156+#include <media/v4l2-dev.h>
157+#include <asm/cacheflush.h>
158+
159+#include "isp.h"
160+#include "ispmmu.h"
161+#include "ispreg.h"
162+#include "omap_previewer.h"
163+
164+#define OMAP_PREV_NAME "omap-previewer"
165+
166+static int prev_major = -1;
167+static struct device *prev_dev;
168+static struct class *prev_class;
169+static struct prev_device *prevdevice;
170+static struct platform_driver omap_previewer_driver;
171+
172+static u32 prev_bufsize;
173+
174+/**
175+ * prev_calculate_crop - Calculate crop size according to device parameters
176+ * @device: Structure containing ISP preview wrapper global information
177+ * @crop: Structure containing crop size
178+ *
179+ * This function is used to calculate frame size reduction depending on
180+ * the features enabled by the application.
181+ **/
182+static void prev_calculate_crop(struct prev_device *device,
183+ struct prev_cropsize *crop)
184+{
185+ dev_dbg(prev_dev, "prev_calculate_crop E\n");
186+
187+ if (!device || !crop) {
188+ dev_err(prev_dev, "\nErron in argument");
189+ return;
190+ }
191+
192+ isppreview_try_size(device->params->size_params.hsize,
193+ device->params->size_params.vsize,
194+ &crop->hcrop, &crop->vcrop);
195+ crop->hcrop &= PREV_16PIX_ALIGN_MASK;
196+ dev_dbg(prev_dev, "prev_calculate_crop L\n");
197+}
198+
199+/**
200+ * prev_get_status - Get status of ISP preview module
201+ * @status: Structure containing the busy state.
202+ *
203+ * Checks if the ISP preview module is busy.
204+ *
205+ * Returns 0 if successful, or -EINVAL if the status parameter is invalid.
206+ **/
207+static int prev_get_status(struct prev_status *status)
208+{
209+ if (!status) {
210+ dev_err(prev_dev, "get_status: invalid parameter\n");
211+ return -EINVAL;
212+ }
213+ status->hw_busy = (char)isppreview_busy();
214+ return 0;
215+}
216+
217+/**
218+ * prev_hw_setup - Stores the desired configuration in the proper HW registers
219+ * @config: Structure containing the desired configuration for ISP preview
220+ * module.
221+ *
222+ * Reads the structure sent, and modifies the desired registers.
223+ *
224+ * Always returns 0.
225+ **/
226+static int prev_hw_setup(struct prev_params *config)
227+{
228+ dev_dbg(prev_dev, "prev_hw_setup E\n");
229+
230+ if (config->features & PREV_AVERAGER)
231+ isppreview_config_averager(config->average);
232+ else
233+ isppreview_config_averager(0);
234+
235+ if (config->features & PREV_INVERSE_ALAW)
236+ isppreview_enable_invalaw(1);
237+ else
238+ isppreview_enable_invalaw(0);
239+
240+ if (config->features & PREV_HORZ_MEDIAN_FILTER) {
241+ isppreview_config_hmed(config->hmf_params);
242+ isppreview_enable_hmed(1);
243+ } else
244+ isppreview_enable_hmed(0);
245+
246+ if (config->features & PREV_DARK_FRAME_SUBTRACT) {
247+ isppreview_set_darkaddr(config->drkf_params.addr);
248+ isppreview_config_darklineoffset(config->drkf_params.offset);
249+ isppreview_enable_drkframe(1);
250+ } else
251+ isppreview_enable_drkframe(0);
252+
253+ if (config->features & PREV_LENS_SHADING) {
254+ isppreview_config_drkf_shadcomp(config->lens_shading_shift);
255+ isppreview_enable_shadcomp(1);
256+ } else
257+ isppreview_enable_shadcomp(0);
258+
259+ dev_dbg(prev_dev, "prev_hw_setup L\n");
260+ return 0;
261+}
262+
263+/**
264+ * prev_validate_params - Validate configuration parameters for Preview Wrapper
265+ * @params: Structure containing configuration parameters
266+ *
267+ * Validate configuration parameters for Preview Wrapper
268+ *
269+ * Returns 0 if successful, or -EINVAL if a parameter value is invalid.
270+ **/
271+static int prev_validate_params(struct prev_params *params)
272+{
273+ if (!params) {
274+ dev_err(prev_dev, "validate_params: error in argument");
275+ goto err_einval;
276+ }
277+
278+ if ((params->features & PREV_AVERAGER) == PREV_AVERAGER) {
279+ if ((params->average != NO_AVE)
280+ && (params->average != AVE_2_PIX)
281+ && (params->average != AVE_4_PIX)
282+ && (params->average != AVE_8_PIX)) {
283+ dev_err(prev_dev, "validate_params: wrong pix "
284+ "average\n");
285+ goto err_einval;
286+ } else if (((params->average == AVE_2_PIX)
287+ && (params->size_params.hsize % 2))
288+ || ((params->average == AVE_4_PIX)
289+ && (params->size_params.hsize % 4))
290+ || ((params->average == AVE_8_PIX)
291+ && (params->size_params.hsize % 8))) {
292+ dev_err(prev_dev, "validate_params: "
293+ "wrong pix average for input size\n");
294+ goto err_einval;
295+ }
296+ }
297+
298+ if ((params->size_params.pixsize != PREV_INWIDTH_8BIT)
299+ && (params->size_params.pixsize
300+ != PREV_INWIDTH_10BIT)) {
301+ dev_err(prev_dev, "validate_params: wrong pixsize\n");
302+ goto err_einval;
303+ }
304+
305+ if (params->size_params.hsize > MAX_IMAGE_WIDTH
306+ || params->size_params.hsize < 0) {
307+ dev_err(prev_dev, "validate_params: wrong hsize\n");
308+ goto err_einval;
309+ }
310+
311+ if ((params->pix_fmt != YCPOS_YCrYCb)
312+ && (YCPOS_YCbYCr != params->pix_fmt)
313+ && (YCPOS_CbYCrY != params->pix_fmt)
314+ && (YCPOS_CrYCbY != params->pix_fmt)) {
315+ dev_err(prev_dev, "validate_params: wrong pix_fmt");
316+ goto err_einval;
317+ }
318+
319+ if ((params->features & PREV_DARK_FRAME_SUBTRACT)
320+ && (params->features
321+ & PREV_DARK_FRAME_CAPTURE)) {
322+ dev_err(prev_dev, "validate_params: DARK FRAME CAPTURE and "
323+ "SUBSTRACT cannot be enabled "
324+ "at same time\n");
325+ goto err_einval;
326+ }
327+
328+ if (params->features & PREV_DARK_FRAME_SUBTRACT)
329+ if (!params->drkf_params.addr
330+ || (params->drkf_params.offset % 32)) {
331+ dev_err(prev_dev, "validate_params: dark frame "
332+ "address\n");
333+ goto err_einval;
334+ }
335+
336+ if (params->features & PREV_LENS_SHADING)
337+ if ((params->lens_shading_shift > 7)
338+ || !params->drkf_params.addr
339+ || (params->drkf_params.offset % 32)) {
340+ dev_err(prev_dev, "validate_params: lens shading "
341+ "shift\n");
342+ goto err_einval;
343+ }
344+
345+ if ((params->size_params.in_pitch <= 0)
346+ || (params->size_params.in_pitch % 32)) {
347+ params->size_params.in_pitch =
348+ (params->size_params.hsize * 2) & 0xFFE0;
349+ dev_err(prev_dev, "\nError in in_pitch; new value = %d",
350+ params->size_params.in_pitch);
351+ }
352+
353+ return 0;
354+err_einval:
355+ return -EINVAL;
356+}
357+
358+/**
359+ * preview_isr - Callback from ISP driver for ISP Preview Interrupt
360+ * @status: ISP IRQ0STATUS register value
361+ * @arg1: Structure containing ISP preview wrapper global information
362+ * @arg2: Currently not used
363+ **/
364+static void preview_isr(unsigned long status, isp_vbq_callback_ptr arg1,
365+ void *arg2)
366+{
367+ struct prev_device *device = (struct prev_device *)arg1;
368+
369+ if ((status & PREV_DONE) != PREV_DONE)
370+ return;
371+
372+ if (device)
373+ complete(&device->wfc);
374+}
375+
376+/**
377+ * prev_do_preview - Performs the Preview process
378+ * @device: Structure containing ISP preview wrapper global information
379+ * @arg: Currently not used
380+ *
381+ * Returns 0 if successful, or -EINVAL if the sent parameters are invalid.
382+ **/
383+static int prev_do_preview(struct prev_device *device, int *arg)
384+{
385+ int bpp, size;
386+ int ret = 0;
387+ u32 out_hsize, out_vsize, out_line_offset;
388+
389+ dev_dbg(prev_dev, "prev_do_preview E\n");
390+
391+ if (!device) {
392+ dev_err(prev_dev, "preview: invalid parameters\n");
393+ return -EINVAL;
394+ }
395+
396+ if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT)
397+ bpp = 1;
398+ else
399+ bpp = 2;
400+
401+ size = device->params->size_params.hsize *
402+ device->params->size_params.vsize * bpp;
403+
404+ ret = isppreview_set_inaddr(device->isp_addr_read);
405+ if (ret)
406+ goto out;
407+
408+ ret = isppreview_set_outaddr(device->isp_addr_read);
409+ if (ret)
410+ goto out;
411+
412+ isppreview_try_size(device->params->size_params.hsize,
413+ device->params->size_params.vsize,
414+ &out_hsize, &out_vsize);
415+
416+ ret = isppreview_config_inlineoffset(device->params->size_params.hsize
417+ * bpp);
418+ if (ret)
419+ goto out;
420+
421+ out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK;
422+
423+ ret = isppreview_config_outlineoffset(out_line_offset);
424+ if (ret)
425+ goto out;
426+
427+ ret = isppreview_config_size(device->params->size_params.hsize,
428+ device->params->size_params.vsize,
429+ out_hsize, out_vsize);
430+ if (ret)
431+ goto out;
432+
433+ isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM);
434+
435+ ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device,
436+ (void *)NULL);
437+ if (ret) {
438+ dev_err(prev_dev, "ERROR while setting Previewer callback!\n");
439+ goto out;
440+ }
441+ isppreview_enable(1);
442+
443+ wait_for_completion_interruptible(&device->wfc);
444+
445+ if (device->isp_addr_read) {
446+ ispmmu_vunmap(device->isp_addr_read);
447+ device->isp_addr_read = 0;
448+ }
449+
450+ ret = isp_unset_callback(CBK_PREV_DONE);
451+
452+ dev_dbg(prev_dev, "prev_do_preview L\n");
453+out:
454+ return ret;
455+}
456+
457+/**
458+ * previewer_vbq_release - Videobuffer queue release
459+ * @q: Structure containing the videobuffer queue.
460+ * @vb: Structure containing the videobuffer used for previewer processing.
461+ **/
462+static void previewer_vbq_release(struct videobuf_queue *q,
463+ struct videobuf_buffer *vb)
464+{
465+ struct prev_fh *fh = q->priv_data;
466+ struct prev_device *device = fh->device;
467+
468+ ispmmu_vunmap(device->isp_addr_read);
469+ device->isp_addr_read = 0;
470+ spin_lock(&device->vbq_lock);
471+ vb->state = VIDEOBUF_NEEDS_INIT;
472+ spin_unlock(&device->vbq_lock);
473+ dev_dbg(prev_dev, "previewer_vbq_release\n");
474+}
475+
476+/**
477+ * previewer_vbq_setup - Sets up the videobuffer size and validates count.
478+ * @q: Structure containing the videobuffer queue.
479+ * @cnt: Number of buffers requested
480+ * @size: Size in bytes of the buffer used for previewing
481+ *
482+ * Always returns 0.
483+ **/
484+static int previewer_vbq_setup(struct videobuf_queue *q,
485+ unsigned int *cnt,
486+ unsigned int *size)
487+{
488+ struct prev_fh *fh = q->priv_data;
489+ struct prev_device *device = fh->device;
490+ u32 bpp = 1;
491+
492+ spin_lock(&device->vbq_lock);
493+ if (*cnt <= 0)
494+ *cnt = VIDEO_MAX_FRAME;
495+
496+ if (*cnt > VIDEO_MAX_FRAME)
497+ *cnt = VIDEO_MAX_FRAME;
498+
499+ if (!device->params->size_params.hsize ||
500+ !device->params->size_params.vsize) {
501+ dev_err(prev_dev, "Can't setup buffer size\n");
502+ spin_unlock(&device->vbq_lock);
503+ return -EINVAL;
504+ }
505+
506+ if (device->params->size_params.pixsize == PREV_INWIDTH_10BIT)
507+ bpp = 2;
508+ *size = prev_bufsize = bpp * device->params->size_params.hsize
509+ * device->params->size_params.vsize;
510+ spin_unlock(&device->vbq_lock);
511+ dev_dbg(prev_dev, "previewer_vbq_setup\n");
512+ return 0;
513+}
514+
515+/**
516+ * previewer_vbq_prepare - Videobuffer is prepared and mmapped.
517+ * @q: Structure containing the videobuffer queue.
518+ * @vb: Structure containing the videobuffer used for previewer processing.
519+ * @field: Type of field to set in videobuffer device.
520+ *
521+ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
522+ * -EIO if the ISP MMU mapping fails
523+ **/
524+static int previewer_vbq_prepare(struct videobuf_queue *q,
525+ struct videobuf_buffer *vb,
526+ enum v4l2_field field)
527+{
528+ struct prev_fh *fh = q->priv_data;
529+ struct prev_device *device = fh->device;
530+ int err = -EINVAL;
531+ unsigned int isp_addr;
532+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
533+
534+ dev_dbg(prev_dev, "previewer_vbq_prepare E\n");
535+ spin_lock(&device->vbq_lock);
536+ if (vb->baddr) {
537+ vb->size = prev_bufsize;
538+ vb->bsize = prev_bufsize;
539+ } else {
540+ spin_unlock(&device->vbq_lock);
541+ dev_err(prev_dev, "No user buffer allocated\n");
542+ goto out;
543+ }
544+
545+ vb->width = device->params->size_params.hsize;
546+ vb->height = device->params->size_params.vsize;
547+ vb->field = field;
548+ spin_unlock(&device->vbq_lock);
549+
550+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
551+ err = videobuf_iolock(q, vb, NULL);
552+ if (!err) {
553+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
554+ if (!isp_addr)
555+ err = -EIO;
556+ else
557+ device->isp_addr_read = isp_addr;
558+ }
559+ }
560+
561+ if (!err) {
562+ vb->state = VIDEOBUF_PREPARED;
563+ flush_cache_user_range(NULL, vb->baddr,
564+ (vb->baddr + vb->bsize));
565+ } else
566+ previewer_vbq_release(q, vb);
567+
568+ dev_dbg(prev_dev, "previewer_vbq_prepare L\n");
569+out:
570+ return err;
571+}
572+
573+static void previewer_vbq_queue(struct videobuf_queue *q,
574+ struct videobuf_buffer *vb)
575+{
576+ return;
577+}
578+
579+/**
580+ * previewer_open - Initializes and opens the Preview Wrapper
581+ * @inode: Inode structure associated with the Preview Wrapper
582+ * @filp: File structure associated with the Preview Wrapper
583+ *
584+ * Returns 0 if successful, -EACCES if its unable to initialize default config,
585+ * -EBUSY if its already opened or the ISP module is not available, or -ENOMEM
586+ * if its unable to allocate the device in kernel space memory.
587+ **/
588+static int previewer_open(struct inode *inode, struct file *filp)
589+{
590+ int ret = 0;
591+ struct prev_device *device = prevdevice;
592+ struct prev_params *config = isppreview_get_config();
593+ struct prev_fh *fh;
594+
595+ if (config == NULL) {
596+ dev_err(prev_dev, "Unable to initialize default config "
597+ "from isppreviewer\n\n");
598+ return -EACCES;
599+ }
600+
601+ if (device->opened || (filp->f_flags & O_NONBLOCK)) {
602+ dev_err(prev_dev, "previewer_open: device is already "
603+ "opened\n");
604+ return -EBUSY;
605+ }
606+
607+ fh = kzalloc(sizeof(struct prev_fh), GFP_KERNEL);
608+ if (NULL == fh)
609+ return -ENOMEM;
610+
611+ isp_get();
612+ ret = isppreview_request();
613+ if (ret) {
614+ isp_put();
615+ dev_err(prev_dev, "Can't acquire isppreview\n");
616+ return ret;
617+ }
618+
619+ device->params = config;
620+ device->opened = 1;
621+
622+ filp->private_data = fh;
623+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
624+ fh->device = device;
625+
626+ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
627+ &device->vbq_lock, fh->type,
628+ V4L2_FIELD_NONE,
629+ sizeof(struct videobuf_buffer), fh);
630+
631+ init_completion(&device->wfc);
632+ device->wfc.done = 0;
633+ mutex_init(&device->prevwrap_mutex);
634+
635+ return 0;
636+}
637+
638+/**
639+ * previewer_release - Releases Preview Wrapper and frees up allocated memory
640+ * @inode: Inode structure associated with the Preview Wrapper
641+ * @filp: File structure associated with the Preview Wrapper
642+ *
643+ * Always returns 0.
644+ **/
645+static int previewer_release(struct inode *inode, struct file *filp)
646+{
647+ struct prev_fh *fh = filp->private_data;
648+ struct prev_device *device = fh->device;
649+ struct videobuf_queue *q = &fh->vbq;
650+
651+ device->opened = 0;
652+ device->params = NULL;
653+ isppreview_free();
654+ videobuf_mmap_free(q);
655+ isp_put();
656+ prev_bufsize = 0;
657+ filp->private_data = NULL;
658+ kfree(fh);
659+
660+ dev_dbg(prev_dev, "previewer_release\n");
661+ return 0;
662+}
663+
664+/**
665+ * previewer_mmap - Memory maps the Preview Wrapper module.
666+ * @file: File structure associated with the Preview Wrapper
667+ * @vma: Virtual memory area structure.
668+ *
669+ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
670+ * function.
671+ **/
672+static int previewer_mmap(struct file *file, struct vm_area_struct *vma)
673+{
674+ struct prev_fh *fh = file->private_data;
675+ dev_dbg(prev_dev, "previewer_mmap\n");
676+
677+ return videobuf_mmap_mapper(&fh->vbq, vma);
678+}
679+
680+/**
681+ * previewer_ioctl - I/O control function for Preview Wrapper
682+ * @inode: Inode structure associated with the Preview Wrapper.
683+ * @file: File structure associated with the Preview Wrapper.
684+ * @cmd: Type of command to execute.
685+ * @arg: Argument to send to requested command.
686+ *
687+ * Returns 0 if successful, -1 if bad command passed or access is denied,
688+ * -EFAULT if copy_from_user() or copy_to_user() fails, -EINVAL if parameter
689+ * validation fails or parameter structure is not present
690+ **/
691+static int previewer_ioctl(struct inode *inode, struct file *file,
692+ unsigned int cmd, unsigned long arg)
693+{
694+ int ret = 0;
695+ struct prev_params params;
696+ struct prev_fh *fh = file->private_data;
697+ struct prev_device *device = fh->device;
698+
699+ dev_dbg(prev_dev, "Entering previewer_ioctl()\n");
700+
701+ if ((_IOC_TYPE(cmd) != PREV_IOC_BASE)
702+ || (_IOC_NR(cmd) > PREV_IOC_MAXNR)) {
703+ dev_err(prev_dev, "Bad command Value \n");
704+ goto err_minusone;
705+ }
706+
707+ if (_IOC_DIR(cmd) & _IOC_READ)
708+ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
709+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
710+ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
711+ if (ret) {
712+ dev_err(prev_dev, "access denied\n");
713+ goto err_minusone;
714+ }
715+
716+ switch (cmd) {
717+ case PREV_REQBUF:
718+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
719+ goto err_eintr;
720+ ret = videobuf_reqbufs(&fh->vbq, (void *)arg);
721+ mutex_unlock(&device->prevwrap_mutex);
722+ break;
723+
724+ case PREV_QUERYBUF:
725+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
726+ goto err_eintr;
727+ ret = videobuf_querybuf(&fh->vbq, (void *)arg);
728+ mutex_unlock(&device->prevwrap_mutex);
729+ break;
730+
731+ case PREV_QUEUEBUF:
732+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
733+ goto err_eintr;
734+ ret = videobuf_qbuf(&fh->vbq, (void *)arg);
735+ mutex_unlock(&device->prevwrap_mutex);
736+ break;
737+
738+ case PREV_SET_PARAM:
739+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
740+ goto err_eintr;
741+ if (copy_from_user(&params, (struct prev_params *)arg,
742+ sizeof(struct prev_params))) {
743+ mutex_unlock(&device->prevwrap_mutex);
744+ return -EFAULT;
745+ }
746+ ret = prev_validate_params(&params);
747+ if (ret < 0) {
748+ dev_err(prev_dev, "Error validating parameters!\n");
749+ mutex_unlock(&device->prevwrap_mutex);
750+ goto out;
751+ }
752+ if (device->params)
753+ memcpy(device->params, &params,
754+ sizeof(struct prev_params));
755+ else {
756+ mutex_unlock(&device->prevwrap_mutex);
757+ return -EINVAL;
758+ }
759+
760+ ret = prev_hw_setup(device->params);
761+ mutex_unlock(&device->prevwrap_mutex);
762+ break;
763+
764+ case PREV_GET_PARAM:
765+ if (copy_to_user((struct prev_params *)arg, device->params,
766+ sizeof(struct prev_params)))
767+ ret = -EFAULT;
768+ break;
769+
770+ case PREV_GET_STATUS:
771+ ret = prev_get_status((struct prev_status *)arg);
772+ break;
773+
774+ case PREV_PREVIEW:
775+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
776+ goto err_eintr;
777+ ret = prev_do_preview(device, (int *)arg);
778+ mutex_unlock(&device->prevwrap_mutex);
779+ break;
780+
781+ case PREV_GET_CROPSIZE:
782+ {
783+ struct prev_cropsize outputsize;
784+ prev_calculate_crop(device, &outputsize);
785+ if (copy_to_user((struct prev_cropsize *)arg, &outputsize,
786+ sizeof(struct prev_cropsize)))
787+ ret = -EFAULT;
788+ }
789+ break;
790+
791+ default:
792+ dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n");
793+ ret = -EINVAL;
794+ }
795+out:
796+ return ret;
797+err_minusone:
798+ return -1;
799+err_eintr:
800+ return -EINTR;
801+}
802+
803+/**
804+ * previewer_platform_release - Acts when Reference count is zero
805+ * @device: Structure containing ISP preview wrapper global information
806+ *
807+ * This is called when the reference count goes to zero
808+ **/
809+static void previewer_platform_release(struct device *device)
810+{
811+ dev_dbg(prev_dev, "previewer_platform_release()\n");
812+}
813+
814+static struct file_operations prev_fops = {
815+ .owner = THIS_MODULE,
816+ .open = previewer_open,
817+ .release = previewer_release,
818+ .mmap = previewer_mmap,
819+ .ioctl = previewer_ioctl,
820+};
821+
822+static struct platform_device omap_previewer_device = {
823+ .name = OMAP_PREV_NAME,
824+ .id = -1,
825+ .dev = {
826+ .release = previewer_platform_release,
827+ }
828+};
829+
830+/**
831+ * previewer_probe - Checks for device presence
832+ * @pdev: Structure containing details of the current device.
833+ *
834+ * Always returns 0
835+ **/
836+static int __init previewer_probe(struct platform_device *pdev)
837+{
838+ return 0;
839+}
840+
841+/**
842+ * previewer_remove - Handles the removal of the driver
843+ * @pdev: Structure containing details of the current device.
844+ *
845+ * Always returns 0.
846+ **/
847+static int previewer_remove(struct platform_device *pdev)
848+{
849+ dev_dbg(prev_dev, "previewer_remove()\n");
850+
851+ platform_device_unregister(&omap_previewer_device);
852+ platform_driver_unregister(&omap_previewer_driver);
853+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
854+ return 0;
855+}
856+
857+static struct platform_driver omap_previewer_driver = {
858+ .probe = previewer_probe,
859+ .remove = previewer_remove,
860+ .driver = {
861+ .owner = THIS_MODULE,
862+ .name = OMAP_PREV_NAME,
863+ },
864+};
865+
866+/**
867+ * omap_previewer_init - Initialization of Preview Wrapper
868+ *
869+ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
870+ * could not register the wrapper as a character device, or other errors if the
871+ * device or driver can't register.
872+ **/
873+static int __init omap_previewer_init(void)
874+{
875+ int ret;
876+ struct prev_device *device;
877+
878+ device = kzalloc(sizeof(struct prev_device), GFP_KERNEL);
879+ if (!device) {
880+ dev_err(prev_dev, OMAP_PREV_NAME ": could not allocate"
881+ " memory\n");
882+ return -ENOMEM;
883+ }
884+ prev_major = register_chrdev(0, OMAP_PREV_NAME, &prev_fops);
885+
886+ if (prev_major < 0) {
887+ dev_err(prev_dev, OMAP_PREV_NAME ": initialization "
888+ "failed. could not register character "
889+ "device\n");
890+ return -ENODEV;
891+ }
892+
893+ ret = platform_driver_register(&omap_previewer_driver);
894+ if (ret) {
895+ dev_err(prev_dev, OMAP_PREV_NAME
896+ ": failed to register platform driver!\n");
897+ goto fail2;
898+ }
899+ ret = platform_device_register(&omap_previewer_device);
900+ if (ret) {
901+ dev_err(prev_dev, OMAP_PREV_NAME
902+ ": failed to register platform device!\n");
903+ goto fail3;
904+ }
905+
906+ prev_class = class_create(THIS_MODULE, OMAP_PREV_NAME);
907+ if (!prev_class)
908+ goto fail4;
909+
910+ prev_dev = device_create(prev_class, prev_dev,
911+ (MKDEV(prev_major, 0)), NULL,
912+ OMAP_PREV_NAME);
913+ dev_dbg(prev_dev, OMAP_PREV_NAME ": Registered Previewer Wrapper\n");
914+ device->opened = 0;
915+
916+ device->vbq_ops.buf_setup = previewer_vbq_setup;
917+ device->vbq_ops.buf_prepare = previewer_vbq_prepare;
918+ device->vbq_ops.buf_release = previewer_vbq_release;
919+ device->vbq_ops.buf_queue = previewer_vbq_queue;
920+ spin_lock_init(&device->vbq_lock);
921+
922+ prevdevice = device;
923+ return 0;
924+
925+fail4:
926+ platform_device_unregister(&omap_previewer_device);
927+fail3:
928+ platform_driver_unregister(&omap_previewer_driver);
929+fail2:
930+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
931+
932+ return ret;
933+}
934+
935+/**
936+ * omap_previewer_exit - Close of Preview Wrapper
937+ **/
938+static void __exit omap_previewer_exit(void)
939+{
940+ previewer_remove(&omap_previewer_device);
941+ kfree(prevdevice);
942+ prev_major = -1;
943+}
944+
945+module_init(omap_previewer_init);
946+module_exit(omap_previewer_exit);
947+
948+MODULE_AUTHOR("Texas Instruments");
949+MODULE_DESCRIPTION("OMAP ISP Previewer");
950+MODULE_LICENSE("GPL");
951diff --git a/drivers/media/video/isp/omap_previewer.h b/drivers/media/video/isp/omap_previewer.h
952new file mode 100644
953index 0000000..0bb31cd
954--- /dev/null
955+++ b/drivers/media/video/isp/omap_previewer.h
956@@ -0,0 +1,162 @@
957+/*
958+ * drivers/media/video/isp/omap_previewer.h
959+ *
960+ * Header file for Preview module wrapper in TI's OMAP3430 ISP
961+ *
962+ * Copyright (C) 2008 Texas Instruments, Inc.
963+ *
964+ * Contributors:
965+ * Leonides Martinez <leonides.martinez@ti.com>
966+ * Sergio Aguirre <saaguirre@ti.com>
967+ *
968+ * This package is free software; you can redistribute it and/or modify
969+ * it under the terms of the GNU General Public License version 2 as
970+ * published by the Free Software Foundation.
971+ *
972+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
973+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
974+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
975+ */
976+
977+#include "isppreview.h"
978+
979+#ifndef OMAP_ISP_PREVIEW_WRAP_H
980+#define OMAP_ISP_PREVIEW_WRAP_H
981+
982+#define PREV_IOC_BASE 'P'
983+#define PREV_REQBUF _IOWR(PREV_IOC_BASE, 1,\
984+ struct v4l2_requestbuffers)
985+#define PREV_QUERYBUF _IOWR(PREV_IOC_BASE, 2,\
986+ struct v4l2_buffer)
987+#define PREV_SET_PARAM _IOW(PREV_IOC_BASE, 3,\
988+ struct prev_params)
989+#define PREV_GET_PARAM _IOWR(PREV_IOC_BASE, 4,\
990+ struct prev_params)
991+#define PREV_PREVIEW _IOR(PREV_IOC_BASE, 5, int)
992+#define PREV_GET_STATUS _IOR(PREV_IOC_BASE, 6, char)
993+#define PREV_GET_CROPSIZE _IOR(PREV_IOC_BASE, 7,\
994+ struct prev_cropsize)
995+#define PREV_QUEUEBUF _IOWR(PREV_IOC_BASE, 8,\
996+ struct v4l2_buffer)
997+#define PREV_IOC_MAXNR 8
998+
999+#define LUMA_TABLE_SIZE 128
1000+#define GAMMA_TABLE_SIZE 1024
1001+#define CFA_COEFF_TABLE_SIZE 576
1002+#define NOISE_FILTER_TABLE_SIZE 256
1003+
1004+#define MAX_IMAGE_WIDTH 3300
1005+
1006+#define PREV_INWIDTH_8BIT 0 /* pixel width of 8 bits */
1007+#define PREV_INWIDTH_10BIT 1 /* pixel width of 10 bits */
1008+
1009+#define PREV_32BYTES_ALIGN_MASK 0xFFFFFFE0
1010+#define PREV_16PIX_ALIGN_MASK 0xFFFFFFF0
1011+
1012+/**
1013+ * struct prev_rgbblending - Structure for RGB2RGB blending parameters
1014+ * @blending: Color correlation 3x3 matrix.
1015+ * @offset: Color correlation offsets.
1016+ */
1017+struct prev_rgbblending {
1018+ short blending[RGB_MAX][RGB_MAX]; /* color correlation 3x3
1019+ * matrix.
1020+ */
1021+ short offset[RGB_MAX]; /* color correlation offsets */
1022+};
1023+
1024+/**
1025+ * struct prev_cfa_coeffs - Structure for CFA coefficients
1026+ * @hthreshold: Horizontal threshold.
1027+ * @vthreshold: Vertical threshold.
1028+ * @coeffs: CFA coefficients
1029+ */
1030+struct prev_cfa_coeffs {
1031+ char hthreshold, vthreshold;
1032+ int coeffs[CFA_COEFF_TABLE_SIZE];
1033+};
1034+
1035+/**
1036+ * struct prev_gamma_coeffs - Structure for Gamma Coefficients
1037+ * @red: Table of gamma correction values for red color.
1038+ * @green: Table of gamma correction values for green color.
1039+ * @blue: Table of gamma correction values for blue color.
1040+ */
1041+struct prev_gamma_coeffs {
1042+ unsigned char red[GAMMA_TABLE_SIZE];
1043+ unsigned char green[GAMMA_TABLE_SIZE];
1044+ unsigned char blue[GAMMA_TABLE_SIZE];
1045+};
1046+
1047+/**
1048+ * struct prev_noiseflt_coeffs - Structure for Noise Filter Coefficients.
1049+ * @noise: Noise filter table.
1050+ * @strength: Used to find out weighted average.
1051+ */
1052+struct prev_noiseflt_coeffs {
1053+ unsigned char noise[NOISE_FILTER_TABLE_SIZE];
1054+ unsigned char strength;
1055+};
1056+
1057+/**
1058+ * struct prev_chroma_spr - Structure for Chroma Suppression.
1059+ * @hpfy: High passed version of Y or normal Y.
1060+ * @threshold: Threshold for chroma suppress.
1061+ * @gain: Chroma suppression gain
1062+ */
1063+struct prev_chroma_spr {
1064+ unsigned char hpfy;
1065+ char threshold;
1066+ unsigned char gain;
1067+};
1068+
1069+/**
1070+ * struct prev_status - Structure to know status of the hardware
1071+ * @hw_busy: Flag to indicate if Hardware is Busy.
1072+ */
1073+struct prev_status {
1074+ char hw_busy;
1075+};
1076+
1077+/**
1078+ * struct prev_cropsize - Structure to know crop size.
1079+ * @hcrop: Horizontal size of crop window.
1080+ * @vcrop: Vertical size of crop window.
1081+ */
1082+struct prev_cropsize {
1083+ int hcrop;
1084+ int vcrop;
1085+};
1086+
1087+/**
1088+ * struct prev_device - Global device information structure.
1089+ * @params: Pointer to structure containing preview parameters.
1090+ * @opened: State of the device.
1091+ * @wfc: Wait for completion. Used for locking operations.
1092+ * @prevwrap_mutex: Mutex for preview wrapper use.
1093+ * @vbq_lock: Spinlock for videobuf queues.
1094+ * @vbq_ops: Videobuf queue operations
1095+ * @isp_addr_read: Input/Output address
1096+ */
1097+struct prev_device {
1098+ struct prev_params *params;
1099+ unsigned char opened;
1100+ struct completion wfc;
1101+ struct mutex prevwrap_mutex; /* For generic internal use */
1102+ spinlock_t vbq_lock; /* For videobuffer queue handling */
1103+ struct videobuf_queue_ops vbq_ops;
1104+ dma_addr_t isp_addr_read;
1105+};
1106+
1107+/**
1108+ * struct prev_fh - Per-filehandle data structure
1109+ * @type: Used buffer type.
1110+ * @vbq: Videobuffer queue.
1111+ * @device: Pointer to device information structure.
1112+ */
1113+struct prev_fh {
1114+ enum v4l2_buf_type type;
1115+ struct videobuf_queue vbq;
1116+ struct prev_device *device;
1117+};
1118+#endif
1119diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
1120new file mode 100644
1121index 0000000..54bc425
1122--- /dev/null
1123+++ b/drivers/media/video/isp/omap_resizer.c
1124@@ -0,0 +1,1634 @@
1125+/*
1126+ * drivers/media/video/isp/omap_resizer.c
1127+ *
1128+ * Wrapper for Resizer module in TI's OMAP3430 ISP
1129+ *
1130+ * Copyright (C) 2008 Texas Instruments, Inc.
1131+ *
1132+ * Contributors:
1133+ * Sergio Aguirre <saaguirre@ti.com>
1134+ * Troy Laramy <t-laramy@ti.com>
1135+ *
1136+ * This package is free software; you can redistribute it and/or modify
1137+ * it under the terms of the GNU General Public License version 2 as
1138+ * published by the Free Software Foundation.
1139+ *
1140+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1141+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1142+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1143+ */
1144+
1145+#include <linux/mutex.h>
1146+#include <linux/cdev.h>
1147+#include <linux/delay.h>
1148+#include <linux/device.h>
1149+#include <linux/fs.h>
1150+#include <linux/mm.h>
1151+#include <linux/module.h>
1152+#include <linux/platform_device.h>
1153+#include <linux/io.h>
1154+#include <linux/uaccess.h>
1155+#include <media/v4l2-dev.h>
1156+#include <asm/cacheflush.h>
1157+
1158+#include "isp.h"
1159+#include "ispmmu.h"
1160+#include "ispreg.h"
1161+#include "ispresizer.h"
1162+#include <linux/omap_resizer.h>
1163+
1164+#define OMAP_REZR_NAME "omap-resizer"
1165+
1166+/* Defines and Constants*/
1167+#define MAX_CHANNELS 16
1168+#define MAX_IMAGE_WIDTH 2047
1169+#define MAX_IMAGE_WIDTH_HIGH 2047
1170+#define ALIGNMENT 16
1171+#define CHANNEL_BUSY 1
1172+#define CHANNEL_FREE 0
1173+#define PIXEL_EVEN 2
1174+#define RATIO_MULTIPLIER 256
1175+/* Bit position Macro */
1176+/* macro for bit set and clear */
1177+#define BITSET(variable, bit) ((variable) | (1 << bit))
1178+#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit)))
1179+#define SET_BIT_INPUTRAM 28
1180+#define SET_BIT_CBLIN 29
1181+#define SET_BIT_INPTYP 27
1182+#define SET_BIT_YCPOS 26
1183+#define INPUT_RAM 1
1184+#define UP_RSZ_RATIO 64
1185+#define DOWN_RSZ_RATIO 512
1186+#define UP_RSZ_RATIO1 513
1187+#define DOWN_RSZ_RATIO1 1024
1188+#define RSZ_IN_SIZE_VERT_SHIFT 16
1189+#define MAX_HORZ_PIXEL_8BIT 31
1190+#define MAX_HORZ_PIXEL_16BIT 15
1191+#define NUM_PHASES 8
1192+#define NUM_TAPS 4
1193+#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x,
1194+ * number of phases
1195+ */
1196+#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x,
1197+ * number of taps
1198+ */
1199+#define ALIGN32 32
1200+#define MAX_COEF_COUNTER 16
1201+#define COEFF_ADDRESS_OFFSET 0x04
1202+
1203+/* Global structure which contains information about number of channels
1204+ and protection variables */
1205+struct device_params {
1206+
1207+ unsigned char opened; /* state of the device */
1208+ struct completion compl_isr; /* Completion for interrupt */
1209+ struct mutex reszwrap_mutex; /* Semaphore for array */
1210+
1211+ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
1212+};
1213+
1214+/* Register mapped structure which contains the every register
1215+ information */
1216+struct resizer_config {
1217+ u32 rsz_pcr; /* pcr register mapping
1218+ * variable.
1219+ */
1220+ u32 rsz_in_start; /* in_start register mapping
1221+ * variable.
1222+ */
1223+ u32 rsz_in_size; /* in_size register mapping
1224+ * variable.
1225+ */
1226+ u32 rsz_out_size; /* out_size register mapping
1227+ * variable.
1228+ */
1229+ u32 rsz_cnt; /* rsz_cnt register mapping
1230+ * variable.
1231+ */
1232+ u32 rsz_sdr_inadd; /* sdr_inadd register mapping
1233+ * variable.
1234+ */
1235+ u32 rsz_sdr_inoff; /* sdr_inoff register mapping
1236+ * variable.
1237+ */
1238+ u32 rsz_sdr_outadd; /* sdr_outadd register mapping
1239+ * variable.
1240+ */
1241+ u32 rsz_sdr_outoff; /* sdr_outbuff register
1242+ * mapping variable.
1243+ */
1244+ u32 rsz_coeff_horz[16]; /* horizontal coefficients
1245+ * mapping array.
1246+ */
1247+ u32 rsz_coeff_vert[16]; /* vertical coefficients
1248+ * mapping array.
1249+ */
1250+ u32 rsz_yehn; /* yehn(luma)register mapping
1251+ * variable.
1252+ */
1253+};
1254+
1255+struct rsz_mult {
1256+ int in_hsize; /* input frame horizontal
1257+ * size.
1258+ */
1259+ int in_vsize; /* input frame vertical size.
1260+ */
1261+ int out_hsize; /* output frame horizontal
1262+ * size.
1263+ */
1264+ int out_vsize; /* output frame vertical
1265+ * size.
1266+ */
1267+ int in_pitch; /* offset between two rows of
1268+ * input frame.
1269+ */
1270+ int out_pitch; /* offset between two rows of
1271+ * output frame.
1272+ */
1273+ int end_hsize;
1274+ int end_vsize;
1275+ int num_htap; /* 0 = 7tap; 1 = 4tap */
1276+ int num_vtap; /* 0 = 7tap; 1 = 4tap */
1277+ int active;
1278+ int inptyp;
1279+ int vrsz;
1280+ int hrsz;
1281+ int hstph; /* for specifying horizontal
1282+ * starting phase.
1283+ */
1284+ int vstph;
1285+ int pix_fmt; /* # defined, UYVY or YUYV. */
1286+ int cbilin; /* # defined, filter with luma
1287+ * or bi-linear.
1288+ */
1289+ u16 tap4filt_coeffs[32]; /* horizontal filter
1290+ * coefficients.
1291+ */
1292+ u16 tap7filt_coeffs[32]; /* vertical filter
1293+ * coefficients.
1294+ */
1295+};
1296+/* Channel specific structure contains information regarding
1297+ the every channel */
1298+struct channel_config {
1299+ struct resizer_config register_config; /* Instance of register set
1300+ * mapping structure
1301+ */
1302+ int status; /* Specifies whether the
1303+ * channel is busy or not
1304+ */
1305+ struct mutex chanprotection_mutex;
1306+ enum config_done config_state;
1307+ u8 input_buf_index;
1308+ u8 output_buf_index;
1309+
1310+};
1311+
1312+/* per-filehandle data structure */
1313+struct rsz_fh {
1314+ struct rsz_params *params;
1315+ struct channel_config *config;
1316+ struct rsz_mult *multipass; /* Multipass to support
1317+ * resizing ration outside
1318+ * of 0.25x to 4x
1319+ */
1320+ spinlock_t vbq_lock; /* spinlock for videobuf
1321+ * queues.
1322+ */
1323+ enum v4l2_buf_type type;
1324+ struct videobuf_queue vbq;
1325+ struct device_params *device;
1326+
1327+ dma_addr_t isp_addr_read; /* Input/Output address */
1328+ dma_addr_t isp_addr_write; /* Input/Output address */
1329+ u32 rsz_bufsize; /* channel specific buffersize
1330+ */
1331+};
1332+
1333+static struct device_params *device_config;
1334+static struct device *rsz_device;
1335+static int rsz_major = -1;
1336+/* functions declaration */
1337+static void rsz_hardware_setup(struct channel_config *rsz_conf_chan);
1338+static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *,
1339+ struct channel_config *);
1340+static int rsz_get_params(struct rsz_params *, struct channel_config *);
1341+static void rsz_copy_data(struct rsz_mult *multipass,
1342+ struct rsz_params *params);
1343+static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1,
1344+ void *arg2);
1345+static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
1346+ struct rsz_cropsize *cropsize);
1347+static int rsz_set_multipass(struct rsz_mult *multipass,
1348+ struct channel_config *rsz_conf_chan);
1349+static int rsz_set_ratio(struct rsz_mult *multipass,
1350+ struct channel_config *rsz_conf_chan);
1351+static void rsz_config_ratio(struct rsz_mult *multipass,
1352+ struct channel_config *rsz_conf_chan);
1353+
1354+/**
1355+ * rsz_hardware_setup - Sets hardware configuration registers
1356+ * @rsz_conf_chan: Structure containing channel configuration
1357+ *
1358+ * Set hardware configuration registers
1359+ **/
1360+static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
1361+{
1362+ int coeffcounter;
1363+ int coeffoffset = 0;
1364+
1365+ omap_writel(rsz_conf_chan->register_config.rsz_cnt,
1366+ OMAP3ISP_RESZ_REG(ISPRSZ_CNT));
1367+
1368+ omap_writel(rsz_conf_chan->register_config.rsz_in_start,
1369+ OMAP3ISP_RESZ_REG(ISPRSZ_IN_START));
1370+ omap_writel(rsz_conf_chan->register_config.rsz_in_size,
1371+ OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE));
1372+
1373+ omap_writel(rsz_conf_chan->register_config.rsz_out_size,
1374+ OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE));
1375+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd,
1376+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD));
1377+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff,
1378+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF));
1379+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd,
1380+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD));
1381+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff,
1382+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF));
1383+ omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH));
1384+
1385+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
1386+ coeffcounter++) {
1387+ omap_writel(rsz_conf_chan->register_config.
1388+ rsz_coeff_horz[coeffcounter],
1389+ OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10
1390+ + coeffoffset));
1391+
1392+ omap_writel(rsz_conf_chan->register_config.
1393+ rsz_coeff_vert[coeffcounter],
1394+ OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10
1395+ + coeffoffset));
1396+ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
1397+ }
1398+}
1399+
1400+/**
1401+ * rsz_start - Enables Resizer Wrapper
1402+ * @arg: Currently not used.
1403+ * @device: Structure containing ISP resizer wrapper global information
1404+ *
1405+ * Submits a resizing task specified by the rsz_resize structure. The call can
1406+ * either be blocked until the task is completed or returned immediately based
1407+ * on the value of the blocking argument in the rsz_resize structure. If it is
1408+ * blocking, the status of the task can be checked by calling ioctl
1409+ * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
1410+ *
1411+ * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
1412+ * event or the state of the channel is not configured.
1413+ **/
1414+int rsz_start(int *arg, struct rsz_fh *fh)
1415+{
1416+ struct channel_config *rsz_conf_chan = fh->config;
1417+ struct rsz_mult *multipass = fh->multipass;
1418+ struct videobuf_queue *q = &fh->vbq;
1419+ int ret;
1420+
1421+ if (rsz_conf_chan->config_state) {
1422+ dev_err(rsz_device, "State not configured \n");
1423+ goto err_einval;
1424+ }
1425+
1426+ rsz_conf_chan->status = CHANNEL_BUSY;
1427+
1428+ rsz_hardware_setup(rsz_conf_chan);
1429+
1430+ if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
1431+ (void *)NULL)) {
1432+ dev_err(rsz_device, "No callback for RSZR\n");
1433+ goto err_einval;
1434+ }
1435+mult:
1436+ device_config->compl_isr.done = 0;
1437+
1438+ ispresizer_enable(1);
1439+
1440+ ret = wait_for_completion_interruptible(&device_config->compl_isr);
1441+ if (ret != 0) {
1442+ dev_dbg(rsz_device, "Unexpected exit from "
1443+ "wait_for_completion_interruptible\n");
1444+ wait_for_completion(&device_config->compl_isr);
1445+ }
1446+
1447+ if (multipass->active) {
1448+ rsz_set_multipass(multipass, rsz_conf_chan);
1449+ goto mult;
1450+ }
1451+
1452+ if (fh->isp_addr_read) {
1453+ ispmmu_vunmap(fh->isp_addr_read);
1454+ fh->isp_addr_read = 0;
1455+ }
1456+ if (fh->isp_addr_write) {
1457+ ispmmu_vunmap(fh->isp_addr_write);
1458+ fh->isp_addr_write = 0;
1459+ }
1460+
1461+ rsz_conf_chan->status = CHANNEL_FREE;
1462+ q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
1463+ q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
1464+ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
1465+ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
1466+
1467+ /* Unmap and free the DMA memory allocated for buffers */
1468+ videobuf_dma_unmap(q, videobuf_to_dma(
1469+ q->bufs[rsz_conf_chan->input_buf_index]));
1470+ videobuf_dma_unmap(q, videobuf_to_dma(
1471+ q->bufs[rsz_conf_chan->output_buf_index]));
1472+ videobuf_dma_free(videobuf_to_dma(
1473+ q->bufs[rsz_conf_chan->input_buf_index]));
1474+ videobuf_dma_free(videobuf_to_dma(
1475+ q->bufs[rsz_conf_chan->output_buf_index]));
1476+
1477+ isp_unset_callback(CBK_RESZ_DONE);
1478+
1479+ return 0;
1480+err_einval:
1481+ return -EINVAL;
1482+}
1483+
1484+/**
1485+ * rsz_set_multipass - Set resizer multipass
1486+ * @rsz_conf_chan: Structure containing channel configuration
1487+ *
1488+ * Returns always 0
1489+ **/
1490+static int rsz_set_multipass(struct rsz_mult *multipass,
1491+ struct channel_config *rsz_conf_chan)
1492+{
1493+ multipass->in_hsize = multipass->out_hsize;
1494+ multipass->in_vsize = multipass->out_vsize;
1495+ multipass->out_hsize = multipass->end_hsize;
1496+ multipass->out_vsize = multipass->end_vsize;
1497+
1498+ multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize
1499+ : (multipass->out_hsize * 2));
1500+ multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize
1501+ : (multipass->in_hsize * 2));
1502+
1503+ rsz_set_ratio(multipass, rsz_conf_chan);
1504+ rsz_config_ratio(multipass, rsz_conf_chan);
1505+ rsz_hardware_setup(rsz_conf_chan);
1506+ return 0;
1507+}
1508+
1509+/**
1510+ * rsz_copy_data - Copy data
1511+ * @params: Structure containing the Resizer Wrapper parameters
1512+ *
1513+ * Copy data
1514+ **/
1515+static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
1516+{
1517+ int i;
1518+ multipass->in_hsize = params->in_hsize;
1519+ multipass->in_vsize = params->in_vsize;
1520+ multipass->out_hsize = params->out_hsize;
1521+ multipass->out_vsize = params->out_vsize;
1522+ multipass->end_hsize = params->out_hsize;
1523+ multipass->end_vsize = params->out_vsize;
1524+ multipass->in_pitch = params->in_pitch;
1525+ multipass->out_pitch = params->out_pitch;
1526+ multipass->hstph = params->hstph;
1527+ multipass->vstph = params->vstph;
1528+ multipass->inptyp = params->inptyp;
1529+ multipass->pix_fmt = params->pix_fmt;
1530+ multipass->cbilin = params->cbilin;
1531+
1532+ for (i = 0; i < 32; i++) {
1533+ multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i];
1534+ multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i];
1535+ }
1536+}
1537+
1538+/**
1539+ * rsz_set_params - Set parameters for resizer wrapper
1540+ * @params: Structure containing the Resizer Wrapper parameters
1541+ * @rsz_conf_chan: Structure containing channel configuration
1542+ *
1543+ * Used to set the parameters of the Resizer hardware, including input and
1544+ * output image size, horizontal and vertical poly-phase filter coefficients,
1545+ * luma enchancement filter coefficients, etc.
1546+ **/
1547+static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
1548+ struct channel_config *rsz_conf_chan)
1549+{
1550+ int mul = 1;
1551+ if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) {
1552+ dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n");
1553+ return -EINVAL;
1554+ }
1555+ if ((params->in_vsize <= 0) || (params->in_hsize <= 0) ||
1556+ (params->out_vsize <= 0) || (params->out_hsize <= 0) ||
1557+ (params->in_pitch <= 0) || (params->out_pitch <= 0)) {
1558+ dev_err(rsz_device, "rsz_set_params: Invalid size params\n");
1559+ return -EINVAL;
1560+ }
1561+ if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) &&
1562+ (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) {
1563+ dev_err(rsz_device, "rsz_set_params: Invalid input type\n");
1564+ return -EINVAL;
1565+ }
1566+ if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) &&
1567+ (params->pix_fmt != RSZ_PIX_FMT_YUYV)) {
1568+ dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n");
1569+ return -EINVAL;
1570+ }
1571+ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
1572+ mul = 2;
1573+ else
1574+ mul = 1;
1575+ if (params->in_pitch < (params->in_hsize * mul)) {
1576+ dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n");
1577+ return -EINVAL;
1578+ }
1579+ if (params->out_pitch < (params->out_hsize * mul)) {
1580+ dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less"
1581+ " than out hsize\n");
1582+ return -EINVAL;
1583+ }
1584+ /* Output H size should be even */
1585+ if ((params->out_hsize % PIXEL_EVEN) != 0) {
1586+ dev_err(rsz_device, "rsz_set_params: Output H size should"
1587+ " be even\n");
1588+ return -EINVAL;
1589+ }
1590+ if (params->horz_starting_pixel < 0) {
1591+ dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot"
1592+ " be less than zero\n");
1593+ return -EINVAL;
1594+ }
1595+
1596+ rsz_copy_data(multipass, params);
1597+ if (0 != rsz_set_ratio(multipass, rsz_conf_chan))
1598+ goto err_einval;
1599+
1600+ if (params->yenh_params.type) {
1601+ if ((multipass->num_htap && multipass->out_hsize >
1602+ 1280) ||
1603+ (!multipass->num_htap && multipass->out_hsize >
1604+ 640))
1605+ goto err_einval;
1606+ }
1607+
1608+ if (INPUT_RAM)
1609+ params->vert_starting_pixel = 0;
1610+
1611+ rsz_conf_chan->register_config.rsz_in_start =
1612+ (params->vert_starting_pixel
1613+ << ISPRSZ_IN_SIZE_VERT_SHIFT)
1614+ & ISPRSZ_IN_SIZE_VERT_MASK;
1615+
1616+ if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
1617+ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT)
1618+ goto err_einval;
1619+ }
1620+ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) {
1621+ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT)
1622+ goto err_einval;
1623+ }
1624+
1625+ rsz_conf_chan->register_config.rsz_in_start |=
1626+ params->horz_starting_pixel
1627+ & ISPRSZ_IN_START_HORZ_ST_MASK;
1628+
1629+ rsz_conf_chan->register_config.rsz_yehn =
1630+ (params->yenh_params.type
1631+ << ISPRSZ_YENH_ALGO_SHIFT)
1632+ & ISPRSZ_YENH_ALGO_MASK;
1633+
1634+ if (params->yenh_params.type) {
1635+ rsz_conf_chan->register_config.rsz_yehn |=
1636+ params->yenh_params.core
1637+ & ISPRSZ_YENH_CORE_MASK;
1638+
1639+ rsz_conf_chan->register_config.rsz_yehn |=
1640+ (params->yenh_params.gain
1641+ << ISPRSZ_YENH_GAIN_SHIFT)
1642+ & ISPRSZ_YENH_GAIN_MASK;
1643+
1644+ rsz_conf_chan->register_config.rsz_yehn |=
1645+ (params->yenh_params.slop
1646+ << ISPRSZ_YENH_SLOP_SHIFT)
1647+ & ISPRSZ_YENH_SLOP_MASK;
1648+ }
1649+
1650+ rsz_config_ratio(multipass, rsz_conf_chan);
1651+
1652+ rsz_conf_chan->config_state = STATE_CONFIGURED;
1653+
1654+ return 0;
1655+err_einval:
1656+ return -EINVAL;
1657+}
1658+
1659+/**
1660+ * rsz_set_ratio - Set ratio
1661+ * @rsz_conf_chan: Structure containing channel configuration
1662+ *
1663+ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
1664+ * being requested, or other ratio configuration value is out of bounds
1665+ **/
1666+static int rsz_set_ratio(struct rsz_mult *multipass,
1667+ struct channel_config *rsz_conf_chan)
1668+{
1669+ int alignment = 0;
1670+
1671+ rsz_conf_chan->register_config.rsz_cnt = 0;
1672+
1673+ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
1674+ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
1675+ dev_err(rsz_device, "Invalid output size!");
1676+ goto err_einval;
1677+ }
1678+ if (multipass->cbilin) {
1679+ rsz_conf_chan->register_config.rsz_cnt =
1680+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1681+ SET_BIT_CBLIN);
1682+ }
1683+ if (INPUT_RAM) {
1684+ rsz_conf_chan->register_config.rsz_cnt =
1685+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1686+ SET_BIT_INPUTRAM);
1687+ }
1688+ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
1689+ rsz_conf_chan->register_config.rsz_cnt =
1690+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1691+ SET_BIT_INPTYP);
1692+ } else {
1693+ rsz_conf_chan->register_config.rsz_cnt =
1694+ BITRESET(rsz_conf_chan->register_config.
1695+ rsz_cnt, SET_BIT_INPTYP);
1696+
1697+ if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) {
1698+ rsz_conf_chan->register_config.rsz_cnt =
1699+ BITRESET(rsz_conf_chan->register_config.
1700+ rsz_cnt, SET_BIT_YCPOS);
1701+ } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) {
1702+ rsz_conf_chan->register_config.rsz_cnt =
1703+ BITSET(rsz_conf_chan->register_config.
1704+ rsz_cnt, SET_BIT_YCPOS);
1705+ }
1706+
1707+ }
1708+ multipass->vrsz =
1709+ (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize;
1710+ multipass->hrsz =
1711+ (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize;
1712+ if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) {
1713+ dev_err(rsz_device, "Upscaling ratio not supported!");
1714+ goto err_einval;
1715+ }
1716+ multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER
1717+ / (multipass->out_vsize - 1);
1718+ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
1719+ * RATIO_MULTIPLIER) /
1720+ (multipass->out_hsize - 1);
1721+
1722+ if (multipass->hrsz <= 512) {
1723+ multipass->hrsz = (multipass->in_hsize - NUM_TAPS)
1724+ * RATIO_MULTIPLIER
1725+ / (multipass->out_hsize - 1);
1726+ if (multipass->hrsz < 64)
1727+ multipass->hrsz = 64;
1728+ if (multipass->hrsz > 512)
1729+ multipass->hrsz = 512;
1730+ if (multipass->hstph > NUM_PHASES)
1731+ goto err_einval;
1732+ multipass->num_htap = 1;
1733+ } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) {
1734+ if (multipass->hstph > NUM_D2PH)
1735+ goto err_einval;
1736+ multipass->num_htap = 0;
1737+ }
1738+
1739+ if (multipass->vrsz <= 512) {
1740+ multipass->vrsz = (multipass->in_vsize - NUM_TAPS)
1741+ * RATIO_MULTIPLIER
1742+ / (multipass->out_vsize - 1);
1743+ if (multipass->vrsz < 64)
1744+ multipass->vrsz = 64;
1745+ if (multipass->vrsz > 512)
1746+ multipass->vrsz = 512;
1747+ if (multipass->vstph > NUM_PHASES)
1748+ goto err_einval;
1749+ multipass->num_vtap = 1;
1750+ } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) {
1751+ if (multipass->vstph > NUM_D2PH)
1752+ goto err_einval;
1753+ multipass->num_vtap = 0;
1754+ }
1755+
1756+ if ((multipass->in_pitch) % ALIGN32) {
1757+ dev_err(rsz_device, "Invalid input pitch: %d \n",
1758+ multipass->in_pitch);
1759+ goto err_einval;
1760+ }
1761+ if ((multipass->out_pitch) % ALIGN32) {
1762+ dev_err(rsz_device, "Invalid output pitch %d \n",
1763+ multipass->out_pitch);
1764+ goto err_einval;
1765+ }
1766+
1767+ if (multipass->vrsz < 256 &&
1768+ (multipass->in_vsize < multipass->out_vsize)) {
1769+ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT)
1770+ alignment = ALIGNMENT;
1771+ else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
1772+ alignment = (ALIGNMENT / 2);
1773+ else
1774+ dev_err(rsz_device, "Invalid input type\n");
1775+
1776+ if (!(((multipass->out_hsize % PIXEL_EVEN) == 0)
1777+ && (multipass->out_hsize % alignment) == 0)) {
1778+ dev_err(rsz_device, "wrong hsize\n");
1779+ goto err_einval;
1780+ }
1781+ }
1782+ if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) {
1783+ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
1784+ dev_err(rsz_device, "wrong width\n");
1785+ goto err_einval;
1786+ }
1787+ multipass->active = 0;
1788+
1789+ } else if (multipass->hrsz > 1024) {
1790+ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
1791+ dev_err(rsz_device, "wrong width\n");
1792+ goto err_einval;
1793+ }
1794+ if (multipass->hstph > NUM_D2PH)
1795+ goto err_einval;
1796+ multipass->num_htap = 0;
1797+ multipass->out_hsize = multipass->in_hsize * 256 / 1024;
1798+ if (multipass->out_hsize % ALIGN32) {
1799+ multipass->out_hsize +=
1800+ abs((multipass->out_hsize % ALIGN32) - ALIGN32);
1801+ }
1802+ multipass->out_pitch = ((multipass->inptyp) ?
1803+ multipass->out_hsize :
1804+ (multipass->out_hsize * 2));
1805+ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
1806+ * RATIO_MULTIPLIER)
1807+ / (multipass->out_hsize - 1);
1808+ multipass->active = 1;
1809+
1810+ }
1811+
1812+ if (multipass->vrsz > 1024) {
1813+ if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) {
1814+ dev_err(rsz_device, "wrong width\n");
1815+ goto err_einval;
1816+ }
1817+
1818+ multipass->out_vsize = multipass->in_vsize * 256 / 1024;
1819+ multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS)
1820+ * RATIO_MULTIPLIER)
1821+ / (multipass->out_vsize - 1);
1822+ multipass->active = 1;
1823+ multipass->num_vtap = 0;
1824+
1825+ }
1826+ rsz_conf_chan->register_config.rsz_out_size =
1827+ multipass->out_hsize
1828+ & ISPRSZ_OUT_SIZE_HORZ_MASK;
1829+
1830+ rsz_conf_chan->register_config.rsz_out_size |=
1831+ (multipass->out_vsize
1832+ << ISPRSZ_OUT_SIZE_VERT_SHIFT)
1833+ & ISPRSZ_OUT_SIZE_VERT_MASK;
1834+
1835+ rsz_conf_chan->register_config.rsz_sdr_inoff =
1836+ multipass->in_pitch
1837+ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
1838+
1839+ rsz_conf_chan->register_config.rsz_sdr_outoff =
1840+ multipass->out_pitch
1841+ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
1842+
1843+ if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
1844+ if (multipass->hstph > NUM_PHASES)
1845+ goto err_einval;
1846+ } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
1847+ if (multipass->hstph > NUM_D2PH)
1848+ goto err_einval;
1849+ }
1850+
1851+ rsz_conf_chan->register_config.rsz_cnt |=
1852+ (multipass->hstph
1853+ << ISPRSZ_CNT_HSTPH_SHIFT)
1854+ & ISPRSZ_CNT_HSTPH_MASK;
1855+
1856+ if (multipass->vrsz >= 64 && multipass->hrsz <= 512) {
1857+ if (multipass->vstph > NUM_PHASES)
1858+ goto err_einval;
1859+ } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) {
1860+ if (multipass->vstph > NUM_D2PH)
1861+ goto err_einval;
1862+ }
1863+
1864+ rsz_conf_chan->register_config.rsz_cnt |=
1865+ (multipass->vstph
1866+ << ISPRSZ_CNT_VSTPH_SHIFT)
1867+ & ISPRSZ_CNT_VSTPH_MASK;
1868+
1869+ rsz_conf_chan->register_config.rsz_cnt |=
1870+ (multipass->hrsz - 1)
1871+ & ISPRSZ_CNT_HRSZ_MASK;
1872+
1873+ rsz_conf_chan->register_config.rsz_cnt |=
1874+ ((multipass->vrsz - 1)
1875+ << ISPRSZ_CNT_VRSZ_SHIFT)
1876+ & ISPRSZ_CNT_VRSZ_MASK;
1877+
1878+ return 0;
1879+err_einval:
1880+ return -EINVAL;
1881+}
1882+
1883+/**
1884+ * rsz_config_ratio - Configure ratio
1885+ * @rsz_conf_chan: Structure containing channel configuration
1886+ *
1887+ * Configure ratio
1888+ **/
1889+static void rsz_config_ratio(struct rsz_mult *multipass,
1890+ struct channel_config *rsz_conf_chan)
1891+{
1892+ int hsize;
1893+ int vsize;
1894+ int coeffcounter;
1895+
1896+ if (multipass->hrsz <= 512) {
1897+ hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1)
1898+ * multipass->hrsz + 16) >> 8) + 7;
1899+ } else {
1900+ hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1)
1901+ * multipass->hrsz + 32) >> 8) + 7;
1902+ }
1903+ if (multipass->vrsz <= 512) {
1904+ vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1)
1905+ * multipass->vrsz + 16) >> 8) + 4;
1906+ } else {
1907+ vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1)
1908+ * multipass->vrsz + 32) >> 8) + 7;
1909+ }
1910+ rsz_conf_chan->register_config.rsz_in_size = hsize;
1911+
1912+ rsz_conf_chan->register_config.rsz_in_size |=
1913+ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
1914+ & ISPRSZ_IN_SIZE_VERT_MASK);
1915+
1916+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
1917+ coeffcounter++) {
1918+ if (multipass->num_htap) {
1919+ rsz_conf_chan->register_config.
1920+ rsz_coeff_horz[coeffcounter] =
1921+ (multipass->tap4filt_coeffs[2
1922+ * coeffcounter]
1923+ & ISPRSZ_HFILT10_COEF0_MASK);
1924+ rsz_conf_chan->register_config.
1925+ rsz_coeff_horz[coeffcounter] |=
1926+ ((multipass->tap4filt_coeffs[2
1927+ * coeffcounter + 1]
1928+ << ISPRSZ_HFILT10_COEF1_SHIFT)
1929+ & ISPRSZ_HFILT10_COEF1_MASK);
1930+ } else {
1931+ rsz_conf_chan->register_config.
1932+ rsz_coeff_horz[coeffcounter] =
1933+ (multipass->tap7filt_coeffs[2
1934+ * coeffcounter]
1935+ & ISPRSZ_HFILT10_COEF0_MASK);
1936+
1937+ rsz_conf_chan->register_config.
1938+ rsz_coeff_horz[coeffcounter] |=
1939+ ((multipass->tap7filt_coeffs[2
1940+ * coeffcounter + 1]
1941+ << ISPRSZ_HFILT10_COEF1_SHIFT)
1942+ & ISPRSZ_HFILT10_COEF1_MASK);
1943+ }
1944+
1945+ if (multipass->num_vtap) {
1946+ rsz_conf_chan->register_config.
1947+ rsz_coeff_vert[coeffcounter] =
1948+ (multipass->tap4filt_coeffs[2
1949+ * coeffcounter]
1950+ & ISPRSZ_VFILT10_COEF0_MASK);
1951+
1952+ rsz_conf_chan->register_config.
1953+ rsz_coeff_vert[coeffcounter] |=
1954+ ((multipass->tap4filt_coeffs[2
1955+ * coeffcounter + 1]
1956+ << ISPRSZ_VFILT10_COEF1_SHIFT) &
1957+ ISPRSZ_VFILT10_COEF1_MASK);
1958+ } else {
1959+ rsz_conf_chan->register_config.
1960+ rsz_coeff_vert[coeffcounter] =
1961+ (multipass->tap7filt_coeffs[2
1962+ * coeffcounter]
1963+ & ISPRSZ_VFILT10_COEF0_MASK);
1964+ rsz_conf_chan->register_config.
1965+ rsz_coeff_vert[coeffcounter] |=
1966+ ((multipass->tap7filt_coeffs[2
1967+ * coeffcounter + 1]
1968+ << ISPRSZ_VFILT10_COEF1_SHIFT)
1969+ & ISPRSZ_VFILT10_COEF1_MASK);
1970+ }
1971+ }
1972+}
1973+
1974+/**
1975+ * rsz_get_params - Gets the parameter values
1976+ * @params: Structure containing the Resizer Wrapper parameters
1977+ * @rsz_conf_chan: Structure containing channel configuration
1978+ *
1979+ * Used to get the Resizer hardware settings associated with the
1980+ * current logical channel represented by fd.
1981+ **/
1982+static int rsz_get_params(struct rsz_params *params,
1983+ struct channel_config *rsz_conf_chan)
1984+{
1985+ int coeffcounter;
1986+
1987+ if (rsz_conf_chan->config_state) {
1988+ dev_err(rsz_device, "state not configured\n");
1989+ return -EINVAL;
1990+ }
1991+
1992+ params->in_hsize = rsz_conf_chan->register_config.rsz_in_size
1993+ & ISPRSZ_IN_SIZE_HORZ_MASK;
1994+ params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size
1995+ & ISPRSZ_IN_SIZE_VERT_MASK)
1996+ >> ISPRSZ_IN_SIZE_VERT_SHIFT;
1997+
1998+ params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff
1999+ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
2000+
2001+ params->out_hsize = rsz_conf_chan->register_config.rsz_out_size
2002+ & ISPRSZ_OUT_SIZE_HORZ_MASK;
2003+
2004+ params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size
2005+ & ISPRSZ_OUT_SIZE_VERT_MASK)
2006+ >> ISPRSZ_OUT_SIZE_VERT_SHIFT;
2007+
2008+ params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff
2009+ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
2010+
2011+ params->cbilin = (rsz_conf_chan->register_config.rsz_cnt
2012+ & SET_BIT_CBLIN) >> SET_BIT_CBLIN;
2013+
2014+ params->inptyp = (rsz_conf_chan->register_config.rsz_cnt
2015+ & ISPRSZ_CNT_INPTYP_MASK)
2016+ >> SET_BIT_INPTYP;
2017+ params->horz_starting_pixel = ((rsz_conf_chan->register_config.
2018+ rsz_in_start
2019+ & ISPRSZ_IN_START_HORZ_ST_MASK));
2020+ params->vert_starting_pixel = ((rsz_conf_chan->register_config.
2021+ rsz_in_start
2022+ & ISPRSZ_IN_START_VERT_ST_MASK)
2023+ >> ISPRSZ_IN_START_VERT_ST_SHIFT);
2024+
2025+ params->hstph = ((rsz_conf_chan->register_config.rsz_cnt
2026+ & ISPRSZ_CNT_HSTPH_MASK
2027+ >> ISPRSZ_CNT_HSTPH_SHIFT));
2028+ params->vstph = ((rsz_conf_chan->register_config.rsz_cnt
2029+ & ISPRSZ_CNT_VSTPH_MASK
2030+ >> ISPRSZ_CNT_VSTPH_SHIFT));
2031+
2032+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
2033+ coeffcounter++) {
2034+ params->tap4filt_coeffs[2 * coeffcounter] =
2035+ rsz_conf_chan->register_config.
2036+ rsz_coeff_horz[coeffcounter]
2037+ & ISPRSZ_HFILT10_COEF0_MASK;
2038+
2039+ params->tap4filt_coeffs[2 * coeffcounter + 1] =
2040+ (rsz_conf_chan->register_config.
2041+ rsz_coeff_horz[coeffcounter]
2042+ & ISPRSZ_HFILT10_COEF1_MASK)
2043+ >> ISPRSZ_HFILT10_COEF1_SHIFT;
2044+
2045+ params->tap7filt_coeffs[2 * coeffcounter] =
2046+ rsz_conf_chan->register_config.
2047+ rsz_coeff_vert[coeffcounter]
2048+ & ISPRSZ_VFILT10_COEF0_MASK;
2049+
2050+ params->tap7filt_coeffs[2 * coeffcounter + 1] =
2051+ (rsz_conf_chan->register_config.
2052+ rsz_coeff_vert[coeffcounter]
2053+ & ISPRSZ_VFILT10_COEF1_MASK)
2054+ >> ISPRSZ_VFILT10_COEF1_SHIFT;
2055+
2056+ }
2057+
2058+ params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn
2059+ & ISPRSZ_YENH_ALGO_MASK)
2060+ >> ISPRSZ_YENH_ALGO_SHIFT;
2061+
2062+ params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn
2063+ & ISPRSZ_YENH_CORE_MASK;
2064+
2065+ params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn
2066+ & ISPRSZ_YENH_GAIN_MASK)
2067+ >> ISPRSZ_YENH_GAIN_SHIFT;
2068+
2069+ params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn
2070+ & ISPRSZ_YENH_SLOP_MASK)
2071+ >> ISPRSZ_YENH_SLOP_SHIFT;
2072+
2073+ params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt
2074+ & ISPRSZ_CNT_PIXFMT_MASK)
2075+ >> SET_BIT_YCPOS);
2076+
2077+ if (params->pix_fmt)
2078+ params->pix_fmt = RSZ_PIX_FMT_UYVY;
2079+ else
2080+ params->pix_fmt = RSZ_PIX_FMT_YUYV;
2081+
2082+ return 0;
2083+}
2084+
2085+/**
2086+ * rsz_calculate_crop - Calculate Crop values
2087+ * @rsz_conf_chan: Structure containing channel configuration
2088+ * @cropsize: Structure containing crop parameters
2089+ *
2090+ * Calculate Crop values
2091+ **/
2092+static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
2093+ struct rsz_cropsize *cropsize)
2094+{
2095+ int luma_enable;
2096+
2097+ cropsize->hcrop = 0;
2098+ cropsize->vcrop = 0;
2099+
2100+ luma_enable = (rsz_conf_chan->register_config.rsz_yehn
2101+ & ISPRSZ_YENH_ALGO_MASK)
2102+ >> ISPRSZ_YENH_ALGO_SHIFT;
2103+
2104+ if (luma_enable)
2105+ cropsize->hcrop += 2;
2106+}
2107+
2108+/**
2109+ * rsz_vbq_release - Videobuffer queue release
2110+ * @q: Structure containing the videobuffer queue file handle, and device
2111+ * structure which contains the actual configuration.
2112+ * @vb: Structure containing the videobuffer used for resizer processing.
2113+ **/
2114+static void rsz_vbq_release(struct videobuf_queue *q,
2115+ struct videobuf_buffer *vb)
2116+{
2117+ int i;
2118+ struct rsz_fh *fh = q->priv_data;
2119+
2120+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
2121+ struct videobuf_dmabuf *dma = NULL;
2122+ if (!q->bufs[i])
2123+ continue;
2124+ if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
2125+ continue;
2126+ dma = videobuf_to_dma(q->bufs[i]);
2127+ videobuf_dma_unmap(q, dma);
2128+ videobuf_dma_free(dma);
2129+ }
2130+
2131+ ispmmu_vunmap(fh->isp_addr_read);
2132+ ispmmu_vunmap(fh->isp_addr_write);
2133+ fh->isp_addr_read = 0;
2134+ fh->isp_addr_write = 0;
2135+ spin_lock(&fh->vbq_lock);
2136+ vb->state = VIDEOBUF_NEEDS_INIT;
2137+ spin_unlock(&fh->vbq_lock);
2138+
2139+}
2140+
2141+/**
2142+ * rsz_vbq_setup - Sets up the videobuffer size and validates count.
2143+ * @q: Structure containing the videobuffer queue file handle, and device
2144+ * structure which contains the actual configuration.
2145+ * @cnt: Number of buffers requested
2146+ * @size: Size in bytes of the buffer used for previewing
2147+ *
2148+ * Always returns 0.
2149+ **/
2150+static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt,
2151+ unsigned int *size)
2152+{
2153+ struct rsz_fh *fh = q->priv_data;
2154+ struct rsz_mult *multipass = fh->multipass;
2155+ u32 insize, outsize;
2156+
2157+ spin_lock(&fh->vbq_lock);
2158+ if (*cnt <= 0)
2159+ *cnt = VIDEO_MAX_FRAME;
2160+
2161+ if (*cnt > VIDEO_MAX_FRAME)
2162+ *cnt = VIDEO_MAX_FRAME;
2163+
2164+ outsize = multipass->out_pitch * multipass->out_vsize;
2165+ insize = multipass->in_pitch * multipass->in_vsize;
2166+ if (*cnt == 1 && (outsize > insize)) {
2167+ dev_err(rsz_device, "2 buffers are required for Upscaling "
2168+ "mode\n");
2169+ goto err_einval;
2170+ }
2171+ if (!fh->params->in_hsize || !fh->params->in_vsize) {
2172+ dev_err(rsz_device, "Can't setup buffer size\n");
2173+ goto err_einval;
2174+ } else {
2175+ if (outsize > insize)
2176+ *size = outsize;
2177+ else
2178+ *size = insize;
2179+
2180+ fh->rsz_bufsize = *size;
2181+ }
2182+ spin_unlock(&fh->vbq_lock);
2183+
2184+ return 0;
2185+err_einval:
2186+ spin_unlock(&fh->vbq_lock);
2187+ return -EINVAL;
2188+}
2189+
2190+/**
2191+ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
2192+ * @q: Structure containing the videobuffer queue file handle, and device
2193+ * structure which contains the actual configuration.
2194+ * @vb: Structure containing the videobuffer used for resizer processing.
2195+ * @field: Type of field to set in videobuffer device.
2196+ *
2197+ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
2198+ * -EIO if the ISP MMU mapping fails
2199+ **/
2200+static int rsz_vbq_prepare(struct videobuf_queue *q,
2201+ struct videobuf_buffer *vb,
2202+ enum v4l2_field field)
2203+{
2204+ struct rsz_fh *fh = q->priv_data;
2205+ struct channel_config *rsz_conf_chan = fh->config;
2206+ struct rsz_mult *multipass = fh->multipass;
2207+ int err = 0;
2208+ unsigned int isp_addr, insize, outsize;
2209+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
2210+
2211+ spin_lock(&fh->vbq_lock);
2212+ if (vb->baddr) {
2213+ vb->size = fh->rsz_bufsize;
2214+ vb->bsize = fh->rsz_bufsize;
2215+ } else {
2216+ spin_unlock(&fh->vbq_lock);
2217+ dev_err(rsz_device, "No user buffer allocated\n");
2218+ goto out;
2219+ }
2220+ if (vb->i) {
2221+ vb->width = fh->params->out_hsize;
2222+ vb->height = fh->params->out_vsize;
2223+ } else {
2224+ vb->width = fh->params->in_hsize;
2225+ vb->height = fh->params->in_vsize;
2226+ }
2227+
2228+ vb->field = field;
2229+ spin_unlock(&fh->vbq_lock);
2230+
2231+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
2232+ err = videobuf_iolock(q, vb, NULL);
2233+ if (!err) {
2234+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
2235+ if (!isp_addr)
2236+ err = -EIO;
2237+ else {
2238+ if (vb->i) {
2239+ rsz_conf_chan->register_config.
2240+ rsz_sdr_outadd
2241+ = isp_addr;
2242+ fh->isp_addr_write = isp_addr;
2243+ rsz_conf_chan->output_buf_index = vb->i;
2244+ } else {
2245+ rsz_conf_chan->register_config.
2246+ rsz_sdr_inadd
2247+ = isp_addr;
2248+ rsz_conf_chan->input_buf_index = vb->i;
2249+ outsize = multipass->out_pitch *
2250+ multipass->out_vsize;
2251+ insize = multipass->in_pitch *
2252+ multipass->in_vsize;
2253+ if (outsize < insize) {
2254+ rsz_conf_chan->register_config.
2255+ rsz_sdr_outadd
2256+ = isp_addr;
2257+ rsz_conf_chan->
2258+ output_buf_index =
2259+ vb->i;
2260+ }
2261+
2262+ fh->isp_addr_read = isp_addr;
2263+ }
2264+ }
2265+ }
2266+
2267+ }
2268+
2269+ if (!err) {
2270+ spin_lock(&fh->vbq_lock);
2271+ vb->state = VIDEOBUF_PREPARED;
2272+ spin_unlock(&fh->vbq_lock);
2273+ flush_cache_user_range(NULL, vb->baddr, (vb->baddr
2274+ + vb->bsize));
2275+ } else
2276+ rsz_vbq_release(q, vb);
2277+
2278+out:
2279+ return err;
2280+}
2281+
2282+static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
2283+{
2284+ return;
2285+}
2286+
2287+/**
2288+ * rsz_open - Initializes and opens the Resizer Wrapper
2289+ * @inode: Inode structure associated with the Resizer Wrapper
2290+ * @filp: File structure associated with the Resizer Wrapper
2291+ *
2292+ * Returns 0 if successful, -EBUSY if its already opened or the ISP module is
2293+ * not available, or -ENOMEM if its unable to allocate the device in kernel
2294+ * space memory.
2295+ **/
2296+static int rsz_open(struct inode *inode, struct file *filp)
2297+{
2298+ int ret = 0;
2299+ struct channel_config *rsz_conf_chan;
2300+ struct rsz_fh *fh;
2301+ struct device_params *device = device_config;
2302+ struct rsz_params *params;
2303+ struct rsz_mult *multipass;
2304+
2305+ if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) {
2306+ printk(KERN_DEBUG "omap-resizer: Device is opened in "
2307+ "non blocking mode\n");
2308+ } else {
2309+ printk(KERN_DEBUG "omap-resizer: Device is opened in blocking "
2310+ "mode\n");
2311+ }
2312+ fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL);
2313+ if (NULL == fh)
2314+ return -ENOMEM;
2315+
2316+ isp_get();
2317+
2318+ rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL);
2319+ if (rsz_conf_chan == NULL) {
2320+ dev_err(rsz_device, "\n cannot allocate memory to config");
2321+ ret = -ENOMEM;
2322+ goto err_enomem0;
2323+ }
2324+ params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL);
2325+ if (params == NULL) {
2326+ dev_err(rsz_device, "\n cannot allocate memory to params");
2327+ ret = -ENOMEM;
2328+ goto err_enomem1;
2329+ }
2330+ multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL);
2331+ if (multipass == NULL) {
2332+ dev_err(rsz_device, "\n cannot allocate memory to multipass");
2333+ ret = -ENOMEM;
2334+ goto err_enomem2;
2335+ }
2336+
2337+ fh->multipass = multipass;
2338+ fh->params = params;
2339+ fh->config = rsz_conf_chan;
2340+
2341+ if (mutex_lock_interruptible(&device->reszwrap_mutex)) {
2342+ ret = -EINTR;
2343+ goto err_enomem2;
2344+ }
2345+ device->opened++;
2346+ mutex_unlock(&device->reszwrap_mutex);
2347+
2348+ rsz_conf_chan->config_state = STATE_NOT_CONFIGURED;
2349+ rsz_conf_chan->status = CHANNEL_FREE;
2350+
2351+ filp->private_data = fh;
2352+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2353+ fh->device = device;
2354+
2355+ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
2356+ &fh->vbq_lock, fh->type,
2357+ V4L2_FIELD_NONE,
2358+ sizeof(struct videobuf_buffer), fh);
2359+
2360+ spin_lock_init(&fh->vbq_lock);
2361+ mutex_init(&rsz_conf_chan->chanprotection_mutex);
2362+
2363+ return 0;
2364+err_enomem2:
2365+ kfree(params);
2366+err_enomem1:
2367+ kfree(rsz_conf_chan);
2368+err_enomem0:
2369+ kfree(fh);
2370+ return ret;
2371+}
2372+
2373+/**
2374+ * rsz_release - Releases Resizer Wrapper and frees up allocated memory
2375+ * @inode: Inode structure associated with the Resizer Wrapper
2376+ * @filp: File structure associated with the Resizer Wrapper
2377+ *
2378+ * Returns 0 if successful, or -EBUSY if channel is being used.
2379+ **/
2380+static int rsz_release(struct inode *inode, struct file *filp)
2381+{
2382+ u32 timeout = 0;
2383+ struct rsz_fh *fh = filp->private_data;
2384+ struct channel_config *rsz_conf_chan = fh->config;
2385+ struct rsz_params *params = fh->params;
2386+ struct rsz_mult *multipass = fh->multipass;
2387+ struct videobuf_queue *q = &fh->vbq;
2388+
2389+ while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) {
2390+ timeout++;
2391+ schedule();
2392+ }
2393+ if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
2394+ return -EINTR;
2395+ device_config->opened--;
2396+ mutex_unlock(&device_config->reszwrap_mutex);
2397+ /* This will Free memory allocated to the buffers,
2398+ * and flushes the queue
2399+ */
2400+ videobuf_queue_cancel(q);
2401+ fh->params = NULL;
2402+ fh->config = NULL;
2403+
2404+ fh->rsz_bufsize = 0;
2405+ filp->private_data = NULL;
2406+
2407+ kfree(rsz_conf_chan);
2408+ kfree(params);
2409+ kfree(multipass);
2410+ kfree(fh);
2411+
2412+ isp_put();
2413+
2414+ return 0;
2415+}
2416+
2417+/**
2418+ * rsz_mmap - Memory maps the Resizer Wrapper module.
2419+ * @file: File structure associated with the Resizer Wrapper
2420+ * @vma: Virtual memory area structure.
2421+ *
2422+ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
2423+ * function.
2424+ **/
2425+static int rsz_mmap(struct file *file, struct vm_area_struct *vma)
2426+{
2427+ struct rsz_fh *fh = file->private_data;
2428+
2429+ return videobuf_mmap_mapper(&fh->vbq, vma);
2430+}
2431+
2432+/**
2433+ * rsz_ioctl - I/O control function for Resizer Wrapper
2434+ * @inode: Inode structure associated with the Resizer Wrapper.
2435+ * @file: File structure associated with the Resizer Wrapper.
2436+ * @cmd: Type of command to execute.
2437+ * @arg: Argument to send to requested command.
2438+ *
2439+ * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command
2440+ * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user()
2441+ * fails, -EINVAL if parameter validation fails or parameter structure is not
2442+ * present.
2443+ **/
2444+static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
2445+ unsigned long arg)
2446+{
2447+ int ret = 0;
2448+ struct rsz_fh *fh = file->private_data;
2449+ struct device_params *device = fh->device;
2450+ struct channel_config *rsz_conf_chan = fh->config;
2451+
2452+ if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE)
2453+ || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) {
2454+ dev_err(rsz_device, "Bad command value \n");
2455+ return -1;
2456+ }
2457+
2458+ if (_IOC_DIR(cmd) & _IOC_READ)
2459+ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
2460+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
2461+ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
2462+
2463+ if (ret) {
2464+ dev_err(rsz_device, "Access denied\n");
2465+ return -1;
2466+ }
2467+
2468+ switch (cmd) {
2469+ case RSZ_REQBUF:
2470+ {
2471+ struct v4l2_requestbuffers req_buf;
2472+ if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg,
2473+ sizeof(struct v4l2_requestbuffers))) {
2474+ return -EFAULT;
2475+ }
2476+ if (mutex_lock_interruptible(&rsz_conf_chan->
2477+ chanprotection_mutex))
2478+ return -EINTR;
2479+ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
2480+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2481+ break;
2482+ }
2483+ case RSZ_QUERYBUF:
2484+ {
2485+ struct v4l2_buffer buf;
2486+ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
2487+ sizeof(struct v4l2_buffer))) {
2488+ return -EFAULT;
2489+ }
2490+ if (mutex_lock_interruptible(&rsz_conf_chan->
2491+ chanprotection_mutex))
2492+ return -EINTR;
2493+ ret = videobuf_querybuf(&fh->vbq, (void *)&buf);
2494+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2495+ if (copy_to_user((struct v4l2_buffer *)arg, &buf,
2496+ sizeof(struct v4l2_buffer)))
2497+ return -EFAULT;
2498+ break;
2499+ }
2500+ case RSZ_QUEUEBUF:
2501+ {
2502+ struct v4l2_buffer buf;
2503+ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
2504+ sizeof(struct v4l2_buffer))) {
2505+ return -EFAULT;
2506+ }
2507+ if (mutex_lock_interruptible(&rsz_conf_chan->
2508+ chanprotection_mutex))
2509+ return -EINTR;
2510+ ret = videobuf_qbuf(&fh->vbq, (void *)&buf);
2511+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2512+ break;
2513+ }
2514+ case RSZ_S_PARAM:
2515+ {
2516+ struct rsz_params *params = fh->params;
2517+ if (copy_from_user(params, (struct rsz_params *)arg,
2518+ sizeof(struct rsz_params))) {
2519+ return -EFAULT;
2520+ }
2521+ if (mutex_lock_interruptible(&rsz_conf_chan->
2522+ chanprotection_mutex))
2523+ return -EINTR;
2524+ ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
2525+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2526+ break;
2527+ }
2528+ case RSZ_G_PARAM:
2529+ ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan);
2530+ break;
2531+
2532+ case RSZ_G_STATUS:
2533+ {
2534+ struct rsz_status *status;
2535+ status = (struct rsz_status *)arg;
2536+ status->chan_busy = rsz_conf_chan->status;
2537+ status->hw_busy = ispresizer_busy();
2538+ status->src = INPUT_RAM;
2539+ break;
2540+ }
2541+ case RSZ_RESIZE:
2542+ if (file->f_flags & O_NONBLOCK) {
2543+ if (ispresizer_busy())
2544+ return -EBUSY;
2545+ else {
2546+ if (!mutex_trylock(&device->reszwrap_mutex))
2547+ return -EBUSY;
2548+ }
2549+ } else {
2550+ if (mutex_lock_interruptible(&device->reszwrap_mutex))
2551+ return -EINTR;
2552+ }
2553+ ret = rsz_start((int *)arg, fh);
2554+ mutex_unlock(&device->reszwrap_mutex);
2555+ break;
2556+ case RSZ_GET_CROPSIZE:
2557+ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
2558+ break;
2559+
2560+ default:
2561+ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
2562+ return -EINVAL;
2563+ }
2564+
2565+ return (long)ret;
2566+}
2567+
2568+static struct file_operations rsz_fops = {
2569+ .owner = THIS_MODULE,
2570+ .open = rsz_open,
2571+ .release = rsz_release,
2572+ .mmap = rsz_mmap,
2573+ .unlocked_ioctl = rsz_unlocked_ioctl,
2574+};
2575+
2576+/**
2577+ * rsz_isr - Interrupt Service Routine for Resizer wrapper
2578+ * @status: ISP IRQ0STATUS register value
2579+ * @arg1: Currently not used
2580+ * @arg2: Currently not used
2581+ *
2582+ * Interrupt Service Routine for Resizer wrapper
2583+ **/
2584+static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
2585+{
2586+
2587+ if ((status & RESZ_DONE) != RESZ_DONE)
2588+ return;
2589+
2590+ complete(&(device_config->compl_isr));
2591+
2592+}
2593+
2594+/**
2595+ * resizer_platform_release - Acts when Reference count is zero
2596+ * @device: Structure containing ISP resizer wrapper global information
2597+ *
2598+ * This is called when the reference count goes to zero.
2599+ **/
2600+static void resizer_platform_release(struct device *device)
2601+{
2602+}
2603+
2604+/**
2605+ * resizer_probe - Checks for device presence
2606+ * @device: Structure containing details of the current device.
2607+ *
2608+ * Always returns 0.
2609+ **/
2610+static int __init resizer_probe(struct platform_device *device)
2611+{
2612+ return 0;
2613+}
2614+
2615+/**
2616+ * resizer_remove - Handles the removal of the driver
2617+ * @omap_resizer_device: Structure containing details of the current device.
2618+ *
2619+ * Always returns 0.
2620+ **/
2621+static int resizer_remove(struct platform_device *omap_resizer_device)
2622+{
2623+ return 0;
2624+}
2625+
2626+static struct class *rsz_class;
2627+static struct cdev c_dev;
2628+static dev_t dev;
2629+static struct platform_device omap_resizer_device = {
2630+ .name = OMAP_REZR_NAME,
2631+ .id = 2,
2632+ .dev = {
2633+ .release = resizer_platform_release,}
2634+};
2635+
2636+static struct platform_driver omap_resizer_driver = {
2637+ .probe = resizer_probe,
2638+ .remove = resizer_remove,
2639+ .driver = {
2640+ .bus = &platform_bus_type,
2641+ .name = OMAP_REZR_NAME,
2642+ },
2643+};
2644+
2645+/**
2646+ * omap_rsz_init - Initialization of Resizer Wrapper
2647+ *
2648+ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
2649+ * could not register the wrapper as a character device, or other errors if the
2650+ * device or driver can't register.
2651+ **/
2652+static int __init omap_rsz_init(void)
2653+{
2654+ int ret = 0;
2655+ struct device_params *device;
2656+ device = kzalloc(sizeof(struct device_params), GFP_KERNEL);
2657+ if (!device) {
2658+ dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate "
2659+ "memory\n");
2660+ return -ENOMEM;
2661+ }
2662+
2663+ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
2664+ if (ret < 0) {
2665+ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
2666+ "Could not allocate region "
2667+ "for character device\n");
2668+ kfree(device);
2669+ return -ENODEV;
2670+ }
2671+
2672+ /* Register the driver in the kernel */
2673+ /* Initialize of character device */
2674+ cdev_init(&c_dev, &rsz_fops);
2675+ c_dev.owner = THIS_MODULE;
2676+ c_dev.ops = &rsz_fops;
2677+
2678+ /* Addding character device */
2679+ ret = cdev_add(&c_dev, dev, 1);
2680+ if (ret) {
2681+ dev_err(rsz_device, OMAP_REZR_NAME ": Error adding "
2682+ "device - %d\n", ret);
2683+ goto fail2;
2684+ }
2685+ rsz_major = MAJOR(dev);
2686+
2687+ /* register driver as a platform driver */
2688+ ret = platform_driver_register(&omap_resizer_driver);
2689+ if (ret) {
2690+ dev_err(rsz_device, OMAP_REZR_NAME
2691+ ": Failed to register platform driver!\n");
2692+ goto fail3;
2693+ }
2694+
2695+ /* Register the drive as a platform device */
2696+ ret = platform_device_register(&omap_resizer_device);
2697+ if (ret) {
2698+ dev_err(rsz_device, OMAP_REZR_NAME
2699+ ": Failed to register platform device!\n");
2700+ goto fail4;
2701+ }
2702+
2703+ rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME);
2704+ if (!rsz_class) {
2705+ dev_err(rsz_device, OMAP_REZR_NAME
2706+ ": Failed to create class!\n");
2707+ goto fail5;
2708+ }
2709+
2710+ /* make entry in the devfs */
2711+ rsz_device = device_create(rsz_class, rsz_device,
2712+ MKDEV(rsz_major, 0), NULL,
2713+ OMAP_REZR_NAME);
2714+ dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n");
2715+ device->opened = 0;
2716+
2717+ device->vbq_ops.buf_setup = rsz_vbq_setup;
2718+ device->vbq_ops.buf_prepare = rsz_vbq_prepare;
2719+ device->vbq_ops.buf_release = rsz_vbq_release;
2720+ device->vbq_ops.buf_queue = rsz_vbq_queue;
2721+ init_completion(&device->compl_isr);
2722+ mutex_init(&device->reszwrap_mutex);
2723+
2724+ device_config = device;
2725+ return 0;
2726+
2727+fail5:
2728+ platform_device_unregister(&omap_resizer_device);
2729+fail4:
2730+ platform_driver_unregister(&omap_resizer_driver);
2731+fail3:
2732+ cdev_del(&c_dev);
2733+fail2:
2734+ unregister_chrdev_region(dev, 1);
2735+ kfree(device);
2736+ return ret;
2737+}
2738+
2739+/**
2740+ * omap_rsz_exit - Close of Resizer Wrapper
2741+ **/
2742+void __exit omap_rsz_exit(void)
2743+{
2744+ device_destroy(rsz_class, dev);
2745+ class_destroy(rsz_class);
2746+ platform_device_unregister(&omap_resizer_device);
2747+ platform_driver_unregister(&omap_resizer_driver);
2748+ cdev_del(&c_dev);
2749+ unregister_chrdev_region(dev, 1);
2750+ kfree(device_config);
2751+}
2752+
2753+module_init(omap_rsz_init)
2754+module_exit(omap_rsz_exit)
2755+
2756+MODULE_AUTHOR("Texas Instruments");
2757+MODULE_DESCRIPTION("OMAP ISP Resizer");
2758+MODULE_LICENSE("GPL");
2759diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
2760new file mode 100644
2761index 0000000..5ac0c88
2762--- /dev/null
2763+++ b/include/linux/omap_resizer.h
2764@@ -0,0 +1,136 @@
2765+/*
2766+ * drivers/media/video/isp/omap_resizer.h
2767+ *
2768+ * Include file for Resizer module wrapper in TI's OMAP3430 ISP
2769+ *
2770+ * Copyright (C) 2008 Texas Instruments, Inc.
2771+ *
2772+ * This package is free software; you can redistribute it and/or modify
2773+ * it under the terms of the GNU General Public License version 2 as
2774+ * published by the Free Software Foundation.
2775+ *
2776+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2777+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2778+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2779+ */
2780+
2781+#ifndef OMAP_RESIZER_H
2782+#define OMAP_RESIZER_H
2783+
2784+#include <linux/types.h>
2785+
2786+/* ioctls definition */
2787+#define RSZ_IOC_BASE 'R'
2788+#define RSZ_IOC_MAXNR 8
2789+
2790+/*Ioctl options which are to be passed while calling the ioctl*/
2791+#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
2792+ struct v4l2_requestbuffers)
2793+#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer)
2794+#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params)
2795+#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params)
2796+#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32)
2797+#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
2798+#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
2799+#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
2800+
2801+#define RSZ_INTYPE_YCBCR422_16BIT 0
2802+#define RSZ_INTYPE_PLANAR_8BIT 1
2803+#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */
2804+#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */
2805+
2806+enum config_done {
2807+ STATE_CONFIGURED, /* Resizer driver configured
2808+ * by application.
2809+ */
2810+ STATE_NOT_CONFIGURED /* Resizer driver not
2811+ * configured by application.
2812+ */
2813+};
2814+
2815+/* Structure Definitions */
2816+
2817+/* used to luma enhancement options */
2818+
2819+struct rsz_yenh {
2820+ __s32 type; /* represents luma enable or
2821+ * disable.
2822+ */
2823+ __u8 gain; /* represents gain. */
2824+ __u8 slop; /* represents slop. */
2825+ __u8 core; /* Represents core value. */
2826+};
2827+
2828+/* Conatins all the parameters for resizing. This structure
2829+ * is used to configure resiser parameters
2830+ */
2831+struct rsz_params {
2832+ __s32 in_hsize; /* input frame horizontal
2833+ * size.
2834+ */
2835+ __s32 in_vsize; /* input frame vertical size */
2836+ __s32 in_pitch; /* offset between two rows of
2837+ * input frame.
2838+ */
2839+ __s32 inptyp; /* for determining 16 bit or
2840+ * 8 bit data.
2841+ */
2842+ __s32 vert_starting_pixel; /* for specifying vertical
2843+ * starting pixel in input.
2844+ */
2845+ __s32 horz_starting_pixel; /* for specyfing horizontal
2846+ * starting pixel in input.
2847+ */
2848+ __s32 cbilin; /* # defined, filter with luma
2849+ * or bi-linear interpolation.
2850+ */
2851+ __s32 pix_fmt; /* # defined, UYVY or YUYV */
2852+ __s32 out_hsize; /* output frame horizontal
2853+ * size.
2854+ */
2855+ __s32 out_vsize; /* output frame vertical
2856+ * size.
2857+ */
2858+ __s32 out_pitch; /* offset between two rows of
2859+ * output frame.
2860+ */
2861+ __s32 hstph; /* for specifying horizontal
2862+ * starting phase.
2863+ */
2864+ __s32 vstph; /* for specifying vertical
2865+ * starting phase.
2866+ */
2867+ __u16 tap4filt_coeffs[32]; /* horizontal filter
2868+ * coefficients.
2869+ */
2870+ __u16 tap7filt_coeffs[32]; /* vertical filter
2871+ * coefficients.
2872+ */
2873+ struct rsz_yenh yenh_params;
2874+};
2875+
2876+/* Contains the status of hardware and channel */
2877+struct rsz_status {
2878+ __s32 chan_busy; /* 1: channel is busy,
2879+ * 0: channel is not busy
2880+ */
2881+ __s32 hw_busy; /* 1: hardware is busy,
2882+ * 0: hardware is not busy
2883+ */
2884+ __s32 src; /* # defined, can be either
2885+ * SD-RAM or CCDC/PREVIEWER
2886+ */
2887+};
2888+
2889+/* Passed by application for getting crop size */
2890+struct rsz_cropsize {
2891+ __u32 hcrop; /* Number of pixels per line
2892+ * cropped in output image.
2893+ */
2894+
2895+ __u32 vcrop; /* Number of lines cropped
2896+ * in output image.
2897+ */
2898+};
2899+
2900+#endif
2901--
29021.6.0.3
2903
2904--- /tmp/Kconfig 2009-04-06 10:56:27.000000000 +0200
2905+++ git/drivers/media/video/Kconfig 2009-04-06 10:57:25.000000000 +0200
2906@@ -711,6 +711,9 @@
2907 CMOS camera controller. This is the controller found on first-
2908 generation OLPC systems.
2909
2910+
2911+source "drivers/media/video/isp/Kconfig"
2912+
2913 config VIDEO_OMAP3
2914 tristate "OMAP 3 Camera support"
2915 select VIDEOBUF_GEN