On Thursday 11 December 2008 21:38:18 Aguirre Rodriguez, Sergio Alberto wrote: > >From 286e60575f345dd8306d20e5d3e80809e3359e86 Mon Sep 17 00:00:00 2001 > From: Sergio Aguirre <saaguirre@xxxxxx> > Date: Thu, 11 Dec 2008 13:35:48 -0600 > Subject: [PATCH] OMAP: CAM: Add Preview and Resizer Wrappers > > This adds the OMAP Preview and Resizer Wrappers to the kernel. > > Signed-off-by: Sergio Aguirre <saaguirre@xxxxxx> > --- > drivers/media/video/Kconfig | 2 + > drivers/media/video/isp/Kconfig | 9 + > drivers/media/video/isp/Makefile | 7 + > drivers/media/video/isp/omap_previewer.c | 825 +++++++++++++++ > drivers/media/video/isp/omap_previewer.h | 162 +++ > drivers/media/video/isp/omap_resizer.c | 1631 ++++++++++++++++++++++++++++++ > include/linux/omap_resizer.h | 136 +++ > 7 files changed, 2772 insertions(+), 0 deletions(-) > create mode 100644 drivers/media/video/isp/Kconfig > create mode 100644 drivers/media/video/isp/omap_previewer.c > create mode 100644 drivers/media/video/isp/omap_previewer.h > 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 47102c2..6150d6f 100644 > --- a/drivers/media/video/Kconfig > +++ b/drivers/media/video/Kconfig > @@ -700,6 +700,8 @@ config VIDEO_CAFE_CCIC > CMOS camera controller. This is the controller found on first- > generation OLPC systems. > > +source "drivers/media/video/isp/Kconfig" > + > config SOC_CAMERA > tristate "SoC camera support" > depends on VIDEO_V4L2 && HAS_DMA > diff --git a/drivers/media/video/isp/Kconfig b/drivers/media/video/isp/Kconfig > new file mode 100644 > index 0000000..eeabc8f > --- /dev/null > +++ b/drivers/media/video/isp/Kconfig > @@ -0,0 +1,9 @@ > +# Kconfig for OMAP3 ISP driver > + > +config VIDEO_OMAP34XX_ISP_PREVIEWER > + tristate "OMAP ISP Previewer" > + depends on !ARCH_OMAP3410 > + > +config VIDEO_OMAP34XX_ISP_RESIZER > + tristate "OMAP ISP Resizer" > + depends on !ARCH_OMAP3410 > diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile > index f2f831c..ac046a1 100644 > --- a/drivers/media/video/isp/Makefile > +++ b/drivers/media/video/isp/Makefile > @@ -7,6 +7,13 @@ 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_PREVIEWER) += \ > + omap_previewer.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/omap_previewer.c b/drivers/media/video/isp/omap_previewer.c > new file mode 100644 > index 0000000..634a056 > --- /dev/null > +++ b/drivers/media/video/isp/omap_previewer.c > @@ -0,0 +1,825 @@ > +/* > + * drivers/media/video/isp/omap_previewer.c > + * > + * Wrapper for Preview module in TI's OMAP3430 ISP > + * > + * Copyright (C) 2008 Texas Instruments, Inc. > + * > + * Contributors: > + * Leonides Martinez <leonides.martinez@xxxxxx> > + * Sergio Aguirre <saaguirre@xxxxxx> > + * > + * 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/device.h> > +#include <linux/delay.h> > +#include <linux/fs.h> > +#include <linux/mm.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/uaccess.h> > +#include <linux/io.h> > +#include <media/v4l2-dev.h> > +#include <asm/cacheflush.h> > + > +#include "isp.h" > +#include "ispmmu.h" > +#include "ispreg.h" > +#include "omap_previewer.h" > + > +#define OMAP_PREV_NAME "omap-previewer" > + > +static int prev_major = -1; > +static struct device *prev_dev; > +static struct class *prev_class; > +static struct prev_device *prevdevice; > +static struct platform_driver omap_previewer_driver; > + > +static u32 prev_bufsize; > + > +/** > + * prev_calculate_crop - Calculate crop size according to device parameters > + * @device: Structure containing ISP preview wrapper global information > + * @crop: Structure containing crop size > + * > + * This function is used to calculate frame size reduction depending on > + * the features enabled by the application. > + **/ > +static void prev_calculate_crop(struct prev_device *device, > + struct prev_cropsize *crop) > +{ > + dev_dbg(prev_dev, "prev_calculate_crop E\n"); > + > + if (!device || !crop) { > + dev_err(prev_dev, "\nErron in argument"); > + return; > + } > + > + isppreview_try_size(device->params->size_params.hsize, > + device->params->size_params.vsize, > + &crop->hcrop, &crop->vcrop); > + crop->hcrop &= PREV_16PIX_ALIGN_MASK; > + dev_dbg(prev_dev, "prev_calculate_crop L\n"); > +} > + > +/** > + * prev_get_status - Get status of ISP preview module > + * @status: Structure containing the busy state. > + * > + * Checks if the ISP preview module is busy. > + * > + * Returns 0 if successful, or -EINVAL if the status parameter is invalid. > + **/ > +static int prev_get_status(struct prev_status *status) > +{ > + if (!status) { > + dev_err(prev_dev, "get_status: invalid parameter\n"); > + return -EINVAL; > + } > + status->hw_busy = (char)isppreview_busy(); > + return 0; > +} > + > +/** > + * prev_hw_setup - Stores the desired configuration in the proper HW registers > + * @config: Structure containing the desired configuration for ISP preview > + * module. > + * > + * Reads the structure sent, and modifies the desired registers. > + * > + * Always returns 0. > + **/ > +static int prev_hw_setup(struct prev_params *config) > +{ > + dev_dbg(prev_dev, "prev_hw_setup E\n"); > + > + if (config->features & PREV_AVERAGER) > + isppreview_config_averager(config->average); > + else > + isppreview_config_averager(0); > + > + if (config->features & PREV_INVERSE_ALAW) > + isppreview_enable_invalaw(1); > + else > + isppreview_enable_invalaw(0); > + > + if (config->features & PREV_HORZ_MEDIAN_FILTER) { > + isppreview_config_hmed(config->hmf_params); > + isppreview_enable_hmed(1); > + } else > + isppreview_enable_hmed(0); > + > + if (config->features & PREV_DARK_FRAME_SUBTRACT) { > + isppreview_set_darkaddr(config->drkf_params.addr); > + isppreview_config_darklineoffset(config->drkf_params.offset); > + isppreview_enable_drkframe(1); > + } else > + isppreview_enable_drkframe(0); > + > + if (config->features & PREV_LENS_SHADING) { > + isppreview_config_drkf_shadcomp(config->lens_shading_shift); > + isppreview_enable_shadcomp(1); > + } else > + isppreview_enable_shadcomp(0); > + > + dev_dbg(prev_dev, "prev_hw_setup L\n"); > + return 0; > +} > + > +/** > + * prev_validate_params - Validate configuration parameters for Preview Wrapper > + * @params: Structure containing configuration parameters > + * > + * Validate configuration parameters for Preview Wrapper > + * > + * Returns 0 if successful, or -EINVAL if a parameter value is invalid. > + **/ > +static int prev_validate_params(struct prev_params *params) > +{ > + if (!params) { > + dev_err(prev_dev, "validate_params: error in argument"); > + goto err_einval; > + } > + > + if ((params->features & PREV_AVERAGER) == PREV_AVERAGER) { > + if ((params->average != NO_AVE) > + && (params->average != AVE_2_PIX) > + && (params->average != AVE_4_PIX) > + && (params->average != AVE_8_PIX)) { > + dev_err(prev_dev, "validate_params: wrong pix " > + "average\n"); > + goto err_einval; > + } else if (((params->average == AVE_2_PIX) > + && (params->size_params.hsize % 2)) > + || ((params->average == AVE_4_PIX) > + && (params->size_params.hsize % 4)) > + || ((params->average == AVE_8_PIX) > + && (params->size_params.hsize % 8))) { > + dev_err(prev_dev, "validate_params: " > + "wrong pix average for input size\n"); > + goto err_einval; > + } > + } > + > + if ((params->size_params.pixsize != PREV_INWIDTH_8BIT) > + && (params->size_params.pixsize > + != PREV_INWIDTH_10BIT)) { > + dev_err(prev_dev, "validate_params: wrong pixsize\n"); > + goto err_einval; > + } > + > + if (params->size_params.hsize > MAX_IMAGE_WIDTH > + || params->size_params.hsize < 0) { > + dev_err(prev_dev, "validate_params: wrong hsize\n"); > + goto err_einval; > + } > + > + if ((params->pix_fmt != YCPOS_YCrYCb) > + && (YCPOS_YCbYCr != params->pix_fmt) > + && (YCPOS_CbYCrY != params->pix_fmt) > + && (YCPOS_CrYCbY != params->pix_fmt)) { > + dev_err(prev_dev, "validate_params: wrong pix_fmt"); > + goto err_einval; > + } > + > + if ((params->features & PREV_DARK_FRAME_SUBTRACT) > + && (params->features > + & PREV_DARK_FRAME_CAPTURE)) { > + dev_err(prev_dev, "validate_params: DARK FRAME CAPTURE and " > + "SUBSTRACT cannot be enabled " > + "at same time\n"); > + goto err_einval; > + } > + > + if (params->features & PREV_DARK_FRAME_SUBTRACT) > + if (!params->drkf_params.addr > + || (params->drkf_params.offset % 32)) { > + dev_err(prev_dev, "validate_params: dark frame " > + "address\n"); > + goto err_einval; > + } > + > + if (params->features & PREV_LENS_SHADING) > + if ((params->lens_shading_shift > 7) > + || !params->drkf_params.addr > + || (params->drkf_params.offset % 32)) { > + dev_err(prev_dev, "validate_params: lens shading " > + "shift\n"); > + goto err_einval; > + } > + > + if ((params->size_params.in_pitch <= 0) > + || (params->size_params.in_pitch % 32)) { > + params->size_params.in_pitch = > + (params->size_params.hsize * 2) & 0xFFE0; > + dev_err(prev_dev, "\nError in in_pitch; new value = %d", > + params->size_params.in_pitch); > + } > + > + return 0; > +err_einval: > + return -EINVAL; > +} > + > +/** > + * preview_isr - Callback from ISP driver for ISP Preview Interrupt > + * @status: ISP IRQ0STATUS register value > + * @arg1: Structure containing ISP preview wrapper global information > + * @arg2: Currently not used > + **/ > +static void preview_isr(unsigned long status, isp_vbq_callback_ptr arg1, > + void *arg2) > +{ > + struct prev_device *device = (struct prev_device *)arg1; > + > + if ((status & PREV_DONE) != PREV_DONE) > + return; > + > + if (device) > + complete(&device->wfc); > +} > + > +/** > + * prev_do_preview - Performs the Preview process > + * @device: Structure containing ISP preview wrapper global information > + * @arg: Currently not used > + * > + * Returns 0 if successful, or -EINVAL if the sent parameters are invalid. > + **/ > +static int prev_do_preview(struct prev_device *device, int *arg) > +{ > + int bpp, size; > + int ret = 0; > + u32 out_hsize, out_vsize, out_line_offset; > + > + dev_dbg(prev_dev, "prev_do_preview E\n"); > + > + if (!device) { > + dev_err(prev_dev, "preview: invalid parameters\n"); > + return -EINVAL; > + } > + > + if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT) > + bpp = 1; > + else > + bpp = 2; > + > + size = device->params->size_params.hsize * > + device->params->size_params.vsize * bpp; > + > + ret = isppreview_set_inaddr(device->isp_addr_read); > + if (ret) > + goto out; > + > + ret = isppreview_set_outaddr(device->isp_addr_read); > + if (ret) > + goto out; > + > + isppreview_try_size(device->params->size_params.hsize, > + device->params->size_params.vsize, > + &out_hsize, &out_vsize); > + > + ret = isppreview_config_inlineoffset(device->params->size_params.hsize > + * bpp); > + if (ret) > + goto out; > + > + out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK; > + > + ret = isppreview_config_outlineoffset(out_line_offset); > + if (ret) > + goto out; > + > + ret = isppreview_config_size(device->params->size_params.hsize, > + device->params->size_params.vsize, > + out_hsize, out_vsize); > + if (ret) > + goto out; > + > + isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM); > + > + ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device, > + (void *)NULL); > + if (ret) { > + dev_err(prev_dev, "ERROR while setting Previewer callback!\n"); > + goto out; > + } > + isppreview_enable(1); > + > + wait_for_completion_interruptible(&device->wfc); > + > + if (device->isp_addr_read) { > + ispmmu_unmap(device->isp_addr_read); > + device->isp_addr_read = 0; > + } > + > + ret = isp_unset_callback(CBK_PREV_DONE); > + > + dev_dbg(prev_dev, "prev_do_preview L\n"); > +out: > + return ret; > +} > + > +/** > + * previewer_vbq_release - Videobuffer queue release > + * @q: Structure containing the videobuffer queue. > + * @vb: Structure containing the videobuffer used for previewer processing. > + **/ > +static void previewer_vbq_release(struct videobuf_queue *q, > + struct videobuf_buffer *vb) > +{ > + struct prev_fh *fh = q->priv_data; > + struct prev_device *device = fh->device; > + > + ispmmu_unmap(device->isp_addr_read); > + device->isp_addr_read = 0; > + spin_lock(&device->vbq_lock); > + vb->state = VIDEOBUF_NEEDS_INIT; > + spin_unlock(&device->vbq_lock); > + dev_dbg(prev_dev, "previewer_vbq_release\n"); > +} > + > +/** > + * previewer_vbq_setup - Sets up the videobuffer size and validates count. > + * @q: Structure containing the videobuffer queue. > + * @cnt: Number of buffers requested > + * @size: Size in bytes of the buffer used for previewing > + * > + * Always returns 0. > + **/ > +static int previewer_vbq_setup(struct videobuf_queue *q, > + unsigned int *cnt, > + unsigned int *size) > +{ > + struct prev_fh *fh = q->priv_data; > + struct prev_device *device = fh->device; > + u32 bpp = 1; > + > + spin_lock(&device->vbq_lock); > + if (*cnt <= 0) > + *cnt = VIDEO_MAX_FRAME; > + > + if (*cnt > VIDEO_MAX_FRAME) > + *cnt = VIDEO_MAX_FRAME; > + > + if (!device->params->size_params.hsize || > + !device->params->size_params.vsize) { > + dev_err(prev_dev, "Can't setup buffer size\n"); > + spin_unlock(&device->vbq_lock); > + return -EINVAL; > + } > + > + if (device->params->size_params.pixsize == PREV_INWIDTH_10BIT) > + bpp = 2; > + *size = prev_bufsize = bpp * device->params->size_params.hsize > + * device->params->size_params.vsize; > + spin_unlock(&device->vbq_lock); > + dev_dbg(prev_dev, "previewer_vbq_setup\n"); > + return 0; > +} > + > +/** > + * previewer_vbq_prepare - Videobuffer is prepared and mmapped. > + * @q: Structure containing the videobuffer queue. > + * @vb: Structure containing the videobuffer used for previewer 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 previewer_vbq_prepare(struct videobuf_queue *q, > + struct videobuf_buffer *vb, > + enum v4l2_field field) > +{ > + struct prev_fh *fh = q->priv_data; > + struct prev_device *device = fh->device; > + int err = -EINVAL; > + unsigned int isp_addr; > + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); > + > + dev_dbg(prev_dev, "previewer_vbq_prepare E\n"); > + spin_lock(&device->vbq_lock); > + if (vb->baddr) { > + vb->size = prev_bufsize; > + vb->bsize = prev_bufsize; > + } else { > + spin_unlock(&device->vbq_lock); > + dev_err(prev_dev, "No user buffer allocated\n"); > + goto out; > + } > + > + vb->width = device->params->size_params.hsize; > + vb->height = device->params->size_params.vsize; > + vb->field = field; > + spin_unlock(&device->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 > + device->isp_addr_read = isp_addr; > + } > + } > + > + if (!err) { > + vb->state = VIDEOBUF_PREPARED; > + flush_cache_user_range(NULL, vb->baddr, > + (vb->baddr + vb->bsize)); > + } else > + previewer_vbq_release(q, vb); > + > + dev_dbg(prev_dev, "previewer_vbq_prepare L\n"); > +out: > + return err; > +} > + > +static void previewer_vbq_queue(struct videobuf_queue *q, > + struct videobuf_buffer *vb) > +{ > + return; > +} > + > +/** > + * previewer_open - Initializes and opens the Preview Wrapper > + * @inode: Inode structure associated with the Preview Wrapper > + * @filp: File structure associated with the Preview Wrapper > + * > + * Returns 0 if successful, -EACCES if its unable to initialize default config, > + * -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 previewer_open(struct inode *inode, struct file *filp) > +{ > + int ret = 0; > + struct prev_device *device = prevdevice; > + struct prev_params *config = isppreview_get_config(); > + struct prev_fh *fh; > + > + if (config == NULL) { > + dev_err(prev_dev, "Unable to initialize default config " > + "from isppreviewer\n\n"); > + return -EACCES; > + } > + > + if (device->opened || (filp->f_flags & O_NONBLOCK)) { > + dev_err(prev_dev, "previewer_open: device is already " > + "opened\n"); > + return -EBUSY; > + } > + > + fh = kzalloc(sizeof(struct prev_fh), GFP_KERNEL); > + if (NULL == fh) > + return -ENOMEM; > + > + isp_get(); > + ret = isppreview_request(); > + if (ret) { > + isp_put(); > + dev_err(prev_dev, "Can't acquire isppreview\n"); > + return ret; > + } > + > + device->params = config; > + device->opened = 1; > + > + filp->private_data = fh; > + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > + fh->device = device; > + > + videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL, > + &device->vbq_lock, fh->type, > + V4L2_FIELD_NONE, > + sizeof(struct videobuf_buffer), fh); > + > + init_completion(&device->wfc); > + device->wfc.done = 0; > + mutex_init(&device->prevwrap_mutex); > + > + return 0; > +} > + > +/** > + * previewer_release - Releases Preview Wrapper and frees up allocated memory > + * @inode: Inode structure associated with the Preview Wrapper > + * @filp: File structure associated with the Preview Wrapper > + * > + * Always returns 0. > + **/ > +static int previewer_release(struct inode *inode, struct file *filp) > +{ > + struct prev_fh *fh = filp->private_data; > + struct prev_device *device = fh->device; > + struct videobuf_queue *q = &fh->vbq; > + > + device->opened = 0; > + device->params = NULL; > + isppreview_free(); > + videobuf_mmap_free(q); > + isp_put(); > + prev_bufsize = 0; > + filp->private_data = NULL; > + kfree(fh); > + > + dev_dbg(prev_dev, "previewer_release\n"); > + return 0; > +} > + > +/** > + * previewer_mmap - Memory maps the Preview Wrapper module. > + * @file: File structure associated with the Preview Wrapper > + * @vma: Virtual memory area structure. > + * > + * Returns 0 if successful, or returned value by the videobuf_mmap_mapper() > + * function. > + **/ > +static int previewer_mmap(struct file *file, struct vm_area_struct *vma) > +{ > + struct prev_fh *fh = file->private_data; > + dev_dbg(prev_dev, "previewer_mmap\n"); > + > + return videobuf_mmap_mapper(&fh->vbq, vma); > +} > + > +/** > + * previewer_ioctl - I/O control function for Preview Wrapper > + * @inode: Inode structure associated with the Preview Wrapper. > + * @file: File structure associated with the Preview Wrapper. > + * @cmd: Type of command to execute. > + * @arg: Argument to send to requested command. > + * > + * Returns 0 if successful, -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 int previewer_ioctl(struct inode *inode, struct file *file, > + unsigned int cmd, unsigned long arg) > +{ > + int ret = 0; > + struct prev_params params; > + struct prev_fh *fh = file->private_data; > + struct prev_device *device = fh->device; > + > + dev_dbg(prev_dev, "Entering previewer_ioctl()\n"); > + > + if ((_IOC_TYPE(cmd) != PREV_IOC_BASE) > + || (_IOC_NR(cmd) > PREV_IOC_MAXNR)) { > + dev_err(prev_dev, "Bad command Value \n"); > + goto err_minusone; > + } > + > + 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(prev_dev, "access denied\n"); > + goto err_minusone; > + } > + > + switch (cmd) { > + case PREV_REQBUF: > + if (mutex_lock_interruptible(&device->prevwrap_mutex)) > + goto err_eintr; > + ret = videobuf_reqbufs(&fh->vbq, (void *)arg); > + mutex_unlock(&device->prevwrap_mutex); > + break; > + > + case PREV_QUERYBUF: > + if (mutex_lock_interruptible(&device->prevwrap_mutex)) > + goto err_eintr; > + ret = videobuf_querybuf(&fh->vbq, (void *)arg); > + mutex_unlock(&device->prevwrap_mutex); > + break; > + > + case PREV_QUEUEBUF: > + if (mutex_lock_interruptible(&device->prevwrap_mutex)) > + goto err_eintr; > + ret = videobuf_qbuf(&fh->vbq, (void *)arg); > + mutex_unlock(&device->prevwrap_mutex); > + break; > + > + case PREV_SET_PARAM: > + if (mutex_lock_interruptible(&device->prevwrap_mutex)) > + goto err_eintr; > + if (copy_from_user(¶ms, (struct prev_params *)arg, > + sizeof(struct prev_params))) { > + mutex_unlock(&device->prevwrap_mutex); > + return -EFAULT; > + } > + ret = prev_validate_params(¶ms); > + if (ret < 0) { > + dev_err(prev_dev, "Error validating parameters!\n"); > + mutex_unlock(&device->prevwrap_mutex); > + goto out; > + } > + if (device->params) > + memcpy(device->params, ¶ms, > + sizeof(struct prev_params)); > + else { > + mutex_unlock(&device->prevwrap_mutex); > + return -EINVAL; > + } > + > + ret = prev_hw_setup(device->params); > + mutex_unlock(&device->prevwrap_mutex); > + break; > + > + case PREV_GET_PARAM: > + if (copy_to_user((struct prev_params *)arg, device->params, > + sizeof(struct prev_params))) > + ret = -EFAULT; > + break; > + > + case PREV_GET_STATUS: > + ret = prev_get_status((struct prev_status *)arg); > + break; > + > + case PREV_PREVIEW: > + if (mutex_lock_interruptible(&device->prevwrap_mutex)) > + goto err_eintr; > + ret = prev_do_preview(device, (int *)arg); > + mutex_unlock(&device->prevwrap_mutex); > + break; > + > + case PREV_GET_CROPSIZE: > + { > + struct prev_cropsize outputsize; > + prev_calculate_crop(device, &outputsize); > + if (copy_to_user((struct prev_cropsize *)arg, &outputsize, > + sizeof(struct prev_cropsize))) > + ret = -EFAULT; > + } > + break; > + > + default: > + dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n"); > + ret = -EINVAL; > + } > +out: > + return ret; > +err_minusone: > + return -1; > +err_eintr: > + return -EINTR; > +} > + > +/** > + * previewer_platform_release - Acts when Reference count is zero > + * @device: Structure containing ISP preview wrapper global information > + * > + * This is called when the reference count goes to zero > + **/ > +static void previewer_platform_release(struct device *device) > +{ > + dev_dbg(prev_dev, "previewer_platform_release()\n"); > +} > + > +static struct file_operations prev_fops = { > + .owner = THIS_MODULE, > + .open = previewer_open, > + .release = previewer_release, > + .mmap = previewer_mmap, > + .ioctl = previewer_ioctl, > +}; > + > +static struct platform_device omap_previewer_device = { > + .name = OMAP_PREV_NAME, > + .id = -1, > + .dev = { > + .release = previewer_platform_release, > + } > +}; > + > +/** > + * previewer_probe - Checks for device presence > + * @pdev: Structure containing details of the current device. > + * > + * Always returns 0 > + **/ > +static int __init previewer_probe(struct platform_device *pdev) > +{ > + return 0; > +} > + > +/** > + * previewer_remove - Handles the removal of the driver > + * @pdev: Structure containing details of the current device. > + * > + * Always returns 0. > + **/ > +static int previewer_remove(struct platform_device *pdev) > +{ > + dev_dbg(prev_dev, "previewer_remove()\n"); > + > + platform_device_unregister(&omap_previewer_device); > + platform_driver_unregister(&omap_previewer_driver); > + unregister_chrdev(prev_major, OMAP_PREV_NAME); > + return 0; > +} > + > +static struct platform_driver omap_previewer_driver = { > + .probe = previewer_probe, > + .remove = previewer_remove, > + .driver = { > + .owner = THIS_MODULE, > + .name = OMAP_PREV_NAME, > + }, > +}; > + > +/** > + * omap_previewer_init - Initialization of Preview 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_previewer_init(void) > +{ > + int ret; > + struct prev_device *device; > + > + device = kzalloc(sizeof(struct prev_device), GFP_KERNEL); > + if (!device) { > + dev_err(prev_dev, OMAP_PREV_NAME ": could not allocate" > + " memory\n"); > + return -ENOMEM; > + } > + prev_major = register_chrdev(0, OMAP_PREV_NAME, &prev_fops); > + > + if (prev_major < 0) { > + dev_err(prev_dev, OMAP_PREV_NAME ": initialization " > + "failed. could not register character " > + "device\n"); > + return -ENODEV; > + } > + > + ret = platform_driver_register(&omap_previewer_driver); > + if (ret) { > + dev_err(prev_dev, OMAP_PREV_NAME > + ": failed to register platform driver!\n"); > + goto fail2; > + } > + ret = platform_device_register(&omap_previewer_device); > + if (ret) { > + dev_err(prev_dev, OMAP_PREV_NAME > + ": failed to register platform device!\n"); > + goto fail3; > + } > + > + prev_class = class_create(THIS_MODULE, OMAP_PREV_NAME); > + if (!prev_class) > + goto fail4; > + > + prev_dev = device_create(prev_class, prev_dev, > + (MKDEV(prev_major, 0)), NULL, > + OMAP_PREV_NAME); > + dev_dbg(prev_dev, OMAP_PREV_NAME ": Registered Previewer Wrapper\n"); > + device->opened = 0; > + > + device->vbq_ops.buf_setup = previewer_vbq_setup; > + device->vbq_ops.buf_prepare = previewer_vbq_prepare; > + device->vbq_ops.buf_release = previewer_vbq_release; > + device->vbq_ops.buf_queue = previewer_vbq_queue; > + spin_lock_init(&device->vbq_lock); > + > + prevdevice = device; > + return 0; > + > +fail4: > + platform_device_unregister(&omap_previewer_device); > +fail3: > + platform_driver_unregister(&omap_previewer_driver); > +fail2: > + unregister_chrdev(prev_major, OMAP_PREV_NAME); > + > + return ret; > +} > + > +/** > + * omap_previewer_exit - Close of Preview Wrapper > + **/ > +static void __exit omap_previewer_exit(void) > +{ > + previewer_remove(&omap_previewer_device); > + kfree(prevdevice); > + prev_major = -1; > +} > + > +module_init(omap_previewer_init); > +module_exit(omap_previewer_exit); > + > +MODULE_AUTHOR("Texas Instruments"); > +MODULE_DESCRIPTION("OMAP ISP Previewer"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/media/video/isp/omap_previewer.h b/drivers/media/video/isp/omap_previewer.h > new file mode 100644 > index 0000000..0bb31cd > --- /dev/null > +++ b/drivers/media/video/isp/omap_previewer.h > @@ -0,0 +1,162 @@ > +/* > + * drivers/media/video/isp/omap_previewer.h > + * > + * Header file for Preview module wrapper in TI's OMAP3430 ISP > + * > + * Copyright (C) 2008 Texas Instruments, Inc. > + * > + * Contributors: > + * Leonides Martinez <leonides.martinez@xxxxxx> > + * Sergio Aguirre <saaguirre@xxxxxx> > + * > + * 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 "isppreview.h" > + > +#ifndef OMAP_ISP_PREVIEW_WRAP_H > +#define OMAP_ISP_PREVIEW_WRAP_H > + > +#define PREV_IOC_BASE 'P' > +#define PREV_REQBUF _IOWR(PREV_IOC_BASE, 1,\ > + struct v4l2_requestbuffers) > +#define PREV_QUERYBUF _IOWR(PREV_IOC_BASE, 2,\ > + struct v4l2_buffer) > +#define PREV_SET_PARAM _IOW(PREV_IOC_BASE, 3,\ > + struct prev_params) > +#define PREV_GET_PARAM _IOWR(PREV_IOC_BASE, 4,\ > + struct prev_params) > +#define PREV_PREVIEW _IOR(PREV_IOC_BASE, 5, int) > +#define PREV_GET_STATUS _IOR(PREV_IOC_BASE, 6, char) > +#define PREV_GET_CROPSIZE _IOR(PREV_IOC_BASE, 7,\ > + struct prev_cropsize) > +#define PREV_QUEUEBUF _IOWR(PREV_IOC_BASE, 8,\ > + struct v4l2_buffer) Isn't this supposed to be used by applications? If so, then all the public API part should go to a header in the include/linux directory. Also inconsistent naming: either pick _G_ or _GET_ (resizer uses mostly _G_, as does v4l2, so I recommend to stick with that). I'm also missing documentation for these new ioctls. Something should be added under the Documentation/video4linux directory. I know, it's not stricly v4l2, but it seems to be the logical place for it. Regards, Hans > +#define PREV_IOC_MAXNR 8 > + > +#define LUMA_TABLE_SIZE 128 > +#define GAMMA_TABLE_SIZE 1024 > +#define CFA_COEFF_TABLE_SIZE 576 > +#define NOISE_FILTER_TABLE_SIZE 256 > + > +#define MAX_IMAGE_WIDTH 3300 > + > +#define PREV_INWIDTH_8BIT 0 /* pixel width of 8 bits */ > +#define PREV_INWIDTH_10BIT 1 /* pixel width of 10 bits */ > + > +#define PREV_32BYTES_ALIGN_MASK 0xFFFFFFE0 > +#define PREV_16PIX_ALIGN_MASK 0xFFFFFFF0 > + > +/** > + * struct prev_rgbblending - Structure for RGB2RGB blending parameters > + * @blending: Color correlation 3x3 matrix. > + * @offset: Color correlation offsets. > + */ > +struct prev_rgbblending { > + short blending[RGB_MAX][RGB_MAX]; /* color correlation 3x3 > + * matrix. > + */ > + short offset[RGB_MAX]; /* color correlation offsets */ > +}; > + > +/** > + * struct prev_cfa_coeffs - Structure for CFA coefficients > + * @hthreshold: Horizontal threshold. > + * @vthreshold: Vertical threshold. > + * @coeffs: CFA coefficients > + */ > +struct prev_cfa_coeffs { > + char hthreshold, vthreshold; > + int coeffs[CFA_COEFF_TABLE_SIZE]; > +}; > + > +/** > + * struct prev_gamma_coeffs - Structure for Gamma Coefficients > + * @red: Table of gamma correction values for red color. > + * @green: Table of gamma correction values for green color. > + * @blue: Table of gamma correction values for blue color. > + */ > +struct prev_gamma_coeffs { > + unsigned char red[GAMMA_TABLE_SIZE]; > + unsigned char green[GAMMA_TABLE_SIZE]; > + unsigned char blue[GAMMA_TABLE_SIZE]; > +}; > + > +/** > + * struct prev_noiseflt_coeffs - Structure for Noise Filter Coefficients. > + * @noise: Noise filter table. > + * @strength: Used to find out weighted average. > + */ > +struct prev_noiseflt_coeffs { > + unsigned char noise[NOISE_FILTER_TABLE_SIZE]; > + unsigned char strength; > +}; > + > +/** > + * struct prev_chroma_spr - Structure for Chroma Suppression. > + * @hpfy: High passed version of Y or normal Y. > + * @threshold: Threshold for chroma suppress. > + * @gain: Chroma suppression gain > + */ > +struct prev_chroma_spr { > + unsigned char hpfy; > + char threshold; > + unsigned char gain; > +}; > + > +/** > + * struct prev_status - Structure to know status of the hardware > + * @hw_busy: Flag to indicate if Hardware is Busy. > + */ > +struct prev_status { > + char hw_busy; > +}; > + > +/** > + * struct prev_cropsize - Structure to know crop size. > + * @hcrop: Horizontal size of crop window. > + * @vcrop: Vertical size of crop window. > + */ > +struct prev_cropsize { > + int hcrop; > + int vcrop; > +}; Don't use int, char, short, etc. Instead use __u8, __u16, etc. in public headers. > + > +/** > + * struct prev_device - Global device information structure. > + * @params: Pointer to structure containing preview parameters. > + * @opened: State of the device. > + * @wfc: Wait for completion. Used for locking operations. > + * @prevwrap_mutex: Mutex for preview wrapper use. > + * @vbq_lock: Spinlock for videobuf queues. > + * @vbq_ops: Videobuf queue operations > + * @isp_addr_read: Input/Output address > + */ > +struct prev_device { > + struct prev_params *params; > + unsigned char opened; > + struct completion wfc; > + struct mutex prevwrap_mutex; /* For generic internal use */ > + spinlock_t vbq_lock; /* For videobuffer queue handling */ > + struct videobuf_queue_ops vbq_ops; > + dma_addr_t isp_addr_read; > +}; > + > +/** > + * struct prev_fh - Per-filehandle data structure > + * @type: Used buffer type. > + * @vbq: Videobuffer queue. > + * @device: Pointer to device information structure. > + */ > +struct prev_fh { > + enum v4l2_buf_type type; > + struct videobuf_queue vbq; > + struct prev_device *device; > +}; > +#endif > diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c > new file mode 100644 > index 0000000..93109e7 > --- /dev/null > +++ b/drivers/media/video/isp/omap_resizer.c > @@ -0,0 +1,1631 @@ > +/* > + * 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@xxxxxx> > + * Troy Laramy <t-laramy@xxxxxx> > + * > + * 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, ISPRSZ_CNT); > + > + omap_writel(rsz_conf_chan->register_config.rsz_in_start, > + ISPRSZ_IN_START); > + omap_writel(rsz_conf_chan->register_config.rsz_in_size, > + ISPRSZ_IN_SIZE); > + > + omap_writel(rsz_conf_chan->register_config.rsz_out_size, > + ISPRSZ_OUT_SIZE); > + omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd, > + ISPRSZ_SDR_INADD); > + omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff, > + ISPRSZ_SDR_INOFF); > + omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd, > + ISPRSZ_SDR_OUTADD); > + omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff, > + ISPRSZ_SDR_OUTOFF); > + omap_writel(rsz_conf_chan->register_config.rsz_yehn, ISPRSZ_YENH); > + > + for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER; > + coeffcounter++) { > + omap_writel(rsz_conf_chan->register_config. > + rsz_coeff_horz[coeffcounter], > + ISPRSZ_HFILT10 + coeffoffset); > + > + omap_writel(rsz_conf_chan->register_config. > + rsz_coeff_vert[coeffcounter], > + 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.5.6.5 > > > -- > video4linux-list mailing list > Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe > https://www.redhat.com/mailman/listinfo/video4linux-list > > -- Hans Verkuil - video4linux developer - sponsored by TANDBERG -- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list