summaryrefslogtreecommitdiff
path: root/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2009-07-26 19:02:41 +0200
committerKoen Kooi <koen@openembedded.org>2009-07-26 19:02:41 +0200
commit8ffb44d28592bc95e4aa235501b381f1086aecb5 (patch)
tree73a957f7943fa632d63462a210109ca1ae4ac66d /recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer
parent156b83943190a7b9b3b85f35bee1378c4c6e9d9c (diff)
linux-kexecboot: add 2.6.29, currently only supports beagle
Diffstat (limited to 'recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer')
-rw-r--r--recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch1890
-rw-r--r--recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch729
-rw-r--r--recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch36
3 files changed, 2655 insertions, 0 deletions
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
new file mode 100644
index 0000000000..3390599292
--- /dev/null
+++ b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0023-OMAP-Resizer-Basic-Resizer-refreshed-with-latest-gi.patch
@@ -0,0 +1,1890 @@
+From 38f3cd5564a466e5251fc2ff47e0504148922304 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:18:56 +0530
+Subject: [PATCH 23/26] OMAP-Resizer: Basic Resizer refreshed with latest gitorious tree
+
+This is same resizer driver patch posted by Sergio onto
+mailing list quite a some time back. This commit refreshes
+the same patch on top of latest gitorious.org tree.
+
+List of New/Modified files:
+ modified: drivers/media/video/Kconfig
+ modified: drivers/media/video/isp/Makefile
+ modified: drivers/media/video/isp/isp.c
+ modified: drivers/media/video/isp/ispreg.h
+ new file: drivers/media/video/isp/omap_resizer.c
+ new file: include/linux/omap_resizer.h
+
+TODO:
+ - Resizer driver needs to be independent from camera and ISP
+ - Custom patches implemented ontop of PSP1.0.2 release
+ to fix some V4L2-buf layer issues.
+ -
+---
+ drivers/media/video/Kconfig | 7 +
+ drivers/media/video/isp/Makefile | 4 +
+ drivers/media/video/isp/isp.c | 15 +
+ drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++++
+ include/linux/omap_resizer.h | 136 +++
+ 5 files changed, 1796 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/isp/omap_resizer.c
+ create mode 100644 include/linux/omap_resizer.h
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 3cdb5a4..d2b4ae1 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -720,6 +720,13 @@ config VIDEO_OMAP3
+ ---help---
+ Driver for an OMAP 3 camera controller.
+
++config VIDEO_OMAP34XX_ISP_RESIZER
++ tristate "OMAP ISP Resizer"
++ depends on VIDEO_V4L2 && ARCH_OMAP34XX
++ select VIDEOBUF_GEN
++ select VIDEOBUF_DMA_SG
++ select OMAP_IOMMU
++
+ config SOC_CAMERA
+ tristate "SoC camera support"
+ depends on VIDEO_V4L2 && HAS_DMA
+diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
+index f14d617..d171fb9 100644
+--- a/drivers/media/video/isp/Makefile
++++ b/drivers/media/video/isp/Makefile
+@@ -7,6 +7,10 @@ else
+ isp-mod-objs += \
+ isp.o ispccdc.o ispmmu.o \
+ isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
++
++obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
++ omap_resizer.o
++
+ endif
+
+ obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
+diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
+index 54c839b..f1f92b4 100644
+--- a/drivers/media/video/isp/isp.c
++++ b/drivers/media/video/isp/isp.c
+@@ -505,6 +505,12 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ IRQ0ENABLE_PRV_DONE_IRQ);
+ break;
++ case CBK_RESZ_DONE:
++ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ,
++ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ IRQ0ENABLE_RSZ_DONE_IRQ);
++ break;
+ default:
+ break;
+ }
+@@ -556,6 +562,10 @@ int isp_unset_callback(enum isp_callback_type type)
+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
+ ~IRQ0ENABLE_PRV_DONE_IRQ);
+ break;
++ case CBK_RESZ_DONE:
++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
++ ~IRQ0ENABLE_RSZ_DONE_IRQ);
++ break;
+ default:
+ break;
+ }
+@@ -938,6 +948,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
+ if (!ispresizer_busy())
+ ispresizer_config_shadow_registers();
+ isp_buf_process(bufs);
++ } else {
++ if (irqdis->isp_callbk[CBK_RESZ_DONE])
++ irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE,
++ irqdis->isp_callbk_arg1[CBK_RESZ_DONE],
++ irqdis->isp_callbk_arg2[CBK_RESZ_DONE]);
+ }
+ }
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+new file mode 100644
+index 0000000..54bc425
+--- /dev/null
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -0,0 +1,1634 @@
++/*
++ * drivers/media/video/isp/omap_resizer.c
++ *
++ * Wrapper for Resizer module in TI's OMAP3430 ISP
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * Contributors:
++ * Sergio Aguirre <saaguirre@ti.com>
++ * Troy Laramy <t-laramy@ti.com>
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <linux/mutex.h>
++#include <linux/cdev.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/uaccess.h>
++#include <media/v4l2-dev.h>
++#include <asm/cacheflush.h>
++
++#include "isp.h"
++#include "ispmmu.h"
++#include "ispreg.h"
++#include "ispresizer.h"
++#include <linux/omap_resizer.h>
++
++#define OMAP_REZR_NAME "omap-resizer"
++
++/* Defines and Constants*/
++#define MAX_CHANNELS 16
++#define MAX_IMAGE_WIDTH 2047
++#define MAX_IMAGE_WIDTH_HIGH 2047
++#define ALIGNMENT 16
++#define CHANNEL_BUSY 1
++#define CHANNEL_FREE 0
++#define PIXEL_EVEN 2
++#define RATIO_MULTIPLIER 256
++/* Bit position Macro */
++/* macro for bit set and clear */
++#define BITSET(variable, bit) ((variable) | (1 << bit))
++#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit)))
++#define SET_BIT_INPUTRAM 28
++#define SET_BIT_CBLIN 29
++#define SET_BIT_INPTYP 27
++#define SET_BIT_YCPOS 26
++#define INPUT_RAM 1
++#define UP_RSZ_RATIO 64
++#define DOWN_RSZ_RATIO 512
++#define UP_RSZ_RATIO1 513
++#define DOWN_RSZ_RATIO1 1024
++#define RSZ_IN_SIZE_VERT_SHIFT 16
++#define MAX_HORZ_PIXEL_8BIT 31
++#define MAX_HORZ_PIXEL_16BIT 15
++#define NUM_PHASES 8
++#define NUM_TAPS 4
++#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x,
++ * number of phases
++ */
++#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x,
++ * number of taps
++ */
++#define ALIGN32 32
++#define MAX_COEF_COUNTER 16
++#define COEFF_ADDRESS_OFFSET 0x04
++
++/* Global structure which contains information about number of channels
++ and protection variables */
++struct device_params {
++
++ unsigned char opened; /* state of the device */
++ struct completion compl_isr; /* Completion for interrupt */
++ struct mutex reszwrap_mutex; /* Semaphore for array */
++
++ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
++};
++
++/* Register mapped structure which contains the every register
++ information */
++struct resizer_config {
++ u32 rsz_pcr; /* pcr register mapping
++ * variable.
++ */
++ u32 rsz_in_start; /* in_start register mapping
++ * variable.
++ */
++ u32 rsz_in_size; /* in_size register mapping
++ * variable.
++ */
++ u32 rsz_out_size; /* out_size register mapping
++ * variable.
++ */
++ u32 rsz_cnt; /* rsz_cnt register mapping
++ * variable.
++ */
++ u32 rsz_sdr_inadd; /* sdr_inadd register mapping
++ * variable.
++ */
++ u32 rsz_sdr_inoff; /* sdr_inoff register mapping
++ * variable.
++ */
++ u32 rsz_sdr_outadd; /* sdr_outadd register mapping
++ * variable.
++ */
++ u32 rsz_sdr_outoff; /* sdr_outbuff register
++ * mapping variable.
++ */
++ u32 rsz_coeff_horz[16]; /* horizontal coefficients
++ * mapping array.
++ */
++ u32 rsz_coeff_vert[16]; /* vertical coefficients
++ * mapping array.
++ */
++ u32 rsz_yehn; /* yehn(luma)register mapping
++ * variable.
++ */
++};
++
++struct rsz_mult {
++ int in_hsize; /* input frame horizontal
++ * size.
++ */
++ int in_vsize; /* input frame vertical size.
++ */
++ int out_hsize; /* output frame horizontal
++ * size.
++ */
++ int out_vsize; /* output frame vertical
++ * size.
++ */
++ int in_pitch; /* offset between two rows of
++ * input frame.
++ */
++ int out_pitch; /* offset between two rows of
++ * output frame.
++ */
++ int end_hsize;
++ int end_vsize;
++ int num_htap; /* 0 = 7tap; 1 = 4tap */
++ int num_vtap; /* 0 = 7tap; 1 = 4tap */
++ int active;
++ int inptyp;
++ int vrsz;
++ int hrsz;
++ int hstph; /* for specifying horizontal
++ * starting phase.
++ */
++ int vstph;
++ int pix_fmt; /* # defined, UYVY or YUYV. */
++ int cbilin; /* # defined, filter with luma
++ * or bi-linear.
++ */
++ u16 tap4filt_coeffs[32]; /* horizontal filter
++ * coefficients.
++ */
++ u16 tap7filt_coeffs[32]; /* vertical filter
++ * coefficients.
++ */
++};
++/* Channel specific structure contains information regarding
++ the every channel */
++struct channel_config {
++ struct resizer_config register_config; /* Instance of register set
++ * mapping structure
++ */
++ int status; /* Specifies whether the
++ * channel is busy or not
++ */
++ struct mutex chanprotection_mutex;
++ enum config_done config_state;
++ u8 input_buf_index;
++ u8 output_buf_index;
++
++};
++
++/* per-filehandle data structure */
++struct rsz_fh {
++ struct rsz_params *params;
++ struct channel_config *config;
++ struct rsz_mult *multipass; /* Multipass to support
++ * resizing ration outside
++ * of 0.25x to 4x
++ */
++ spinlock_t vbq_lock; /* spinlock for videobuf
++ * queues.
++ */
++ enum v4l2_buf_type type;
++ struct videobuf_queue vbq;
++ struct device_params *device;
++
++ dma_addr_t isp_addr_read; /* Input/Output address */
++ dma_addr_t isp_addr_write; /* Input/Output address */
++ u32 rsz_bufsize; /* channel specific buffersize
++ */
++};
++
++static struct device_params *device_config;
++static struct device *rsz_device;
++static int rsz_major = -1;
++/* functions declaration */
++static void rsz_hardware_setup(struct channel_config *rsz_conf_chan);
++static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *,
++ struct channel_config *);
++static int rsz_get_params(struct rsz_params *, struct channel_config *);
++static void rsz_copy_data(struct rsz_mult *multipass,
++ struct rsz_params *params);
++static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1,
++ void *arg2);
++static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
++ struct rsz_cropsize *cropsize);
++static int rsz_set_multipass(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++static int rsz_set_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++static void rsz_config_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan);
++
++/**
++ * rsz_hardware_setup - Sets hardware configuration registers
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Set hardware configuration registers
++ **/
++static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
++{
++ int coeffcounter;
++ int coeffoffset = 0;
++
++ omap_writel(rsz_conf_chan->register_config.rsz_cnt,
++ OMAP3ISP_RESZ_REG(ISPRSZ_CNT));
++
++ omap_writel(rsz_conf_chan->register_config.rsz_in_start,
++ OMAP3ISP_RESZ_REG(ISPRSZ_IN_START));
++ omap_writel(rsz_conf_chan->register_config.rsz_in_size,
++ OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE));
++
++ omap_writel(rsz_conf_chan->register_config.rsz_out_size,
++ OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD));
++ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff,
++ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF));
++ omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH));
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ omap_writel(rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter],
++ OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10
++ + coeffoffset));
++
++ omap_writel(rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter],
++ OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10
++ + coeffoffset));
++ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
++ }
++}
++
++/**
++ * rsz_start - Enables Resizer Wrapper
++ * @arg: Currently not used.
++ * @device: Structure containing ISP resizer wrapper global information
++ *
++ * Submits a resizing task specified by the rsz_resize structure. The call can
++ * either be blocked until the task is completed or returned immediately based
++ * on the value of the blocking argument in the rsz_resize structure. If it is
++ * blocking, the status of the task can be checked by calling ioctl
++ * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
++ *
++ * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
++ * event or the state of the channel is not configured.
++ **/
++int rsz_start(int *arg, struct rsz_fh *fh)
++{
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_mult *multipass = fh->multipass;
++ struct videobuf_queue *q = &fh->vbq;
++ int ret;
++
++ if (rsz_conf_chan->config_state) {
++ dev_err(rsz_device, "State not configured \n");
++ goto err_einval;
++ }
++
++ rsz_conf_chan->status = CHANNEL_BUSY;
++
++ rsz_hardware_setup(rsz_conf_chan);
++
++ if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
++ (void *)NULL)) {
++ dev_err(rsz_device, "No callback for RSZR\n");
++ goto err_einval;
++ }
++mult:
++ device_config->compl_isr.done = 0;
++
++ ispresizer_enable(1);
++
++ ret = wait_for_completion_interruptible(&device_config->compl_isr);
++ if (ret != 0) {
++ dev_dbg(rsz_device, "Unexpected exit from "
++ "wait_for_completion_interruptible\n");
++ wait_for_completion(&device_config->compl_isr);
++ }
++
++ if (multipass->active) {
++ rsz_set_multipass(multipass, rsz_conf_chan);
++ goto mult;
++ }
++
++ if (fh->isp_addr_read) {
++ ispmmu_unmap(fh->isp_addr_read);
++ fh->isp_addr_read = 0;
++ }
++ if (fh->isp_addr_write) {
++ ispmmu_unmap(fh->isp_addr_write);
++ fh->isp_addr_write = 0;
++ }
++
++ rsz_conf_chan->status = CHANNEL_FREE;
++ q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
++ q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
++ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
++ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
++
++ /* Unmap and free the DMA memory allocated for buffers */
++ videobuf_dma_unmap(q, videobuf_to_dma(
++ q->bufs[rsz_conf_chan->input_buf_index]));
++ videobuf_dma_unmap(q, videobuf_to_dma(
++ q->bufs[rsz_conf_chan->output_buf_index]));
++ videobuf_dma_free(videobuf_to_dma(
++ q->bufs[rsz_conf_chan->input_buf_index]));
++ videobuf_dma_free(videobuf_to_dma(
++ q->bufs[rsz_conf_chan->output_buf_index]));
++
++ isp_unset_callback(CBK_RESZ_DONE);
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_set_multipass - Set resizer multipass
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Returns always 0
++ **/
++static int rsz_set_multipass(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ multipass->in_hsize = multipass->out_hsize;
++ multipass->in_vsize = multipass->out_vsize;
++ multipass->out_hsize = multipass->end_hsize;
++ multipass->out_vsize = multipass->end_vsize;
++
++ multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize
++ : (multipass->out_hsize * 2));
++ multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize
++ : (multipass->in_hsize * 2));
++
++ rsz_set_ratio(multipass, rsz_conf_chan);
++ rsz_config_ratio(multipass, rsz_conf_chan);
++ rsz_hardware_setup(rsz_conf_chan);
++ return 0;
++}
++
++/**
++ * rsz_copy_data - Copy data
++ * @params: Structure containing the Resizer Wrapper parameters
++ *
++ * Copy data
++ **/
++static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
++{
++ int i;
++ multipass->in_hsize = params->in_hsize;
++ multipass->in_vsize = params->in_vsize;
++ multipass->out_hsize = params->out_hsize;
++ multipass->out_vsize = params->out_vsize;
++ multipass->end_hsize = params->out_hsize;
++ multipass->end_vsize = params->out_vsize;
++ multipass->in_pitch = params->in_pitch;
++ multipass->out_pitch = params->out_pitch;
++ multipass->hstph = params->hstph;
++ multipass->vstph = params->vstph;
++ multipass->inptyp = params->inptyp;
++ multipass->pix_fmt = params->pix_fmt;
++ multipass->cbilin = params->cbilin;
++
++ for (i = 0; i < 32; i++) {
++ multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i];
++ multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i];
++ }
++}
++
++/**
++ * rsz_set_params - Set parameters for resizer wrapper
++ * @params: Structure containing the Resizer Wrapper parameters
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Used to set the parameters of the Resizer hardware, including input and
++ * output image size, horizontal and vertical poly-phase filter coefficients,
++ * luma enchancement filter coefficients, etc.
++ **/
++static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
++ struct channel_config *rsz_conf_chan)
++{
++ int mul = 1;
++ if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) {
++ dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n");
++ return -EINVAL;
++ }
++ if ((params->in_vsize <= 0) || (params->in_hsize <= 0) ||
++ (params->out_vsize <= 0) || (params->out_hsize <= 0) ||
++ (params->in_pitch <= 0) || (params->out_pitch <= 0)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid size params\n");
++ return -EINVAL;
++ }
++ if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) &&
++ (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid input type\n");
++ return -EINVAL;
++ }
++ if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) &&
++ (params->pix_fmt != RSZ_PIX_FMT_YUYV)) {
++ dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n");
++ return -EINVAL;
++ }
++ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
++ mul = 2;
++ else
++ mul = 1;
++ if (params->in_pitch < (params->in_hsize * mul)) {
++ dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n");
++ return -EINVAL;
++ }
++ if (params->out_pitch < (params->out_hsize * mul)) {
++ dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less"
++ " than out hsize\n");
++ return -EINVAL;
++ }
++ /* Output H size should be even */
++ if ((params->out_hsize % PIXEL_EVEN) != 0) {
++ dev_err(rsz_device, "rsz_set_params: Output H size should"
++ " be even\n");
++ return -EINVAL;
++ }
++ if (params->horz_starting_pixel < 0) {
++ dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot"
++ " be less than zero\n");
++ return -EINVAL;
++ }
++
++ rsz_copy_data(multipass, params);
++ if (0 != rsz_set_ratio(multipass, rsz_conf_chan))
++ goto err_einval;
++
++ if (params->yenh_params.type) {
++ if ((multipass->num_htap && multipass->out_hsize >
++ 1280) ||
++ (!multipass->num_htap && multipass->out_hsize >
++ 640))
++ goto err_einval;
++ }
++
++ if (INPUT_RAM)
++ params->vert_starting_pixel = 0;
++
++ rsz_conf_chan->register_config.rsz_in_start =
++ (params->vert_starting_pixel
++ << ISPRSZ_IN_SIZE_VERT_SHIFT)
++ & ISPRSZ_IN_SIZE_VERT_MASK;
++
++ if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
++ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT)
++ goto err_einval;
++ }
++ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) {
++ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_in_start |=
++ params->horz_starting_pixel
++ & ISPRSZ_IN_START_HORZ_ST_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn =
++ (params->yenh_params.type
++ << ISPRSZ_YENH_ALGO_SHIFT)
++ & ISPRSZ_YENH_ALGO_MASK;
++
++ if (params->yenh_params.type) {
++ rsz_conf_chan->register_config.rsz_yehn |=
++ params->yenh_params.core
++ & ISPRSZ_YENH_CORE_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn |=
++ (params->yenh_params.gain
++ << ISPRSZ_YENH_GAIN_SHIFT)
++ & ISPRSZ_YENH_GAIN_MASK;
++
++ rsz_conf_chan->register_config.rsz_yehn |=
++ (params->yenh_params.slop
++ << ISPRSZ_YENH_SLOP_SHIFT)
++ & ISPRSZ_YENH_SLOP_MASK;
++ }
++
++ rsz_config_ratio(multipass, rsz_conf_chan);
++
++ rsz_conf_chan->config_state = STATE_CONFIGURED;
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_set_ratio - Set ratio
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
++ * being requested, or other ratio configuration value is out of bounds
++ **/
++static int rsz_set_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ int alignment = 0;
++
++ rsz_conf_chan->register_config.rsz_cnt = 0;
++
++ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
++ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
++ dev_err(rsz_device, "Invalid output size!");
++ goto err_einval;
++ }
++ if (multipass->cbilin) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_CBLIN);
++ }
++ if (INPUT_RAM) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_INPUTRAM);
++ }
++ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.rsz_cnt,
++ SET_BIT_INPTYP);
++ } else {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITRESET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_INPTYP);
++
++ if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITRESET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_YCPOS);
++ } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) {
++ rsz_conf_chan->register_config.rsz_cnt =
++ BITSET(rsz_conf_chan->register_config.
++ rsz_cnt, SET_BIT_YCPOS);
++ }
++
++ }
++ multipass->vrsz =
++ (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize;
++ multipass->hrsz =
++ (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize;
++ if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) {
++ dev_err(rsz_device, "Upscaling ratio not supported!");
++ goto err_einval;
++ }
++ multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER
++ / (multipass->out_vsize - 1);
++ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER) /
++ (multipass->out_hsize - 1);
++
++ if (multipass->hrsz <= 512) {
++ multipass->hrsz = (multipass->in_hsize - NUM_TAPS)
++ * RATIO_MULTIPLIER
++ / (multipass->out_hsize - 1);
++ if (multipass->hrsz < 64)
++ multipass->hrsz = 64;
++ if (multipass->hrsz > 512)
++ multipass->hrsz = 512;
++ if (multipass->hstph > NUM_PHASES)
++ goto err_einval;
++ multipass->num_htap = 1;
++ } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) {
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_htap = 0;
++ }
++
++ if (multipass->vrsz <= 512) {
++ multipass->vrsz = (multipass->in_vsize - NUM_TAPS)
++ * RATIO_MULTIPLIER
++ / (multipass->out_vsize - 1);
++ if (multipass->vrsz < 64)
++ multipass->vrsz = 64;
++ if (multipass->vrsz > 512)
++ multipass->vrsz = 512;
++ if (multipass->vstph > NUM_PHASES)
++ goto err_einval;
++ multipass->num_vtap = 1;
++ } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) {
++ if (multipass->vstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_vtap = 0;
++ }
++
++ if ((multipass->in_pitch) % ALIGN32) {
++ dev_err(rsz_device, "Invalid input pitch: %d \n",
++ multipass->in_pitch);
++ goto err_einval;
++ }
++ if ((multipass->out_pitch) % ALIGN32) {
++ dev_err(rsz_device, "Invalid output pitch %d \n",
++ multipass->out_pitch);
++ goto err_einval;
++ }
++
++ if (multipass->vrsz < 256 &&
++ (multipass->in_vsize < multipass->out_vsize)) {
++ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT)
++ alignment = ALIGNMENT;
++ else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
++ alignment = (ALIGNMENT / 2);
++ else
++ dev_err(rsz_device, "Invalid input type\n");
++
++ if (!(((multipass->out_hsize % PIXEL_EVEN) == 0)
++ && (multipass->out_hsize % alignment) == 0)) {
++ dev_err(rsz_device, "wrong hsize\n");
++ goto err_einval;
++ }
++ }
++ if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) {
++ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++ multipass->active = 0;
++
++ } else if (multipass->hrsz > 1024) {
++ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ multipass->num_htap = 0;
++ multipass->out_hsize = multipass->in_hsize * 256 / 1024;
++ if (multipass->out_hsize % ALIGN32) {
++ multipass->out_hsize +=
++ abs((multipass->out_hsize % ALIGN32) - ALIGN32);
++ }
++ multipass->out_pitch = ((multipass->inptyp) ?
++ multipass->out_hsize :
++ (multipass->out_hsize * 2));
++ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER)
++ / (multipass->out_hsize - 1);
++ multipass->active = 1;
++
++ }
++
++ if (multipass->vrsz > 1024) {
++ if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) {
++ dev_err(rsz_device, "wrong width\n");
++ goto err_einval;
++ }
++
++ multipass->out_vsize = multipass->in_vsize * 256 / 1024;
++ multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS)
++ * RATIO_MULTIPLIER)
++ / (multipass->out_vsize - 1);
++ multipass->active = 1;
++ multipass->num_vtap = 0;
++
++ }
++ rsz_conf_chan->register_config.rsz_out_size =
++ multipass->out_hsize
++ & ISPRSZ_OUT_SIZE_HORZ_MASK;
++
++ rsz_conf_chan->register_config.rsz_out_size |=
++ (multipass->out_vsize
++ << ISPRSZ_OUT_SIZE_VERT_SHIFT)
++ & ISPRSZ_OUT_SIZE_VERT_MASK;
++
++ rsz_conf_chan->register_config.rsz_sdr_inoff =
++ multipass->in_pitch
++ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
++
++ rsz_conf_chan->register_config.rsz_sdr_outoff =
++ multipass->out_pitch
++ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
++
++ if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->hstph > NUM_PHASES)
++ goto err_einval;
++ } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->hstph > NUM_D2PH)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->hstph
++ << ISPRSZ_CNT_HSTPH_SHIFT)
++ & ISPRSZ_CNT_HSTPH_MASK;
++
++ if (multipass->vrsz >= 64 && multipass->hrsz <= 512) {
++ if (multipass->vstph > NUM_PHASES)
++ goto err_einval;
++ } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) {
++ if (multipass->vstph > NUM_D2PH)
++ goto err_einval;
++ }
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->vstph
++ << ISPRSZ_CNT_VSTPH_SHIFT)
++ & ISPRSZ_CNT_VSTPH_MASK;
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ (multipass->hrsz - 1)
++ & ISPRSZ_CNT_HRSZ_MASK;
++
++ rsz_conf_chan->register_config.rsz_cnt |=
++ ((multipass->vrsz - 1)
++ << ISPRSZ_CNT_VRSZ_SHIFT)
++ & ISPRSZ_CNT_VRSZ_MASK;
++
++ return 0;
++err_einval:
++ return -EINVAL;
++}
++
++/**
++ * rsz_config_ratio - Configure ratio
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Configure ratio
++ **/
++static void rsz_config_ratio(struct rsz_mult *multipass,
++ struct channel_config *rsz_conf_chan)
++{
++ int hsize;
++ int vsize;
++ int coeffcounter;
++
++ if (multipass->hrsz <= 512) {
++ hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1)
++ * multipass->hrsz + 16) >> 8) + 7;
++ } else {
++ hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1)
++ * multipass->hrsz + 32) >> 8) + 7;
++ }
++ if (multipass->vrsz <= 512) {
++ vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1)
++ * multipass->vrsz + 16) >> 8) + 4;
++ } else {
++ vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1)
++ * multipass->vrsz + 32) >> 8) + 7;
++ }
++ rsz_conf_chan->register_config.rsz_in_size = hsize;
++
++ rsz_conf_chan->register_config.rsz_in_size |=
++ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
++ & ISPRSZ_IN_SIZE_VERT_MASK);
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ if (multipass->num_htap) {
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] =
++ (multipass->tap4filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK);
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] |=
++ ((multipass->tap4filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_HFILT10_COEF1_SHIFT)
++ & ISPRSZ_HFILT10_COEF1_MASK);
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] =
++ (multipass->tap7filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK);
++
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter] |=
++ ((multipass->tap7filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_HFILT10_COEF1_SHIFT)
++ & ISPRSZ_HFILT10_COEF1_MASK);
++ }
++
++ if (multipass->num_vtap) {
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] =
++ (multipass->tap4filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK);
++
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] |=
++ ((multipass->tap4filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_VFILT10_COEF1_SHIFT) &
++ ISPRSZ_VFILT10_COEF1_MASK);
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] =
++ (multipass->tap7filt_coeffs[2
++ * coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK);
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter] |=
++ ((multipass->tap7filt_coeffs[2
++ * coeffcounter + 1]
++ << ISPRSZ_VFILT10_COEF1_SHIFT)
++ & ISPRSZ_VFILT10_COEF1_MASK);
++ }
++ }
++}
++
++/**
++ * rsz_get_params - Gets the parameter values
++ * @params: Structure containing the Resizer Wrapper parameters
++ * @rsz_conf_chan: Structure containing channel configuration
++ *
++ * Used to get the Resizer hardware settings associated with the
++ * current logical channel represented by fd.
++ **/
++static int rsz_get_params(struct rsz_params *params,
++ struct channel_config *rsz_conf_chan)
++{
++ int coeffcounter;
++
++ if (rsz_conf_chan->config_state) {
++ dev_err(rsz_device, "state not configured\n");
++ return -EINVAL;
++ }
++
++ params->in_hsize = rsz_conf_chan->register_config.rsz_in_size
++ & ISPRSZ_IN_SIZE_HORZ_MASK;
++ params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size
++ & ISPRSZ_IN_SIZE_VERT_MASK)
++ >> ISPRSZ_IN_SIZE_VERT_SHIFT;
++
++ params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff
++ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
++
++ params->out_hsize = rsz_conf_chan->register_config.rsz_out_size
++ & ISPRSZ_OUT_SIZE_HORZ_MASK;
++
++ params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size
++ & ISPRSZ_OUT_SIZE_VERT_MASK)
++ >> ISPRSZ_OUT_SIZE_VERT_SHIFT;
++
++ params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff
++ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
++
++ params->cbilin = (rsz_conf_chan->register_config.rsz_cnt
++ & SET_BIT_CBLIN) >> SET_BIT_CBLIN;
++
++ params->inptyp = (rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_INPTYP_MASK)
++ >> SET_BIT_INPTYP;
++ params->horz_starting_pixel = ((rsz_conf_chan->register_config.
++ rsz_in_start
++ & ISPRSZ_IN_START_HORZ_ST_MASK));
++ params->vert_starting_pixel = ((rsz_conf_chan->register_config.
++ rsz_in_start
++ & ISPRSZ_IN_START_VERT_ST_MASK)
++ >> ISPRSZ_IN_START_VERT_ST_SHIFT);
++
++ params->hstph = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_HSTPH_MASK
++ >> ISPRSZ_CNT_HSTPH_SHIFT));
++ params->vstph = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_VSTPH_MASK
++ >> ISPRSZ_CNT_VSTPH_SHIFT));
++
++ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
++ coeffcounter++) {
++ params->tap4filt_coeffs[2 * coeffcounter] =
++ rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter]
++ & ISPRSZ_HFILT10_COEF0_MASK;
++
++ params->tap4filt_coeffs[2 * coeffcounter + 1] =
++ (rsz_conf_chan->register_config.
++ rsz_coeff_horz[coeffcounter]
++ & ISPRSZ_HFILT10_COEF1_MASK)
++ >> ISPRSZ_HFILT10_COEF1_SHIFT;
++
++ params->tap7filt_coeffs[2 * coeffcounter] =
++ rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter]
++ & ISPRSZ_VFILT10_COEF0_MASK;
++
++ params->tap7filt_coeffs[2 * coeffcounter + 1] =
++ (rsz_conf_chan->register_config.
++ rsz_coeff_vert[coeffcounter]
++ & ISPRSZ_VFILT10_COEF1_MASK)
++ >> ISPRSZ_VFILT10_COEF1_SHIFT;
++
++ }
++
++ params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_ALGO_MASK)
++ >> ISPRSZ_YENH_ALGO_SHIFT;
++
++ params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_CORE_MASK;
++
++ params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_GAIN_MASK)
++ >> ISPRSZ_YENH_GAIN_SHIFT;
++
++ params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_SLOP_MASK)
++ >> ISPRSZ_YENH_SLOP_SHIFT;
++
++ params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt
++ & ISPRSZ_CNT_PIXFMT_MASK)
++ >> SET_BIT_YCPOS);
++
++ if (params->pix_fmt)
++ params->pix_fmt = RSZ_PIX_FMT_UYVY;
++ else
++ params->pix_fmt = RSZ_PIX_FMT_YUYV;
++
++ return 0;
++}
++
++/**
++ * rsz_calculate_crop - Calculate Crop values
++ * @rsz_conf_chan: Structure containing channel configuration
++ * @cropsize: Structure containing crop parameters
++ *
++ * Calculate Crop values
++ **/
++static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
++ struct rsz_cropsize *cropsize)
++{
++ int luma_enable;
++
++ cropsize->hcrop = 0;
++ cropsize->vcrop = 0;
++
++ luma_enable = (rsz_conf_chan->register_config.rsz_yehn
++ & ISPRSZ_YENH_ALGO_MASK)
++ >> ISPRSZ_YENH_ALGO_SHIFT;
++
++ if (luma_enable)
++ cropsize->hcrop += 2;
++}
++
++/**
++ * rsz_vbq_release - Videobuffer queue release
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @vb: Structure containing the videobuffer used for resizer processing.
++ **/
++static void rsz_vbq_release(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ int i;
++ struct rsz_fh *fh = q->priv_data;
++
++ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
++ struct videobuf_dmabuf *dma = NULL;
++ if (!q->bufs[i])
++ continue;
++ if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
++ continue;
++ dma = videobuf_to_dma(q->bufs[i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ }
++
++ ispmmu_unmap(fh->isp_addr_read);
++ ispmmu_unmap(fh->isp_addr_write);
++ fh->isp_addr_read = 0;
++ fh->isp_addr_write = 0;
++ spin_lock(&fh->vbq_lock);
++ vb->state = VIDEOBUF_NEEDS_INIT;
++ spin_unlock(&fh->vbq_lock);
++
++}
++
++/**
++ * rsz_vbq_setup - Sets up the videobuffer size and validates count.
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @cnt: Number of buffers requested
++ * @size: Size in bytes of the buffer used for previewing
++ *
++ * Always returns 0.
++ **/
++static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt,
++ unsigned int *size)
++{
++ struct rsz_fh *fh = q->priv_data;
++ struct rsz_mult *multipass = fh->multipass;
++ u32 insize, outsize;
++
++ spin_lock(&fh->vbq_lock);
++ if (*cnt <= 0)
++ *cnt = VIDEO_MAX_FRAME;
++
++ if (*cnt > VIDEO_MAX_FRAME)
++ *cnt = VIDEO_MAX_FRAME;
++
++ outsize = multipass->out_pitch * multipass->out_vsize;
++ insize = multipass->in_pitch * multipass->in_vsize;
++ if (*cnt == 1 && (outsize > insize)) {
++ dev_err(rsz_device, "2 buffers are required for Upscaling "
++ "mode\n");
++ goto err_einval;
++ }
++ if (!fh->params->in_hsize || !fh->params->in_vsize) {
++ dev_err(rsz_device, "Can't setup buffer size\n");
++ goto err_einval;
++ } else {
++ if (outsize > insize)
++ *size = outsize;
++ else
++ *size = insize;
++
++ fh->rsz_bufsize = *size;
++ }
++ spin_unlock(&fh->vbq_lock);
++
++ return 0;
++err_einval:
++ spin_unlock(&fh->vbq_lock);
++ return -EINVAL;
++}
++
++/**
++ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
++ * @q: Structure containing the videobuffer queue file handle, and device
++ * structure which contains the actual configuration.
++ * @vb: Structure containing the videobuffer used for resizer processing.
++ * @field: Type of field to set in videobuffer device.
++ *
++ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
++ * -EIO if the ISP MMU mapping fails
++ **/
++static int rsz_vbq_prepare(struct videobuf_queue *q,
++ struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ struct rsz_fh *fh = q->priv_data;
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_mult *multipass = fh->multipass;
++ int err = 0;
++ unsigned int isp_addr, insize, outsize;
++ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
++
++ spin_lock(&fh->vbq_lock);
++ if (vb->baddr) {
++ vb->size = fh->rsz_bufsize;
++ vb->bsize = fh->rsz_bufsize;
++ } else {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "No user buffer allocated\n");
++ goto out;
++ }
++ if (vb->i) {
++ vb->width = fh->params->out_hsize;
++ vb->height = fh->params->out_vsize;
++ } else {
++ vb->width = fh->params->in_hsize;
++ vb->height = fh->params->in_vsize;
++ }
++
++ vb->field = field;
++ spin_unlock(&fh->vbq_lock);
++
++ if (vb->state == VIDEOBUF_NEEDS_INIT) {
++ err = videobuf_iolock(q, vb, NULL);
++ if (!err) {
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ if (!isp_addr)
++ err = -EIO;
++ else {
++ if (vb->i) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ fh->isp_addr_write = isp_addr;
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd
++ = isp_addr;
++ rsz_conf_chan->input_buf_index = vb->i;
++ outsize = multipass->out_pitch *
++ multipass->out_vsize;
++ insize = multipass->in_pitch *
++ multipass->in_vsize;
++ if (outsize < insize) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->
++ output_buf_index =
++ vb->i;
++ }
++
++ fh->isp_addr_read = isp_addr;
++ }
++ }
++ }
++
++ }
++
++ if (!err) {
++ spin_lock(&fh->vbq_lock);
++ vb->state = VIDEOBUF_PREPARED;
++ spin_unlock(&fh->vbq_lock);
++ flush_cache_user_range(NULL, vb->baddr, (vb->baddr
++ + vb->bsize));
++ } else
++ rsz_vbq_release(q, vb);
++
++out:
++ return err;
++}
++
++static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
++{
++ return;
++}
++
++/**
++ * rsz_open - Initializes and opens the Resizer Wrapper
++ * @inode: Inode structure associated with the Resizer Wrapper
++ * @filp: File structure associated with the Resizer Wrapper
++ *
++ * Returns 0 if successful, -EBUSY if its already opened or the ISP module is
++ * not available, or -ENOMEM if its unable to allocate the device in kernel
++ * space memory.
++ **/
++static int rsz_open(struct inode *inode, struct file *filp)
++{
++ int ret = 0;
++ struct channel_config *rsz_conf_chan;
++ struct rsz_fh *fh;
++ struct device_params *device = device_config;
++ struct rsz_params *params;
++ struct rsz_mult *multipass;
++
++ if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) {
++ printk(KERN_DEBUG "omap-resizer: Device is opened in "
++ "non blocking mode\n");
++ } else {
++ printk(KERN_DEBUG "omap-resizer: Device is opened in blocking "
++ "mode\n");
++ }
++ fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL);
++ if (NULL == fh)
++ return -ENOMEM;
++
++ isp_get();
++
++ rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL);
++ if (rsz_conf_chan == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to config");
++ ret = -ENOMEM;
++ goto err_enomem0;
++ }
++ params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL);
++ if (params == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to params");
++ ret = -ENOMEM;
++ goto err_enomem1;
++ }
++ multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL);
++ if (multipass == NULL) {
++ dev_err(rsz_device, "\n cannot allocate memory to multipass");
++ ret = -ENOMEM;
++ goto err_enomem2;
++ }
++
++ fh->multipass = multipass;
++ fh->params = params;
++ fh->config = rsz_conf_chan;
++
++ if (mutex_lock_interruptible(&device->reszwrap_mutex)) {
++ ret = -EINTR;
++ goto err_enomem2;
++ }
++ device->opened++;
++ mutex_unlock(&device->reszwrap_mutex);
++
++ rsz_conf_chan->config_state = STATE_NOT_CONFIGURED;
++ rsz_conf_chan->status = CHANNEL_FREE;
++
++ filp->private_data = fh;
++ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ fh->device = device;
++
++ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
++ &fh->vbq_lock, fh->type,
++ V4L2_FIELD_NONE,
++ sizeof(struct videobuf_buffer), fh);
++
++ spin_lock_init(&fh->vbq_lock);
++ mutex_init(&rsz_conf_chan->chanprotection_mutex);
++
++ return 0;
++err_enomem2:
++ kfree(params);
++err_enomem1:
++ kfree(rsz_conf_chan);
++err_enomem0:
++ kfree(fh);
++ return ret;
++}
++
++/**
++ * rsz_release - Releases Resizer Wrapper and frees up allocated memory
++ * @inode: Inode structure associated with the Resizer Wrapper
++ * @filp: File structure associated with the Resizer Wrapper
++ *
++ * Returns 0 if successful, or -EBUSY if channel is being used.
++ **/
++static int rsz_release(struct inode *inode, struct file *filp)
++{
++ u32 timeout = 0;
++ struct rsz_fh *fh = filp->private_data;
++ struct channel_config *rsz_conf_chan = fh->config;
++ struct rsz_params *params = fh->params;
++ struct rsz_mult *multipass = fh->multipass;
++ struct videobuf_queue *q = &fh->vbq;
++
++ while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) {
++ timeout++;
++ schedule();
++ }
++ if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
++ return -EINTR;
++ device_config->opened--;
++ mutex_unlock(&device_config->reszwrap_mutex);
++ /* This will Free memory allocated to the buffers,
++ * and flushes the queue
++ */
++ videobuf_queue_cancel(q);
++ fh->params = NULL;
++ fh->config = NULL;
++
++ fh->rsz_bufsize = 0;
++ filp->private_data = NULL;
++
++ kfree(rsz_conf_chan);
++ kfree(params);
++ kfree(multipass);
++ kfree(fh);
++
++ isp_put();
++
++ return 0;
++}
++
++/**
++ * rsz_mmap - Memory maps the Resizer Wrapper module.
++ * @file: File structure associated with the Resizer Wrapper
++ * @vma: Virtual memory area structure.
++ *
++ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
++ * function.
++ **/
++static int rsz_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct rsz_fh *fh = file->private_data;
++
++ return videobuf_mmap_mapper(&fh->vbq, vma);
++}
++
++/**
++ * rsz_ioctl - I/O control function for Resizer Wrapper
++ * @inode: Inode structure associated with the Resizer Wrapper.
++ * @file: File structure associated with the Resizer Wrapper.
++ * @cmd: Type of command to execute.
++ * @arg: Argument to send to requested command.
++ *
++ * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command
++ * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user()
++ * fails, -EINVAL if parameter validation fails or parameter structure is not
++ * present.
++ **/
++static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ int ret = 0;
++ struct rsz_fh *fh = file->private_data;
++ struct device_params *device = fh->device;
++ struct channel_config *rsz_conf_chan = fh->config;
++
++ if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE)
++ || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) {
++ dev_err(rsz_device, "Bad command value \n");
++ return -1;
++ }
++
++ if (_IOC_DIR(cmd) & _IOC_READ)
++ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
++ else if (_IOC_DIR(cmd) & _IOC_WRITE)
++ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
++
++ if (ret) {
++ dev_err(rsz_device, "Access denied\n");
++ return -1;
++ }
++
++ switch (cmd) {
++ case RSZ_REQBUF:
++ {
++ struct v4l2_requestbuffers req_buf;
++ if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg,
++ sizeof(struct v4l2_requestbuffers))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_QUERYBUF:
++ {
++ struct v4l2_buffer buf;
++ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
++ sizeof(struct v4l2_buffer))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_querybuf(&fh->vbq, (void *)&buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ if (copy_to_user((struct v4l2_buffer *)arg, &buf,
++ sizeof(struct v4l2_buffer)))
++ return -EFAULT;
++ break;
++ }
++ case RSZ_QUEUEBUF:
++ {
++ struct v4l2_buffer buf;
++ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
++ sizeof(struct v4l2_buffer))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = videobuf_qbuf(&fh->vbq, (void *)&buf);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_S_PARAM:
++ {
++ struct rsz_params *params = fh->params;
++ if (copy_from_user(params, (struct rsz_params *)arg,
++ sizeof(struct rsz_params))) {
++ return -EFAULT;
++ }
++ if (mutex_lock_interruptible(&rsz_conf_chan->
++ chanprotection_mutex))
++ return -EINTR;
++ ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
++ }
++ case RSZ_G_PARAM:
++ ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan);
++ break;
++
++ case RSZ_G_STATUS:
++ {
++ struct rsz_status *status;
++ status = (struct rsz_status *)arg;
++ status->chan_busy = rsz_conf_chan->status;
++ status->hw_busy = ispresizer_busy();
++ status->src = INPUT_RAM;
++ break;
++ }
++ case RSZ_RESIZE:
++ if (file->f_flags & O_NONBLOCK) {
++ if (ispresizer_busy())
++ return -EBUSY;
++ else {
++ if (!mutex_trylock(&device->reszwrap_mutex))
++ return -EBUSY;
++ }
++ } else {
++ if (mutex_lock_interruptible(&device->reszwrap_mutex))
++ return -EINTR;
++ }
++ ret = rsz_start((int *)arg, fh);
++ mutex_unlock(&device->reszwrap_mutex);
++ break;
++ case RSZ_GET_CROPSIZE:
++ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
++ break;
++
++ default:
++ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
++ return -EINVAL;
++ }
++
++ return (long)ret;
++}
++
++static struct file_operations rsz_fops = {
++ .owner = THIS_MODULE,
++ .open = rsz_open,
++ .release = rsz_release,
++ .mmap = rsz_mmap,
++ .unlocked_ioctl = rsz_unlocked_ioctl,
++};
++
++/**
++ * rsz_isr - Interrupt Service Routine for Resizer wrapper
++ * @status: ISP IRQ0STATUS register value
++ * @arg1: Currently not used
++ * @arg2: Currently not used
++ *
++ * Interrupt Service Routine for Resizer wrapper
++ **/
++static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
++{
++
++ if ((status & RESZ_DONE) != RESZ_DONE)
++ return;
++
++ complete(&(device_config->compl_isr));
++
++}
++
++/**
++ * resizer_platform_release - Acts when Reference count is zero
++ * @device: Structure containing ISP resizer wrapper global information
++ *
++ * This is called when the reference count goes to zero.
++ **/
++static void resizer_platform_release(struct device *device)
++{
++}
++
++/**
++ * resizer_probe - Checks for device presence
++ * @device: Structure containing details of the current device.
++ *
++ * Always returns 0.
++ **/
++static int __init resizer_probe(struct platform_device *device)
++{
++ return 0;
++}
++
++/**
++ * resizer_remove - Handles the removal of the driver
++ * @omap_resizer_device: Structure containing details of the current device.
++ *
++ * Always returns 0.
++ **/
++static int resizer_remove(struct platform_device *omap_resizer_device)
++{
++ return 0;
++}
++
++static struct class *rsz_class;
++static struct cdev c_dev;
++static dev_t dev;
++static struct platform_device omap_resizer_device = {
++ .name = OMAP_REZR_NAME,
++ .id = 2,
++ .dev = {
++ .release = resizer_platform_release,}
++};
++
++static struct platform_driver omap_resizer_driver = {
++ .probe = resizer_probe,
++ .remove = resizer_remove,
++ .driver = {
++ .bus = &platform_bus_type,
++ .name = OMAP_REZR_NAME,
++ },
++};
++
++/**
++ * omap_rsz_init - Initialization of Resizer Wrapper
++ *
++ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
++ * could not register the wrapper as a character device, or other errors if the
++ * device or driver can't register.
++ **/
++static int __init omap_rsz_init(void)
++{
++ int ret = 0;
++ struct device_params *device;
++ device = kzalloc(sizeof(struct device_params), GFP_KERNEL);
++ if (!device) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate "
++ "memory\n");
++ return -ENOMEM;
++ }
++
++ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
++ if (ret < 0) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
++ "Could not allocate region "
++ "for character device\n");
++ kfree(device);
++ return -ENODEV;
++ }
++
++ /* Register the driver in the kernel */
++ /* Initialize of character device */
++ cdev_init(&c_dev, &rsz_fops);
++ c_dev.owner = THIS_MODULE;
++ c_dev.ops = &rsz_fops;
++
++ /* Addding character device */
++ ret = cdev_add(&c_dev, dev, 1);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME ": Error adding "
++ "device - %d\n", ret);
++ goto fail2;
++ }
++ rsz_major = MAJOR(dev);
++
++ /* register driver as a platform driver */
++ ret = platform_driver_register(&omap_resizer_driver);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to register platform driver!\n");
++ goto fail3;
++ }
++
++ /* Register the drive as a platform device */
++ ret = platform_device_register(&omap_resizer_device);
++ if (ret) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to register platform device!\n");
++ goto fail4;
++ }
++
++ rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME);
++ if (!rsz_class) {
++ dev_err(rsz_device, OMAP_REZR_NAME
++ ": Failed to create class!\n");
++ goto fail5;
++ }
++
++ /* make entry in the devfs */
++ rsz_device = device_create(rsz_class, rsz_device,
++ MKDEV(rsz_major, 0), NULL,
++ OMAP_REZR_NAME);
++ dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n");
++ device->opened = 0;
++
++ device->vbq_ops.buf_setup = rsz_vbq_setup;
++ device->vbq_ops.buf_prepare = rsz_vbq_prepare;
++ device->vbq_ops.buf_release = rsz_vbq_release;
++ device->vbq_ops.buf_queue = rsz_vbq_queue;
++ init_completion(&device->compl_isr);
++ mutex_init(&device->reszwrap_mutex);
++
++ device_config = device;
++ return 0;
++
++fail5:
++ platform_device_unregister(&omap_resizer_device);
++fail4:
++ platform_driver_unregister(&omap_resizer_driver);
++fail3:
++ cdev_del(&c_dev);
++fail2:
++ unregister_chrdev_region(dev, 1);
++ kfree(device);
++ return ret;
++}
++
++/**
++ * omap_rsz_exit - Close of Resizer Wrapper
++ **/
++void __exit omap_rsz_exit(void)
++{
++ device_destroy(rsz_class, dev);
++ class_destroy(rsz_class);
++ platform_device_unregister(&omap_resizer_device);
++ platform_driver_unregister(&omap_resizer_driver);
++ cdev_del(&c_dev);
++ unregister_chrdev_region(dev, 1);
++ kfree(device_config);
++}
++
++module_init(omap_rsz_init)
++module_exit(omap_rsz_exit)
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_DESCRIPTION("OMAP ISP Resizer");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
+new file mode 100644
+index 0000000..5ac0c88
+--- /dev/null
++++ b/include/linux/omap_resizer.h
+@@ -0,0 +1,136 @@
++/*
++ * drivers/media/video/isp/omap_resizer.h
++ *
++ * Include file for Resizer module wrapper in TI's OMAP3430 ISP
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef OMAP_RESIZER_H
++#define OMAP_RESIZER_H
++
++#include <linux/types.h>
++
++/* ioctls definition */
++#define RSZ_IOC_BASE 'R'
++#define RSZ_IOC_MAXNR 8
++
++/*Ioctl options which are to be passed while calling the ioctl*/
++#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
++ struct v4l2_requestbuffers)
++#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer)
++#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params)
++#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params)
++#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32)
++#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
++#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
++#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
++
++#define RSZ_INTYPE_YCBCR422_16BIT 0
++#define RSZ_INTYPE_PLANAR_8BIT 1
++#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */
++#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */
++
++enum config_done {
++ STATE_CONFIGURED, /* Resizer driver configured
++ * by application.
++ */
++ STATE_NOT_CONFIGURED /* Resizer driver not
++ * configured by application.
++ */
++};
++
++/* Structure Definitions */
++
++/* used to luma enhancement options */
++
++struct rsz_yenh {
++ __s32 type; /* represents luma enable or
++ * disable.
++ */
++ __u8 gain; /* represents gain. */
++ __u8 slop; /* represents slop. */
++ __u8 core; /* Represents core value. */
++};
++
++/* Conatins all the parameters for resizing. This structure
++ * is used to configure resiser parameters
++ */
++struct rsz_params {
++ __s32 in_hsize; /* input frame horizontal
++ * size.
++ */
++ __s32 in_vsize; /* input frame vertical size */
++ __s32 in_pitch; /* offset between two rows of
++ * input frame.
++ */
++ __s32 inptyp; /* for determining 16 bit or
++ * 8 bit data.
++ */
++ __s32 vert_starting_pixel; /* for specifying vertical
++ * starting pixel in input.
++ */
++ __s32 horz_starting_pixel; /* for specyfing horizontal
++ * starting pixel in input.
++ */
++ __s32 cbilin; /* # defined, filter with luma
++ * or bi-linear interpolation.
++ */
++ __s32 pix_fmt; /* # defined, UYVY or YUYV */
++ __s32 out_hsize; /* output frame horizontal
++ * size.
++ */
++ __s32 out_vsize; /* output frame vertical
++ * size.
++ */
++ __s32 out_pitch; /* offset between two rows of
++ * output frame.
++ */
++ __s32 hstph; /* for specifying horizontal
++ * starting phase.
++ */
++ __s32 vstph; /* for specifying vertical
++ * starting phase.
++ */
++ __u16 tap4filt_coeffs[32]; /* horizontal filter
++ * coefficients.
++ */
++ __u16 tap7filt_coeffs[32]; /* vertical filter
++ * coefficients.
++ */
++ struct rsz_yenh yenh_params;
++};
++
++/* Contains the status of hardware and channel */
++struct rsz_status {
++ __s32 chan_busy; /* 1: channel is busy,
++ * 0: channel is not busy
++ */
++ __s32 hw_busy; /* 1: hardware is busy,
++ * 0: hardware is not busy
++ */
++ __s32 src; /* # defined, can be either
++ * SD-RAM or CCDC/PREVIEWER
++ */
++};
++
++/* Passed by application for getting crop size */
++struct rsz_cropsize {
++ __u32 hcrop; /* Number of pixels per line
++ * cropped in output image.
++ */
++
++ __u32 vcrop; /* Number of lines cropped
++ * in output image.
++ */
++};
++
++#endif
+--
+1.6.2.4
+
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
new file mode 100644
index 0000000000..2c3023643e
--- /dev/null
+++ b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0024-OMAP3-Resizer-V4L2-buf-layer-issues-fixed.patch
@@ -0,0 +1,729 @@
+From ad3bbadb7fc39a946dfd0cdac19e2ec8647b2c2c Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 17:20:27 +0530
+Subject: [PATCH 24/26] OMAP3-Resizer: V4L2-buf layer issues fixed
+
+V4L2-Buffer layer issues fixed under this commit.
+This patch is same as available with PSP1.0.2 release
+
+The discussion is initiated on this with V4L2 mailing list.
+
+Please note that this patch is not being tested.
+---
+ drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++--------
+ include/linux/omap_resizer.h | 3 +-
+ 2 files changed, 321 insertions(+), 99 deletions(-)
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+index 54bc425..8059c70 100644
+--- a/drivers/media/video/isp/omap_resizer.c
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -28,6 +28,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/uaccess.h>
++#include <linux/pci.h>
+ #include <media/v4l2-dev.h>
+ #include <asm/cacheflush.h>
+
+@@ -76,6 +77,10 @@
+ #define MAX_COEF_COUNTER 16
+ #define COEFF_ADDRESS_OFFSET 0x04
+
++#define RSZ_DEF_REQ_EXP 0xE /* Default read operation expand
++ * for the Resizer driver; value
++ * taken from Davinci.
++ */
+ /* Global structure which contains information about number of channels
+ and protection variables */
+ struct device_params {
+@@ -85,6 +90,7 @@ struct device_params {
+ struct mutex reszwrap_mutex; /* Semaphore for array */
+
+ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
++ unsigned long extra_page_addr;
+ };
+
+ /* Register mapped structure which contains the every register
+@@ -126,6 +132,9 @@ struct resizer_config {
+ u32 rsz_yehn; /* yehn(luma)register mapping
+ * variable.
+ */
++ u32 sdr_req_exp; /* Configuration for Non
++ * real time read expand
++ */
+ };
+
+ struct rsz_mult {
+@@ -179,6 +188,7 @@ struct channel_config {
+ * channel is busy or not
+ */
+ struct mutex chanprotection_mutex;
++ int buf_address[VIDEO_MAX_FRAME];
+ enum config_done config_state;
+ u8 input_buf_index;
+ u8 output_buf_index;
+@@ -200,8 +210,6 @@ struct rsz_fh {
+ struct videobuf_queue vbq;
+ struct device_params *device;
+
+- dma_addr_t isp_addr_read; /* Input/Output address */
+- dma_addr_t isp_addr_write; /* Input/Output address */
+ u32 rsz_bufsize; /* channel specific buffersize
+ */
+ };
+@@ -227,6 +235,10 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
+ static void rsz_config_ratio(struct rsz_mult *multipass,
+ struct channel_config *rsz_conf_chan);
+
++static void inline rsz_set_exp(unsigned int exp)
++{
++ omap_writel(((exp & 0x3FF) << 10), OMAP3ISP_SBL_REG(0xF8));
++}
+ /**
+ * rsz_hardware_setup - Sets hardware configuration registers
+ * @rsz_conf_chan: Structure containing channel configuration
+@@ -271,12 +283,15 @@ static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
+ + coeffoffset));
+ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
+ }
++ /* Configure the read expand register */
++ rsz_set_exp(rsz_conf_chan->register_config.sdr_req_exp);
+ }
+
+ /**
+ * rsz_start - Enables Resizer Wrapper
+ * @arg: Currently not used.
+- * @device: Structure containing ISP resizer wrapper global information
++ * @fh: File structure containing ISP resizer information specific to
++ * channel opened.
+ *
+ * Submits a resizing task specified by the rsz_resize structure. The call can
+ * either be blocked until the task is completed or returned immediately based
+@@ -292,12 +307,18 @@ int rsz_start(int *arg, struct rsz_fh *fh)
+ struct channel_config *rsz_conf_chan = fh->config;
+ struct rsz_mult *multipass = fh->multipass;
+ struct videobuf_queue *q = &fh->vbq;
++ struct videobuf_buffer *buf;
+ int ret;
+
+ if (rsz_conf_chan->config_state) {
+ dev_err(rsz_device, "State not configured \n");
+ goto err_einval;
+ }
++ if (!rsz_conf_chan->register_config.rsz_sdr_inadd ||
++ !rsz_conf_chan->register_config.rsz_sdr_outadd) {
++ dev_err(rsz_device, "address is null\n");
++ goto err_einval;
++ }
+
+ rsz_conf_chan->status = CHANNEL_BUSY;
+
+@@ -325,33 +346,22 @@ mult:
+ goto mult;
+ }
+
+- if (fh->isp_addr_read) {
+- ispmmu_unmap(fh->isp_addr_read);
+- fh->isp_addr_read = 0;
+- }
+- if (fh->isp_addr_write) {
+- ispmmu_unmap(fh->isp_addr_write);
+- fh->isp_addr_write = 0;
+- }
+-
+ rsz_conf_chan->status = CHANNEL_FREE;
+- q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
+- q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
+ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
+ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
+
+- /* Unmap and free the DMA memory allocated for buffers */
+- videobuf_dma_unmap(q, videobuf_to_dma(
+- q->bufs[rsz_conf_chan->input_buf_index]));
+- videobuf_dma_unmap(q, videobuf_to_dma(
+- q->bufs[rsz_conf_chan->output_buf_index]));
+- videobuf_dma_free(videobuf_to_dma(
+- q->bufs[rsz_conf_chan->input_buf_index]));
+- videobuf_dma_free(videobuf_to_dma(
+- q->bufs[rsz_conf_chan->output_buf_index]));
+-
+ isp_unset_callback(CBK_RESZ_DONE);
+
++ /* Empty the Videobuf queue which was filled during the qbuf */
++ buf = q->bufs[rsz_conf_chan->input_buf_index];
++ buf->state = VIDEOBUF_IDLE;
++ list_del(&buf->stream);
++ if (rsz_conf_chan->input_buf_index != rsz_conf_chan->output_buf_index) {
++ buf = q->bufs[rsz_conf_chan->output_buf_index];
++ buf->state = VIDEOBUF_IDLE;
++ list_del(&buf->stream);
++ }
++
+ return 0;
+ err_einval:
+ return -EINVAL;
+@@ -359,6 +369,8 @@ err_einval:
+
+ /**
+ * rsz_set_multipass - Set resizer multipass
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Returns always 0
+@@ -384,6 +396,8 @@ static int rsz_set_multipass(struct rsz_mult *multipass,
+
+ /**
+ * rsz_copy_data - Copy data
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @params: Structure containing the Resizer Wrapper parameters
+ *
+ * Copy data
+@@ -413,6 +427,8 @@ static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
+
+ /**
+ * rsz_set_params - Set parameters for resizer wrapper
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @params: Structure containing the Resizer Wrapper parameters
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+@@ -524,6 +540,8 @@ static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
+ }
+
+ rsz_config_ratio(multipass, rsz_conf_chan);
++ /* Default value for read expand:Taken from Davinci */
++ rsz_conf_chan->register_config.sdr_req_exp = RSZ_DEF_REQ_EXP;
+
+ rsz_conf_chan->config_state = STATE_CONFIGURED;
+
+@@ -534,6 +552,8 @@ err_einval:
+
+ /**
+ * rsz_set_ratio - Set ratio
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
+@@ -548,7 +568,8 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
+
+ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
+ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
+- dev_err(rsz_device, "Invalid output size!");
++ dev_err(rsz_device, "Invalid output size! - %d", \
++ multipass->out_hsize);
+ goto err_einval;
+ }
+ if (multipass->cbilin) {
+@@ -758,6 +779,8 @@ err_einval:
+
+ /**
+ * rsz_config_ratio - Configure ratio
++ * @multipass: Structure containing channel configuration
++ for multipass support
+ * @rsz_conf_chan: Structure containing channel configuration
+ *
+ * Configure ratio
+@@ -789,6 +812,20 @@ static void rsz_config_ratio(struct rsz_mult *multipass,
+ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
+ & ISPRSZ_IN_SIZE_VERT_MASK);
+
++ /* This is another workaround for the ISP-MMU translation fault.
++ For the parameters whose image size comes exactly to PAGE_SIZE
++ generates ISP-MMU translation fault. The root-cause is the equation
++ input width = (32*sph + (ow - 1)*hrsz + 16) >> 8 + 7
++ = (64*sph + (ow - 1)*hrsz + 32) >> 8 + 7
++ input height = (32*spv + (oh - 1)*vrsz + 16) >> 8 + 4
++ = (64*spv + (oh - 1)*vrsz + 32) >> 8 + 7
++
++ we are adjusting the input width to suit for Resizer module,
++ application should use this configuration henceforth.
++ */
++ multipass->in_hsize = hsize;
++ multipass->in_vsize = vsize;
++
+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
+ coeffcounter++) {
+ if (multipass->num_htap) {
+@@ -990,24 +1027,15 @@ static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
+ static void rsz_vbq_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
+ {
+- int i;
+ struct rsz_fh *fh = q->priv_data;
++ struct videobuf_dmabuf *dma = NULL;
+
+- for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+- struct videobuf_dmabuf *dma = NULL;
+- if (!q->bufs[i])
+- continue;
+- if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
+- continue;
+- dma = videobuf_to_dma(q->bufs[i]);
+- videobuf_dma_unmap(q, dma);
+- videobuf_dma_free(dma);
+- }
++ dma = videobuf_to_dma(q->bufs[vb->i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ ispmmu_unmap(fh->config->buf_address[vb->i]);
++ fh->config->buf_address[vb->i] = 0;
+
+- ispmmu_unmap(fh->isp_addr_read);
+- ispmmu_unmap(fh->isp_addr_write);
+- fh->isp_addr_read = 0;
+- fh->isp_addr_write = 0;
+ spin_lock(&fh->vbq_lock);
+ vb->state = VIDEOBUF_NEEDS_INIT;
+ spin_unlock(&fh->vbq_lock);
+@@ -1062,7 +1090,105 @@ err_einval:
+ spin_unlock(&fh->vbq_lock);
+ return -EINVAL;
+ }
++/*
++ * This function is work around for the videobuf_iolock API,
++ * for User memory allocated with ioremap (VM_IO flag) the API
++ * get_user_pages fails.
++ *
++ * To fulfill this requirement, we have completely ignored VM layer of
++ * Linux, and configuring the ISP MMU with physical address.
++ */
++static int omap_videobuf_dma_init_user(struct videobuf_buffer *vb,
++ unsigned long physp, unsigned long asize)
++{
++ struct videobuf_dmabuf *dma;
++ struct scatterlist *sglist;
++ unsigned long data, first, last;
++ int len, i = 0;
++
++ dma = videobuf_to_dma(vb);
++ data = vb->baddr;
++
++ first = (data & PAGE_MASK) >> PAGE_SHIFT;
++ last = ((data+asize-1) & PAGE_MASK) >> PAGE_SHIFT;
++ dma->offset = data & ~PAGE_MASK;
++ dma->nr_pages = last-first+1;
++
++ dma->direction = PCI_DMA_FROMDEVICE;
++ /*
++ * Allocate array of sglen + 1, to add entry of extra page
++ * for input buffer. Driver always uses 0th buffer as input buffer.
++ */
++ len = dma->nr_pages + (vb->i ? 0 : 1);
++ sglist = kcalloc(len, sizeof(*sglist), GFP_KERNEL);
++ if (NULL == sglist)
++ return -ENOMEM;
++
++ sglist[0].offset = 0;
++ sglist[0].length = PAGE_SIZE - dma->offset;
++ sglist[0].dma_address = (dma_addr_t)physp;
++ physp += sglist[0].length;
++ /*
++ * Iterate in a loop for the number of pages
++ */
++ for (i = 1; i < (len - (vb->i ? 0 : 1)); i++) {
++ sglist[i].offset = 0;
++ sglist[i].length = PAGE_SIZE;
++ sglist[i].dma_address = (dma_addr_t)physp;
++ physp += PAGE_SIZE;
++ }
++ if (0 == vb->i) {
++ sglist[i].offset = 0;
++ sglist[i].length = PAGE_SIZE;
++ sglist[i].dma_address =
++ (dma_addr_t)device_config->extra_page_addr;
++ }
++ dma->sglist = sglist;
++ dma->sglen = len;
++ return 0;
++
++ }
++/*
++ * This function is workaround for the issue, where ISP-MMU generated
++ * translation fault for specific params whose size is aligned to PAGE_SIZE.
++
++ * As a workaround we are padding one extra page for input buffer. This page
++ * we are allocating during init time and will not be released through-out
++ * life time of resizer driver. Please note that Resizer module only reads
++ * from this extra page.
++ */
++int omap_create_sg(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
++{
++ struct scatterlist *sglist;
++ int sglen;
+
++ sglen = dma->sglen;
++ sglist = kcalloc(sglen + 1, sizeof(*sglist), GFP_KERNEL);
++ if (NULL == sglist)
++ return -ENOMEM;
++ /*
++ * Copy the sglist locally
++ */
++ memcpy(sglist, dma->sglist, sglen * sizeof(*sglist));
++ /*
++ * Release the old sglist, since we already copied it locally
++ */
++ videobuf_dma_unmap(q, dma);
++ /*
++ * Add extra entry to sglist to work with specific params, whose
++ * buffer address alined to PAGE_SIZE.
++ */
++ sglist[sglen].offset = 0;
++ sglist[sglen].length = PAGE_SIZE;
++ sglist[sglen].dma_address = (dma_addr_t)device_config->extra_page_addr;
++ sglen++;
++ /*
++ * Save the sglist for mapping to ISP-MMU space
++ */
++ dma->sglist = sglist;
++ dma->sglen = sglen;
++ return 0;
++}
+ /**
+ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
+ * @q: Structure containing the videobuffer queue file handle, and device
+@@ -1079,19 +1205,24 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+ {
+ struct rsz_fh *fh = q->priv_data;
+ struct channel_config *rsz_conf_chan = fh->config;
+- struct rsz_mult *multipass = fh->multipass;
+ int err = 0;
+ unsigned int isp_addr, insize, outsize;
+- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
+-
++ struct rsz_mult *multipass = fh->multipass;
+ spin_lock(&fh->vbq_lock);
+ if (vb->baddr) {
++ /* Check for 32 byte alignement */
++ if (vb->baddr != (vb->baddr & ~0x1F)) {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "Buffer address should be aligned \
++ to 32 byte\n");
++ return -EINVAL;
++ }
+ vb->size = fh->rsz_bufsize;
+ vb->bsize = fh->rsz_bufsize;
+ } else {
+ spin_unlock(&fh->vbq_lock);
+ dev_err(rsz_device, "No user buffer allocated\n");
+- goto out;
++ return -EINVAL;
+ }
+ if (vb->i) {
+ vb->width = fh->params->out_hsize;
+@@ -1103,55 +1234,128 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+
+ vb->field = field;
+ spin_unlock(&fh->vbq_lock);
++ /*
++ * Calculate input and output sizes, will be used while mapping
++ * user pages
++ */
++ outsize = multipass->out_pitch * multipass->out_vsize;
++ insize = multipass->in_pitch * multipass->in_vsize;
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+- err = videobuf_iolock(q, vb, NULL);
+- if (!err) {
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
+- if (!isp_addr)
+- err = -EIO;
+- else {
+- if (vb->i) {
+- rsz_conf_chan->register_config.
+- rsz_sdr_outadd
+- = isp_addr;
+- fh->isp_addr_write = isp_addr;
+- rsz_conf_chan->output_buf_index = vb->i;
+- } else {
++ struct videobuf_dmabuf *dma;
++ struct vm_area_struct *vma;
++ spin_lock(&fh->vbq_lock);
++ dma = videobuf_to_dma(vb);
++ vma = find_vma(current->mm, vb->baddr);
++ if ((vma) && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) {
++ /* This will catch ioremaped buffers to the kernel.
++ * It gives two possible scenarios -
++ * - Driver allocates buffer using either
++ * dma_alloc_coherent or get_free_pages,
++ * and maps to user space using
++ * io_remap_pfn_range/remap_pfn_range
++ * - Drivers maps memory outside from Linux using
++ * io_remap
++ */
++ unsigned long physp = 0, asize;
++ asize = vb->i ? outsize : insize;
++ if ((vb->baddr + asize) > vma->vm_end) {
++ spin_unlock(&fh->vbq_lock);
++ dev_err(rsz_device, "User Buffer Allocation:" \
++ "err=%lu[%lu]\n",\
++ (vma->vm_end - vb->baddr), asize);
++ return -ENOMEM;
++ }
++ physp = (vma->vm_pgoff << PAGE_SHIFT) +
++ (vb->baddr - vma->vm_start);
++ err = omap_videobuf_dma_init_user(vb, physp, asize);
++ spin_unlock(&fh->vbq_lock);
++ if (0 != err)
++ return err;
++ } else {
++ err = videobuf_iolock(q, vb, NULL);
++ /*
++ * In case of user pointer mode, the get_user_pages
++ * will fail if user has allocated less memory than
++ * vb->size. But it is not error from resizer driver
++ * point of view. so handled seperately
++ */
++ if ((err < 0) && (dma->nr_pages > 0))
++ err = videobuf_dma_map(q, dma);
++ if (err)
++ goto buf_release;
++ /*
++ * Add one extra page for input buffer
++ */
++ if (0 == vb->i)
++ err = omap_create_sg(q, dma);
++ if (err)
++ goto buf_release;
++ spin_unlock(&fh->vbq_lock);
++ }
++ isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ if (!isp_addr)
++ err = -EIO;
++ else {
++ if (vb->i) {
++ rsz_conf_chan->buf_address[vb->i] = isp_addr;
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->buf_address[vb->i] = isp_addr;
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd
++ = isp_addr;
++ rsz_conf_chan->input_buf_index = vb->i;
++ if (outsize < insize && rsz_conf_chan->
++ register_config.
++ rsz_sdr_outadd == 0) {
+ rsz_conf_chan->register_config.
+- rsz_sdr_inadd
+- = isp_addr;
+- rsz_conf_chan->input_buf_index = vb->i;
+- outsize = multipass->out_pitch *
+- multipass->out_vsize;
+- insize = multipass->in_pitch *
+- multipass->in_vsize;
+- if (outsize < insize) {
+- rsz_conf_chan->register_config.
+- rsz_sdr_outadd
+- = isp_addr;
+- rsz_conf_chan->
+- output_buf_index =
+- vb->i;
+- }
+-
+- fh->isp_addr_read = isp_addr;
++ rsz_sdr_outadd
++ = isp_addr;
++ rsz_conf_chan->
++ output_buf_index =
++ vb->i;
+ }
+ }
+ }
+
+- }
++ } else {
++ if(vb->i) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd =
++ rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->output_buf_index = vb->i;
++ } else {
++ rsz_conf_chan->register_config.
++ rsz_sdr_inadd =
++ rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->input_buf_index = vb->i;
++ if(outsize < insize && rsz_conf_chan->
++ register_config.
++ rsz_sdr_outadd == 0) {
++ rsz_conf_chan->register_config.
++ rsz_sdr_outadd
++ = rsz_conf_chan->buf_address[vb->i];
++ rsz_conf_chan->output_buf_index = vb->i;
++ }
++
++ }
+
++ }
+ if (!err) {
+ spin_lock(&fh->vbq_lock);
+ vb->state = VIDEOBUF_PREPARED;
+ spin_unlock(&fh->vbq_lock);
+- flush_cache_user_range(NULL, vb->baddr, (vb->baddr
+- + vb->bsize));
+ } else
+ rsz_vbq_release(q, vb);
+
+-out:
++ return err;
++buf_release:
++ spin_unlock(&fh->vbq_lock);
++ rsz_vbq_release(q, vb);
+ return err;
+ }
+
+@@ -1255,7 +1459,8 @@ err_enomem0:
+ **/
+ static int rsz_release(struct inode *inode, struct file *filp)
+ {
+- u32 timeout = 0;
++ int i;
++ unsigned int timeout = 0;
+ struct rsz_fh *fh = filp->private_data;
+ struct channel_config *rsz_conf_chan = fh->config;
+ struct rsz_params *params = fh->params;
+@@ -1266,17 +1471,17 @@ static int rsz_release(struct inode *inode, struct file *filp)
+ timeout++;
+ schedule();
+ }
+- if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
+- return -EINTR;
+- device_config->opened--;
+- mutex_unlock(&device_config->reszwrap_mutex);
+- /* This will Free memory allocated to the buffers,
+- * and flushes the queue
+- */
+- videobuf_queue_cancel(q);
+- fh->params = NULL;
+- fh->config = NULL;
++ /* Free memory allocated to the buffers */
++ for (i = 0 ; i < VIDEO_MAX_FRAME ; i++) {
++ struct videobuf_dmabuf *dma = NULL;
++ if (!q->bufs[i])
++ continue;
++ dma = videobuf_to_dma(q->bufs[i]);
++ videobuf_dma_unmap(q, dma);
++ videobuf_dma_free(dma);
++ }
+
++ videobuf_mmap_free(q);
+ fh->rsz_bufsize = 0;
+ filp->private_data = NULL;
+
+@@ -1286,7 +1491,8 @@ static int rsz_release(struct inode *inode, struct file *filp)
+ kfree(fh);
+
+ isp_put();
+-
++ fh->params = NULL;
++ fh->config = NULL;
+ return 0;
+ }
+
+@@ -1353,6 +1559,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ chanprotection_mutex))
+ return -EINTR;
+ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
++ if (ret >= 0) {
++ if (copy_to_user((struct v4l2_requestbuffers *)arg,
++ &req_buf, sizeof(struct
++ v4l2_requestbuffers)))
++ return -EFAULT;
++ }
+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
+ break;
+ }
+@@ -1394,11 +1606,7 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ sizeof(struct rsz_params))) {
+ return -EFAULT;
+ }
+- if (mutex_lock_interruptible(&rsz_conf_chan->
+- chanprotection_mutex))
+- return -EINTR;
+- ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
+- mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ ret = rsz_set_params(fh->multipass, fh->params, rsz_conf_chan);
+ break;
+ }
+ case RSZ_G_PARAM:
+@@ -1433,6 +1641,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
+ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
+ break;
+
++ case RSZ_S_EXP:
++ if (mutex_lock_interruptible(&rsz_conf_chan->chanprotection_mutex))
++ return -EINTR;
++ rsz_conf_chan->register_config.sdr_req_exp = *((unsigned int *)arg);
++ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
++ break;
+ default:
+ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
+ return -EINVAL;
+@@ -1535,14 +1749,18 @@ static int __init omap_rsz_init(void)
+ "memory\n");
+ return -ENOMEM;
+ }
+-
++ device->extra_page_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
++ if (!device->extra_page_addr) {
++ dev_err(rsz_device, OMAP_REZR_NAME ":Allocation failed. ");
++ kfree(device);
++ return -ENOMEM;
++ }
+ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
+ if (ret < 0) {
+ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
+ "Could not allocate region "
+ "for character device\n");
+- kfree(device);
+- return -ENODEV;
++ goto fail1;
+ }
+
+ /* Register the driver in the kernel */
+@@ -1608,6 +1826,8 @@ fail3:
+ cdev_del(&c_dev);
+ fail2:
+ unregister_chrdev_region(dev, 1);
++fail1:
++ free_pages((unsigned long)device->extra_page_addr, 0);
+ kfree(device);
+ return ret;
+ }
+@@ -1623,6 +1843,7 @@ void __exit omap_rsz_exit(void)
+ platform_driver_unregister(&omap_resizer_driver);
+ cdev_del(&c_dev);
+ unregister_chrdev_region(dev, 1);
++ free_pages((unsigned long)device_config->extra_page_addr, 0);
+ kfree(device_config);
+ }
+
+diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
+index 5ac0c88..47b8dd8 100644
+--- a/include/linux/omap_resizer.h
++++ b/include/linux/omap_resizer.h
+@@ -21,7 +21,7 @@
+
+ /* ioctls definition */
+ #define RSZ_IOC_BASE 'R'
+-#define RSZ_IOC_MAXNR 8
++#define RSZ_IOC_MAXNR 9
+
+ /*Ioctl options which are to be passed while calling the ioctl*/
+ #define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
+@@ -33,6 +33,7 @@
+ #define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
+ #define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
+ #define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
++#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE, 9, __s32)
+
+ #define RSZ_INTYPE_YCBCR422_16BIT 0
+ #define RSZ_INTYPE_PLANAR_8BIT 1
+--
+1.6.2.4
+
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
new file mode 100644
index 0000000000..143a846e3c
--- /dev/null
+++ b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/resizer/0025-OMAP3-Resizer-Build-issues-fixed.patch
@@ -0,0 +1,36 @@
+From 9fec955e98b4ef7922f629e3a81d2d1af216e028 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <vaibhav@psp-nfs-02.india.ti.com>
+Date: Wed, 29 Apr 2009 18:12:42 +0530
+Subject: [PATCH 25/26] OMAP3-Resizer: Build issues fixed
+
+There were some building issues with latest gitorious tree,
+fixed them.
+---
+ drivers/media/video/isp/omap_resizer.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
+index 8059c70..dd90b24 100644
+--- a/drivers/media/video/isp/omap_resizer.c
++++ b/drivers/media/video/isp/omap_resizer.c
+@@ -1033,7 +1033,7 @@ static void rsz_vbq_release(struct videobuf_queue *q,
+ dma = videobuf_to_dma(q->bufs[vb->i]);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+- ispmmu_unmap(fh->config->buf_address[vb->i]);
++ ispmmu_vunmap(fh->config->buf_address[vb->i]);
+ fh->config->buf_address[vb->i] = 0;
+
+ spin_lock(&fh->vbq_lock);
+@@ -1293,7 +1293,7 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
+ goto buf_release;
+ spin_unlock(&fh->vbq_lock);
+ }
+- isp_addr = ispmmu_map_sg(dma->sglist, dma->sglen);
++ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
+ if (!isp_addr)
+ err = -EIO;
+ else {
+--
+1.6.2.4
+