add support for autofocus unit of dm365 SoC. The autofocus register seup, isr and parameter calidation functionality is implemented as part of this module. Signed-off-by: Manjunath Hadli <manjunath.hadli@xxxxxx> --- drivers/media/video/davinci/dm365_af.c | 564 ++++++++++++++++++++++++++++++++ drivers/media/video/davinci/dm365_af.h | 59 ++++ include/linux/dm365_af.h | 203 ++++++++++++ 3 files changed, 826 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/davinci/dm365_af.c create mode 100644 drivers/media/video/davinci/dm365_af.h create mode 100644 include/linux/dm365_af.h diff --git a/drivers/media/video/davinci/dm365_af.c b/drivers/media/video/davinci/dm365_af.c new file mode 100644 index 0000000..7d0240e --- /dev/null +++ b/drivers/media/video/davinci/dm365_af.c @@ -0,0 +1,564 @@ +/* +* Copyright (C) 2011 Texas Instruments Inc +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <media/v4l2-device.h> +#include "dm365_a3_hw.h" +#include "vpss.h" +#include "vpfe_af.h" + +#define DRIVERNAME "DM365AF" + +/*Global structure for device */ +static struct af_device *af_dev_configptr; +static struct device *afdev; + +/* inline function to free reserver pages */ +inline void af_free_pages(unsigned long addr, unsigned long bufsize) +{ + unsigned long tempaddr; + unsigned long size; + + tempaddr = addr; + if (!addr) + return; + + size = PAGE_SIZE << (get_order(bufsize)); + while (size > 0) { + ClearPageReserved(virt_to_page(addr)); + addr += PAGE_SIZE; + size -= PAGE_SIZE; + } + free_pages(tempaddr, get_order(bufsize)); +} + +/* Function to check paxel parameters */ +static int af_validate_parameters(void) +{ + dev_dbg(afdev, "auto focus validate parameters\n"); + + /* Check horizontal Count */ + if (af_dev_configptr->config->paxel_config.hz_cnt < + AF_PAXEL_HORIZONTAL_COUNT_MIN || + af_dev_configptr->config->paxel_config.hz_cnt > + AF_PAXEL_HORIZONTAL_COUNT_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Horizontal Count is incorrect\n"); + return -EINVAL; + } + /* Check Vertical Count */ + if (af_dev_configptr->config->paxel_config.vt_cnt < + AF_PAXEL_VERTICAL_COUNT_MIN || + af_dev_configptr->config->paxel_config.vt_cnt > + AF_PAXEL_VERTICAL_COUNT_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Vertical Count is incorrect\n"); + return -EINVAL; + } + /* Check line increment */ + if (NOT_EVEN == + CHECK_EVEN(af_dev_configptr->config->paxel_config.line_incr) || + af_dev_configptr->config->paxel_config.line_incr < + AF_LINE_INCR_MIN || + af_dev_configptr->config->paxel_config.line_incr > + AF_LINE_INCR_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Line Increment is incorrect\n"); + return -EINVAL; + } + if (af_dev_configptr->config->fv_sel == AF_HFV_AND_VFV && (NOT_EVEN == + CHECK_EVEN(af_dev_configptr->config->paxel_config.column_incr) || + af_dev_configptr->config->paxel_config.column_incr < + AF_COLUMN_INCR_MIN || + af_dev_configptr->config->paxel_config.column_incr > + AF_COLUMN_INCR_MAX)) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Column Increment is incorrect\n"); + return -EINVAL; + } + /* Check width */ + if (NOT_EVEN == + CHECK_EVEN(af_dev_configptr->config->paxel_config.width) || + af_dev_configptr->config->paxel_config.width < AF_WIDTH_MIN || + af_dev_configptr->config->paxel_config.width > AF_WIDTH_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Width is incorrect\n"); + return -EINVAL; + } + /* Check Height */ + if (NOT_EVEN == + CHECK_EVEN(af_dev_configptr->config->paxel_config.height) || + af_dev_configptr->config->paxel_config.height < AF_HEIGHT_MIN || + af_dev_configptr->config->paxel_config.height > AF_HEIGHT_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel Height is incorrect\n"); + return -EINVAL; + } + /* Check Horizontal Start */ + if (NOT_EVEN == + CHECK_EVEN(af_dev_configptr->config->paxel_config.hz_start) || + (af_dev_configptr->config->paxel_config.hz_start < + (af_dev_configptr->config->iir_config.hz_start_pos + 2)) || + af_dev_configptr->config->paxel_config.hz_start < + AF_HZSTART_MIN || + af_dev_configptr->config->paxel_config.hz_start > + AF_HZSTART_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel horizontal start is incorrect\n"); + return -EINVAL; + } + /* Check Vertical Start */ + if (af_dev_configptr->config->paxel_config.vt_start < AF_VTSTART_MIN || + af_dev_configptr->config->paxel_config.vt_start > AF_VTSTART_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "Paxel vertical start is incorrect\n"); + return -EINVAL; + } + /* Check Threshold */ + if (af_dev_configptr->config->hmf_config.threshold > AF_MEDTH_MAX && + af_dev_configptr->config->hmf_config.enable == H3A_AF_ENABLE) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, + "Horizontal Median Filter Threshold is incorrect\n"); + return -EINVAL; + } + /* Check IIRSH start */ + if (af_dev_configptr->config->iir_config.hz_start_pos > AF_IIRSH_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, + "IIR FITLER horizontal start position incorrect\n"); + return -EINVAL; + } + /* Verify ALaw */ + if (af_dev_configptr->config->alaw_enable < H3A_AF_DISABLE || + af_dev_configptr->config->alaw_enable > H3A_AF_ENABLE) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "ALaw Setting is incorrect\n"); + return -EINVAL; + } + /* Verify Horizontal Median Filter Setting */ + if (af_dev_configptr->config->hmf_config.enable < H3A_AF_DISABLE || + af_dev_configptr->config->hmf_config.enable > H3A_AF_ENABLE) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, + "Horizontal Median Filter Setting is incorrect\n"); + return -EINVAL; + } + /* Check RGB position if HFV used */ + if (af_dev_configptr->config->fv_sel == AF_HFV_ONLY && + (af_dev_configptr->config->rgb_pos < GR_GB_BAYER || + af_dev_configptr->config->rgb_pos > RB_GG_CUSTOM)) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "RGB Position Setting is incorrect\n"); + return -EINVAL; + } + if (af_dev_configptr->config->fv_sel == AF_HFV_AND_VFV) { + /* Check for threshold values */ + if (af_dev_configptr->config->fir_config.hfv_thr1 > + AF_HFV_THR_MAX || + af_dev_configptr->config->fir_config.hfv_thr2 > + AF_HFV_THR_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "HFV FIR 1 or FIR 2 Threshold" + " incorrect\n"); + return -EINVAL; + } + if (af_dev_configptr->config->fir_config.vfv_thr1 > + AF_VFV_THR_MAX || + af_dev_configptr->config->fir_config.vfv_thr2 > + AF_VFV_THR_MAX) { + dev_err(afdev, "Invalid Parameters\n"); + dev_err(afdev, "VFV FIR 1 or FIR 2 Threshold" + " incorrect\n"); + return -EINVAL; + } + } + + return 0; +} + +/* Function to perform hardware set up */ +static int af_hardware_setup(void) +{ + unsigned long adr, size; + unsigned int busyaf; + /* Size for buffer in bytes */ + int buff_size; + int result; + + /* Get the value of PCR register */ + busyaf = af_get_hw_state(); + /* If busy bit is 1 then busy lock registers caanot be configured */ + if (busyaf == 1) { + /* Hardware cannot be configure while engine is busy */ + dev_err(afdev, "AF_register_setup_ERROR : Engine Busy"); + dev_err(afdev, "\n Configuration cannot be done "); + return -EBUSY; + } + /* Check IIR Coefficient and start Values */ + result = af_validate_parameters(); + if (result < 0) + return result; + + /* Compute buffer size */ + if (af_dev_configptr->config->fv_sel == AF_HFV_ONLY) + buff_size = (af_dev_configptr->config->paxel_config.hz_cnt) * + (af_dev_configptr->config->paxel_config.vt_cnt) * + AF_PAXEL_SIZE_HF_ONLY; + else + buff_size = (af_dev_configptr->config->paxel_config.hz_cnt) * + (af_dev_configptr->config->paxel_config.vt_cnt) * + AF_PAXEL_SIZE_HF_VF; + + /* Deallocate the previosu buffers free old buffers */ + if (af_dev_configptr->buff_old) + af_free_pages((unsigned long)af_dev_configptr->buff_old, + af_dev_configptr->size_paxel); + + /* Free current buffer */ + if (af_dev_configptr->buff_curr) + af_free_pages((unsigned long)af_dev_configptr->buff_curr, + af_dev_configptr->size_paxel); + + /* Free application buffers */ + if (af_dev_configptr->buff_app) + af_free_pages((unsigned long)af_dev_configptr->buff_app, + af_dev_configptr->size_paxel); + + /* + * Reallocate the buffer as per new paxel configurations + * Allocate memory for old buffer + */ + af_dev_configptr->buff_old = (void *)__get_free_pages(GFP_KERNEL | + GFP_DMA, get_order(buff_size)); + + if (af_dev_configptr->buff_old == NULL) + return -ENOMEM; + + /* allocate the memory for storing old statistics */ + adr = (unsigned long)af_dev_configptr->buff_old; + size = PAGE_SIZE << (get_order(buff_size)); + while (size > 0) { + /* + * make sure the frame buffers + * are never swapped out of memory + */ + SetPageReserved(virt_to_page(adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + /* Allocate memory for current buffer */ + af_dev_configptr->buff_curr = (void *)__get_free_pages(GFP_KERNEL | + GFP_DMA, get_order(buff_size)); + + /* Free the previously allocated buffer */ + if (af_dev_configptr->buff_curr == NULL) { + if (af_dev_configptr->buff_old) + af_free_pages((unsigned long)af_dev_configptr-> + buff_old, buff_size); + return -ENOMEM; + } + + adr = (unsigned long)af_dev_configptr->buff_curr; + size = PAGE_SIZE << (get_order(buff_size)); + while (size > 0) { + /* + * make sure the frame buffers + * are never swapped out of memory + */ + SetPageReserved(virt_to_page(adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + /* Allocate memory for old buffer */ + af_dev_configptr->buff_app = (void *)__get_free_pages(GFP_KERNEL | + GFP_DMA, get_order(buff_size)); + + if (af_dev_configptr->buff_app == NULL) { + /* Free the previously allocated buffer */ + if (af_dev_configptr->buff_curr) + af_free_pages((unsigned long)af_dev_configptr-> + buff_curr, buff_size); + /* Free the previously allocated buffer */ + if (af_dev_configptr->buff_old) + af_free_pages((unsigned long)af_dev_configptr-> + buff_old, buff_size); + return -ENOMEM; + } + + adr = (unsigned long)af_dev_configptr->buff_app; + size = PAGE_SIZE << (get_order(buff_size)); + while (size > 0) { + /* + * make sure the frame buffers + * are never swapped out of memory + */ + SetPageReserved(virt_to_page(adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + result = af_register_setup(afdev, af_dev_configptr); + if (result < 0) + return result; + af_dev_configptr->size_paxel = buff_size; + /* Set configuration flag to indicate HW setup done */ + af_dev_configptr->af_config = H3A_AF_CONFIG; + + return 0; +} + +int af_open(void) +{ + /* Return if device is in use */ + if (af_dev_configptr->in_use == AF_IN_USE) + return -EBUSY; + af_dev_configptr->config = NULL; + + /* Allocate memory for Device Structure */ + af_dev_configptr->config = kmalloc(sizeof(struct af_configuration) + , GFP_KERNEL); + if (af_dev_configptr->config == NULL) { + dev_err(afdev, "Error : Kmalloc fail\n"); + return -ENOMEM; + } + /* Driver is in use */ + af_dev_configptr->in_use = AF_IN_USE; + /* Hardware is not set up */ + af_dev_configptr->af_config = H3A_AF_CONFIG_NOT_DONE; + /* No statistics are available */ + af_dev_configptr->buffer_filled = 0; + + return 0; +} + +int af_release(void) +{ + af_engine_setup(afdev, 0); + /* free current buffer */ + if (af_dev_configptr->buff_curr) + af_free_pages((unsigned long)af_dev_configptr->buff_curr, + af_dev_configptr->size_paxel); + + /* Free old buffer */ + if (af_dev_configptr->buff_old) + af_free_pages((unsigned long)af_dev_configptr->buff_old, + af_dev_configptr->size_paxel); + + /* Free application buffer */ + if (af_dev_configptr->buff_app) + af_free_pages((unsigned long)af_dev_configptr->buff_app, + af_dev_configptr->size_paxel); + + /* Release memory for configuration structure of this channel */ + af_dev_configptr->buff_curr = NULL; + af_dev_configptr->buff_old = NULL; + af_dev_configptr->buff_app = NULL; + kfree(af_dev_configptr->config); + af_dev_configptr->config = NULL; + /* Device is not in use */ + af_dev_configptr->in_use = AF_NOT_IN_USE; + + return 0; +} + +/* + * This function will process IOCTL commands sent by the application and + * control the device IO operations. + */ +int af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct af_configuration afconfig = *(af_dev_configptr->config); + struct af_statdata *stat_data = (struct af_statdata *)arg; + void *buff_temp; + int result; + + switch (cmd) { + + /* + * This ioctl is used to perform hardware + * set up for AF Engine. It will configure all the registers. + */ + case AF_S_PARAM: + memcpy(af_dev_configptr->config, (struct af_configuration *)arg, + sizeof(struct af_configuration)); + + /* Call AF_hardware_setup to perform register configuration */ + result = af_hardware_setup(); + if (!result) { + /* + * Hardware Set up is successful + * Return the no of bytes required for buffer + */ + result = af_dev_configptr->size_paxel; + } else { + dev_err(afdev, "Error : AF_S_PARAM failed\n"); + /* Change Configuration Structure to original */ + *(af_dev_configptr->config) = afconfig; + } + break; + + /* This ioctl will get the paramters from application */ + case AF_G_PARAM: + /* Check if Hardware is configured or not */ + if (af_dev_configptr->af_config == H3A_AF_CONFIG) { + memcpy((struct af_configuration *)arg, + af_dev_configptr->config, + sizeof(struct af_configuration)); + result = af_dev_configptr->size_paxel; + } else { + dev_dbg(afdev, "Error : AF Hardware not configured.\n"); + result = -EINVAL; + } + + break; + + case AF_GET_STAT: + /* Implement the read functionality */ + if (af_dev_configptr->buffer_filled != 1) + return -EINVAL; + + if (stat_data->buf_length < af_dev_configptr->size_paxel) + return -EINVAL; + + disable_irq(3); + af_dev_configptr->buffer_filled = 0; + /* Swap application buffer and old buffer */ + buff_temp = af_dev_configptr->buff_old; + af_dev_configptr->buff_old = af_dev_configptr->buff_app; + af_dev_configptr->buff_app = buff_temp; + /* Enable the interrupts once swapping is done */ + enable_irq(3); + /* + * Copy the entire statistics located in application + * buffer to user space + */ + memcpy(stat_data->buffer, af_dev_configptr->buff_app, + af_dev_configptr->size_paxel); + result = af_dev_configptr->size_paxel; + + break; + default: + dev_err(afdev, "Error : Invalid IOCTL!\n"); + result = -ENOTTY; + break; + } + + return result; +} + +/* This function will handle the H3A interrupt. */ +static irqreturn_t af_isr(int irq, void *dev_id) +{ + struct v4l2_subdev *sd = dev_id; + void *buff_temp; + int enaf; + + /* Get the value of PCR register */ + enaf = af_get_enable(); + + /* If AF Engine has enabled, interrupt is not for AF */ + if (!enaf || !af_dev_configptr) + return IRQ_RETVAL(IRQ_NONE); + + /* + * Service the Interrupt. Set buffer filled flag to indicate + * statistics are available. Swap current buffer and old buffer + */ + buff_temp = af_dev_configptr->buff_curr; + af_dev_configptr->buff_curr = af_dev_configptr->buff_old; + af_dev_configptr->buff_old = buff_temp; + + /* Set AF Buf st to current register address */ + if (af_dev_configptr->buff_curr) + af_set_address(afdev, + (unsigned long)virt_to_phys(af_dev_configptr->buff_curr)); + + /* Wake up read as new statistics are available */ + af_dev_configptr->buffer_filled = 1; + + /* queue the event with v4l2 */ + af_queue_event(sd); + + return IRQ_RETVAL(IRQ_HANDLED); + +} + +int af_set_stream(struct v4l2_subdev *sd, int enable) +{ + int result; + + if (!enable) { + /* stop capture */ + free_irq(3, sd); + /* Disable AEW Engine */ + af_engine_setup(afdev, 0); + return 0; + } + /* start capture */ + /* Enable AEW Engine if Hardware set up is done */ + if (af_dev_configptr->af_config == H3A_AF_CONFIG_NOT_DONE) { + dev_err(afdev, "Error : AF Hardware is not configured.\n"); + return -EINVAL; + } + result = request_irq(3, af_isr, IRQF_SHARED, "dm365_h3a_af", + (void *)sd); + if (result != 0) + return result; + + /* Enable AF Engine */ + af_engine_setup(afdev, 1); + + return 0; +} + +int af_init(struct platform_device *pdev) +{ + /* allocate memory for device structure and initialize it with 0 */ + af_dev_configptr = kmalloc(sizeof(struct af_device), GFP_KERNEL); + if (!af_dev_configptr) { + printk(KERN_ERR "af_init: Error : kmalloc fail\n"); + return -ENOMEM; + } + + /* Initialize device structure */ + memset((unsigned char *)af_dev_configptr, 0, sizeof(struct af_device)); + af_dev_configptr->in_use = AF_NOT_IN_USE; + af_dev_configptr->buffer_filled = 0; + afdev = &pdev->dev; + + return 0; +} + +void af_cleanup(void) +{ + /* in use */ + if (af_dev_configptr->in_use == AF_IN_USE) { + printk(KERN_ERR "Error : dm365_af in use."); + return; + } + /* Free device structure */ + kfree(af_dev_configptr); + af_dev_configptr = NULL; +} diff --git a/drivers/media/video/davinci/dm365_af.h b/drivers/media/video/davinci/dm365_af.h new file mode 100644 index 0000000..0483a92 --- /dev/null +++ b/drivers/media/video/davinci/dm365_af.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2011 Texas Instruments Inc +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef AF_DM365_DRIVER_H +#define AF_DM365_DRIVER_H + +#include <linux/ioctl.h> +#include <linux/wait.h> +#include <linux/mutex.h> +#include <linux/io.h> +#include <linux/dm365_af.h> + +/* Device Constants */ +#define AF_MAJOR_NUMBER 0 +#define AF_NR_DEVS 1 +#define AF_TIMEOUT ((300 * HZ) / 1000) + +/* Structure for device of AF Engine */ +struct af_device { + /* Driver usage counter */ + enum af_in_use_flag in_use; + /* Device configuration structure */ + struct af_configuration *config; + /* Contains the latest statistics */ + void *buff_old; + /* Buffer in which HW will fill the statistics or HW is already + * filling statistics + */ + void *buff_curr; + /* Buffer which will be passed to */ + void *buff_app; + /* user space on read call Size of image buffer */ + unsigned int buff_size; + /* Flag indicates */ + int buffer_filled; + /* statistics are available Paxel size in bytes */ + int size_paxel; + /* Wait queue for driver */ + wait_queue_head_t af_wait_queue; + /* mutex for driver */ + struct mutex read_blocked; + /* Flag indicates Engine is configured */ + enum af_config_flag af_config; +}; + +#endif /* AF_DM365_DRIVER_H */ diff --git a/include/linux/dm365_af.h b/include/linux/dm365_af.h new file mode 100644 index 0000000..43385cf --- /dev/null +++ b/include/linux/dm365_af.h @@ -0,0 +1,203 @@ +/* +* Copyright (C) 2011 Texas Instruments Inc +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DM365_AF_INCLUDE_H +#define _DM365_AF_INCLUDE_H + +/* Range Constants */ + +#define AF_PAXEL_HORIZONTAL_COUNT_MIN 1 +#define AF_PAXEL_HORIZONTAL_COUNT_MAX 36 + +#define AF_PAXEL_VERTICAL_COUNT_MIN 1 +#define AF_PAXEL_VERTICAL_COUNT_MAX 128 + +#define AF_PAXEL_HF_VF_COUNT_MAX 12 +#define AF_PAXEL_HF_VF_COUNT_MIN 1 + +#define AF_WIDTH_MIN 8 +#define AF_WIDTH_MAX 512 + +#define AF_LINE_INCR_MIN 2 +#define AF_LINE_INCR_MAX 32 + +#define AF_COLUMN_INCR_MIN 2 +#define AF_COLUMN_INCR_MAX 32 + +#define AF_HEIGHT_MIN 2 +#define AF_HEIGHT_MAX 512 + +#define AF_HZSTART_MIN 2 +#define AF_HZSTART_MAX 4094 + +#define AF_VTSTART_MIN 0 +#define AF_VTSTART_MAX 4095 + +#define AF_MEDTH_MAX 255 + +#define AF_IIRSH_MAX 4094 + +/* Statistics data size per paxel */ +#define AF_PAXEL_SIZE_HF_ONLY 48 +#define AF_PAXEL_SIZE_HF_VF 64 + +#define AF_NUMBER_OF_HFV_COEF 11 +#define AF_NUMBER_OF_VFV_COEF 5 +#define AF_HFV_COEF_MASK 0xfff +#define AF_VFV_COEF_MASK 0xff +#define AF_HFV_THR_MAX 0xffff +#define AF_VFV_THR_MAX 0xffff + +/* list of ioctls */ +#define AF_IOC_MAXNR 5 +#define AF_MAGIC_NO 'a' +#define AF_S_PARAM _IOWR(AF_MAGIC_NO, 1, struct af_configuration) +#define AF_G_PARAM _IOWR(AF_MAGIC_NO, 2, struct af_configuration) +#define AF_GET_STAT _IOWR(AF_MAGIC_NO, 3, struct af_statdata) + +/* enum used for status of specific feature */ +enum af_enable_flag { + H3A_AF_DISABLE, + H3A_AF_ENABLE +}; + +enum af_config_flag { + H3A_AF_CONFIG_NOT_DONE, + H3A_AF_CONFIG +}; + +struct af_reg_dump { + unsigned int addr; + unsigned int val; +}; + +/* enum used for keep track of whether hardware is used */ +enum af_in_use_flag { + AF_NOT_IN_USE, + AF_IN_USE +}; + +enum af_mode { + ACCUMULATOR_SUMMED, + ACCUMULATOR_PEAK +}; + +/* Focus value selection */ +enum af_focus_val_sel { + /* 4 color Horizontal focus value only */ + AF_HFV_ONLY, + /* 1 color Horizontal focus value & 1 color Vertical focus vlaue */ + AF_HFV_AND_VFV +}; + + +/* Red, Green, and blue pixel location in the AF windows */ +enum rgbpos { + /* GR and GB as Bayer pattern */ + GR_GB_BAYER, + /* RG and GB as Bayer pattern */ + RG_GB_BAYER, + /* GR and BG as Bayer pattern */ + GR_BG_BAYER, + /* RG and BG as Bayer pattern */ + RG_BG_BAYER, + /* GG and RB as custom pattern */ + GG_RB_CUSTOM, + /* RB and GG as custom pattern */ + RB_GG_CUSTOM +}; + +/* Contains the information regarding the Horizontal Median Filter */ +struct af_hmf { + /* Status of Horizontal Median Filter */ + enum af_enable_flag enable; + /* Threshhold Value for Horizontal Median Filter */ + unsigned int threshold; +}; + +/* Contains the information regarding the IIR Filters */ +struct af_iir { + /* IIR Start Register Value */ + unsigned int hz_start_pos; + /* IIR Filter Coefficient for Set 0 */ + int coeff_set0[AF_NUMBER_OF_HFV_COEF]; + /* IIR Filter Coefficient for Set 1 */ + int coeff_set1[AF_NUMBER_OF_HFV_COEF]; +}; + +/* Contains the information regarding the VFV FIR filters */ +struct af_fir { + /* FIR 1 coefficents */ + int coeff_1[AF_NUMBER_OF_VFV_COEF]; + /* FIR 2 coefficents */ + int coeff_2[AF_NUMBER_OF_VFV_COEF]; + /* Horizontal FV threshold for FIR 1 */ + unsigned int hfv_thr1; + /* Horizontal FV threshold for FIR 2 */ + unsigned int hfv_thr2; + /* Vertical FV threshold for FIR 1 */ + unsigned int vfv_thr1; + /* Vertical FV threshold for FIR 2 */ + unsigned int vfv_thr2; +}; +/* Contains the information regarding the Paxels Structure in AF Engine */ +struct af_paxel { + /* Width of the Paxel */ + unsigned int width; + /* Height of the Paxel */ + unsigned int height; + /* Horizontal Start Position */ + unsigned int hz_start; + /* Vertical Start Position */ + unsigned int vt_start; + /* Horizontal Count */ + unsigned int hz_cnt; + /* Vertical Count */ + unsigned int vt_cnt; + /* Line Increment */ + unsigned int line_incr; + /* Column Increment. Only for VFV */ + unsigned int column_incr; +}; + + +/* Contains the parameters required for hardware set up of AF Engine */ +struct af_configuration { + /* ALAW status */ + enum af_enable_flag alaw_enable; + /* Focus value selection */ + enum af_focus_val_sel fv_sel; + /* HMF configurations */ + struct af_hmf hmf_config; + /* RGB Positions. Only applicable with AF_HFV_ONLY selection */ + enum rgbpos rgb_pos; + /* IIR filter configurations */ + struct af_iir iir_config; + /* FIR filter configuration */ + struct af_fir fir_config; + /* Paxel parameters */ + struct af_paxel paxel_config; + /* Accumulator mode */ + enum af_mode mode; +}; + +struct af_statdata { + void *buffer; + int buf_length; +}; + +#endif -- 1.6.2.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html