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:
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