Staging: HTC Dream: add camera support

This patch adds driver for HTC Dream camera. I guess driver is
slightly higher quality than usual for staging/ , but it is fairly big
and I don't feel like doing all the cleanups myself. Also some parts
can probably be removed, as they did not end up in shipping hardware..

Signed-off-by: Pavel Machek <pavel@ucw.cz>
Cc: Brian Swetland <swetland@google.com>
Cc: Iliyan Malchev <ibm@android.com>
Cc: San Mehat <san@android.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Brian Swetland 2009-07-17 14:45:17 +02:00 committed by Greg Kroah-Hartman
parent caff4caead
commit eb7b797b40
23 changed files with 17951 additions and 0 deletions

View File

@ -0,0 +1,46 @@
comment "Qualcomm MSM Camera And Video"
menuconfig MSM_CAMERA
bool "Qualcomm MSM camera and video capture support"
depends on ARCH_MSM && VIDEO_V4L2_COMMON
help
Say Y here to enable selecting the video adapters for
Qualcomm msm camera and video encoding
config MSM_CAMERA_DEBUG
bool "Qualcomm MSM camera debugging with printk"
depends on MSM_CAMERA
help
Enable printk() debug for msm camera
config MSM_CAMERA_FLASH
bool "Qualcomm MSM camera flash support"
depends on MSM_CAMERA
---help---
Enable support for LED flash for msm camera
comment "Camera Sensor Selection"
config MT9T013
bool "Sensor mt9t013 (BAYER 3M)"
depends on MSM_CAMERA
---help---
MICRON 3M Bayer Sensor with AutoFocus
config MT9D112
bool "Sensor mt9d112 (YUV 2M)"
depends on MSM_CAMERA
---help---
MICRON 2M YUV Sensor
config MT9P012
bool "Sensor mt9p012 (BAYER 5M)"
depends on MSM_CAMERA
---help---
MICRON 5M Bayer Sensor with Autofocus
config S5K3E2FX
bool "Sensor s5k3e2fx (Samsung 5M)"
depends on MSM_CAMERA
---help---
Samsung 5M with Autofocus

View File

@ -0,0 +1,7 @@
obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
obj-$(CONFIG_MT9D112) += mt9d112.o mt9d112_reg.o
obj-$(CONFIG_MT9P012) += mt9p012_fox.o mt9p012_reg.o
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o msm_v4l2.o
obj-$(CONFIG_S5K3E2FX) += s5k3e2fx.o
obj-$(CONFIG_ARCH_MSM) += msm_vfe7x.o msm_io7x.o
obj-$(CONFIG_ARCH_QSD) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,291 @@
/*
* Copyright (c) 2008-2009 QUALCOMM Incorporated
*/
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <mach/gpio.h>
#include <mach/board.h>
#include <mach/camera.h>
#define CAMIF_CFG_RMSK 0x1fffff
#define CAM_SEL_BMSK 0x2
#define CAM_PCLK_SRC_SEL_BMSK 0x60000
#define CAM_PCLK_INVERT_BMSK 0x80000
#define CAM_PAD_REG_SW_RESET_BMSK 0x100000
#define EXT_CAM_HSYNC_POL_SEL_BMSK 0x10000
#define EXT_CAM_VSYNC_POL_SEL_BMSK 0x8000
#define MDDI_CLK_CHICKEN_BIT_BMSK 0x80
#define CAM_SEL_SHFT 0x1
#define CAM_PCLK_SRC_SEL_SHFT 0x11
#define CAM_PCLK_INVERT_SHFT 0x13
#define CAM_PAD_REG_SW_RESET_SHFT 0x14
#define EXT_CAM_HSYNC_POL_SEL_SHFT 0x10
#define EXT_CAM_VSYNC_POL_SEL_SHFT 0xF
#define MDDI_CLK_CHICKEN_BIT_SHFT 0x7
#define APPS_RESET_OFFSET 0x00000210
static struct clk *camio_vfe_mdc_clk;
static struct clk *camio_mdc_clk;
static struct clk *camio_vfe_clk;
static struct msm_camera_io_ext camio_ext;
static struct resource *appio, *mdcio;
void __iomem *appbase, *mdcbase;
static struct msm_camera_io_ext camio_ext;
static struct resource *appio, *mdcio;
void __iomem *appbase, *mdcbase;
extern int clk_set_flags(struct clk *clk, unsigned long flags);
int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
{
int rc = -1;
struct clk *clk = NULL;
switch (clktype) {
case CAMIO_VFE_MDC_CLK:
clk = camio_vfe_mdc_clk = clk_get(NULL, "vfe_mdc_clk");
break;
case CAMIO_MDC_CLK:
clk = camio_mdc_clk = clk_get(NULL, "mdc_clk");
break;
case CAMIO_VFE_CLK:
clk = camio_vfe_clk = clk_get(NULL, "vfe_clk");
break;
default:
break;
}
if (!IS_ERR(clk)) {
clk_enable(clk);
rc = 0;
}
return rc;
}
int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
{
int rc = -1;
struct clk *clk = NULL;
switch (clktype) {
case CAMIO_VFE_MDC_CLK:
clk = camio_vfe_mdc_clk;
break;
case CAMIO_MDC_CLK:
clk = camio_mdc_clk;
break;
case CAMIO_VFE_CLK:
clk = camio_vfe_clk;
break;
default:
break;
}
if (!IS_ERR(clk)) {
clk_disable(clk);
clk_put(clk);
rc = 0;
}
return rc;
}
void msm_camio_clk_rate_set(int rate)
{
struct clk *clk = camio_vfe_clk;
if (clk != ERR_PTR(-ENOENT))
clk_set_rate(clk, rate);
}
int msm_camio_enable(struct platform_device *pdev)
{
int rc = 0;
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camio_ext = camdev->ioext;
appio = request_mem_region(camio_ext.appphy,
camio_ext.appsz, pdev->name);
if (!appio) {
rc = -EBUSY;
goto enable_fail;
}
appbase = ioremap(camio_ext.appphy,
camio_ext.appsz);
if (!appbase) {
rc = -ENOMEM;
goto apps_no_mem;
}
mdcio = request_mem_region(camio_ext.mdcphy,
camio_ext.mdcsz, pdev->name);
if (!mdcio) {
rc = -EBUSY;
goto mdc_busy;
}
mdcbase = ioremap(camio_ext.mdcphy,
camio_ext.mdcsz);
if (!mdcbase) {
rc = -ENOMEM;
goto mdc_no_mem;
}
camdev->camera_gpio_on();
msm_camio_clk_enable(CAMIO_VFE_CLK);
msm_camio_clk_enable(CAMIO_MDC_CLK);
msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
return 0;
mdc_no_mem:
release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
mdc_busy:
iounmap(appbase);
apps_no_mem:
release_mem_region(camio_ext.appphy, camio_ext.appsz);
enable_fail:
return rc;
}
void msm_camio_disable(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
iounmap(mdcbase);
release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
iounmap(appbase);
release_mem_region(camio_ext.appphy, camio_ext.appsz);
camdev->camera_gpio_off();
msm_camio_clk_disable(CAMIO_VFE_CLK);
msm_camio_clk_disable(CAMIO_MDC_CLK);
msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
}
void msm_camio_camif_pad_reg_reset(void)
{
uint32_t reg;
uint32_t mask, value;
/* select CLKRGM_VFE_SRC_CAM_VFE_SRC: internal source */
msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_SEL_BMSK |
CAM_PCLK_SRC_SEL_BMSK |
CAM_PCLK_INVERT_BMSK;
value = 1 << CAM_SEL_SHFT |
3 << CAM_PCLK_SRC_SEL_SHFT |
0 << CAM_PCLK_INVERT_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
mdelay(10);
}
void msm_camio_vfe_blk_reset(void)
{
uint32_t val;
val = readl(appbase + 0x00000210);
val |= 0x1;
writel(val, appbase + 0x00000210);
mdelay(10);
val = readl(appbase + 0x00000210);
val &= ~0x1;
writel(val, appbase + 0x00000210);
mdelay(10);
}
void msm_camio_camif_pad_reg_reset_2(void)
{
uint32_t reg;
uint32_t mask, value;
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
}
void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
{
struct clk *clk = NULL;
clk = camio_vfe_clk;
if (clk != NULL && clk != ERR_PTR(-ENOENT)) {
switch (srctype) {
case MSM_CAMIO_CLK_SRC_INTERNAL:
clk_set_flags(clk, 0x00000100 << 1);
break;
case MSM_CAMIO_CLK_SRC_EXTERNAL:
clk_set_flags(clk, 0x00000100);
break;
default:
break;
}
}
}
int msm_camio_probe_on(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camdev->camera_gpio_on();
return msm_camio_clk_enable(CAMIO_VFE_CLK);
}
int msm_camio_probe_off(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camdev->camera_gpio_off();
return msm_camio_clk_disable(CAMIO_VFE_CLK);
}

View File

@ -0,0 +1,320 @@
/*
* Copyright (c) 2008-2009 QUALCOMM Incorporated
*/
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <mach/gpio.h>
#include <mach/board.h>
#include <mach/camera.h>
#define CAMIF_CFG_RMSK 0x1fffff
#define CAM_SEL_BMSK 0x2
#define CAM_PCLK_SRC_SEL_BMSK 0x60000
#define CAM_PCLK_INVERT_BMSK 0x80000
#define CAM_PAD_REG_SW_RESET_BMSK 0x100000
#define EXT_CAM_HSYNC_POL_SEL_BMSK 0x10000
#define EXT_CAM_VSYNC_POL_SEL_BMSK 0x8000
#define MDDI_CLK_CHICKEN_BIT_BMSK 0x80
#define CAM_SEL_SHFT 0x1
#define CAM_PCLK_SRC_SEL_SHFT 0x11
#define CAM_PCLK_INVERT_SHFT 0x13
#define CAM_PAD_REG_SW_RESET_SHFT 0x14
#define EXT_CAM_HSYNC_POL_SEL_SHFT 0x10
#define EXT_CAM_VSYNC_POL_SEL_SHFT 0xF
#define MDDI_CLK_CHICKEN_BIT_SHFT 0x7
#define APPS_RESET_OFFSET 0x00000210
static struct clk *camio_vfe_mdc_clk;
static struct clk *camio_mdc_clk;
static struct clk *camio_vfe_clk;
static struct clk *camio_vfe_axi_clk;
static struct msm_camera_io_ext camio_ext;
static struct resource *appio, *mdcio;
void __iomem *appbase, *mdcbase;
extern int clk_set_flags(struct clk *clk, unsigned long flags);
int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
{
int rc = 0;
struct clk *clk = NULL;
switch (clktype) {
case CAMIO_VFE_MDC_CLK:
camio_vfe_mdc_clk =
clk = clk_get(NULL, "vfe_mdc_clk");
break;
case CAMIO_MDC_CLK:
camio_mdc_clk =
clk = clk_get(NULL, "mdc_clk");
break;
case CAMIO_VFE_CLK:
camio_vfe_clk =
clk = clk_get(NULL, "vfe_clk");
break;
case CAMIO_VFE_AXI_CLK:
camio_vfe_axi_clk =
clk = clk_get(NULL, "vfe_axi_clk");
break;
default:
break;
}
if (!IS_ERR(clk))
clk_enable(clk);
else
rc = -1;
return rc;
}
int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
{
int rc = 0;
struct clk *clk = NULL;
switch (clktype) {
case CAMIO_VFE_MDC_CLK:
clk = camio_vfe_mdc_clk;
break;
case CAMIO_MDC_CLK:
clk = camio_mdc_clk;
break;
case CAMIO_VFE_CLK:
clk = camio_vfe_clk;
break;
case CAMIO_VFE_AXI_CLK:
clk = camio_vfe_axi_clk;
break;
default:
break;
}
if (!IS_ERR(clk)) {
clk_disable(clk);
clk_put(clk);
} else
rc = -1;
return rc;
}
void msm_camio_clk_rate_set(int rate)
{
struct clk *clk = camio_vfe_mdc_clk;
/* TODO: check return */
clk_set_rate(clk, rate);
}
int msm_camio_enable(struct platform_device *pdev)
{
int rc = 0;
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camio_ext = camdev->ioext;
appio = request_mem_region(camio_ext.appphy,
camio_ext.appsz, pdev->name);
if (!appio) {
rc = -EBUSY;
goto enable_fail;
}
appbase = ioremap(camio_ext.appphy,
camio_ext.appsz);
if (!appbase) {
rc = -ENOMEM;
goto apps_no_mem;
}
mdcio = request_mem_region(camio_ext.mdcphy,
camio_ext.mdcsz, pdev->name);
if (!mdcio) {
rc = -EBUSY;
goto mdc_busy;
}
mdcbase = ioremap(camio_ext.mdcphy,
camio_ext.mdcsz);
if (!mdcbase) {
rc = -ENOMEM;
goto mdc_no_mem;
}
camdev->camera_gpio_on();
msm_camio_clk_enable(CAMIO_VFE_CLK);
msm_camio_clk_enable(CAMIO_MDC_CLK);
msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
msm_camio_clk_enable(CAMIO_VFE_AXI_CLK);
return 0;
mdc_no_mem:
release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
mdc_busy:
iounmap(appbase);
apps_no_mem:
release_mem_region(camio_ext.appphy, camio_ext.appsz);
enable_fail:
return rc;
}
void msm_camio_disable(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
iounmap(mdcbase);
release_mem_region(camio_ext.mdcphy, camio_ext.mdcsz);
iounmap(appbase);
release_mem_region(camio_ext.appphy, camio_ext.appsz);
camdev->camera_gpio_off();
msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
msm_camio_clk_disable(CAMIO_MDC_CLK);
msm_camio_clk_disable(CAMIO_VFE_CLK);
msm_camio_clk_disable(CAMIO_VFE_AXI_CLK);
}
void msm_camio_camif_pad_reg_reset(void)
{
uint32_t reg;
uint32_t mask, value;
/* select CLKRGM_VFE_SRC_CAM_VFE_SRC: internal source */
msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_SEL_BMSK |
CAM_PCLK_SRC_SEL_BMSK |
CAM_PCLK_INVERT_BMSK |
EXT_CAM_HSYNC_POL_SEL_BMSK |
EXT_CAM_VSYNC_POL_SEL_BMSK |
MDDI_CLK_CHICKEN_BIT_BMSK;
value = 1 << CAM_SEL_SHFT |
3 << CAM_PCLK_SRC_SEL_SHFT |
0 << CAM_PCLK_INVERT_SHFT |
0 << EXT_CAM_HSYNC_POL_SEL_SHFT |
0 << EXT_CAM_VSYNC_POL_SEL_SHFT |
0 << MDDI_CLK_CHICKEN_BIT_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
msm_camio_clk_sel(MSM_CAMIO_CLK_SRC_EXTERNAL);
mdelay(10);
/* todo: check return */
if (camio_vfe_clk)
clk_set_rate(camio_vfe_clk, 96000000);
}
void msm_camio_vfe_blk_reset(void)
{
uint32_t val;
val = readl(appbase + 0x00000210);
val |= 0x1;
writel(val, appbase + 0x00000210);
mdelay(10);
val = readl(appbase + 0x00000210);
val &= ~0x1;
writel(val, appbase + 0x00000210);
mdelay(10);
}
void msm_camio_camif_pad_reg_reset_2(void)
{
uint32_t reg;
uint32_t mask, value;
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 1 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
reg = (readl(mdcbase)) & CAMIF_CFG_RMSK;
mask = CAM_PAD_REG_SW_RESET_BMSK;
value = 0 << CAM_PAD_REG_SW_RESET_SHFT;
writel((reg & (~mask)) | (value & mask), mdcbase);
mdelay(10);
}
void msm_camio_clk_sel(enum msm_camio_clk_src_type srctype)
{
struct clk *clk = NULL;
clk = camio_vfe_clk;
if (clk != NULL) {
switch (srctype) {
case MSM_CAMIO_CLK_SRC_INTERNAL:
clk_set_flags(clk, 0x00000100 << 1);
break;
case MSM_CAMIO_CLK_SRC_EXTERNAL:
clk_set_flags(clk, 0x00000100);
break;
default:
break;
}
}
}
void msm_camio_clk_axi_rate_set(int rate)
{
struct clk *clk = camio_vfe_axi_clk;
/* todo: check return */
clk_set_rate(clk, rate);
}
int msm_camio_probe_on(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camdev->camera_gpio_on();
return msm_camio_clk_enable(CAMIO_VFE_MDC_CLK);
}
int msm_camio_probe_off(struct platform_device *pdev)
{
struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
struct msm_camera_device_platform_data *camdev = sinfo->pdata;
camdev->camera_gpio_off();
return msm_camio_clk_disable(CAMIO_VFE_MDC_CLK);
}

View File

@ -0,0 +1,793 @@
/*
*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*
*/
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/ioctl.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>
#include <linux/proc_fs.h>
#include <media/v4l2-dev.h>
#include <media/msm_camera.h>
#include <mach/camera.h>
#include <media/v4l2-ioctl.h>
/*#include <linux/platform_device.h>*/
#define MSM_V4L2_START_SNAPSHOT _IOWR('V', BASE_VIDIOC_PRIVATE+1, \
struct v4l2_buffer)
#define MSM_V4L2_GET_PICTURE _IOWR('V', BASE_VIDIOC_PRIVATE+2, \
struct v4l2_buffer)
#define MSM_V4L2_DEVICE_NAME "msm_v4l2"
#define MSM_V4L2_PROC_NAME "msm_v4l2"
#define MSM_V4L2_DEVNUM_MPEG2 0
#define MSM_V4L2_DEVNUM_YUV 20
/* HVGA-P (portrait) and HVGA-L (landscape) */
#define MSM_V4L2_WIDTH 480
#define MSM_V4L2_HEIGHT 320
#if 1
#define D(fmt, args...) printk(KERN_INFO "msm_v4l2: " fmt, ##args)
#else
#define D(fmt, args...) do {} while (0)
#endif
#define PREVIEW_FRAMES_NUM 4
struct msm_v4l2_device {
struct list_head read_queue;
struct v4l2_format current_cap_format;
struct v4l2_format current_pix_format;
struct video_device *pvdev;
struct msm_v4l2_driver *drv;
uint8_t opencnt;
spinlock_t read_queue_lock;
};
static struct msm_v4l2_device *g_pmsm_v4l2_dev;
static DEFINE_MUTEX(msm_v4l2_opencnt_lock);
static int msm_v4l2_open(struct file *f)
{
int rc = 0;
D("%s\n", __func__);
mutex_lock(&msm_v4l2_opencnt_lock);
if (!g_pmsm_v4l2_dev->opencnt) {
rc = g_pmsm_v4l2_dev->drv->open(
g_pmsm_v4l2_dev->drv->sync,
MSM_APPS_ID_V4L2);
}
g_pmsm_v4l2_dev->opencnt++;
mutex_unlock(&msm_v4l2_opencnt_lock);
return rc;
}
static int msm_v4l2_release(struct file *f)
{
int rc = 0;
D("%s\n", __func__);
mutex_lock(&msm_v4l2_opencnt_lock);
if (!g_pmsm_v4l2_dev->opencnt) {
g_pmsm_v4l2_dev->opencnt--;
if (!g_pmsm_v4l2_dev->opencnt) {
rc = g_pmsm_v4l2_dev->drv->release(
g_pmsm_v4l2_dev->drv->sync);
}
}
mutex_unlock(&msm_v4l2_opencnt_lock);
return rc;
}
static unsigned int msm_v4l2_poll(struct file *f, struct poll_table_struct *w)
{
return g_pmsm_v4l2_dev->drv->drv_poll(g_pmsm_v4l2_dev->drv->sync, f, w);
}
static long msm_v4l2_ioctl(struct file *filep,
unsigned int cmd, unsigned long arg)
{
struct msm_ctrl_cmd *ctrlcmd;
D("msm_v4l2_ioctl, cmd = %d, %d\n", cmd, __LINE__);
switch (cmd) {
case MSM_V4L2_START_SNAPSHOT:
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_ioctl: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->length = 0;
ctrlcmd->value = NULL;
ctrlcmd->timeout_ms = 10000;
D("msm_v4l2_ioctl, MSM_V4L2_START_SNAPSHOT v4l2 ioctl %d\n",
cmd);
ctrlcmd->type = MSM_V4L2_SNAPSHOT;
return g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync,
ctrlcmd);
case MSM_V4L2_GET_PICTURE:
D("msm_v4l2_ioctl, MSM_V4L2_GET_PICTURE v4l2 ioctl %d\n", cmd);
ctrlcmd = (struct msm_ctrl_cmd *)arg;
return g_pmsm_v4l2_dev->drv->get_pict(
g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
default:
D("msm_v4l2_ioctl, standard v4l2 ioctl %d\n", cmd);
return video_ioctl2(filep, cmd, arg);
}
}
static void msm_v4l2_release_dev(struct video_device *d)
{
D("%s\n", __func__);
}
static int msm_v4l2_querycap(struct file *f,
void *pctx, struct v4l2_capability *pcaps)
{
D("%s\n", __func__);
strncpy(pcaps->driver, MSM_APPS_ID_V4L2, sizeof(pcaps->driver));
strncpy(pcaps->card,
MSM_V4L2_DEVICE_NAME, sizeof(pcaps->card));
pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
return 0;
}
static int msm_v4l2_s_std(struct file *f, void *pctx, v4l2_std_id *pnorm)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_queryctrl(struct file *f,
void *pctx, struct v4l2_queryctrl *pqctrl)
{
int rc = 0;
struct msm_ctrl_cmd *ctrlcmd;
D("%s\n", __func__);
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_queryctrl: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_QUERY_CTRL;
ctrlcmd->length = sizeof(struct v4l2_queryctrl);
ctrlcmd->value = pqctrl;
ctrlcmd->timeout_ms = 10000;
rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
if (rc < 0)
return -1;
return ctrlcmd->status;
}
static int msm_v4l2_g_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
{
int rc = 0;
struct msm_ctrl_cmd *ctrlcmd;
D("%s\n", __func__);
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_g_ctrl: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_GET_CTRL;
ctrlcmd->length = sizeof(struct v4l2_control);
ctrlcmd->value = c;
ctrlcmd->timeout_ms = 10000;
rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
if (rc < 0)
return -1;
return ctrlcmd->status;
}
static int msm_v4l2_s_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
{
int rc = 0;
struct msm_ctrl_cmd *ctrlcmd;
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_s_ctrl: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_SET_CTRL;
ctrlcmd->length = sizeof(struct v4l2_control);
ctrlcmd->value = c;
ctrlcmd->timeout_ms = 10000;
D("%s\n", __func__);
rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
if (rc < 0)
return -1;
return ctrlcmd->status;
}
static int msm_v4l2_reqbufs(struct file *f,
void *pctx, struct v4l2_requestbuffers *b)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_querybuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
{
struct msm_pmem_info pmem_buf;
#if 0
__u32 width = 0;
__u32 height = 0;
__u32 y_size = 0;
__u32 y_pad = 0;
/* FIXME: g_pmsm_v4l2_dev->current_pix_format.fmt.pix.width; */
width = 640;
/* FIXME: g_pmsm_v4l2_dev->current_pix_format.fmt.pix.height; */
height = 480;
D("%s: width = %d, height = %d\n", __func__, width, height);
y_size = width * height;
y_pad = y_size % 4;
#endif
__u32 y_pad = pb->bytesused % 4;
/* V4L2 videodev will do the copy_from_user. */
memset(&pmem_buf, 0, sizeof(struct msm_pmem_info));
pmem_buf.type = MSM_PMEM_OUTPUT2;
pmem_buf.vaddr = (void *)pb->m.userptr;
pmem_buf.y_off = 0;
pmem_buf.fd = (int)pb->reserved;
/* pmem_buf.cbcr_off = (y_size + y_pad); */
pmem_buf.cbcr_off = (pb->bytesused + y_pad);
g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync, &pmem_buf);
return 0;
}
static int msm_v4l2_qbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
{
/*
__u32 y_size = 0;
__u32 y_pad = 0;
__u32 width = 0;
__u32 height = 0;
*/
__u32 y_pad = 0;
struct msm_pmem_info meminfo;
struct msm_frame frame;
static int cnt;
if ((pb->flags >> 16) & 0x0001) {
/* this is for previwe */
#if 0
width = 640;
height = 480;
/* V4L2 videodev will do the copy_from_user. */
D("%s: width = %d, height = %d\n", __func__, width, height);
y_size = width * height;
y_pad = y_size % 4;
#endif
y_pad = pb->bytesused % 4;
if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
/* this qbuf is actually for releasing */
frame.buffer = pb->m.userptr;
frame.y_off = 0;
/* frame.cbcr_off = (y_size + y_pad); */
frame.cbcr_off = (pb->bytesused + y_pad);
frame.fd = pb->reserved;
D("V4L2_BUF_TYPE_PRIVATE: pb->bytesused = %d \n",
pb->bytesused);
g_pmsm_v4l2_dev->drv->put_frame(
g_pmsm_v4l2_dev->drv->sync,
&frame);
return 0;
}
D("V4L2_BUF_TYPE_VIDEO_CAPTURE: pb->bytesused = %d \n",
pb->bytesused);
meminfo.type = MSM_PMEM_OUTPUT2;
meminfo.fd = (int)pb->reserved;
meminfo.vaddr = (void *)pb->m.userptr;
meminfo.y_off = 0;
/* meminfo.cbcr_off = (y_size + y_pad); */
meminfo.cbcr_off = (pb->bytesused + y_pad);
if (cnt == PREVIEW_FRAMES_NUM - 1)
meminfo.active = 0;
else
meminfo.active = 1;
cnt++;
g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
&meminfo);
} else if ((pb->flags) & 0x0001) {
/* this is for snapshot */
__u32 y_size = 0;
if ((pb->flags >> 8) & 0x01) {
y_size = pb->bytesused;
meminfo.type = MSM_PMEM_THUMBAIL;
} else if ((pb->flags >> 9) & 0x01) {
y_size = pb->bytesused;
meminfo.type = MSM_PMEM_MAINIMG;
}
y_pad = y_size % 4;
meminfo.fd = (int)pb->reserved;
meminfo.vaddr = (void *)pb->m.userptr;
meminfo.y_off = 0;
/* meminfo.cbcr_off = (y_size + y_pad); */
meminfo.cbcr_off = (y_size + y_pad);
meminfo.active = 1;
g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
&meminfo);
}
return 0;
}
static int msm_v4l2_dqbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
{
struct msm_frame frame;
D("%s\n", __func__);
/* V4L2 videodev will do the copy_to_user. */
if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
D("%s, %d\n", __func__, __LINE__);
g_pmsm_v4l2_dev->drv->get_frame(
g_pmsm_v4l2_dev->drv->sync,
&frame);
pb->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pb->m.userptr = (unsigned long)frame.buffer; /* FIXME */
pb->reserved = (int)frame.fd;
/* pb->length = (int)frame.cbcr_off; */
pb->bytesused = frame.cbcr_off;
} else if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
__u32 y_pad = pb->bytesused % 4;
frame.buffer = pb->m.userptr;
frame.y_off = 0;
/* frame.cbcr_off = (y_size + y_pad); */
frame.cbcr_off = (pb->bytesused + y_pad);
frame.fd = pb->reserved;
g_pmsm_v4l2_dev->drv->put_frame(
g_pmsm_v4l2_dev->drv->sync,
&frame);
}
return 0;
}
static int msm_v4l2_streamon(struct file *f, void *pctx, enum v4l2_buf_type i)
{
struct msm_ctrl_cmd *ctrlcmd;
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_STREAM_ON;
ctrlcmd->timeout_ms = 10000;
ctrlcmd->length = 0;
ctrlcmd->value = NULL;
D("%s\n", __func__);
g_pmsm_v4l2_dev->drv->ctrl(
g_pmsm_v4l2_dev->drv->sync,
ctrlcmd);
D("%s after drv->ctrl \n", __func__);
return 0;
}
static int msm_v4l2_streamoff(struct file *f, void *pctx, enum v4l2_buf_type i)
{
struct msm_ctrl_cmd *ctrlcmd;
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_STREAM_OFF;
ctrlcmd->timeout_ms = 10000;
ctrlcmd->length = 0;
ctrlcmd->value = NULL;
D("%s\n", __func__);
g_pmsm_v4l2_dev->drv->ctrl(
g_pmsm_v4l2_dev->drv->sync,
ctrlcmd);
return 0;
}
static int msm_v4l2_enum_fmt_overlay(struct file *f,
void *pctx, struct v4l2_fmtdesc *pfmtdesc)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_enum_fmt_cap(struct file *f,
void *pctx, struct v4l2_fmtdesc *pfmtdesc)
{
D("%s\n", __func__);
switch (pfmtdesc->index) {
case 0:
pfmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pfmtdesc->flags = 0;
strncpy(pfmtdesc->description, "YUV 4:2:0",
sizeof(pfmtdesc->description));
pfmtdesc->pixelformat = V4L2_PIX_FMT_YVU420;
break;
default:
return -EINVAL;
}
return 0;
}
static int msm_v4l2_g_fmt_cap(struct file *f,
void *pctx, struct v4l2_format *pfmt)
{
D("%s\n", __func__);
pfmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
pfmt->fmt.pix.field = V4L2_FIELD_ANY;
pfmt->fmt.pix.bytesperline = 0;
pfmt->fmt.pix.sizeimage = 0;
pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
pfmt->fmt.pix.priv = 0;
return 0;
}
static int msm_v4l2_s_fmt_cap(struct file *f,
void *pctx, struct v4l2_format *pfmt)
{
struct msm_ctrl_cmd *ctrlcmd;
D("%s\n", __func__);
ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
if (!ctrlcmd) {
CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
return -ENOMEM;
}
ctrlcmd->type = MSM_V4L2_VID_CAP_TYPE;
ctrlcmd->length = sizeof(struct v4l2_format);
ctrlcmd->value = pfmt;
ctrlcmd->timeout_ms = 10000;
if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -1;
#if 0
/* FIXEME */
if (pfmt->fmt.pix.pixelformat != V4L2_PIX_FMT_YVU420)
return -EINVAL;
#endif
/* Ok, but check other params, too. */
#if 0
memcpy(&g_pmsm_v4l2_dev->current_pix_format.fmt.pix, pfmt,
sizeof(struct v4l2_format));
#endif
g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
return 0;
}
static int msm_v4l2_g_fmt_overlay(struct file *f,
void *pctx, struct v4l2_format *pfmt)
{
D("%s\n", __func__);
pfmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
pfmt->fmt.pix.field = V4L2_FIELD_ANY;
pfmt->fmt.pix.bytesperline = 0;
pfmt->fmt.pix.sizeimage = 0;
pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
pfmt->fmt.pix.priv = 0;
return 0;
}
static int msm_v4l2_s_fmt_overlay(struct file *f,
void *pctx, struct v4l2_format *pfmt)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_overlay(struct file *f, void *pctx, unsigned int i)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_g_jpegcomp(struct file *f,
void *pctx, struct v4l2_jpegcompression *pcomp)
{
D("%s\n", __func__);
return 0;
}
static int msm_v4l2_s_jpegcomp(struct file *f,
void *pctx, struct v4l2_jpegcompression *pcomp)
{
D("%s\n", __func__);
return 0;
}
#ifdef CONFIG_PROC_FS
int msm_v4l2_read_proc(char *pbuf, char **start, off_t offset,
int count, int *eof, void *data)
{
int len = 0;
len += snprintf(pbuf, strlen("stats\n") + 1, "stats\n");
if (g_pmsm_v4l2_dev) {
len += snprintf(pbuf, strlen("mode: ") + 1, "mode: ");
if (g_pmsm_v4l2_dev->current_cap_format.type
== V4L2_BUF_TYPE_VIDEO_CAPTURE)
len += snprintf(pbuf, strlen("capture\n") + 1,
"capture\n");
else
len += snprintf(pbuf, strlen("unknown\n") + 1,
"unknown\n");
len += snprintf(pbuf, 21, "resolution: %dx%d\n",
g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
width,
g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
height);
len += snprintf(pbuf,
strlen("pixel format: ") + 1, "pixel format: ");
if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.pixelformat
== V4L2_PIX_FMT_YVU420)
len += snprintf(pbuf, strlen("yvu420\n") + 1,
"yvu420\n");
else
len += snprintf(pbuf, strlen("unknown\n") + 1,
"unknown\n");
len += snprintf(pbuf, strlen("colorspace: ") + 1,
"colorspace: ");
if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.colorspace
== V4L2_COLORSPACE_JPEG)
len += snprintf(pbuf, strlen("jpeg\n") + 1, "jpeg\n");
else
len += snprintf(pbuf, strlen("unknown\n") + 1,
"unknown\n");
}
*eof = 1;
return len;
}
#endif
static const struct v4l2_file_operations msm_v4l2_fops = {
.owner = THIS_MODULE,
.open = msm_v4l2_open,
.poll = msm_v4l2_poll,
.release = msm_v4l2_release,
.ioctl = msm_v4l2_ioctl,
};
static void msm_v4l2_dev_init(struct msm_v4l2_device *pmsm_v4l2_dev)
{
pmsm_v4l2_dev->read_queue_lock =
__SPIN_LOCK_UNLOCKED(pmsm_v4l2_dev->read_queue_lock);
INIT_LIST_HEAD(&pmsm_v4l2_dev->read_queue);
}
static int msm_v4l2_try_fmt_cap(struct file *file,
void *fh, struct v4l2_format *f)
{
/* FIXME */
return 0;
}
static int mm_v4l2_try_fmt_type_private(struct file *file,
void *fh, struct v4l2_format *f)
{
/* FIXME */
return 0;
}
/*
* should the following structure be used instead of the code in the function?
* static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
* .vidioc_querycap = ....
* }
*/
static const struct v4l2_ioctl_ops msm_ioctl_ops = {
.vidioc_querycap = msm_v4l2_querycap,
.vidioc_s_std = msm_v4l2_s_std,
.vidioc_queryctrl = msm_v4l2_queryctrl,
.vidioc_g_ctrl = msm_v4l2_g_ctrl,
.vidioc_s_ctrl = msm_v4l2_s_ctrl,
.vidioc_reqbufs = msm_v4l2_reqbufs,
.vidioc_querybuf = msm_v4l2_querybuf,
.vidioc_qbuf = msm_v4l2_qbuf,
.vidioc_dqbuf = msm_v4l2_dqbuf,
.vidioc_streamon = msm_v4l2_streamon,
.vidioc_streamoff = msm_v4l2_streamoff,
.vidioc_enum_fmt_vid_overlay = msm_v4l2_enum_fmt_overlay,
.vidioc_enum_fmt_vid_cap = msm_v4l2_enum_fmt_cap,
.vidioc_try_fmt_vid_cap = msm_v4l2_try_fmt_cap,
.vidioc_try_fmt_type_private = mm_v4l2_try_fmt_type_private,
.vidioc_g_fmt_vid_cap = msm_v4l2_g_fmt_cap,
.vidioc_s_fmt_vid_cap = msm_v4l2_s_fmt_cap,
.vidioc_g_fmt_vid_overlay = msm_v4l2_g_fmt_overlay,
.vidioc_s_fmt_vid_overlay = msm_v4l2_s_fmt_overlay,
.vidioc_overlay = msm_v4l2_overlay,
.vidioc_g_jpegcomp = msm_v4l2_g_jpegcomp,
.vidioc_s_jpegcomp = msm_v4l2_s_jpegcomp,
};
static int msm_v4l2_video_dev_init(struct video_device *pvd)
{
strncpy(pvd->name, MSM_APPS_ID_V4L2, sizeof(pvd->name));
pvd->vfl_type = 1;
pvd->fops = &msm_v4l2_fops;
pvd->release = msm_v4l2_release_dev;
pvd->minor = -1;
pvd->ioctl_ops = &msm_ioctl_ops;
return msm_v4l2_register(g_pmsm_v4l2_dev->drv);
}
static int __init msm_v4l2_init(void)
{
int rc = -ENOMEM;
struct video_device *pvdev = NULL;
struct msm_v4l2_device *pmsm_v4l2_dev = NULL;
D("%s\n", __func__);
pvdev = video_device_alloc();
if (pvdev == NULL)
return rc;
pmsm_v4l2_dev =
kzalloc(sizeof(struct msm_v4l2_device), GFP_KERNEL);
if (pmsm_v4l2_dev == NULL) {
video_device_release(pvdev);
return rc;
}
msm_v4l2_dev_init(pmsm_v4l2_dev);
g_pmsm_v4l2_dev = pmsm_v4l2_dev;
g_pmsm_v4l2_dev->pvdev = pvdev;
g_pmsm_v4l2_dev->drv =
kzalloc(sizeof(struct msm_v4l2_driver), GFP_KERNEL);
if (!g_pmsm_v4l2_dev->drv) {
video_device_release(pvdev);
kfree(pmsm_v4l2_dev);
return rc;
}
rc = msm_v4l2_video_dev_init(pvdev);
if (rc < 0) {
video_device_release(pvdev);
kfree(g_pmsm_v4l2_dev->drv);
kfree(pmsm_v4l2_dev);
return rc;
}
if (video_register_device(pvdev, VFL_TYPE_GRABBER,
MSM_V4L2_DEVNUM_YUV)) {
D("failed to register device\n");
video_device_release(pvdev);
kfree(g_pmsm_v4l2_dev);
g_pmsm_v4l2_dev = NULL;
return -ENOENT;
}
#ifdef CONFIG_PROC_FS
create_proc_read_entry(MSM_V4L2_PROC_NAME,
0, NULL, msm_v4l2_read_proc, NULL);
#endif
return 0;
}
static void __exit msm_v4l2_exit(void)
{
struct video_device *pvdev = g_pmsm_v4l2_dev->pvdev;
D("%s\n", __func__);
#ifdef CONFIG_PROC_FS
remove_proc_entry(MSM_V4L2_PROC_NAME, NULL);
#endif
video_unregister_device(pvdev);
video_device_release(pvdev);
msm_v4l2_unregister(g_pmsm_v4l2_dev->drv);
kfree(g_pmsm_v4l2_dev->drv);
g_pmsm_v4l2_dev->drv = NULL;
kfree(g_pmsm_v4l2_dev);
g_pmsm_v4l2_dev = NULL;
}
module_init(msm_v4l2_init);
module_exit(msm_v4l2_exit);
MODULE_DESCRIPTION("MSM V4L2 driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,701 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#include <linux/msm_adsp.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/android_pmem.h>
#include <mach/msm_adsp.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include "msm_vfe7x.h"
#define QDSP_CMDQUEUE QDSP_vfeCommandQueue
#define VFE_RESET_CMD 0
#define VFE_START_CMD 1
#define VFE_STOP_CMD 2
#define VFE_FRAME_ACK 20
#define STATS_AF_ACK 21
#define STATS_WE_ACK 22
#define MSG_STOP_ACK 1
#define MSG_SNAPSHOT 2
#define MSG_OUTPUT1 6
#define MSG_OUTPUT2 7
#define MSG_STATS_AF 8
#define MSG_STATS_WE 9
static struct msm_adsp_module *qcam_mod;
static struct msm_adsp_module *vfe_mod;
static struct msm_vfe_callback *resp;
static void *extdata;
static uint32_t extlen;
struct mutex vfe_lock;
static void *vfe_syncdata;
static uint8_t vfestopped;
static struct stop_event stopevent;
static void vfe_7x_convert(struct msm_vfe_phy_info *pinfo,
enum vfe_resp_msg type,
void *data, void **ext, int32_t *elen)
{
switch (type) {
case VFE_MSG_OUTPUT1:
case VFE_MSG_OUTPUT2: {
pinfo->y_phy = ((struct vfe_endframe *)data)->y_address;
pinfo->cbcr_phy =
((struct vfe_endframe *)data)->cbcr_address;
CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
pinfo->y_phy, pinfo->cbcr_phy);
((struct vfe_frame_extra *)extdata)->bl_evencol =
((struct vfe_endframe *)data)->blacklevelevencolumn;
((struct vfe_frame_extra *)extdata)->bl_oddcol =
((struct vfe_endframe *)data)->blackleveloddcolumn;
((struct vfe_frame_extra *)extdata)->g_def_p_cnt =
((struct vfe_endframe *)data)->greendefectpixelcount;
((struct vfe_frame_extra *)extdata)->r_b_def_p_cnt =
((struct vfe_endframe *)data)->redbluedefectpixelcount;
*ext = extdata;
*elen = extlen;
}
break;
case VFE_MSG_STATS_AF:
case VFE_MSG_STATS_WE:
pinfo->sbuf_phy = *(uint32_t *)data;
break;
default:
break;
} /* switch */
}
static void vfe_7x_ops(void *driver_data, unsigned id, size_t len,
void (*getevent)(void *ptr, size_t len))
{
uint32_t evt_buf[3];
struct msm_vfe_resp *rp;
void *data;
len = (id == (uint16_t)-1) ? 0 : len;
data = resp->vfe_alloc(sizeof(struct msm_vfe_resp) + len, vfe_syncdata);
if (!data) {
pr_err("rp: cannot allocate buffer\n");
return;
}
rp = (struct msm_vfe_resp *)data;
rp->evt_msg.len = len;
if (id == ((uint16_t)-1)) {
/* event */
rp->type = VFE_EVENT;
rp->evt_msg.type = MSM_CAMERA_EVT;
getevent(evt_buf, sizeof(evt_buf));
rp->evt_msg.msg_id = evt_buf[0];
resp->vfe_resp(rp, MSM_CAM_Q_VFE_EVT, vfe_syncdata);
} else {
/* messages */
rp->evt_msg.type = MSM_CAMERA_MSG;
rp->evt_msg.msg_id = id;
rp->evt_msg.data = rp + 1;
getevent(rp->evt_msg.data, len);
switch (rp->evt_msg.msg_id) {
case MSG_SNAPSHOT:
rp->type = VFE_MSG_SNAPSHOT;
break;
case MSG_OUTPUT1:
rp->type = VFE_MSG_OUTPUT1;
vfe_7x_convert(&(rp->phy), VFE_MSG_OUTPUT1,
rp->evt_msg.data, &(rp->extdata),
&(rp->extlen));
break;
case MSG_OUTPUT2:
rp->type = VFE_MSG_OUTPUT2;
vfe_7x_convert(&(rp->phy), VFE_MSG_OUTPUT2,
rp->evt_msg.data, &(rp->extdata),
&(rp->extlen));
break;
case MSG_STATS_AF:
rp->type = VFE_MSG_STATS_AF;
vfe_7x_convert(&(rp->phy), VFE_MSG_STATS_AF,
rp->evt_msg.data, NULL, NULL);
break;
case MSG_STATS_WE:
rp->type = VFE_MSG_STATS_WE;
vfe_7x_convert(&(rp->phy), VFE_MSG_STATS_WE,
rp->evt_msg.data, NULL, NULL);
CDBG("MSG_STATS_WE: phy = 0x%x\n", rp->phy.sbuf_phy);
break;
case MSG_STOP_ACK:
rp->type = VFE_MSG_GENERAL;
stopevent.state = 1;
wake_up(&stopevent.wait);
break;
default:
rp->type = VFE_MSG_GENERAL;
break;
}
resp->vfe_resp(rp, MSM_CAM_Q_VFE_MSG, vfe_syncdata);
}
}
static struct msm_adsp_ops vfe_7x_sync = {
.event = vfe_7x_ops,
};
static int vfe_7x_enable(struct camera_enable_cmd *enable)
{
int rc = -EFAULT;
if (!strcmp(enable->name, "QCAMTASK"))
rc = msm_adsp_enable(qcam_mod);
else if (!strcmp(enable->name, "VFETASK"))
rc = msm_adsp_enable(vfe_mod);
return rc;
}
static int vfe_7x_disable(struct camera_enable_cmd *enable,
struct platform_device *dev __attribute__((unused)))
{
int rc = -EFAULT;
if (!strcmp(enable->name, "QCAMTASK"))
rc = msm_adsp_disable(qcam_mod);
else if (!strcmp(enable->name, "VFETASK"))
rc = msm_adsp_disable(vfe_mod);
return rc;
}
static int vfe_7x_stop(void)
{
int rc = 0;
uint32_t stopcmd = VFE_STOP_CMD;
rc = msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
&stopcmd, sizeof(uint32_t));
if (rc < 0) {
CDBG("%s:%d: failed rc = %d \n", __func__, __LINE__, rc);
return rc;
}
stopevent.state = 0;
rc = wait_event_timeout(stopevent.wait,
stopevent.state != 0,
msecs_to_jiffies(stopevent.timeout));
return rc;
}
static void vfe_7x_release(struct platform_device *pdev)
{
mutex_lock(&vfe_lock);
vfe_syncdata = NULL;
mutex_unlock(&vfe_lock);
if (!vfestopped) {
CDBG("%s:%d:Calling vfe_7x_stop()\n", __func__, __LINE__);
vfe_7x_stop();
} else
vfestopped = 0;
msm_adsp_disable(qcam_mod);
msm_adsp_disable(vfe_mod);
msm_adsp_put(qcam_mod);
msm_adsp_put(vfe_mod);
msm_camio_disable(pdev);
kfree(extdata);
extlen = 0;
}
static int vfe_7x_init(struct msm_vfe_callback *presp,
struct platform_device *dev)
{
int rc = 0;
init_waitqueue_head(&stopevent.wait);
stopevent.timeout = 200;
stopevent.state = 0;
if (presp && presp->vfe_resp)
resp = presp;
else
return -EFAULT;
/* Bring up all the required GPIOs and Clocks */
rc = msm_camio_enable(dev);
if (rc < 0)
return rc;
msm_camio_camif_pad_reg_reset();
extlen = sizeof(struct vfe_frame_extra);
extdata =
kmalloc(sizeof(extlen), GFP_ATOMIC);
if (!extdata) {
rc = -ENOMEM;
goto init_fail;
}
rc = msm_adsp_get("QCAMTASK", &qcam_mod, &vfe_7x_sync, NULL);
if (rc) {
rc = -EBUSY;
goto get_qcam_fail;
}
rc = msm_adsp_get("VFETASK", &vfe_mod, &vfe_7x_sync, NULL);
if (rc) {
rc = -EBUSY;
goto get_vfe_fail;
}
return 0;
get_vfe_fail:
msm_adsp_put(qcam_mod);
get_qcam_fail:
kfree(extdata);
init_fail:
extlen = 0;
return rc;
}
static int vfe_7x_config_axi(int mode,
struct axidata *ad, struct axiout *ao)
{
struct msm_pmem_region *regptr;
unsigned long *bptr;
int cnt;
int rc = 0;
if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
regptr = ad->region;
CDBG("bufnum1 = %d\n", ad->bufnum1);
CDBG("config_axi1: O1, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
regptr->paddr, regptr->y_off, regptr->cbcr_off);
bptr = &ao->output1buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum1; cnt++) {
*bptr = regptr->paddr + regptr->y_off;
bptr++;
*bptr = regptr->paddr + regptr->cbcr_off;
bptr++;
regptr++;
}
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum1); cnt++) {
*bptr = regptr->paddr + regptr->y_off;
bptr++;
*bptr = regptr->paddr + regptr->cbcr_off;
bptr++;
}
} /* if OUTPUT1 or Both */
if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
regptr = &(ad->region[ad->bufnum1]);
CDBG("bufnum2 = %d\n", ad->bufnum2);
CDBG("config_axi2: O2, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
regptr->paddr, regptr->y_off, regptr->cbcr_off);
bptr = &ao->output2buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum2; cnt++) {
*bptr = regptr->paddr + regptr->y_off;
bptr++;
*bptr = regptr->paddr + regptr->cbcr_off;
bptr++;
regptr++;
}
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum2); cnt++) {
*bptr = regptr->paddr + regptr->y_off;
bptr++;
*bptr = regptr->paddr + regptr->cbcr_off;
bptr++;
}
}
return rc;
}
static int vfe_7x_config(struct msm_vfe_cfg_cmd *cmd, void *data)
{
struct msm_pmem_region *regptr;
unsigned char buf[256];
struct vfe_stats_ack sack;
struct axidata *axid;
uint32_t i;
struct vfe_stats_we_cfg *scfg = NULL;
struct vfe_stats_af_cfg *sfcfg = NULL;
struct axiout *axio = NULL;
void *cmd_data = NULL;
void *cmd_data_alloc = NULL;
long rc = 0;
struct msm_vfe_command_7k *vfecmd;
vfecmd =
kmalloc(sizeof(struct msm_vfe_command_7k),
GFP_ATOMIC);
if (!vfecmd) {
pr_err("vfecmd alloc failed!\n");
return -ENOMEM;
}
if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE) {
if (copy_from_user(vfecmd,
(void __user *)(cmd->value),
sizeof(struct msm_vfe_command_7k))) {
rc = -EFAULT;
goto config_failure;
}
}
switch (cmd->cmd_type) {
case CMD_STATS_ENABLE:
case CMD_STATS_AXI_CFG: {
axid = data;
if (!axid) {
rc = -EFAULT;
goto config_failure;
}
scfg =
kmalloc(sizeof(struct vfe_stats_we_cfg),
GFP_ATOMIC);
if (!scfg) {
rc = -ENOMEM;
goto config_failure;
}
if (copy_from_user(scfg,
(void __user *)(vfecmd->value),
vfecmd->length)) {
rc = -EFAULT;
goto config_done;
}
CDBG("STATS_ENABLE: bufnum = %d, enabling = %d\n",
axid->bufnum1, scfg->wb_expstatsenable);
if (axid->bufnum1 > 0) {
regptr = axid->region;
for (i = 0; i < axid->bufnum1; i++) {
CDBG("STATS_ENABLE, phy = 0x%lx\n",
regptr->paddr);
scfg->wb_expstatoutputbuffer[i] =
(void *)regptr->paddr;
regptr++;
}
cmd_data = scfg;
} else {
rc = -EINVAL;
goto config_done;
}
}
break;
case CMD_STATS_AF_ENABLE:
case CMD_STATS_AF_AXI_CFG: {
axid = data;
if (!axid) {
rc = -EFAULT;
goto config_failure;
}
sfcfg =
kmalloc(sizeof(struct vfe_stats_af_cfg),
GFP_ATOMIC);
if (!sfcfg) {
rc = -ENOMEM;
goto config_failure;
}
if (copy_from_user(sfcfg,
(void __user *)(vfecmd->value),
vfecmd->length)) {
rc = -EFAULT;
goto config_done;
}
CDBG("AF_ENABLE: bufnum = %d, enabling = %d\n",
axid->bufnum1, sfcfg->af_enable);
if (axid->bufnum1 > 0) {
regptr = axid->region;
for (i = 0; i < axid->bufnum1; i++) {
CDBG("STATS_ENABLE, phy = 0x%lx\n",
regptr->paddr);
sfcfg->af_outbuf[i] =
(void *)regptr->paddr;
regptr++;
}
cmd_data = sfcfg;
} else {
rc = -EINVAL;
goto config_done;
}
}
break;
case CMD_FRAME_BUF_RELEASE: {
struct msm_frame *b;
unsigned long p;
struct vfe_outputack fack;
if (!data) {
rc = -EFAULT;
goto config_failure;
}
b = (struct msm_frame *)(cmd->value);
p = *(unsigned long *)data;
fack.header = VFE_FRAME_ACK;
fack.output2newybufferaddress =
(void *)(p + b->y_off);
fack.output2newcbcrbufferaddress =
(void *)(p + b->cbcr_off);
vfecmd->queue = QDSP_CMDQUEUE;
vfecmd->length = sizeof(struct vfe_outputack);
cmd_data = &fack;
}
break;
case CMD_SNAP_BUF_RELEASE:
break;
case CMD_STATS_BUF_RELEASE: {
CDBG("vfe_7x_config: CMD_STATS_BUF_RELEASE\n");
if (!data) {
rc = -EFAULT;
goto config_failure;
}
sack.header = STATS_WE_ACK;
sack.bufaddr = (void *)*(uint32_t *)data;
vfecmd->queue = QDSP_CMDQUEUE;
vfecmd->length = sizeof(struct vfe_stats_ack);
cmd_data = &sack;
}
break;
case CMD_STATS_AF_BUF_RELEASE: {
CDBG("vfe_7x_config: CMD_STATS_AF_BUF_RELEASE\n");
if (!data) {
rc = -EFAULT;
goto config_failure;
}
sack.header = STATS_AF_ACK;
sack.bufaddr = (void *)*(uint32_t *)data;
vfecmd->queue = QDSP_CMDQUEUE;
vfecmd->length = sizeof(struct vfe_stats_ack);
cmd_data = &sack;
}
break;
case CMD_GENERAL:
case CMD_STATS_DISABLE: {
if (vfecmd->length > 256) {
cmd_data_alloc =
cmd_data = kmalloc(vfecmd->length, GFP_ATOMIC);
if (!cmd_data) {
rc = -ENOMEM;
goto config_failure;
}
} else
cmd_data = buf;
if (copy_from_user(cmd_data,
(void __user *)(vfecmd->value),
vfecmd->length)) {
rc = -EFAULT;
goto config_done;
}
if (vfecmd->queue == QDSP_CMDQUEUE) {
switch (*(uint32_t *)cmd_data) {
case VFE_RESET_CMD:
msm_camio_vfe_blk_reset();
msm_camio_camif_pad_reg_reset_2();
vfestopped = 0;
break;
case VFE_START_CMD:
msm_camio_camif_pad_reg_reset_2();
vfestopped = 0;
break;
case VFE_STOP_CMD:
vfestopped = 1;
goto config_send;
default:
break;
}
} /* QDSP_CMDQUEUE */
}
break;
case CMD_AXI_CFG_OUT1: {
axid = data;
if (!axid) {
rc = -EFAULT;
goto config_failure;
}
axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
if (!axio) {
rc = -ENOMEM;
goto config_failure;
}
if (copy_from_user(axio, (void *)(vfecmd->value),
sizeof(struct axiout))) {
rc = -EFAULT;
goto config_done;
}
vfe_7x_config_axi(OUTPUT_1, axid, axio);
cmd_data = axio;
}
break;
case CMD_AXI_CFG_OUT2:
case CMD_RAW_PICT_AXI_CFG: {
axid = data;
if (!axid) {
rc = -EFAULT;
goto config_failure;
}
axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
if (!axio) {
rc = -ENOMEM;
goto config_failure;
}
if (copy_from_user(axio, (void __user *)(vfecmd->value),
sizeof(struct axiout))) {
rc = -EFAULT;
goto config_done;
}
vfe_7x_config_axi(OUTPUT_2, axid, axio);
cmd_data = axio;
}
break;
case CMD_AXI_CFG_SNAP_O1_AND_O2: {
axid = data;
if (!axid) {
rc = -EFAULT;
goto config_failure;
}
axio = kmalloc(sizeof(struct axiout), GFP_ATOMIC);
if (!axio) {
rc = -ENOMEM;
goto config_failure;
}
if (copy_from_user(axio, (void __user *)(vfecmd->value),
sizeof(struct axiout))) {
rc = -EFAULT;
goto config_done;
}
vfe_7x_config_axi(OUTPUT_1_AND_2, axid, axio);
cmd_data = axio;
}
break;
default:
break;
} /* switch */
if (vfestopped)
goto config_done;
config_send:
CDBG("send adsp command = %d\n", *(uint32_t *)cmd_data);
rc = msm_adsp_write(vfe_mod, vfecmd->queue,
cmd_data, vfecmd->length);
config_done:
if (cmd_data_alloc != NULL)
kfree(cmd_data_alloc);
config_failure:
kfree(scfg);
kfree(axio);
kfree(vfecmd);
return rc;
}
void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
{
mutex_init(&vfe_lock);
fptr->vfe_init = vfe_7x_init;
fptr->vfe_enable = vfe_7x_enable;
fptr->vfe_config = vfe_7x_config;
fptr->vfe_disable = vfe_7x_disable;
fptr->vfe_release = vfe_7x_release;
vfe_syncdata = data;
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef __MSM_VFE7X_H__
#define __MSM_VFE7X_H__
#include <media/msm_camera.h>
#include <mach/camera.h>
struct vfe_frame_extra {
uint32_t bl_evencol;
uint32_t bl_oddcol;
uint16_t g_def_p_cnt;
uint16_t r_b_def_p_cnt;
};
struct vfe_endframe {
uint32_t y_address;
uint32_t cbcr_address;
unsigned int blacklevelevencolumn:23;
uint16_t reserved1:9;
unsigned int blackleveloddcolumn:23;
uint16_t reserved2:9;
uint16_t greendefectpixelcount:8;
uint16_t reserved3:8;
uint16_t redbluedefectpixelcount:8;
uint16_t reserved4:8;
} __attribute__((packed, aligned(4)));
struct vfe_outputack {
uint32_t header;
void *output2newybufferaddress;
void *output2newcbcrbufferaddress;
} __attribute__((packed, aligned(4)));
struct vfe_stats_ack {
uint32_t header;
/* MUST BE 64 bit ALIGNED */
void *bufaddr;
} __attribute__((packed, aligned(4)));
/* AXI Output Config Command sent to DSP */
struct axiout {
uint32_t cmdheader:32;
int outputmode:3;
uint8_t format:2;
uint32_t /* reserved */ : 27;
/* AXI Output 1 Y Configuration, Part 1 */
uint32_t out1yimageheight:12;
uint32_t /* reserved */ : 4;
uint32_t out1yimagewidthin64bitwords:10;
uint32_t /* reserved */ : 6;
/* AXI Output 1 Y Configuration, Part 2 */
uint8_t out1yburstlen:2;
uint32_t out1ynumrows:12;
uint32_t out1yrowincin64bitincs:12;
uint32_t /* reserved */ : 6;
/* AXI Output 1 CbCr Configuration, Part 1 */
uint32_t out1cbcrimageheight:12;
uint32_t /* reserved */ : 4;
uint32_t out1cbcrimagewidthin64bitwords:10;
uint32_t /* reserved */ : 6;
/* AXI Output 1 CbCr Configuration, Part 2 */
uint8_t out1cbcrburstlen:2;
uint32_t out1cbcrnumrows:12;
uint32_t out1cbcrrowincin64bitincs:12;
uint32_t /* reserved */ : 6;
/* AXI Output 2 Y Configuration, Part 1 */
uint32_t out2yimageheight:12;
uint32_t /* reserved */ : 4;
uint32_t out2yimagewidthin64bitwords:10;
uint32_t /* reserved */ : 6;
/* AXI Output 2 Y Configuration, Part 2 */
uint8_t out2yburstlen:2;
uint32_t out2ynumrows:12;
uint32_t out2yrowincin64bitincs:12;
uint32_t /* reserved */ : 6;
/* AXI Output 2 CbCr Configuration, Part 1 */
uint32_t out2cbcrimageheight:12;
uint32_t /* reserved */ : 4;
uint32_t out2cbcrimagewidtein64bitwords:10;
uint32_t /* reserved */ : 6;
/* AXI Output 2 CbCr Configuration, Part 2 */
uint8_t out2cbcrburstlen:2;
uint32_t out2cbcrnumrows:12;
uint32_t out2cbcrrowincin64bitincs:12;
uint32_t /* reserved */ : 6;
/* Address configuration:
* output1 phisycal address */
unsigned long output1buffer1_y_phy;
unsigned long output1buffer1_cbcr_phy;
unsigned long output1buffer2_y_phy;
unsigned long output1buffer2_cbcr_phy;
unsigned long output1buffer3_y_phy;
unsigned long output1buffer3_cbcr_phy;
unsigned long output1buffer4_y_phy;
unsigned long output1buffer4_cbcr_phy;
unsigned long output1buffer5_y_phy;
unsigned long output1buffer5_cbcr_phy;
unsigned long output1buffer6_y_phy;
unsigned long output1buffer6_cbcr_phy;
unsigned long output1buffer7_y_phy;
unsigned long output1buffer7_cbcr_phy;
unsigned long output1buffer8_y_phy;
unsigned long output1buffer8_cbcr_phy;
/* output2 phisycal address */
unsigned long output2buffer1_y_phy;
unsigned long output2buffer1_cbcr_phy;
unsigned long output2buffer2_y_phy;
unsigned long output2buffer2_cbcr_phy;
unsigned long output2buffer3_y_phy;
unsigned long output2buffer3_cbcr_phy;
unsigned long output2buffer4_y_phy;
unsigned long output2buffer4_cbcr_phy;
unsigned long output2buffer5_y_phy;
unsigned long output2buffer5_cbcr_phy;
unsigned long output2buffer6_y_phy;
unsigned long output2buffer6_cbcr_phy;
unsigned long output2buffer7_y_phy;
unsigned long output2buffer7_cbcr_phy;
unsigned long output2buffer8_y_phy;
unsigned long output2buffer8_cbcr_phy;
} __attribute__((packed, aligned(4)));
struct vfe_stats_we_cfg {
uint32_t header;
/* White Balance/Exposure Statistic Selection */
uint8_t wb_expstatsenable:1;
uint8_t wb_expstatbuspriorityselection:1;
unsigned int wb_expstatbuspriorityvalue:4;
unsigned int /* reserved */ : 26;
/* White Balance/Exposure Statistic Configuration, Part 1 */
uint8_t exposurestatregions:1;
uint8_t exposurestatsubregions:1;
unsigned int /* reserved */ : 14;
unsigned int whitebalanceminimumy:8;
unsigned int whitebalancemaximumy:8;
/* White Balance/Exposure Statistic Configuration, Part 2 */
uint8_t wb_expstatslopeofneutralregionline[
NUM_WB_EXP_NEUTRAL_REGION_LINES];
/* White Balance/Exposure Statistic Configuration, Part 3 */
unsigned int wb_expstatcrinterceptofneutralregionline2:12;
unsigned int /* reserved */ : 4;
unsigned int wb_expstatcbinterceptofneutralreginnline1:12;
unsigned int /* reserved */ : 4;
/* White Balance/Exposure Statistic Configuration, Part 4 */
unsigned int wb_expstatcrinterceptofneutralregionline4:12;
unsigned int /* reserved */ : 4;
unsigned int wb_expstatcbinterceptofneutralregionline3:12;
unsigned int /* reserved */ : 4;
/* White Balance/Exposure Statistic Output Buffer Header */
unsigned int wb_expmetricheaderpattern:8;
unsigned int /* reserved */ : 24;
/* White Balance/Exposure Statistic Output Buffers-MUST
* BE 64 bit ALIGNED */
void *wb_expstatoutputbuffer[NUM_WB_EXP_STAT_OUTPUT_BUFFERS];
} __attribute__((packed, aligned(4)));
struct vfe_stats_af_cfg {
uint32_t header;
/* Autofocus Statistic Selection */
uint8_t af_enable:1;
uint8_t af_busprioritysel:1;
unsigned int af_buspriorityval:4;
unsigned int /* reserved */ : 26;
/* Autofocus Statistic Configuration, Part 1 */
unsigned int af_singlewinvoffset:12;
unsigned int /* reserved */ : 4;
unsigned int af_singlewinhoffset:12;
unsigned int /* reserved */ : 3;
uint8_t af_winmode:1;
/* Autofocus Statistic Configuration, Part 2 */
unsigned int af_singglewinvh:11;
unsigned int /* reserved */ : 5;
unsigned int af_singlewinhw:11;
unsigned int /* reserved */ : 5;
/* Autofocus Statistic Configuration, Parts 3-6 */
uint8_t af_multiwingrid[NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS];
/* Autofocus Statistic Configuration, Part 7 */
signed int af_metrichpfcoefa00:5;
signed int af_metrichpfcoefa04:5;
unsigned int af_metricmaxval:11;
uint8_t af_metricsel:1;
unsigned int /* reserved */ : 10;
/* Autofocus Statistic Configuration, Part 8 */
signed int af_metrichpfcoefa20:5;
signed int af_metrichpfcoefa21:5;
signed int af_metrichpfcoefa22:5;
signed int af_metrichpfcoefa23:5;
signed int af_metrichpfcoefa24:5;
unsigned int /* reserved */ : 7;
/* Autofocus Statistic Output Buffer Header */
unsigned int af_metrichp:8;
unsigned int /* reserved */ : 24;
/* Autofocus Statistic Output Buffers - MUST BE 64 bit ALIGNED!!! */
void *af_outbuf[NUM_AF_STAT_OUTPUT_BUFFERS];
} __attribute__((packed, aligned(4))); /* VFE_StatsAutofocusConfigCmdType */
struct msm_camera_frame_msg {
unsigned long output_y_address;
unsigned long output_cbcr_address;
unsigned int blacklevelevenColumn:23;
uint16_t reserved1:9;
unsigned int blackleveloddColumn:23;
uint16_t reserved2:9;
uint16_t greendefectpixelcount:8;
uint16_t reserved3:8;
uint16_t redbluedefectpixelcount:8;
uint16_t reserved4:8;
} __attribute__((packed, aligned(4)));
/* New one for 7k */
struct msm_vfe_command_7k {
uint16_t queue;
uint16_t length;
void *value;
};
struct stop_event {
wait_queue_head_t wait;
int state;
int timeout;
};
#endif /* __MSM_VFE7X_H__ */

View File

@ -0,0 +1,756 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include "msm_vfe8x_proc.h"
#define ON 1
#define OFF 0
struct mutex vfe_lock;
static void *vfe_syncdata;
static int vfe_enable(struct camera_enable_cmd *enable)
{
int rc = 0;
return rc;
}
static int vfe_disable(struct camera_enable_cmd *enable,
struct platform_device *dev)
{
int rc = 0;
vfe_stop();
msm_camio_disable(dev);
return rc;
}
static void vfe_release(struct platform_device *dev)
{
msm_camio_disable(dev);
vfe_cmd_release(dev);
mutex_lock(&vfe_lock);
vfe_syncdata = NULL;
mutex_unlock(&vfe_lock);
}
static void vfe_config_axi(int mode,
struct axidata *ad, struct vfe_cmd_axi_output_config *ao)
{
struct msm_pmem_region *regptr;
int i, j;
uint32_t *p1, *p2;
if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
regptr = ad->region;
for (i = 0;
i < ad->bufnum1; i++) {
p1 = &(ao->output1.outputY.outFragments[i][0]);
p2 = &(ao->output1.outputCbcr.outFragments[i][0]);
for (j = 0;
j < ao->output1.fragmentCount; j++) {
*p1 = regptr->paddr + regptr->y_off;
p1++;
*p2 = regptr->paddr + regptr->cbcr_off;
p2++;
}
regptr++;
}
} /* if OUTPUT1 or Both */
if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
regptr = &(ad->region[ad->bufnum1]);
CDBG("bufnum2 = %d\n", ad->bufnum2);
for (i = 0;
i < ad->bufnum2; i++) {
p1 = &(ao->output2.outputY.outFragments[i][0]);
p2 = &(ao->output2.outputCbcr.outFragments[i][0]);
CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, cbcr_off = %d\n",
regptr->paddr, regptr->y_off, regptr->cbcr_off);
for (j = 0;
j < ao->output2.fragmentCount; j++) {
*p1 = regptr->paddr + regptr->y_off;
CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
p1++;
*p2 = regptr->paddr + regptr->cbcr_off;
CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
p2++;
}
regptr++;
}
}
}
static int vfe_proc_general(struct msm_vfe_command_8k *cmd)
{
int rc = 0;
CDBG("vfe_proc_general: cmdID = %d\n", cmd->id);
switch (cmd->id) {
case VFE_CMD_ID_RESET:
msm_camio_vfe_blk_reset();
msm_camio_camif_pad_reg_reset_2();
vfe_reset();
break;
case VFE_CMD_ID_START: {
struct vfe_cmd_start start;
if (copy_from_user(&start,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
/* msm_camio_camif_pad_reg_reset_2(); */
msm_camio_camif_pad_reg_reset();
vfe_start(&start);
}
break;
case VFE_CMD_ID_CAMIF_CONFIG: {
struct vfe_cmd_camif_config camif;
if (copy_from_user(&camif,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_camif_config(&camif);
}
break;
case VFE_CMD_ID_BLACK_LEVEL_CONFIG: {
struct vfe_cmd_black_level_config bl;
if (copy_from_user(&bl,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_black_level_config(&bl);
}
break;
case VFE_CMD_ID_ROLL_OFF_CONFIG: {
struct vfe_cmd_roll_off_config rolloff;
if (copy_from_user(&rolloff,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_roll_off_config(&rolloff);
}
break;
case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_CONFIG: {
struct vfe_cmd_demux_channel_gain_config demuxc;
if (copy_from_user(&demuxc,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
/* demux is always enabled. */
vfe_demux_channel_gain_config(&demuxc);
}
break;
case VFE_CMD_ID_DEMOSAIC_CONFIG: {
struct vfe_cmd_demosaic_config demosaic;
if (copy_from_user(&demosaic,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_demosaic_config(&demosaic);
}
break;
case VFE_CMD_ID_FOV_CROP_CONFIG:
case VFE_CMD_ID_FOV_CROP_UPDATE: {
struct vfe_cmd_fov_crop_config fov;
if (copy_from_user(&fov,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_fov_crop_config(&fov);
}
break;
case VFE_CMD_ID_MAIN_SCALER_CONFIG:
case VFE_CMD_ID_MAIN_SCALER_UPDATE: {
struct vfe_cmd_main_scaler_config mainds;
if (copy_from_user(&mainds,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_main_scaler_config(&mainds);
}
break;
case VFE_CMD_ID_WHITE_BALANCE_CONFIG:
case VFE_CMD_ID_WHITE_BALANCE_UPDATE: {
struct vfe_cmd_white_balance_config wb;
if (copy_from_user(&wb,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_white_balance_config(&wb);
}
break;
case VFE_CMD_ID_COLOR_CORRECTION_CONFIG:
case VFE_CMD_ID_COLOR_CORRECTION_UPDATE: {
struct vfe_cmd_color_correction_config cc;
if (copy_from_user(&cc,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_color_correction_config(&cc);
}
break;
case VFE_CMD_ID_LA_CONFIG: {
struct vfe_cmd_la_config la;
if (copy_from_user(&la,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_la_config(&la);
}
break;
case VFE_CMD_ID_RGB_GAMMA_CONFIG: {
struct vfe_cmd_rgb_gamma_config rgb;
if (copy_from_user(&rgb,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
rc = vfe_rgb_gamma_config(&rgb);
}
break;
case VFE_CMD_ID_CHROMA_ENHAN_CONFIG:
case VFE_CMD_ID_CHROMA_ENHAN_UPDATE: {
struct vfe_cmd_chroma_enhan_config chrom;
if (copy_from_user(&chrom,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_chroma_enhan_config(&chrom);
}
break;
case VFE_CMD_ID_CHROMA_SUPPRESSION_CONFIG:
case VFE_CMD_ID_CHROMA_SUPPRESSION_UPDATE: {
struct vfe_cmd_chroma_suppression_config chromsup;
if (copy_from_user(&chromsup,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_chroma_sup_config(&chromsup);
}
break;
case VFE_CMD_ID_ASF_CONFIG: {
struct vfe_cmd_asf_config asf;
if (copy_from_user(&asf,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_asf_config(&asf);
}
break;
case VFE_CMD_ID_SCALER2Y_CONFIG:
case VFE_CMD_ID_SCALER2Y_UPDATE: {
struct vfe_cmd_scaler2_config ds2y;
if (copy_from_user(&ds2y,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_scaler2y_config(&ds2y);
}
break;
case VFE_CMD_ID_SCALER2CbCr_CONFIG:
case VFE_CMD_ID_SCALER2CbCr_UPDATE: {
struct vfe_cmd_scaler2_config ds2cbcr;
if (copy_from_user(&ds2cbcr,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_scaler2cbcr_config(&ds2cbcr);
}
break;
case VFE_CMD_ID_CHROMA_SUBSAMPLE_CONFIG: {
struct vfe_cmd_chroma_subsample_config sub;
if (copy_from_user(&sub,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_chroma_subsample_config(&sub);
}
break;
case VFE_CMD_ID_FRAME_SKIP_CONFIG: {
struct vfe_cmd_frame_skip_config fskip;
if (copy_from_user(&fskip,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_frame_skip_config(&fskip);
}
break;
case VFE_CMD_ID_OUTPUT_CLAMP_CONFIG: {
struct vfe_cmd_output_clamp_config clamp;
if (copy_from_user(&clamp,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_output_clamp_config(&clamp);
}
break;
/* module update commands */
case VFE_CMD_ID_BLACK_LEVEL_UPDATE: {
struct vfe_cmd_black_level_config blk;
if (copy_from_user(&blk,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_black_level_update(&blk);
}
break;
case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_UPDATE: {
struct vfe_cmd_demux_channel_gain_config dmu;
if (copy_from_user(&dmu,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_demux_channel_gain_update(&dmu);
}
break;
case VFE_CMD_ID_DEMOSAIC_BPC_UPDATE: {
struct vfe_cmd_demosaic_bpc_update demo_bpc;
if (copy_from_user(&demo_bpc,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_demosaic_bpc_update(&demo_bpc);
}
break;
case VFE_CMD_ID_DEMOSAIC_ABF_UPDATE: {
struct vfe_cmd_demosaic_abf_update demo_abf;
if (copy_from_user(&demo_abf,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_demosaic_abf_update(&demo_abf);
}
break;
case VFE_CMD_ID_LA_UPDATE: {
struct vfe_cmd_la_config la;
if (copy_from_user(&la,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_la_update(&la);
}
break;
case VFE_CMD_ID_RGB_GAMMA_UPDATE: {
struct vfe_cmd_rgb_gamma_config rgb;
if (copy_from_user(&rgb,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
rc = vfe_rgb_gamma_update(&rgb);
}
break;
case VFE_CMD_ID_ASF_UPDATE: {
struct vfe_cmd_asf_update asf;
if (copy_from_user(&asf,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_asf_update(&asf);
}
break;
case VFE_CMD_ID_FRAME_SKIP_UPDATE: {
struct vfe_cmd_frame_skip_update fskip;
if (copy_from_user(&fskip,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_frame_skip_update(&fskip);
}
break;
case VFE_CMD_ID_CAMIF_FRAME_UPDATE: {
struct vfe_cmds_camif_frame fup;
if (copy_from_user(&fup,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_camif_frame_update(&fup);
}
break;
/* stats update commands */
case VFE_CMD_ID_STATS_AUTOFOCUS_UPDATE: {
struct vfe_cmd_stats_af_update afup;
if (copy_from_user(&afup,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_stats_update_af(&afup);
}
break;
case VFE_CMD_ID_STATS_WB_EXP_UPDATE: {
struct vfe_cmd_stats_wb_exp_update wbexp;
if (copy_from_user(&wbexp,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_stats_update_wb_exp(&wbexp);
}
break;
/* control of start, stop, update, etc... */
case VFE_CMD_ID_STOP:
vfe_stop();
break;
case VFE_CMD_ID_GET_HW_VERSION:
break;
/* stats */
case VFE_CMD_ID_STATS_SETTING: {
struct vfe_cmd_stats_setting stats;
if (copy_from_user(&stats,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_stats_setting(&stats);
}
break;
case VFE_CMD_ID_STATS_AUTOFOCUS_START: {
struct vfe_cmd_stats_af_start af;
if (copy_from_user(&af,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_stats_start_af(&af);
}
break;
case VFE_CMD_ID_STATS_AUTOFOCUS_STOP:
vfe_stats_af_stop();
break;
case VFE_CMD_ID_STATS_WB_EXP_START: {
struct vfe_cmd_stats_wb_exp_start awexp;
if (copy_from_user(&awexp,
(void __user *) cmd->value, cmd->length))
rc = -EFAULT;
vfe_stats_start_wb_exp(&awexp);
}
break;
case VFE_CMD_ID_STATS_WB_EXP_STOP:
vfe_stats_wb_exp_stop();
break;
case VFE_CMD_ID_ASYNC_TIMER_SETTING:
break;
case VFE_CMD_ID_UPDATE:
vfe_update();
break;
/* test gen */
case VFE_CMD_ID_TEST_GEN_START:
break;
/*
acknowledge from upper layer
these are not in general command.
case VFE_CMD_ID_OUTPUT1_ACK:
break;
case VFE_CMD_ID_OUTPUT2_ACK:
break;
case VFE_CMD_ID_EPOCH1_ACK:
break;
case VFE_CMD_ID_EPOCH2_ACK:
break;
case VFE_CMD_ID_STATS_AUTOFOCUS_ACK:
break;
case VFE_CMD_ID_STATS_WB_EXP_ACK:
break;
*/
default:
break;
} /* switch */
return rc;
}
static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data)
{
struct msm_pmem_region *regptr;
struct msm_vfe_command_8k vfecmd;
uint32_t i;
void *cmd_data = NULL;
long rc = 0;
struct vfe_cmd_axi_output_config *axio = NULL;
struct vfe_cmd_stats_setting *scfg = NULL;
if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
if (copy_from_user(&vfecmd,
(void __user *)(cmd->value),
sizeof(struct msm_vfe_command_8k)))
return -EFAULT;
}
CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
switch (cmd->cmd_type) {
case CMD_GENERAL:
rc = vfe_proc_general(&vfecmd);
break;
case CMD_STATS_ENABLE:
case CMD_STATS_AXI_CFG: {
struct axidata *axid;
axid = data;
if (!axid)
return -EFAULT;
scfg =
kmalloc(sizeof(struct vfe_cmd_stats_setting),
GFP_ATOMIC);
if (!scfg)
return -ENOMEM;
if (copy_from_user(scfg,
(void __user *)(vfecmd.value),
vfecmd.length)) {
kfree(scfg);
return -EFAULT;
}
regptr = axid->region;
if (axid->bufnum1 > 0) {
for (i = 0; i < axid->bufnum1; i++) {
scfg->awbBuffer[i] =
(uint32_t)(regptr->paddr);
regptr++;
}
}
if (axid->bufnum2 > 0) {
for (i = 0; i < axid->bufnum2; i++) {
scfg->afBuffer[i] =
(uint32_t)(regptr->paddr);
regptr++;
}
}
vfe_stats_config(scfg);
}
break;
case CMD_STATS_AF_AXI_CFG: {
}
break;
case CMD_FRAME_BUF_RELEASE: {
/* preview buffer release */
struct msm_frame *b;
unsigned long p;
struct vfe_cmd_output_ack fack;
if (!data)
return -EFAULT;
b = (struct msm_frame *)(cmd->value);
p = *(unsigned long *)data;
b->path = MSM_FRAME_ENC;
fack.ybufaddr[0] =
(uint32_t)(p + b->y_off);
fack.chromabufaddr[0] =
(uint32_t)(p + b->cbcr_off);
if (b->path == MSM_FRAME_PREV_1)
vfe_output1_ack(&fack);
if (b->path == MSM_FRAME_ENC ||
b->path == MSM_FRAME_PREV_2)
vfe_output2_ack(&fack);
}
break;
case CMD_SNAP_BUF_RELEASE: {
}
break;
case CMD_STATS_BUF_RELEASE: {
struct vfe_cmd_stats_wb_exp_ack sack;
if (!data)
return -EFAULT;
sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
vfe_stats_wb_exp_ack(&sack);
}
break;
case CMD_AXI_CFG_OUT1: {
struct axidata *axid;
axid = data;
if (!axid)
return -EFAULT;
axio =
kmalloc(sizeof(struct vfe_cmd_axi_output_config),
GFP_ATOMIC);
if (!axio)
return -ENOMEM;
if (copy_from_user(axio, (void __user *)(vfecmd.value),
sizeof(struct vfe_cmd_axi_output_config))) {
kfree(axio);
return -EFAULT;
}
vfe_config_axi(OUTPUT_1, axid, axio);
vfe_axi_output_config(axio);
}
break;
case CMD_AXI_CFG_OUT2:
case CMD_RAW_PICT_AXI_CFG: {
struct axidata *axid;
axid = data;
if (!axid)
return -EFAULT;
axio =
kmalloc(sizeof(struct vfe_cmd_axi_output_config),
GFP_ATOMIC);
if (!axio)
return -ENOMEM;
if (copy_from_user(axio, (void __user *)(vfecmd.value),
sizeof(struct vfe_cmd_axi_output_config))) {
kfree(axio);
return -EFAULT;
}
vfe_config_axi(OUTPUT_2, axid, axio);
axio->outputDataSize = 0;
vfe_axi_output_config(axio);
}
break;
case CMD_AXI_CFG_SNAP_O1_AND_O2: {
struct axidata *axid;
axid = data;
if (!axid)
return -EFAULT;
axio =
kmalloc(sizeof(struct vfe_cmd_axi_output_config),
GFP_ATOMIC);
if (!axio)
return -ENOMEM;
if (copy_from_user(axio, (void __user *)(vfecmd.value),
sizeof(struct vfe_cmd_axi_output_config))) {
kfree(axio);
return -EFAULT;
}
vfe_config_axi(OUTPUT_1_AND_2,
axid, axio);
vfe_axi_output_config(axio);
cmd_data = axio;
}
break;
default:
break;
} /* switch */
kfree(scfg);
kfree(axio);
/*
if (cmd->length > 256 &&
cmd_data &&
(cmd->cmd_type == CMD_GENERAL ||
cmd->cmd_type == CMD_STATS_DISABLE)) {
kfree(cmd_data);
}
*/
return rc;
}
static int vfe_init(struct msm_vfe_callback *presp,
struct platform_device *dev)
{
int rc = 0;
rc = vfe_cmd_init(presp, dev, vfe_syncdata);
if (rc < 0)
return rc;
/* Bring up all the required GPIOs and Clocks */
return msm_camio_enable(dev);
}
void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
{
mutex_init(&vfe_lock);
fptr->vfe_init = vfe_init;
fptr->vfe_enable = vfe_enable;
fptr->vfe_config = vfe_config;
fptr->vfe_disable = vfe_disable;
fptr->vfe_release = vfe_release;
vfe_syncdata = data;
}

View File

@ -0,0 +1,895 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef __MSM_VFE8X_H__
#define __MSM_VFE8X_H__
#define TRUE 1
#define FALSE 0
#define boolean uint8_t
enum VFE_STATE {
VFE_STATE_IDLE,
VFE_STATE_ACTIVE
};
enum vfe_cmd_id {
/*
*Important! Command_ID are arranged in order.
*Don't change!*/
VFE_CMD_ID_START,
VFE_CMD_ID_RESET,
/* bus and camif config */
VFE_CMD_ID_AXI_INPUT_CONFIG,
VFE_CMD_ID_CAMIF_CONFIG,
VFE_CMD_ID_AXI_OUTPUT_CONFIG,
/* module config */
VFE_CMD_ID_BLACK_LEVEL_CONFIG,
VFE_CMD_ID_ROLL_OFF_CONFIG,
VFE_CMD_ID_DEMUX_CHANNEL_GAIN_CONFIG,
VFE_CMD_ID_DEMOSAIC_CONFIG,
VFE_CMD_ID_FOV_CROP_CONFIG,
VFE_CMD_ID_MAIN_SCALER_CONFIG,
VFE_CMD_ID_WHITE_BALANCE_CONFIG,
VFE_CMD_ID_COLOR_CORRECTION_CONFIG,
VFE_CMD_ID_LA_CONFIG,
VFE_CMD_ID_RGB_GAMMA_CONFIG,
VFE_CMD_ID_CHROMA_ENHAN_CONFIG,
VFE_CMD_ID_CHROMA_SUPPRESSION_CONFIG,
VFE_CMD_ID_ASF_CONFIG,
VFE_CMD_ID_SCALER2Y_CONFIG,
VFE_CMD_ID_SCALER2CbCr_CONFIG,
VFE_CMD_ID_CHROMA_SUBSAMPLE_CONFIG,
VFE_CMD_ID_FRAME_SKIP_CONFIG,
VFE_CMD_ID_OUTPUT_CLAMP_CONFIG,
/* test gen */
VFE_CMD_ID_TEST_GEN_START,
VFE_CMD_ID_UPDATE,
/* ackownledge from upper layer */
VFE_CMD_ID_OUTPUT1_ACK,
VFE_CMD_ID_OUTPUT2_ACK,
VFE_CMD_ID_EPOCH1_ACK,
VFE_CMD_ID_EPOCH2_ACK,
VFE_CMD_ID_STATS_AUTOFOCUS_ACK,
VFE_CMD_ID_STATS_WB_EXP_ACK,
/* module update commands */
VFE_CMD_ID_BLACK_LEVEL_UPDATE,
VFE_CMD_ID_DEMUX_CHANNEL_GAIN_UPDATE,
VFE_CMD_ID_DEMOSAIC_BPC_UPDATE,
VFE_CMD_ID_DEMOSAIC_ABF_UPDATE,
VFE_CMD_ID_FOV_CROP_UPDATE,
VFE_CMD_ID_WHITE_BALANCE_UPDATE,
VFE_CMD_ID_COLOR_CORRECTION_UPDATE,
VFE_CMD_ID_LA_UPDATE,
VFE_CMD_ID_RGB_GAMMA_UPDATE,
VFE_CMD_ID_CHROMA_ENHAN_UPDATE,
VFE_CMD_ID_CHROMA_SUPPRESSION_UPDATE,
VFE_CMD_ID_MAIN_SCALER_UPDATE,
VFE_CMD_ID_SCALER2CbCr_UPDATE,
VFE_CMD_ID_SCALER2Y_UPDATE,
VFE_CMD_ID_ASF_UPDATE,
VFE_CMD_ID_FRAME_SKIP_UPDATE,
VFE_CMD_ID_CAMIF_FRAME_UPDATE,
/* stats update commands */
VFE_CMD_ID_STATS_AUTOFOCUS_UPDATE,
VFE_CMD_ID_STATS_WB_EXP_UPDATE,
/* control of start, stop, update, etc... */
VFE_CMD_ID_STOP,
VFE_CMD_ID_GET_HW_VERSION,
/* stats */
VFE_CMD_ID_STATS_SETTING,
VFE_CMD_ID_STATS_AUTOFOCUS_START,
VFE_CMD_ID_STATS_AUTOFOCUS_STOP,
VFE_CMD_ID_STATS_WB_EXP_START,
VFE_CMD_ID_STATS_WB_EXP_STOP,
VFE_CMD_ID_ASYNC_TIMER_SETTING,
/* max id */
VFE_CMD_ID_MAX
};
struct vfe_cmd_hw_version {
uint32_t minorVersion;
uint32_t majorVersion;
uint32_t coreVersion;
};
enum VFE_CAMIF_SYNC_EDGE {
VFE_CAMIF_SYNC_EDGE_ActiveHigh,
VFE_CAMIF_SYNC_EDGE_ActiveLow
};
enum VFE_CAMIF_SYNC_MODE {
VFE_CAMIF_SYNC_MODE_APS,
VFE_CAMIF_SYNC_MODE_EFS,
VFE_CAMIF_SYNC_MODE_ELS,
VFE_CAMIF_SYNC_MODE_ILLEGAL
};
struct vfe_cmds_camif_efs {
uint8_t efsendofline;
uint8_t efsstartofline;
uint8_t efsendofframe;
uint8_t efsstartofframe;
};
struct vfe_cmds_camif_frame {
uint16_t pixelsPerLine;
uint16_t linesPerFrame;
};
struct vfe_cmds_camif_window {
uint16_t firstpixel;
uint16_t lastpixel;
uint16_t firstline;
uint16_t lastline;
};
enum CAMIF_SUBSAMPLE_FRAME_SKIP {
CAMIF_SUBSAMPLE_FRAME_SKIP_0,
CAMIF_SUBSAMPLE_FRAME_SKIP_AllFrames,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_2Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_3Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_4Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_5Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_6Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_7Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_8Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_9Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_10Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_11Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_12Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_13Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_14Frame,
CAMIF_SUBSAMPLE_FRAME_SKIP_ONE_OUT_OF_EVERY_15Frame
};
struct vfe_cmds_camif_subsample {
uint16_t pixelskipmask;
uint16_t lineskipmask;
enum CAMIF_SUBSAMPLE_FRAME_SKIP frameskip;
uint8_t frameskipmode;
uint8_t pixelskipwrap;
};
struct vfe_cmds_camif_epoch {
uint8_t enable;
uint16_t lineindex;
};
struct vfe_cmds_camif_cfg {
enum VFE_CAMIF_SYNC_EDGE vSyncEdge;
enum VFE_CAMIF_SYNC_EDGE hSyncEdge;
enum VFE_CAMIF_SYNC_MODE syncMode;
uint8_t vfeSubSampleEnable;
uint8_t busSubSampleEnable;
uint8_t irqSubSampleEnable;
uint8_t binningEnable;
uint8_t misrEnable;
};
struct vfe_cmd_camif_config {
struct vfe_cmds_camif_cfg camifConfig;
struct vfe_cmds_camif_efs EFS;
struct vfe_cmds_camif_frame frame;
struct vfe_cmds_camif_window window;
struct vfe_cmds_camif_subsample subsample;
struct vfe_cmds_camif_epoch epoch1;
struct vfe_cmds_camif_epoch epoch2;
};
enum VFE_AXI_OUTPUT_MODE {
VFE_AXI_OUTPUT_MODE_Output1,
VFE_AXI_OUTPUT_MODE_Output2,
VFE_AXI_OUTPUT_MODE_Output1AndOutput2,
VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2,
VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1,
VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2,
VFE_AXI_LAST_OUTPUT_MODE_ENUM
};
enum VFE_RAW_WR_PATH_SEL {
VFE_RAW_OUTPUT_DISABLED,
VFE_RAW_OUTPUT_ENC_CBCR_PATH,
VFE_RAW_OUTPUT_VIEW_CBCR_PATH,
VFE_RAW_OUTPUT_PATH_INVALID
};
enum VFE_RAW_PIXEL_DATA_SIZE {
VFE_RAW_PIXEL_DATA_SIZE_8BIT,
VFE_RAW_PIXEL_DATA_SIZE_10BIT,
VFE_RAW_PIXEL_DATA_SIZE_12BIT,
};
#define VFE_AXI_OUTPUT_BURST_LENGTH 4
#define VFE_MAX_NUM_FRAGMENTS_PER_FRAME 4
#define VFE_AXI_OUTPUT_CFG_FRAME_COUNT 3
struct vfe_cmds_axi_out_per_component {
uint16_t imageWidth;
uint16_t imageHeight;
uint16_t outRowCount;
uint16_t outRowIncrement;
uint32_t outFragments[VFE_AXI_OUTPUT_CFG_FRAME_COUNT]
[VFE_MAX_NUM_FRAGMENTS_PER_FRAME];
};
struct vfe_cmds_axi_per_output_path {
uint8_t fragmentCount;
struct vfe_cmds_axi_out_per_component outputY;
struct vfe_cmds_axi_out_per_component outputCbcr;
};
enum VFE_AXI_BURST_LENGTH {
VFE_AXI_BURST_LENGTH_IS_2 = 2,
VFE_AXI_BURST_LENGTH_IS_4 = 4,
VFE_AXI_BURST_LENGTH_IS_8 = 8,
VFE_AXI_BURST_LENGTH_IS_16 = 16
};
struct vfe_cmd_axi_output_config {
enum VFE_AXI_BURST_LENGTH burstLength;
enum VFE_AXI_OUTPUT_MODE outputMode;
enum VFE_RAW_PIXEL_DATA_SIZE outputDataSize;
struct vfe_cmds_axi_per_output_path output1;
struct vfe_cmds_axi_per_output_path output2;
};
struct vfe_cmd_fov_crop_config {
uint8_t enable;
uint16_t firstPixel;
uint16_t lastPixel;
uint16_t firstLine;
uint16_t lastLine;
};
struct vfe_cmds_main_scaler_stripe_init {
uint16_t MNCounterInit;
uint16_t phaseInit;
};
struct vfe_cmds_scaler_one_dimension {
uint8_t enable;
uint16_t inputSize;
uint16_t outputSize;
uint32_t phaseMultiplicationFactor;
uint8_t interpolationResolution;
};
struct vfe_cmd_main_scaler_config {
uint8_t enable;
struct vfe_cmds_scaler_one_dimension hconfig;
struct vfe_cmds_scaler_one_dimension vconfig;
struct vfe_cmds_main_scaler_stripe_init MNInitH;
struct vfe_cmds_main_scaler_stripe_init MNInitV;
};
struct vfe_cmd_scaler2_config {
uint8_t enable;
struct vfe_cmds_scaler_one_dimension hconfig;
struct vfe_cmds_scaler_one_dimension vconfig;
};
struct vfe_cmd_frame_skip_config {
uint8_t output1Period;
uint32_t output1Pattern;
uint8_t output2Period;
uint32_t output2Pattern;
};
struct vfe_cmd_frame_skip_update {
uint32_t output1Pattern;
uint32_t output2Pattern;
};
struct vfe_cmd_output_clamp_config {
uint8_t minCh0;
uint8_t minCh1;
uint8_t minCh2;
uint8_t maxCh0;
uint8_t maxCh1;
uint8_t maxCh2;
};
struct vfe_cmd_chroma_subsample_config {
uint8_t enable;
uint8_t cropEnable;
uint8_t vsubSampleEnable;
uint8_t hsubSampleEnable;
uint8_t vCosited;
uint8_t hCosited;
uint8_t vCositedPhase;
uint8_t hCositedPhase;
uint16_t cropWidthFirstPixel;
uint16_t cropWidthLastPixel;
uint16_t cropHeightFirstLine;
uint16_t cropHeightLastLine;
};
enum VFE_START_INPUT_SOURCE {
VFE_START_INPUT_SOURCE_CAMIF,
VFE_START_INPUT_SOURCE_TESTGEN,
VFE_START_INPUT_SOURCE_AXI,
VFE_START_INPUT_SOURCE_INVALID
};
enum VFE_START_OPERATION_MODE {
VFE_START_OPERATION_MODE_CONTINUOUS,
VFE_START_OPERATION_MODE_SNAPSHOT
};
enum VFE_START_PIXEL_PATTERN {
VFE_BAYER_RGRGRG,
VFE_BAYER_GRGRGR,
VFE_BAYER_BGBGBG,
VFE_BAYER_GBGBGB,
VFE_YUV_YCbYCr,
VFE_YUV_YCrYCb,
VFE_YUV_CbYCrY,
VFE_YUV_CrYCbY
};
enum VFE_BUS_RD_INPUT_PIXEL_PATTERN {
VFE_BAYER_RAW,
VFE_YUV_INTERLEAVED,
VFE_YUV_PSEUDO_PLANAR_Y,
VFE_YUV_PSEUDO_PLANAR_CBCR
};
enum VFE_YUV_INPUT_COSITING_MODE {
VFE_YUV_COSITED,
VFE_YUV_INTERPOLATED
};
struct vfe_cmd_start {
enum VFE_START_INPUT_SOURCE inputSource;
enum VFE_START_OPERATION_MODE operationMode;
uint8_t snapshotCount;
enum VFE_START_PIXEL_PATTERN pixel;
enum VFE_YUV_INPUT_COSITING_MODE yuvInputCositingMode;
};
struct vfe_cmd_output_ack {
uint32_t ybufaddr[VFE_MAX_NUM_FRAGMENTS_PER_FRAME];
uint32_t chromabufaddr[VFE_MAX_NUM_FRAGMENTS_PER_FRAME];
};
#define VFE_STATS_BUFFER_COUNT 3
struct vfe_cmd_stats_setting {
uint16_t frameHDimension;
uint16_t frameVDimension;
uint8_t afBusPrioritySelection;
uint8_t afBusPriority;
uint8_t awbBusPrioritySelection;
uint8_t awbBusPriority;
uint8_t histBusPrioritySelection;
uint8_t histBusPriority;
uint32_t afBuffer[VFE_STATS_BUFFER_COUNT];
uint32_t awbBuffer[VFE_STATS_BUFFER_COUNT];
uint32_t histBuffer[VFE_STATS_BUFFER_COUNT];
};
struct vfe_cmd_stats_af_start {
uint8_t enable;
uint8_t windowMode;
uint16_t windowHOffset;
uint16_t windowVOffset;
uint16_t windowWidth;
uint16_t windowHeight;
uint8_t gridForMultiWindows[16];
uint8_t metricSelection;
int16_t metricMax;
int8_t highPassCoef[7];
int8_t bufferHeader;
};
struct vfe_cmd_stats_af_update {
uint8_t windowMode;
uint16_t windowHOffset;
uint16_t windowVOffset;
uint16_t windowWidth;
uint16_t windowHeight;
};
struct vfe_cmd_stats_wb_exp_start {
uint8_t enable;
uint8_t wbExpRegions;
uint8_t wbExpSubRegion;
uint8_t awbYMin;
uint8_t awbYMax;
int8_t awbMCFG[4];
int16_t awbCCFG[4];
int8_t axwHeader;
};
struct vfe_cmd_stats_wb_exp_update {
uint8_t wbExpRegions;
uint8_t wbExpSubRegion;
int8_t awbYMin;
int8_t awbYMax;
int8_t awbMCFG[4];
int16_t awbCCFG[4];
};
struct vfe_cmd_stats_af_ack {
uint32_t nextAFOutputBufferAddr;
};
struct vfe_cmd_stats_wb_exp_ack {
uint32_t nextWbExpOutputBufferAddr;
};
struct vfe_cmd_black_level_config {
uint8_t enable;
uint16_t evenEvenAdjustment;
uint16_t evenOddAdjustment;
uint16_t oddEvenAdjustment;
uint16_t oddOddAdjustment;
};
/* 13*1 */
#define VFE_ROLL_OFF_INIT_TABLE_SIZE 13
/* 13*16 */
#define VFE_ROLL_OFF_DELTA_TABLE_SIZE 208
struct vfe_cmd_roll_off_config {
uint8_t enable;
uint16_t gridWidth;
uint16_t gridHeight;
uint16_t yDelta;
uint8_t gridXIndex;
uint8_t gridYIndex;
uint16_t gridPixelXIndex;
uint16_t gridPixelYIndex;
uint16_t yDeltaAccum;
uint16_t initTableR[VFE_ROLL_OFF_INIT_TABLE_SIZE];
uint16_t initTableGr[VFE_ROLL_OFF_INIT_TABLE_SIZE];
uint16_t initTableB[VFE_ROLL_OFF_INIT_TABLE_SIZE];
uint16_t initTableGb[VFE_ROLL_OFF_INIT_TABLE_SIZE];
int16_t deltaTableR[VFE_ROLL_OFF_DELTA_TABLE_SIZE];
int16_t deltaTableGr[VFE_ROLL_OFF_DELTA_TABLE_SIZE];
int16_t deltaTableB[VFE_ROLL_OFF_DELTA_TABLE_SIZE];
int16_t deltaTableGb[VFE_ROLL_OFF_DELTA_TABLE_SIZE];
};
struct vfe_cmd_demux_channel_gain_config {
uint16_t ch0EvenGain;
uint16_t ch0OddGain;
uint16_t ch1Gain;
uint16_t ch2Gain;
};
struct vfe_cmds_demosaic_abf {
uint8_t enable;
uint8_t forceOn;
uint8_t shift;
uint16_t lpThreshold;
uint16_t max;
uint16_t min;
uint8_t ratio;
};
struct vfe_cmds_demosaic_bpc {
uint8_t enable;
uint16_t fmaxThreshold;
uint16_t fminThreshold;
uint16_t redDiffThreshold;
uint16_t blueDiffThreshold;
uint16_t greenDiffThreshold;
};
struct vfe_cmd_demosaic_config {
uint8_t enable;
uint8_t slopeShift;
struct vfe_cmds_demosaic_abf abfConfig;
struct vfe_cmds_demosaic_bpc bpcConfig;
};
struct vfe_cmd_demosaic_bpc_update {
struct vfe_cmds_demosaic_bpc bpcUpdate;
};
struct vfe_cmd_demosaic_abf_update {
struct vfe_cmds_demosaic_abf abfUpdate;
};
struct vfe_cmd_white_balance_config {
uint8_t enable;
uint16_t ch2Gain;
uint16_t ch1Gain;
uint16_t ch0Gain;
};
enum VFE_COLOR_CORRECTION_COEF_QFACTOR {
COEF_IS_Q7_SIGNED,
COEF_IS_Q8_SIGNED,
COEF_IS_Q9_SIGNED,
COEF_IS_Q10_SIGNED
};
struct vfe_cmd_color_correction_config {
uint8_t enable;
enum VFE_COLOR_CORRECTION_COEF_QFACTOR coefQFactor;
int16_t C0;
int16_t C1;
int16_t C2;
int16_t C3;
int16_t C4;
int16_t C5;
int16_t C6;
int16_t C7;
int16_t C8;
int16_t K0;
int16_t K1;
int16_t K2;
};
#define VFE_LA_TABLE_LENGTH 256
struct vfe_cmd_la_config {
uint8_t enable;
int16_t table[VFE_LA_TABLE_LENGTH];
};
#define VFE_GAMMA_TABLE_LENGTH 256
enum VFE_RGB_GAMMA_TABLE_SELECT {
RGB_GAMMA_CH0_SELECTED,
RGB_GAMMA_CH1_SELECTED,
RGB_GAMMA_CH2_SELECTED,
RGB_GAMMA_CH0_CH1_SELECTED,
RGB_GAMMA_CH0_CH2_SELECTED,
RGB_GAMMA_CH1_CH2_SELECTED,
RGB_GAMMA_CH0_CH1_CH2_SELECTED
};
struct vfe_cmd_rgb_gamma_config {
uint8_t enable;
enum VFE_RGB_GAMMA_TABLE_SELECT channelSelect;
int16_t table[VFE_GAMMA_TABLE_LENGTH];
};
struct vfe_cmd_chroma_enhan_config {
uint8_t enable;
int16_t am;
int16_t ap;
int16_t bm;
int16_t bp;
int16_t cm;
int16_t cp;
int16_t dm;
int16_t dp;
int16_t kcr;
int16_t kcb;
int16_t RGBtoYConversionV0;
int16_t RGBtoYConversionV1;
int16_t RGBtoYConversionV2;
uint8_t RGBtoYConversionOffset;
};
struct vfe_cmd_chroma_suppression_config {
uint8_t enable;
uint8_t m1;
uint8_t m3;
uint8_t n1;
uint8_t n3;
uint8_t nn1;
uint8_t mm1;
};
struct vfe_cmd_asf_config {
uint8_t enable;
uint8_t smoothFilterEnabled;
uint8_t sharpMode;
uint8_t smoothCoefCenter;
uint8_t smoothCoefSurr;
uint8_t normalizeFactor;
uint8_t sharpK1;
uint8_t sharpK2;
uint8_t sharpThreshE1;
int8_t sharpThreshE2;
int8_t sharpThreshE3;
int8_t sharpThreshE4;
int8_t sharpThreshE5;
int8_t filter1Coefficients[9];
int8_t filter2Coefficients[9];
uint8_t cropEnable;
uint16_t cropFirstPixel;
uint16_t cropLastPixel;
uint16_t cropFirstLine;
uint16_t cropLastLine;
};
struct vfe_cmd_asf_update {
uint8_t enable;
uint8_t smoothFilterEnabled;
uint8_t sharpMode;
uint8_t smoothCoefCenter;
uint8_t smoothCoefSurr;
uint8_t normalizeFactor;
uint8_t sharpK1;
uint8_t sharpK2;
uint8_t sharpThreshE1;
int8_t sharpThreshE2;
int8_t sharpThreshE3;
int8_t sharpThreshE4;
int8_t sharpThreshE5;
int8_t filter1Coefficients[9];
int8_t filter2Coefficients[9];
uint8_t cropEnable;
};
enum VFE_TEST_GEN_SYNC_EDGE {
VFE_TEST_GEN_SYNC_EDGE_ActiveHigh,
VFE_TEST_GEN_SYNC_EDGE_ActiveLow
};
struct vfe_cmd_test_gen_start {
uint8_t pixelDataSelect;
uint8_t systematicDataSelect;
enum VFE_TEST_GEN_SYNC_EDGE hsyncEdge;
enum VFE_TEST_GEN_SYNC_EDGE vsyncEdge;
uint16_t numFrame;
enum VFE_RAW_PIXEL_DATA_SIZE pixelDataSize;
uint16_t imageWidth;
uint16_t imageHeight;
uint32_t startOfFrameOffset;
uint32_t endOfFrameNOffset;
uint16_t startOfLineOffset;
uint16_t endOfLineNOffset;
uint16_t hbi;
uint8_t vblEnable;
uint16_t vbl;
uint8_t startOfFrameDummyLine;
uint8_t endOfFrameDummyLine;
uint8_t unicolorBarEnable;
uint8_t colorBarsSplitEnable;
uint8_t unicolorBarSelect;
enum VFE_START_PIXEL_PATTERN colorBarsPixelPattern;
uint8_t colorBarsRotatePeriod;
uint16_t testGenRandomSeed;
};
struct vfe_cmd_bus_pm_start {
uint8_t output2YWrPmEnable;
uint8_t output2CbcrWrPmEnable;
uint8_t output1YWrPmEnable;
uint8_t output1CbcrWrPmEnable;
};
struct vfe_cmd_camif_frame_update {
struct vfe_cmds_camif_frame camifFrame;
};
struct vfe_cmd_sync_timer_setting {
uint8_t whichSyncTimer;
uint8_t operation;
uint8_t polarity;
uint16_t repeatCount;
uint16_t hsyncCount;
uint32_t pclkCount;
uint32_t outputDuration;
};
struct vfe_cmd_async_timer_setting {
uint8_t whichAsyncTimer;
uint8_t operation;
uint8_t polarity;
uint16_t repeatCount;
uint16_t inactiveCount;
uint32_t activeCount;
};
struct vfe_frame_skip_counts {
uint32_t totalFrameCount;
uint32_t output1Count;
uint32_t output2Count;
};
enum VFE_AXI_RD_UNPACK_HBI_SEL {
VFE_AXI_RD_HBI_32_CLOCK_CYCLES,
VFE_AXI_RD_HBI_64_CLOCK_CYCLES,
VFE_AXI_RD_HBI_128_CLOCK_CYCLES,
VFE_AXI_RD_HBI_256_CLOCK_CYCLES,
VFE_AXI_RD_HBI_512_CLOCK_CYCLES,
VFE_AXI_RD_HBI_1024_CLOCK_CYCLES,
VFE_AXI_RD_HBI_2048_CLOCK_CYCLES,
VFE_AXI_RD_HBI_4096_CLOCK_CYCLES
};
struct vfe_cmd_axi_input_config {
uint32_t fragAddr[4];
uint8_t totalFragmentCount;
uint16_t ySize;
uint16_t xOffset;
uint16_t xSize;
uint16_t rowIncrement;
uint16_t numOfRows;
enum VFE_AXI_BURST_LENGTH burstLength;
uint8_t unpackPhase;
enum VFE_AXI_RD_UNPACK_HBI_SEL unpackHbi;
enum VFE_RAW_PIXEL_DATA_SIZE pixelSize;
uint8_t padRepeatCountLeft;
uint8_t padRepeatCountRight;
uint8_t padRepeatCountTop;
uint8_t padRepeatCountBottom;
uint8_t padLeftComponentSelectCycle0;
uint8_t padLeftComponentSelectCycle1;
uint8_t padLeftComponentSelectCycle2;
uint8_t padLeftComponentSelectCycle3;
uint8_t padLeftStopCycle0;
uint8_t padLeftStopCycle1;
uint8_t padLeftStopCycle2;
uint8_t padLeftStopCycle3;
uint8_t padRightComponentSelectCycle0;
uint8_t padRightComponentSelectCycle1;
uint8_t padRightComponentSelectCycle2;
uint8_t padRightComponentSelectCycle3;
uint8_t padRightStopCycle0;
uint8_t padRightStopCycle1;
uint8_t padRightStopCycle2;
uint8_t padRightStopCycle3;
uint8_t padTopLineCount;
uint8_t padBottomLineCount;
};
struct vfe_interrupt_status {
uint8_t camifErrorIrq;
uint8_t camifSofIrq;
uint8_t camifEolIrq;
uint8_t camifEofIrq;
uint8_t camifEpoch1Irq;
uint8_t camifEpoch2Irq;
uint8_t camifOverflowIrq;
uint8_t ceIrq;
uint8_t regUpdateIrq;
uint8_t resetAckIrq;
uint8_t encYPingpongIrq;
uint8_t encCbcrPingpongIrq;
uint8_t viewYPingpongIrq;
uint8_t viewCbcrPingpongIrq;
uint8_t rdPingpongIrq;
uint8_t afPingpongIrq;
uint8_t awbPingpongIrq;
uint8_t histPingpongIrq;
uint8_t encIrq;
uint8_t viewIrq;
uint8_t busOverflowIrq;
uint8_t afOverflowIrq;
uint8_t awbOverflowIrq;
uint8_t syncTimer0Irq;
uint8_t syncTimer1Irq;
uint8_t syncTimer2Irq;
uint8_t asyncTimer0Irq;
uint8_t asyncTimer1Irq;
uint8_t asyncTimer2Irq;
uint8_t asyncTimer3Irq;
uint8_t axiErrorIrq;
uint8_t violationIrq;
uint8_t anyErrorIrqs;
uint8_t anyOutput1PathIrqs;
uint8_t anyOutput2PathIrqs;
uint8_t anyOutputPathIrqs;
uint8_t anyAsyncTimerIrqs;
uint8_t anySyncTimerIrqs;
uint8_t anyIrqForActiveStatesOnly;
};
enum VFE_MESSAGE_ID {
VFE_MSG_ID_RESET_ACK,
VFE_MSG_ID_START_ACK,
VFE_MSG_ID_STOP_ACK,
VFE_MSG_ID_UPDATE_ACK,
VFE_MSG_ID_OUTPUT1,
VFE_MSG_ID_OUTPUT2,
VFE_MSG_ID_SNAPSHOT_DONE,
VFE_MSG_ID_STATS_AUTOFOCUS,
VFE_MSG_ID_STATS_WB_EXP,
VFE_MSG_ID_EPOCH1,
VFE_MSG_ID_EPOCH2,
VFE_MSG_ID_SYNC_TIMER0_DONE,
VFE_MSG_ID_SYNC_TIMER1_DONE,
VFE_MSG_ID_SYNC_TIMER2_DONE,
VFE_MSG_ID_ASYNC_TIMER0_DONE,
VFE_MSG_ID_ASYNC_TIMER1_DONE,
VFE_MSG_ID_ASYNC_TIMER2_DONE,
VFE_MSG_ID_ASYNC_TIMER3_DONE,
VFE_MSG_ID_AF_OVERFLOW,
VFE_MSG_ID_AWB_OVERFLOW,
VFE_MSG_ID_AXI_ERROR,
VFE_MSG_ID_CAMIF_OVERFLOW,
VFE_MSG_ID_VIOLATION,
VFE_MSG_ID_CAMIF_ERROR,
VFE_MSG_ID_BUS_OVERFLOW,
};
struct vfe_msg_stats_autofocus {
uint32_t afBuffer;
uint32_t frameCounter;
};
struct vfe_msg_stats_wb_exp {
uint32_t awbBuffer;
uint32_t frameCounter;
};
struct vfe_frame_bpc_info {
uint32_t greenDefectPixelCount;
uint32_t redBlueDefectPixelCount;
};
struct vfe_frame_asf_info {
uint32_t asfMaxEdge;
uint32_t asfHbiCount;
};
struct vfe_msg_camif_status {
uint8_t camifState;
uint32_t pixelCount;
uint32_t lineCount;
};
struct vfe_bus_pm_per_path {
uint32_t yWrPmStats0;
uint32_t yWrPmStats1;
uint32_t cbcrWrPmStats0;
uint32_t cbcrWrPmStats1;
};
struct vfe_bus_performance_monitor {
struct vfe_bus_pm_per_path encPathPmInfo;
struct vfe_bus_pm_per_path viewPathPmInfo;
};
struct vfe_irq_thread_msg {
uint32_t vfeIrqStatus;
uint32_t camifStatus;
uint32_t demosaicStatus;
uint32_t asfMaxEdge;
struct vfe_bus_performance_monitor pmInfo;
};
struct vfe_msg_output {
uint32_t yBuffer;
uint32_t cbcrBuffer;
struct vfe_frame_bpc_info bpcInfo;
struct vfe_frame_asf_info asfInfo;
uint32_t frameCounter;
struct vfe_bus_pm_per_path pmData;
};
struct vfe_message {
enum VFE_MESSAGE_ID _d;
union {
struct vfe_msg_output msgOutput1;
struct vfe_msg_output msgOutput2;
struct vfe_msg_stats_autofocus msgStatsAf;
struct vfe_msg_stats_wb_exp msgStatsWbExp;
struct vfe_msg_camif_status msgCamifError;
struct vfe_bus_performance_monitor msgBusOverflow;
} _u;
};
/* New one for 8k */
struct msm_vfe_command_8k {
int32_t id;
uint16_t length;
void *value;
};
struct vfe_frame_extra {
struct vfe_frame_bpc_info bpcInfo;
struct vfe_frame_asf_info asfInfo;
uint32_t frameCounter;
struct vfe_bus_pm_per_path pmData;
};
#endif /* __MSM_VFE8X_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,761 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <media/msm_camera.h>
#include <mach/gpio.h>
#include "mt9d112.h"
/* Micron MT9D112 Registers and their values */
/* Sensor Core Registers */
#define REG_MT9D112_MODEL_ID 0x3000
#define MT9D112_MODEL_ID 0x1580
/* SOC Registers Page 1 */
#define REG_MT9D112_SENSOR_RESET 0x301A
#define REG_MT9D112_STANDBY_CONTROL 0x3202
#define REG_MT9D112_MCU_BOOT 0x3386
struct mt9d112_work {
struct work_struct work;
};
static struct mt9d112_work *mt9d112_sensorw;
static struct i2c_client *mt9d112_client;
struct mt9d112_ctrl {
const struct msm_camera_sensor_info *sensordata;
};
static struct mt9d112_ctrl *mt9d112_ctrl;
static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue);
DECLARE_MUTEX(mt9d112_sem);
/*=============================================================
EXTERNAL DECLARATIONS
==============================================================*/
extern struct mt9d112_reg mt9d112_regs;
/*=============================================================*/
static int mt9d112_reset(const struct msm_camera_sensor_info *dev)
{
int rc = 0;
rc = gpio_request(dev->sensor_reset, "mt9d112");
if (!rc) {
rc = gpio_direction_output(dev->sensor_reset, 0);
mdelay(20);
rc = gpio_direction_output(dev->sensor_reset, 1);
}
gpio_free(dev->sensor_reset);
return rc;
}
static int32_t mt9d112_i2c_txdata(unsigned short saddr,
unsigned char *txdata, int length)
{
struct i2c_msg msg[] = {
{
.addr = saddr,
.flags = 0,
.len = length,
.buf = txdata,
},
};
if (i2c_transfer(mt9d112_client->adapter, msg, 1) < 0) {
CDBG("mt9d112_i2c_txdata failed\n");
return -EIO;
}
return 0;
}
static int32_t mt9d112_i2c_write(unsigned short saddr,
unsigned short waddr, unsigned short wdata, enum mt9d112_width width)
{
int32_t rc = -EIO;
unsigned char buf[4];
memset(buf, 0, sizeof(buf));
switch (width) {
case WORD_LEN: {
buf[0] = (waddr & 0xFF00)>>8;
buf[1] = (waddr & 0x00FF);
buf[2] = (wdata & 0xFF00)>>8;
buf[3] = (wdata & 0x00FF);
rc = mt9d112_i2c_txdata(saddr, buf, 4);
}
break;
case BYTE_LEN: {
buf[0] = waddr;
buf[1] = wdata;
rc = mt9d112_i2c_txdata(saddr, buf, 2);
}
break;
default:
break;
}
if (rc < 0)
CDBG(
"i2c_write failed, addr = 0x%x, val = 0x%x!\n",
waddr, wdata);
return rc;
}
static int32_t mt9d112_i2c_write_table(
struct mt9d112_i2c_reg_conf const *reg_conf_tbl,
int num_of_items_in_table)
{
int i;
int32_t rc = -EIO;
for (i = 0; i < num_of_items_in_table; i++) {
rc = mt9d112_i2c_write(mt9d112_client->addr,
reg_conf_tbl->waddr, reg_conf_tbl->wdata,
reg_conf_tbl->width);
if (rc < 0)
break;
if (reg_conf_tbl->mdelay_time != 0)
mdelay(reg_conf_tbl->mdelay_time);
reg_conf_tbl++;
}
return rc;
}
static int mt9d112_i2c_rxdata(unsigned short saddr,
unsigned char *rxdata, int length)
{
struct i2c_msg msgs[] = {
{
.addr = saddr,
.flags = 0,
.len = 2,
.buf = rxdata,
},
{
.addr = saddr,
.flags = I2C_M_RD,
.len = length,
.buf = rxdata,
},
};
if (i2c_transfer(mt9d112_client->adapter, msgs, 2) < 0) {
CDBG("mt9d112_i2c_rxdata failed!\n");
return -EIO;
}
return 0;
}
static int32_t mt9d112_i2c_read(unsigned short saddr,
unsigned short raddr, unsigned short *rdata, enum mt9d112_width width)
{
int32_t rc = 0;
unsigned char buf[4];
if (!rdata)
return -EIO;
memset(buf, 0, sizeof(buf));
switch (width) {
case WORD_LEN: {
buf[0] = (raddr & 0xFF00)>>8;
buf[1] = (raddr & 0x00FF);
rc = mt9d112_i2c_rxdata(saddr, buf, 2);
if (rc < 0)
return rc;
*rdata = buf[0] << 8 | buf[1];
}
break;
default:
break;
}
if (rc < 0)
CDBG("mt9d112_i2c_read failed!\n");
return rc;
}
static int32_t mt9d112_set_lens_roll_off(void)
{
int32_t rc = 0;
rc = mt9d112_i2c_write_table(&mt9d112_regs.rftbl[0],
mt9d112_regs.rftbl_size);
return rc;
}
static long mt9d112_reg_init(void)
{
int32_t array_length;
int32_t i;
long rc;
/* PLL Setup Start */
rc = mt9d112_i2c_write_table(&mt9d112_regs.plltbl[0],
mt9d112_regs.plltbl_size);
if (rc < 0)
return rc;
/* PLL Setup End */
array_length = mt9d112_regs.prev_snap_reg_settings_size;
/* Configure sensor for Preview mode and Snapshot mode */
for (i = 0; i < array_length; i++) {
rc = mt9d112_i2c_write(mt9d112_client->addr,
mt9d112_regs.prev_snap_reg_settings[i].register_address,
mt9d112_regs.prev_snap_reg_settings[i].register_value,
WORD_LEN);
if (rc < 0)
return rc;
}
/* Configure for Noise Reduction, Saturation and Aperture Correction */
array_length = mt9d112_regs.noise_reduction_reg_settings_size;
for (i = 0; i < array_length; i++) {
rc = mt9d112_i2c_write(mt9d112_client->addr,
mt9d112_regs.noise_reduction_reg_settings[i].register_address,
mt9d112_regs.noise_reduction_reg_settings[i].register_value,
WORD_LEN);
if (rc < 0)
return rc;
}
/* Set Color Kill Saturation point to optimum value */
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x35A4,
0x0593,
WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write_table(&mt9d112_regs.stbl[0],
mt9d112_regs.stbl_size);
if (rc < 0)
return rc;
rc = mt9d112_set_lens_roll_off();
if (rc < 0)
return rc;
return 0;
}
static long mt9d112_set_sensor_mode(int mode)
{
uint16_t clock;
long rc = 0;
switch (mode) {
case SENSOR_PREVIEW_MODE:
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA20C, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0004, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA215, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0004, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA20B, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0000, WORD_LEN);
if (rc < 0)
return rc;
clock = 0x0250;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x341C, clock, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA103, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0001, WORD_LEN);
if (rc < 0)
return rc;
mdelay(5);
break;
case SENSOR_SNAPSHOT_MODE:
/* Switch to lower fps for Snapshot */
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x341C, 0x0120, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA120, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0002, WORD_LEN);
if (rc < 0)
return rc;
mdelay(5);
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA103, WORD_LEN);
if (rc < 0)
return rc;
rc =
mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0002, WORD_LEN);
if (rc < 0)
return rc;
break;
default:
return -EINVAL;
}
return 0;
}
static long mt9d112_set_effect(int mode, int effect)
{
uint16_t reg_addr;
uint16_t reg_val;
long rc = 0;
switch (mode) {
case SENSOR_PREVIEW_MODE:
/* Context A Special Effects */
reg_addr = 0x2799;
break;
case SENSOR_SNAPSHOT_MODE:
/* Context B Special Effects */
reg_addr = 0x279B;
break;
default:
reg_addr = 0x2799;
break;
}
switch (effect) {
case CAMERA_EFFECT_OFF: {
reg_val = 0x6440;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
}
break;
case CAMERA_EFFECT_MONO: {
reg_val = 0x6441;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
}
break;
case CAMERA_EFFECT_NEGATIVE: {
reg_val = 0x6443;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
}
break;
case CAMERA_EFFECT_SOLARIZE: {
reg_val = 0x6445;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
}
break;
case CAMERA_EFFECT_SEPIA: {
reg_val = 0x6442;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
}
break;
case CAMERA_EFFECT_PASTEL:
case CAMERA_EFFECT_MOSAIC:
case CAMERA_EFFECT_RESIZE:
return -EINVAL;
default: {
reg_val = 0x6440;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, reg_addr, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, reg_val, WORD_LEN);
if (rc < 0)
return rc;
return -EINVAL;
}
}
/* Refresh Sequencer */
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x338C, 0xA103, WORD_LEN);
if (rc < 0)
return rc;
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x3390, 0x0005, WORD_LEN);
return rc;
}
static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info *data)
{
uint16_t model_id = 0;
int rc = 0;
CDBG("init entry \n");
rc = mt9d112_reset(data);
if (rc < 0) {
CDBG("reset failed!\n");
goto init_probe_fail;
}
mdelay(5);
/* Micron suggested Power up block Start:
* Put MCU into Reset - Stop MCU */
rc = mt9d112_i2c_write(mt9d112_client->addr,
REG_MT9D112_MCU_BOOT, 0x0501, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
/* Pull MCU from Reset - Start MCU */
rc = mt9d112_i2c_write(mt9d112_client->addr,
REG_MT9D112_MCU_BOOT, 0x0500, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
mdelay(5);
/* Micron Suggested - Power up block */
rc = mt9d112_i2c_write(mt9d112_client->addr,
REG_MT9D112_SENSOR_RESET, 0x0ACC, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
rc = mt9d112_i2c_write(mt9d112_client->addr,
REG_MT9D112_STANDBY_CONTROL, 0x0008, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
/* FUSED_DEFECT_CORRECTION */
rc = mt9d112_i2c_write(mt9d112_client->addr,
0x33F4, 0x031D, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
mdelay(5);
/* Micron suggested Power up block End */
/* Read the Model ID of the sensor */
rc = mt9d112_i2c_read(mt9d112_client->addr,
REG_MT9D112_MODEL_ID, &model_id, WORD_LEN);
if (rc < 0)
goto init_probe_fail;
CDBG("mt9d112 model_id = 0x%x\n", model_id);
/* Check if it matches it with the value in Datasheet */
if (model_id != MT9D112_MODEL_ID) {
rc = -EINVAL;
goto init_probe_fail;
}
rc = mt9d112_reg_init();
if (rc < 0)
goto init_probe_fail;
return rc;
init_probe_fail:
return rc;
}
int mt9d112_sensor_init(const struct msm_camera_sensor_info *data)
{
int rc = 0;
mt9d112_ctrl = kzalloc(sizeof(struct mt9d112_ctrl), GFP_KERNEL);
if (!mt9d112_ctrl) {
CDBG("mt9d112_init failed!\n");
rc = -ENOMEM;
goto init_done;
}
if (data)
mt9d112_ctrl->sensordata = data;
/* Input MCLK = 24MHz */
msm_camio_clk_rate_set(24000000);
mdelay(5);
msm_camio_camif_pad_reg_reset();
rc = mt9d112_sensor_init_probe(data);
if (rc < 0) {
CDBG("mt9d112_sensor_init failed!\n");
goto init_fail;
}
init_done:
return rc;
init_fail:
kfree(mt9d112_ctrl);
return rc;
}
static int mt9d112_init_client(struct i2c_client *client)
{
/* Initialize the MSM_CAMI2C Chip */
init_waitqueue_head(&mt9d112_wait_queue);
return 0;
}
int mt9d112_sensor_config(void __user *argp)
{
struct sensor_cfg_data cfg_data;
long rc = 0;
if (copy_from_user(&cfg_data,
(void *)argp,
sizeof(struct sensor_cfg_data)))
return -EFAULT;
/* down(&mt9d112_sem); */
CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
cfg_data.cfgtype, cfg_data.mode);
switch (cfg_data.cfgtype) {
case CFG_SET_MODE:
rc = mt9d112_set_sensor_mode(
cfg_data.mode);
break;
case CFG_SET_EFFECT:
rc = mt9d112_set_effect(cfg_data.mode,
cfg_data.cfg.effect);
break;
case CFG_GET_AF_MAX_STEPS:
default:
rc = -EINVAL;
break;
}
/* up(&mt9d112_sem); */
return rc;
}
int mt9d112_sensor_release(void)
{
int rc = 0;
/* down(&mt9d112_sem); */
kfree(mt9d112_ctrl);
/* up(&mt9d112_sem); */
return rc;
}
static int mt9d112_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc = 0;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
rc = -ENOTSUPP;
goto probe_failure;
}
mt9d112_sensorw =
kzalloc(sizeof(struct mt9d112_work), GFP_KERNEL);
if (!mt9d112_sensorw) {
rc = -ENOMEM;
goto probe_failure;
}
i2c_set_clientdata(client, mt9d112_sensorw);
mt9d112_init_client(client);
mt9d112_client = client;
CDBG("mt9d112_probe succeeded!\n");
return 0;
probe_failure:
kfree(mt9d112_sensorw);
mt9d112_sensorw = NULL;
CDBG("mt9d112_probe failed!\n");
return rc;
}
static const struct i2c_device_id mt9d112_i2c_id[] = {
{ "mt9d112", 0},
{ },
};
static struct i2c_driver mt9d112_i2c_driver = {
.id_table = mt9d112_i2c_id,
.probe = mt9d112_i2c_probe,
.remove = __exit_p(mt9d112_i2c_remove),
.driver = {
.name = "mt9d112",
},
};
static int mt9d112_sensor_probe(const struct msm_camera_sensor_info *info,
struct msm_sensor_ctrl *s)
{
int rc = i2c_add_driver(&mt9d112_i2c_driver);
if (rc < 0 || mt9d112_client == NULL) {
rc = -ENOTSUPP;
goto probe_done;
}
/* Input MCLK = 24MHz */
msm_camio_clk_rate_set(24000000);
mdelay(5);
rc = mt9d112_sensor_init_probe(info);
if (rc < 0)
goto probe_done;
s->s_init = mt9d112_sensor_init;
s->s_release = mt9d112_sensor_release;
s->s_config = mt9d112_sensor_config;
probe_done:
CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
return rc;
}
static int __mt9d112_probe(struct platform_device *pdev)
{
return msm_camera_drv_start(pdev, mt9d112_sensor_probe);
}
static struct platform_driver msm_camera_driver = {
.probe = __mt9d112_probe,
.driver = {
.name = "msm_camera_mt9d112",
.owner = THIS_MODULE,
},
};
static int __init mt9d112_init(void)
{
return platform_driver_register(&msm_camera_driver);
}
module_init(mt9d112_init);

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef MT9D112_H
#define MT9D112_H
#include <linux/types.h>
#include <mach/camera.h>
enum mt9d112_width {
WORD_LEN,
BYTE_LEN
};
struct mt9d112_i2c_reg_conf {
unsigned short waddr;
unsigned short wdata;
enum mt9d112_width width;
unsigned short mdelay_time;
};
struct mt9d112_reg {
const struct register_address_value_pair *prev_snap_reg_settings;
uint16_t prev_snap_reg_settings_size;
const struct register_address_value_pair *noise_reduction_reg_settings;
uint16_t noise_reduction_reg_settings_size;
const struct mt9d112_i2c_reg_conf *plltbl;
uint16_t plltbl_size;
const struct mt9d112_i2c_reg_conf *stbl;
uint16_t stbl_size;
const struct mt9d112_i2c_reg_conf *rftbl;
uint16_t rftbl_size;
};
#endif /* MT9D112_H */

View File

@ -0,0 +1,307 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#include "mt9d112.h"
struct register_address_value_pair
preview_snapshot_mode_reg_settings_array[] = {
{0x338C, 0x2703},
{0x3390, 800}, /* Output Width (P) = 640 */
{0x338C, 0x2705},
{0x3390, 600}, /* Output Height (P) = 480 */
{0x338C, 0x2707},
{0x3390, 0x0640}, /* Output Width (S) = 1600 */
{0x338C, 0x2709},
{0x3390, 0x04B0}, /* Output Height (S) = 1200 */
{0x338C, 0x270D},
{0x3390, 0x0000}, /* Row Start (P) = 0 */
{0x338C, 0x270F},
{0x3390, 0x0000}, /* Column Start (P) = 0 */
{0x338C, 0x2711},
{0x3390, 0x04BD}, /* Row End (P) = 1213 */
{0x338C, 0x2713},
{0x3390, 0x064D}, /* Column End (P) = 1613 */
{0x338C, 0x2715},
{0x3390, 0x0000}, /* Extra Delay (P) = 0 */
{0x338C, 0x2717},
{0x3390, 0x2111}, /* Row Speed (P) = 8465 */
{0x338C, 0x2719},
{0x3390, 0x046C}, /* Read Mode (P) = 1132 */
{0x338C, 0x271B},
{0x3390, 0x024F}, /* Sensor_Sample_Time_pck(P) = 591 */
{0x338C, 0x271D},
{0x3390, 0x0102}, /* Sensor_Fine_Correction(P) = 258 */
{0x338C, 0x271F},
{0x3390, 0x0279}, /* Sensor_Fine_IT_min(P) = 633 */
{0x338C, 0x2721},
{0x3390, 0x0155}, /* Sensor_Fine_IT_max_margin(P) = 341 */
{0x338C, 0x2723},
{0x3390, 659}, /* Frame Lines (P) = 679 */
{0x338C, 0x2725},
{0x3390, 0x0824}, /* Line Length (P) = 2084 */
{0x338C, 0x2727},
{0x3390, 0x2020},
{0x338C, 0x2729},
{0x3390, 0x2020},
{0x338C, 0x272B},
{0x3390, 0x1020},
{0x338C, 0x272D},
{0x3390, 0x2007},
{0x338C, 0x272F},
{0x3390, 0x0004}, /* Row Start(S) = 4 */
{0x338C, 0x2731},
{0x3390, 0x0004}, /* Column Start(S) = 4 */
{0x338C, 0x2733},
{0x3390, 0x04BB}, /* Row End(S) = 1211 */
{0x338C, 0x2735},
{0x3390, 0x064B}, /* Column End(S) = 1611 */
{0x338C, 0x2737},
{0x3390, 0x04CE}, /* Extra Delay(S) = 1230 */
{0x338C, 0x2739},
{0x3390, 0x2111}, /* Row Speed(S) = 8465 */
{0x338C, 0x273B},
{0x3390, 0x0024}, /* Read Mode(S) = 36 */
{0x338C, 0x273D},
{0x3390, 0x0120}, /* Sensor sample time pck(S) = 288 */
{0x338C, 0x2741},
{0x3390, 0x0169}, /* Sensor_Fine_IT_min(P) = 361 */
{0x338C, 0x2745},
{0x3390, 0x04FF}, /* Frame Lines(S) = 1279 */
{0x338C, 0x2747},
{0x3390, 0x0824}, /* Line Length(S) = 2084 */
{0x338C, 0x2751},
{0x3390, 0x0000}, /* Crop_X0(P) = 0 */
{0x338C, 0x2753},
{0x3390, 0x0320}, /* Crop_X1(P) = 800 */
{0x338C, 0x2755},
{0x3390, 0x0000}, /* Crop_Y0(P) = 0 */
{0x338C, 0x2757},
{0x3390, 0x0258}, /* Crop_Y1(P) = 600 */
{0x338C, 0x275F},
{0x3390, 0x0000}, /* Crop_X0(S) = 0 */
{0x338C, 0x2761},
{0x3390, 0x0640}, /* Crop_X1(S) = 1600 */
{0x338C, 0x2763},
{0x3390, 0x0000}, /* Crop_Y0(S) = 0 */
{0x338C, 0x2765},
{0x3390, 0x04B0}, /* Crop_Y1(S) = 1200 */
{0x338C, 0x222E},
{0x3390, 0x00A0}, /* R9 Step = 160 */
{0x338C, 0xA408},
{0x3390, 0x001F},
{0x338C, 0xA409},
{0x3390, 0x0021},
{0x338C, 0xA40A},
{0x3390, 0x0025},
{0x338C, 0xA40B},
{0x3390, 0x0027},
{0x338C, 0x2411},
{0x3390, 0x00A0},
{0x338C, 0x2413},
{0x3390, 0x00C0},
{0x338C, 0x2415},
{0x3390, 0x00A0},
{0x338C, 0x2417},
{0x3390, 0x00C0},
{0x338C, 0x2799},
{0x3390, 0x6408}, /* MODE_SPEC_EFFECTS(P) */
{0x338C, 0x279B},
{0x3390, 0x6408}, /* MODE_SPEC_EFFECTS(S) */
};
static struct register_address_value_pair
noise_reduction_reg_settings_array[] = {
{0x338C, 0xA76D},
{0x3390, 0x0003},
{0x338C, 0xA76E},
{0x3390, 0x0003},
{0x338C, 0xA76F},
{0x3390, 0},
{0x338C, 0xA770},
{0x3390, 21},
{0x338C, 0xA771},
{0x3390, 37},
{0x338C, 0xA772},
{0x3390, 63},
{0x338C, 0xA773},
{0x3390, 100},
{0x338C, 0xA774},
{0x3390, 128},
{0x338C, 0xA775},
{0x3390, 151},
{0x338C, 0xA776},
{0x3390, 169},
{0x338C, 0xA777},
{0x3390, 186},
{0x338C, 0xA778},
{0x3390, 199},
{0x338C, 0xA779},
{0x3390, 210},
{0x338C, 0xA77A},
{0x3390, 220},
{0x338C, 0xA77B},
{0x3390, 228},
{0x338C, 0xA77C},
{0x3390, 234},
{0x338C, 0xA77D},
{0x3390, 240},
{0x338C, 0xA77E},
{0x3390, 244},
{0x338C, 0xA77F},
{0x3390, 248},
{0x338C, 0xA780},
{0x3390, 252},
{0x338C, 0xA781},
{0x3390, 255},
{0x338C, 0xA782},
{0x3390, 0},
{0x338C, 0xA783},
{0x3390, 21},
{0x338C, 0xA784},
{0x3390, 37},
{0x338C, 0xA785},
{0x3390, 63},
{0x338C, 0xA786},
{0x3390, 100},
{0x338C, 0xA787},
{0x3390, 128},
{0x338C, 0xA788},
{0x3390, 151},
{0x338C, 0xA789},
{0x3390, 169},
{0x338C, 0xA78A},
{0x3390, 186},
{0x338C, 0xA78B},
{0x3390, 199},
{0x338C, 0xA78C},
{0x3390, 210},
{0x338C, 0xA78D},
{0x3390, 220},
{0x338C, 0xA78E},
{0x3390, 228},
{0x338C, 0xA78F},
{0x3390, 234},
{0x338C, 0xA790},
{0x3390, 240},
{0x338C, 0xA791},
{0x3390, 244},
{0x338C, 0xA793},
{0x3390, 252},
{0x338C, 0xA794},
{0x3390, 255},
{0x338C, 0xA103},
{0x3390, 6},
};
static const struct mt9d112_i2c_reg_conf const lens_roll_off_tbl[] = {
{ 0x34CE, 0x81A0, WORD_LEN, 0 },
{ 0x34D0, 0x6331, WORD_LEN, 0 },
{ 0x34D2, 0x3394, WORD_LEN, 0 },
{ 0x34D4, 0x9966, WORD_LEN, 0 },
{ 0x34D6, 0x4B25, WORD_LEN, 0 },
{ 0x34D8, 0x2670, WORD_LEN, 0 },
{ 0x34DA, 0x724C, WORD_LEN, 0 },
{ 0x34DC, 0xFFFD, WORD_LEN, 0 },
{ 0x34DE, 0x00CA, WORD_LEN, 0 },
{ 0x34E6, 0x00AC, WORD_LEN, 0 },
{ 0x34EE, 0x0EE1, WORD_LEN, 0 },
{ 0x34F6, 0x0D87, WORD_LEN, 0 },
{ 0x3500, 0xE1F7, WORD_LEN, 0 },
{ 0x3508, 0x1CF4, WORD_LEN, 0 },
{ 0x3510, 0x1D28, WORD_LEN, 0 },
{ 0x3518, 0x1F26, WORD_LEN, 0 },
{ 0x3520, 0x2220, WORD_LEN, 0 },
{ 0x3528, 0x333D, WORD_LEN, 0 },
{ 0x3530, 0x15D9, WORD_LEN, 0 },
{ 0x3538, 0xCFB8, WORD_LEN, 0 },
{ 0x354C, 0x05FE, WORD_LEN, 0 },
{ 0x3544, 0x05F8, WORD_LEN, 0 },
{ 0x355C, 0x0596, WORD_LEN, 0 },
{ 0x3554, 0x0611, WORD_LEN, 0 },
{ 0x34E0, 0x00F2, WORD_LEN, 0 },
{ 0x34E8, 0x00A8, WORD_LEN, 0 },
{ 0x34F0, 0x0F7B, WORD_LEN, 0 },
{ 0x34F8, 0x0CD7, WORD_LEN, 0 },
{ 0x3502, 0xFEDB, WORD_LEN, 0 },
{ 0x350A, 0x13E4, WORD_LEN, 0 },
{ 0x3512, 0x1F2C, WORD_LEN, 0 },
{ 0x351A, 0x1D20, WORD_LEN, 0 },
{ 0x3522, 0x2422, WORD_LEN, 0 },
{ 0x352A, 0x2925, WORD_LEN, 0 },
{ 0x3532, 0x1D04, WORD_LEN, 0 },
{ 0x353A, 0xFBF2, WORD_LEN, 0 },
{ 0x354E, 0x0616, WORD_LEN, 0 },
{ 0x3546, 0x0597, WORD_LEN, 0 },
{ 0x355E, 0x05CD, WORD_LEN, 0 },
{ 0x3556, 0x0529, WORD_LEN, 0 },
{ 0x34E4, 0x00B2, WORD_LEN, 0 },
{ 0x34EC, 0x005E, WORD_LEN, 0 },
{ 0x34F4, 0x0F43, WORD_LEN, 0 },
{ 0x34FC, 0x0E2F, WORD_LEN, 0 },
{ 0x3506, 0xF9FC, WORD_LEN, 0 },
{ 0x350E, 0x0CE4, WORD_LEN, 0 },
{ 0x3516, 0x1E1E, WORD_LEN, 0 },
{ 0x351E, 0x1B19, WORD_LEN, 0 },
{ 0x3526, 0x151B, WORD_LEN, 0 },
{ 0x352E, 0x1416, WORD_LEN, 0 },
{ 0x3536, 0x10FC, WORD_LEN, 0 },
{ 0x353E, 0xC018, WORD_LEN, 0 },
{ 0x3552, 0x06B4, WORD_LEN, 0 },
{ 0x354A, 0x0506, WORD_LEN, 0 },
{ 0x3562, 0x06AB, WORD_LEN, 0 },
{ 0x355A, 0x063A, WORD_LEN, 0 },
{ 0x34E2, 0x00E5, WORD_LEN, 0 },
{ 0x34EA, 0x008B, WORD_LEN, 0 },
{ 0x34F2, 0x0E4C, WORD_LEN, 0 },
{ 0x34FA, 0x0CA3, WORD_LEN, 0 },
{ 0x3504, 0x0907, WORD_LEN, 0 },
{ 0x350C, 0x1DFD, WORD_LEN, 0 },
{ 0x3514, 0x1E24, WORD_LEN, 0 },
{ 0x351C, 0x2529, WORD_LEN, 0 },
{ 0x3524, 0x1D20, WORD_LEN, 0 },
{ 0x352C, 0x2332, WORD_LEN, 0 },
{ 0x3534, 0x10E9, WORD_LEN, 0 },
{ 0x353C, 0x0BCB, WORD_LEN, 0 },
{ 0x3550, 0x04EF, WORD_LEN, 0 },
{ 0x3548, 0x0609, WORD_LEN, 0 },
{ 0x3560, 0x0580, WORD_LEN, 0 },
{ 0x3558, 0x05DD, WORD_LEN, 0 },
{ 0x3540, 0x0000, WORD_LEN, 0 },
{ 0x3542, 0x0000, WORD_LEN, 0 }
};
static const struct mt9d112_i2c_reg_conf const pll_setup_tbl[] = {
{ 0x341E, 0x8F09, WORD_LEN, 0 },
{ 0x341C, 0x0250, WORD_LEN, 0 },
{ 0x341E, 0x8F09, WORD_LEN, 5 },
{ 0x341E, 0x8F08, WORD_LEN, 0 }
};
/* Refresh Sequencer */
static const struct mt9d112_i2c_reg_conf const sequencer_tbl[] = {
{ 0x338C, 0x2799, WORD_LEN, 0},
{ 0x3390, 0x6440, WORD_LEN, 5},
{ 0x338C, 0x279B, WORD_LEN, 0},
{ 0x3390, 0x6440, WORD_LEN, 5},
{ 0x338C, 0xA103, WORD_LEN, 0},
{ 0x3390, 0x0005, WORD_LEN, 5},
{ 0x338C, 0xA103, WORD_LEN, 0},
{ 0x3390, 0x0006, WORD_LEN, 5}
};
struct mt9d112_reg mt9d112_regs = {
.prev_snap_reg_settings = &preview_snapshot_mode_reg_settings_array[0],
.prev_snap_reg_settings_size = ARRAY_SIZE(preview_snapshot_mode_reg_settings_array),
.noise_reduction_reg_settings = &noise_reduction_reg_settings_array[0],
.noise_reduction_reg_settings_size = ARRAY_SIZE(noise_reduction_reg_settings_array),
.plltbl = pll_setup_tbl,
.plltbl_size = ARRAY_SIZE(pll_setup_tbl),
.stbl = sequencer_tbl,
.stbl_size = ARRAY_SIZE(sequencer_tbl),
.rftbl = lens_roll_off_tbl,
.rftbl_size = ARRAY_SIZE(lens_roll_off_tbl)
};

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef MT9T012_H
#define MT9T012_H
#include <linux/types.h>
struct reg_struct {
uint16_t vt_pix_clk_div; /* 0x0300 */
uint16_t vt_sys_clk_div; /* 0x0302 */
uint16_t pre_pll_clk_div; /* 0x0304 */
uint16_t pll_multiplier; /* 0x0306 */
uint16_t op_pix_clk_div; /* 0x0308 */
uint16_t op_sys_clk_div; /* 0x030A */
uint16_t scale_m; /* 0x0404 */
uint16_t row_speed; /* 0x3016 */
uint16_t x_addr_start; /* 0x3004 */
uint16_t x_addr_end; /* 0x3008 */
uint16_t y_addr_start; /* 0x3002 */
uint16_t y_addr_end; /* 0x3006 */
uint16_t read_mode; /* 0x3040 */
uint16_t x_output_size ; /* 0x034C */
uint16_t y_output_size; /* 0x034E */
uint16_t line_length_pck; /* 0x300C */
uint16_t frame_length_lines; /* 0x300A */
uint16_t coarse_int_time; /* 0x3012 */
uint16_t fine_int_time; /* 0x3014 */
};
struct mt9p012_i2c_reg_conf {
unsigned short waddr;
unsigned short wdata;
};
struct mt9p012_reg {
struct reg_struct *reg_pat;
uint16_t reg_pat_size;
struct mt9p012_i2c_reg_conf *ttbl;
uint16_t ttbl_size;
struct mt9p012_i2c_reg_conf *lctbl;
uint16_t lctbl_size;
struct mt9p012_i2c_reg_conf *rftbl;
uint16_t rftbl_size;
};
#endif /* MT9T012_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,573 @@
/*
* Copyright (C) 2009 QUALCOMM Incorporated.
*/
#include "mt9p012.h"
#include <linux/kernel.h>
/*Micron settings from Applications for lower power consumption.*/
struct reg_struct mt9p012_reg_pat[2] = {
{ /* Preview */
/* vt_pix_clk_div REG=0x0300 */
6, /* 5 */
/* vt_sys_clk_div REG=0x0302 */
1,
/* pre_pll_clk_div REG=0x0304 */
2,
/* pll_multiplier REG=0x0306 */
60,
/* op_pix_clk_div REG=0x0308 */
8, /* 10 */
/* op_sys_clk_div REG=0x030A */
1,
/* scale_m REG=0x0404 */
16,
/* row_speed REG=0x3016 */
0x0111,
/* x_addr_start REG=0x3004 */
8,
/* x_addr_end REG=0x3008 */
2597,
/* y_addr_start REG=0x3002 */
8,
/* y_addr_end REG=0x3006 */
1949,
/* read_mode REG=0x3040
* Preview 2x2 skipping */
0x00C3,
/* x_output_size REG=0x034C */
1296,
/* y_output_size REG=0x034E */
972,
/* line_length_pck REG=0x300C */
3784,
/* frame_length_lines REG=0x300A */
1057,
/* coarse_integration_time REG=0x3012 */
16,
/* fine_integration_time REG=0x3014 */
1764
},
{ /*Snapshot*/
/* vt_pix_clk_div REG=0x0300 */
6,
/* vt_sys_clk_div REG=0x0302 */
1,
/* pre_pll_clk_div REG=0x0304 */
2,
/* pll_multiplier REG=0x0306
* 60 for 10fps snapshot */
60,
/* op_pix_clk_div REG=0x0308 */
8,
/* op_sys_clk_div REG=0x030A */
1,
/* scale_m REG=0x0404 */
16,
/* row_speed REG=0x3016 */
0x0111,
/* x_addr_start REG=0x3004 */
8,
/* x_addr_end REG=0x3008 */
2615,
/* y_addr_start REG=0x3002 */
8,
/* y_addr_end REG=0x3006 */
1967,
/* read_mode REG=0x3040 */
0x0041,
/* x_output_size REG=0x034C */
2608,
/* y_output_size REG=0x034E */
1960,
/* line_length_pck REG=0x300C */
3911,
/* frame_length_lines REG=0x300A //10 fps snapshot */
2045,
/* coarse_integration_time REG=0x3012 */
16,
/* fine_integration_time REG=0x3014 */
882
}
};
struct mt9p012_i2c_reg_conf mt9p012_test_tbl[] = {
{0x3044, 0x0544 & 0xFBFF},
{0x30CA, 0x0004 | 0x0001},
{0x30D4, 0x9020 & 0x7FFF},
{0x31E0, 0x0003 & 0xFFFE},
{0x3180, 0x91FF & 0x7FFF},
{0x301A, (0x10CC | 0x8000) & 0xFFF7},
{0x301E, 0x0000},
{0x3780, 0x0000},
};
struct mt9p012_i2c_reg_conf mt9p012_lc_tbl[] = {
/* [Lens shading 85 Percent TL84] */
/* P_RD_P0Q0 */
{0x360A, 0x7FEF},
/* P_RD_P0Q1 */
{0x360C, 0x232C},
/* P_RD_P0Q2 */
{0x360E, 0x7050},
/* P_RD_P0Q3 */
{0x3610, 0xF3CC},
/* P_RD_P0Q4 */
{0x3612, 0x89D1},
/* P_RD_P1Q0 */
{0x364A, 0xBE0D},
/* P_RD_P1Q1 */
{0x364C, 0x9ACB},
/* P_RD_P1Q2 */
{0x364E, 0x2150},
/* P_RD_P1Q3 */
{0x3650, 0xB26B},
/* P_RD_P1Q4 */
{0x3652, 0x9511},
/* P_RD_P2Q0 */
{0x368A, 0x2151},
/* P_RD_P2Q1 */
{0x368C, 0x00AD},
/* P_RD_P2Q2 */
{0x368E, 0x8334},
/* P_RD_P2Q3 */
{0x3690, 0x478E},
/* P_RD_P2Q4 */
{0x3692, 0x0515},
/* P_RD_P3Q0 */
{0x36CA, 0x0710},
/* P_RD_P3Q1 */
{0x36CC, 0x452D},
/* P_RD_P3Q2 */
{0x36CE, 0xF352},
/* P_RD_P3Q3 */
{0x36D0, 0x190F},
/* P_RD_P3Q4 */
{0x36D2, 0x4413},
/* P_RD_P4Q0 */
{0x370A, 0xD112},
/* P_RD_P4Q1 */
{0x370C, 0xF50F},
/* P_RD_P4Q2 */
{0x370C, 0xF50F},
/* P_RD_P4Q3 */
{0x3710, 0xDC11},
/* P_RD_P4Q4 */
{0x3712, 0xD776},
/* P_GR_P0Q0 */
{0x3600, 0x1750},
/* P_GR_P0Q1 */
{0x3602, 0xF0AC},
/* P_GR_P0Q2 */
{0x3604, 0x4711},
/* P_GR_P0Q3 */
{0x3606, 0x07CE},
/* P_GR_P0Q4 */
{0x3608, 0x96B2},
/* P_GR_P1Q0 */
{0x3640, 0xA9AE},
/* P_GR_P1Q1 */
{0x3642, 0xF9AC},
/* P_GR_P1Q2 */
{0x3644, 0x39F1},
/* P_GR_P1Q3 */
{0x3646, 0x016F},
/* P_GR_P1Q4 */
{0x3648, 0x8AB2},
/* P_GR_P2Q0 */
{0x3680, 0x1752},
/* P_GR_P2Q1 */
{0x3682, 0x70F0},
/* P_GR_P2Q2 */
{0x3684, 0x83F5},
/* P_GR_P2Q3 */
{0x3686, 0x8392},
/* P_GR_P2Q4 */
{0x3688, 0x1FD6},
/* P_GR_P3Q0 */
{0x36C0, 0x1131},
/* P_GR_P3Q1 */
{0x36C2, 0x3DAF},
/* P_GR_P3Q2 */
{0x36C4, 0x89B4},
/* P_GR_P3Q3 */
{0x36C6, 0xA391},
/* P_GR_P3Q4 */
{0x36C8, 0x1334},
/* P_GR_P4Q0 */
{0x3700, 0xDC13},
/* P_GR_P4Q1 */
{0x3702, 0xD052},
/* P_GR_P4Q2 */
{0x3704, 0x5156},
/* P_GR_P4Q3 */
{0x3706, 0x1F13},
/* P_GR_P4Q4 */
{0x3708, 0x8C38},
/* P_BL_P0Q0 */
{0x3614, 0x0050},
/* P_BL_P0Q1 */
{0x3616, 0xBD4C},
/* P_BL_P0Q2 */
{0x3618, 0x41B0},
/* P_BL_P0Q3 */
{0x361A, 0x660D},
/* P_BL_P0Q4 */
{0x361C, 0xC590},
/* P_BL_P1Q0 */
{0x3654, 0x87EC},
/* P_BL_P1Q1 */
{0x3656, 0xE44C},
/* P_BL_P1Q2 */
{0x3658, 0x302E},
/* P_BL_P1Q3 */
{0x365A, 0x106E},
/* P_BL_P1Q4 */
{0x365C, 0xB58E},
/* P_BL_P2Q0 */
{0x3694, 0x0DD1},
/* P_BL_P2Q1 */
{0x3696, 0x2A50},
/* P_BL_P2Q2 */
{0x3698, 0xC793},
/* P_BL_P2Q3 */
{0x369A, 0xE8F1},
/* P_BL_P2Q4 */
{0x369C, 0x4174},
/* P_BL_P3Q0 */
{0x36D4, 0x01EF},
/* P_BL_P3Q1 */
{0x36D6, 0x06CF},
/* P_BL_P3Q2 */
{0x36D8, 0x8D91},
/* P_BL_P3Q3 */
{0x36DA, 0x91F0},
/* P_BL_P3Q4 */
{0x36DC, 0x52EF},
/* P_BL_P4Q0 */
{0x3714, 0xA6D2},
/* P_BL_P4Q1 */
{0x3716, 0xA312},
/* P_BL_P4Q2 */
{0x3718, 0x2695},
/* P_BL_P4Q3 */
{0x371A, 0x3953},
/* P_BL_P4Q4 */
{0x371C, 0x9356},
/* P_GB_P0Q0 */
{0x361E, 0x7EAF},
/* P_GB_P0Q1 */
{0x3620, 0x2A4C},
/* P_GB_P0Q2 */
{0x3622, 0x49F0},
{0x3624, 0xF1EC},
/* P_GB_P0Q4 */
{0x3626, 0xC670},
/* P_GB_P1Q0 */
{0x365E, 0x8E0C},
/* P_GB_P1Q1 */
{0x3660, 0xC2A9},
/* P_GB_P1Q2 */
{0x3662, 0x274F},
/* P_GB_P1Q3 */
{0x3664, 0xADAB},
/* P_GB_P1Q4 */
{0x3666, 0x8EF0},
/* P_GB_P2Q0 */
{0x369E, 0x09B1},
/* P_GB_P2Q1 */
{0x36A0, 0xAA2E},
/* P_GB_P2Q2 */
{0x36A2, 0xC3D3},
/* P_GB_P2Q3 */
{0x36A4, 0x7FAF},
/* P_GB_P2Q4 */
{0x36A6, 0x3F34},
/* P_GB_P3Q0 */
{0x36DE, 0x4C8F},
/* P_GB_P3Q1 */
{0x36E0, 0x886E},
/* P_GB_P3Q2 */
{0x36E2, 0xE831},
/* P_GB_P3Q3 */
{0x36E4, 0x1FD0},
/* P_GB_P3Q4 */
{0x36E6, 0x1192},
/* P_GB_P4Q0 */
{0x371E, 0xB952},
/* P_GB_P4Q1 */
{0x3720, 0x6DCF},
/* P_GB_P4Q2 */
{0x3722, 0x1B55},
/* P_GB_P4Q3 */
{0x3724, 0xA112},
/* P_GB_P4Q4 */
{0x3726, 0x82F6},
/* POLY_ORIGIN_C */
{0x3782, 0x0510},
/* POLY_ORIGIN_R */
{0x3784, 0x0390},
/* POLY_SC_ENABLE */
{0x3780, 0x8000},
};
/* rolloff table for illuminant A */
struct mt9p012_i2c_reg_conf mt9p012_rolloff_tbl[] = {
/* P_RD_P0Q0 */
{0x360A, 0x7FEF},
/* P_RD_P0Q1 */
{0x360C, 0x232C},
/* P_RD_P0Q2 */
{0x360E, 0x7050},
/* P_RD_P0Q3 */
{0x3610, 0xF3CC},
/* P_RD_P0Q4 */
{0x3612, 0x89D1},
/* P_RD_P1Q0 */
{0x364A, 0xBE0D},
/* P_RD_P1Q1 */
{0x364C, 0x9ACB},
/* P_RD_P1Q2 */
{0x364E, 0x2150},
/* P_RD_P1Q3 */
{0x3650, 0xB26B},
/* P_RD_P1Q4 */
{0x3652, 0x9511},
/* P_RD_P2Q0 */
{0x368A, 0x2151},
/* P_RD_P2Q1 */
{0x368C, 0x00AD},
/* P_RD_P2Q2 */
{0x368E, 0x8334},
/* P_RD_P2Q3 */
{0x3690, 0x478E},
/* P_RD_P2Q4 */
{0x3692, 0x0515},
/* P_RD_P3Q0 */
{0x36CA, 0x0710},
/* P_RD_P3Q1 */
{0x36CC, 0x452D},
/* P_RD_P3Q2 */
{0x36CE, 0xF352},
/* P_RD_P3Q3 */
{0x36D0, 0x190F},
/* P_RD_P3Q4 */
{0x36D2, 0x4413},
/* P_RD_P4Q0 */
{0x370A, 0xD112},
/* P_RD_P4Q1 */
{0x370C, 0xF50F},
/* P_RD_P4Q2 */
{0x370E, 0x6375},
/* P_RD_P4Q3 */
{0x3710, 0xDC11},
/* P_RD_P4Q4 */
{0x3712, 0xD776},
/* P_GR_P0Q0 */
{0x3600, 0x1750},
/* P_GR_P0Q1 */
{0x3602, 0xF0AC},
/* P_GR_P0Q2 */
{0x3604, 0x4711},
/* P_GR_P0Q3 */
{0x3606, 0x07CE},
/* P_GR_P0Q4 */
{0x3608, 0x96B2},
/* P_GR_P1Q0 */
{0x3640, 0xA9AE},
/* P_GR_P1Q1 */
{0x3642, 0xF9AC},
/* P_GR_P1Q2 */
{0x3644, 0x39F1},
/* P_GR_P1Q3 */
{0x3646, 0x016F},
/* P_GR_P1Q4 */
{0x3648, 0x8AB2},
/* P_GR_P2Q0 */
{0x3680, 0x1752},
/* P_GR_P2Q1 */
{0x3682, 0x70F0},
/* P_GR_P2Q2 */
{0x3684, 0x83F5},
/* P_GR_P2Q3 */
{0x3686, 0x8392},
/* P_GR_P2Q4 */
{0x3688, 0x1FD6},
/* P_GR_P3Q0 */
{0x36C0, 0x1131},
/* P_GR_P3Q1 */
{0x36C2, 0x3DAF},
/* P_GR_P3Q2 */
{0x36C4, 0x89B4},
/* P_GR_P3Q3 */
{0x36C6, 0xA391},
/* P_GR_P3Q4 */
{0x36C8, 0x1334},
/* P_GR_P4Q0 */
{0x3700, 0xDC13},
/* P_GR_P4Q1 */
{0x3702, 0xD052},
/* P_GR_P4Q2 */
{0x3704, 0x5156},
/* P_GR_P4Q3 */
{0x3706, 0x1F13},
/* P_GR_P4Q4 */
{0x3708, 0x8C38},
/* P_BL_P0Q0 */
{0x3614, 0x0050},
/* P_BL_P0Q1 */
{0x3616, 0xBD4C},
/* P_BL_P0Q2 */
{0x3618, 0x41B0},
/* P_BL_P0Q3 */
{0x361A, 0x660D},
/* P_BL_P0Q4 */
{0x361C, 0xC590},
/* P_BL_P1Q0 */
{0x3654, 0x87EC},
/* P_BL_P1Q1 */
{0x3656, 0xE44C},
/* P_BL_P1Q2 */
{0x3658, 0x302E},
/* P_BL_P1Q3 */
{0x365A, 0x106E},
/* P_BL_P1Q4 */
{0x365C, 0xB58E},
/* P_BL_P2Q0 */
{0x3694, 0x0DD1},
/* P_BL_P2Q1 */
{0x3696, 0x2A50},
/* P_BL_P2Q2 */
{0x3698, 0xC793},
/* P_BL_P2Q3 */
{0x369A, 0xE8F1},
/* P_BL_P2Q4 */
{0x369C, 0x4174},
/* P_BL_P3Q0 */
{0x36D4, 0x01EF},
/* P_BL_P3Q1 */
{0x36D6, 0x06CF},
/* P_BL_P3Q2 */
{0x36D8, 0x8D91},
/* P_BL_P3Q3 */
{0x36DA, 0x91F0},
/* P_BL_P3Q4 */
{0x36DC, 0x52EF},
/* P_BL_P4Q0 */
{0x3714, 0xA6D2},
/* P_BL_P4Q1 */
{0x3716, 0xA312},
/* P_BL_P4Q2 */
{0x3718, 0x2695},
/* P_BL_P4Q3 */
{0x371A, 0x3953},
/* P_BL_P4Q4 */
{0x371C, 0x9356},
/* P_GB_P0Q0 */
{0x361E, 0x7EAF},
/* P_GB_P0Q1 */
{0x3620, 0x2A4C},
/* P_GB_P0Q2 */
{0x3622, 0x49F0},
{0x3624, 0xF1EC},
/* P_GB_P0Q4 */
{0x3626, 0xC670},
/* P_GB_P1Q0 */
{0x365E, 0x8E0C},
/* P_GB_P1Q1 */
{0x3660, 0xC2A9},
/* P_GB_P1Q2 */
{0x3662, 0x274F},
/* P_GB_P1Q3 */
{0x3664, 0xADAB},
/* P_GB_P1Q4 */
{0x3666, 0x8EF0},
/* P_GB_P2Q0 */
{0x369E, 0x09B1},
/* P_GB_P2Q1 */
{0x36A0, 0xAA2E},
/* P_GB_P2Q2 */
{0x36A2, 0xC3D3},
/* P_GB_P2Q3 */
{0x36A4, 0x7FAF},
/* P_GB_P2Q4 */
{0x36A6, 0x3F34},
/* P_GB_P3Q0 */
{0x36DE, 0x4C8F},
/* P_GB_P3Q1 */
{0x36E0, 0x886E},
/* P_GB_P3Q2 */
{0x36E2, 0xE831},
/* P_GB_P3Q3 */
{0x36E4, 0x1FD0},
/* P_GB_P3Q4 */
{0x36E6, 0x1192},
/* P_GB_P4Q0 */
{0x371E, 0xB952},
/* P_GB_P4Q1 */
{0x3720, 0x6DCF},
/* P_GB_P4Q2 */
{0x3722, 0x1B55},
/* P_GB_P4Q3 */
{0x3724, 0xA112},
/* P_GB_P4Q4 */
{0x3726, 0x82F6},
/* POLY_ORIGIN_C */
{0x3782, 0x0510},
/* POLY_ORIGIN_R */
{0x3784, 0x0390},
/* POLY_SC_ENABLE */
{0x3780, 0x8000},
};
struct mt9p012_reg mt9p012_regs = {
.reg_pat = &mt9p012_reg_pat[0],
.reg_pat_size = ARRAY_SIZE(mt9p012_reg_pat),
.ttbl = &mt9p012_test_tbl[0],
.ttbl_size = ARRAY_SIZE(mt9p012_test_tbl),
.lctbl = &mt9p012_lc_tbl[0],
.lctbl_size = ARRAY_SIZE(mt9p012_lc_tbl),
.rftbl = &mt9p012_rolloff_tbl[0],
.rftbl_size = ARRAY_SIZE(mt9p012_rolloff_tbl)
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef MT9T013_H
#define MT9T013_H
#include <linux/types.h>
struct reg_struct {
uint16_t vt_pix_clk_div; /* 0x0300 */
uint16_t vt_sys_clk_div; /* 0x0302 */
uint16_t pre_pll_clk_div; /* 0x0304 */
uint16_t pll_multiplier; /* 0x0306 */
uint16_t op_pix_clk_div; /* 0x0308 */
uint16_t op_sys_clk_div; /* 0x030A */
uint16_t scale_m; /* 0x0404 */
uint16_t row_speed; /* 0x3016 */
uint16_t x_addr_start; /* 0x3004 */
uint16_t x_addr_end; /* 0x3008 */
uint16_t y_addr_start; /* 0x3002 */
uint16_t y_addr_end; /* 0x3006 */
uint16_t read_mode; /* 0x3040 */
uint16_t x_output_size; /* 0x034C */
uint16_t y_output_size; /* 0x034E */
uint16_t line_length_pck; /* 0x300C */
uint16_t frame_length_lines; /* 0x300A */
uint16_t coarse_int_time; /* 0x3012 */
uint16_t fine_int_time; /* 0x3014 */
};
struct mt9t013_i2c_reg_conf {
unsigned short waddr;
unsigned short wdata;
};
struct mt9t013_reg {
struct reg_struct *reg_pat;
uint16_t reg_pat_size;
struct mt9t013_i2c_reg_conf *ttbl;
uint16_t ttbl_size;
struct mt9t013_i2c_reg_conf *lctbl;
uint16_t lctbl_size;
struct mt9t013_i2c_reg_conf *rftbl;
uint16_t rftbl_size;
};
#endif /* #define MT9T013_H */

View File

@ -0,0 +1,266 @@
/*
* Copyright (C) 2009 QUALCOMM Incorporated.
*/
#include "mt9t013.h"
#include <linux/kernel.h>
struct reg_struct const mt9t013_reg_pat[2] = {
{ /* Preview 2x2 binning 20fps, pclk MHz, MCLK 24MHz */
/* vt_pix_clk_div:REG=0x0300 update get_snapshot_fps
* if this change */
8,
/* vt_sys_clk_div: REG=0x0302 update get_snapshot_fps
* if this change */
1,
/* pre_pll_clk_div REG=0x0304 update get_snapshot_fps
* if this change */
2,
/* pll_multiplier REG=0x0306 60 for 30fps preview, 40
* for 20fps preview
* 46 for 30fps preview, try 47/48 to increase further */
46,
/* op_pix_clk_div REG=0x0308 */
8,
/* op_sys_clk_div REG=0x030A */
1,
/* scale_m REG=0x0404 */
16,
/* row_speed REG=0x3016 */
0x0111,
/* x_addr_start REG=0x3004 */
8,
/* x_addr_end REG=0x3008 */
2053,
/* y_addr_start REG=0x3002 */
8,
/* y_addr_end REG=0x3006 */
1541,
/* read_mode REG=0x3040 */
0x046C,
/* x_output_size REG=0x034C */
1024,
/* y_output_size REG=0x034E */
768,
/* line_length_pck REG=0x300C */
2616,
/* frame_length_lines REG=0x300A */
916,
/* coarse_int_time REG=0x3012 */
16,
/* fine_int_time REG=0x3014 */
1461
},
{ /*Snapshot */
/* vt_pix_clk_div REG=0x0300 update get_snapshot_fps
* if this change */
8,
/* vt_sys_clk_div REG=0x0302 update get_snapshot_fps
* if this change */
1,
/* pre_pll_clk_div REG=0x0304 update get_snapshot_fps
* if this change */
2,
/* pll_multiplier REG=0x0306 50 for 15fps snapshot,
* 40 for 10fps snapshot
* 46 for 30fps snapshot, try 47/48 to increase further */
46,
/* op_pix_clk_div REG=0x0308 */
8,
/* op_sys_clk_div REG=0x030A */
1,
/* scale_m REG=0x0404 */
16,
/* row_speed REG=0x3016 */
0x0111,
/* x_addr_start REG=0x3004 */
8,
/* x_addr_end REG=0x3008 */
2071,
/* y_addr_start REG=0x3002 */
8,
/* y_addr_end REG=0x3006 */
1551,
/* read_mode REG=0x3040 */
0x0024,
/* x_output_size REG=0x034C */
2064,
/* y_output_size REG=0x034E */
1544,
/* line_length_pck REG=0x300C */
2952,
/* frame_length_lines REG=0x300A */
1629,
/* coarse_int_time REG=0x3012 */
16,
/* fine_int_time REG=0x3014 */
733
}
};
struct mt9t013_i2c_reg_conf mt9t013_test_tbl[] = {
{ 0x3044, 0x0544 & 0xFBFF },
{ 0x30CA, 0x0004 | 0x0001 },
{ 0x30D4, 0x9020 & 0x7FFF },
{ 0x31E0, 0x0003 & 0xFFFE },
{ 0x3180, 0x91FF & 0x7FFF },
{ 0x301A, (0x10CC | 0x8000) & 0xFFF7 },
{ 0x301E, 0x0000 },
{ 0x3780, 0x0000 },
};
/* [Lens shading 85 Percent TL84] */
struct mt9t013_i2c_reg_conf mt9t013_lc_tbl[] = {
{ 0x360A, 0x0290 }, /* P_RD_P0Q0 */
{ 0x360C, 0xC92D }, /* P_RD_P0Q1 */
{ 0x360E, 0x0771 }, /* P_RD_P0Q2 */
{ 0x3610, 0xE38C }, /* P_RD_P0Q3 */
{ 0x3612, 0xD74F }, /* P_RD_P0Q4 */
{ 0x364A, 0x168C }, /* P_RD_P1Q0 */
{ 0x364C, 0xCACB }, /* P_RD_P1Q1 */
{ 0x364E, 0x8C4C }, /* P_RD_P1Q2 */
{ 0x3650, 0x0BEA }, /* P_RD_P1Q3 */
{ 0x3652, 0xDC0F }, /* P_RD_P1Q4 */
{ 0x368A, 0x70B0 }, /* P_RD_P2Q0 */
{ 0x368C, 0x200B }, /* P_RD_P2Q1 */
{ 0x368E, 0x30B2 }, /* P_RD_P2Q2 */
{ 0x3690, 0xD04F }, /* P_RD_P2Q3 */
{ 0x3692, 0xACF5 }, /* P_RD_P2Q4 */
{ 0x36CA, 0xF7C9 }, /* P_RD_P3Q0 */
{ 0x36CC, 0x2AED }, /* P_RD_P3Q1 */
{ 0x36CE, 0xA652 }, /* P_RD_P3Q2 */
{ 0x36D0, 0x8192 }, /* P_RD_P3Q3 */
{ 0x36D2, 0x3A15 }, /* P_RD_P3Q4 */
{ 0x370A, 0xDA30 }, /* P_RD_P4Q0 */
{ 0x370C, 0x2E2F }, /* P_RD_P4Q1 */
{ 0x370E, 0xBB56 }, /* P_RD_P4Q2 */
{ 0x3710, 0x8195 }, /* P_RD_P4Q3 */
{ 0x3712, 0x02F9 }, /* P_RD_P4Q4 */
{ 0x3600, 0x0230 }, /* P_GR_P0Q0 */
{ 0x3602, 0x58AD }, /* P_GR_P0Q1 */
{ 0x3604, 0x18D1 }, /* P_GR_P0Q2 */
{ 0x3606, 0x260D }, /* P_GR_P0Q3 */
{ 0x3608, 0xF530 }, /* P_GR_P0Q4 */
{ 0x3640, 0x17EB }, /* P_GR_P1Q0 */
{ 0x3642, 0x3CAB }, /* P_GR_P1Q1 */
{ 0x3644, 0x87CE }, /* P_GR_P1Q2 */
{ 0x3646, 0xC02E }, /* P_GR_P1Q3 */
{ 0x3648, 0xF48F }, /* P_GR_P1Q4 */
{ 0x3680, 0x5350 }, /* P_GR_P2Q0 */
{ 0x3682, 0x7EAF }, /* P_GR_P2Q1 */
{ 0x3684, 0x4312 }, /* P_GR_P2Q2 */
{ 0x3686, 0xC652 }, /* P_GR_P2Q3 */
{ 0x3688, 0xBC15 }, /* P_GR_P2Q4 */
{ 0x36C0, 0xB8AD }, /* P_GR_P3Q0 */
{ 0x36C2, 0xBDCD }, /* P_GR_P3Q1 */
{ 0x36C4, 0xE4B2 }, /* P_GR_P3Q2 */
{ 0x36C6, 0xB50F }, /* P_GR_P3Q3 */
{ 0x36C8, 0x5B95 }, /* P_GR_P3Q4 */
{ 0x3700, 0xFC90 }, /* P_GR_P4Q0 */
{ 0x3702, 0x8C51 }, /* P_GR_P4Q1 */
{ 0x3704, 0xCED6 }, /* P_GR_P4Q2 */
{ 0x3706, 0xB594 }, /* P_GR_P4Q3 */
{ 0x3708, 0x0A39 }, /* P_GR_P4Q4 */
{ 0x3614, 0x0230 }, /* P_BL_P0Q0 */
{ 0x3616, 0x160D }, /* P_BL_P0Q1 */
{ 0x3618, 0x08D1 }, /* P_BL_P0Q2 */
{ 0x361A, 0x98AB }, /* P_BL_P0Q3 */
{ 0x361C, 0xEA50 }, /* P_BL_P0Q4 */
{ 0x3654, 0xB4EA }, /* P_BL_P1Q0 */
{ 0x3656, 0xEA6C }, /* P_BL_P1Q1 */
{ 0x3658, 0xFE08 }, /* P_BL_P1Q2 */
{ 0x365A, 0x2C6E }, /* P_BL_P1Q3 */
{ 0x365C, 0xEB0E }, /* P_BL_P1Q4 */
{ 0x3694, 0x6DF0 }, /* P_BL_P2Q0 */
{ 0x3696, 0x3ACF }, /* P_BL_P2Q1 */
{ 0x3698, 0x3E0F }, /* P_BL_P2Q2 */
{ 0x369A, 0xB2B1 }, /* P_BL_P2Q3 */
{ 0x369C, 0xC374 }, /* P_BL_P2Q4 */
{ 0x36D4, 0xF2AA }, /* P_BL_P3Q0 */
{ 0x36D6, 0x8CCC }, /* P_BL_P3Q1 */
{ 0x36D8, 0xDEF2 }, /* P_BL_P3Q2 */
{ 0x36DA, 0xFA11 }, /* P_BL_P3Q3 */
{ 0x36DC, 0x42F5 }, /* P_BL_P3Q4 */
{ 0x3714, 0xF4F1 }, /* P_BL_P4Q0 */
{ 0x3716, 0xF6F0 }, /* P_BL_P4Q1 */
{ 0x3718, 0x8FD6 }, /* P_BL_P4Q2 */
{ 0x371A, 0xEA14 }, /* P_BL_P4Q3 */
{ 0x371C, 0x6338 }, /* P_BL_P4Q4 */
{ 0x361E, 0x0350 }, /* P_GB_P0Q0 */
{ 0x3620, 0x91AE }, /* P_GB_P0Q1 */
{ 0x3622, 0x0571 }, /* P_GB_P0Q2 */
{ 0x3624, 0x100D }, /* P_GB_P0Q3 */
{ 0x3626, 0xCA70 }, /* P_GB_P0Q4 */
{ 0x365E, 0xE6CB }, /* P_GB_P1Q0 */
{ 0x3660, 0x50ED }, /* P_GB_P1Q1 */
{ 0x3662, 0x3DAE }, /* P_GB_P1Q2 */
{ 0x3664, 0xAA4F }, /* P_GB_P1Q3 */
{ 0x3666, 0xDC50 }, /* P_GB_P1Q4 */
{ 0x369E, 0x5470 }, /* P_GB_P2Q0 */
{ 0x36A0, 0x1F6E }, /* P_GB_P2Q1 */
{ 0x36A2, 0x6671 }, /* P_GB_P2Q2 */
{ 0x36A4, 0xC010 }, /* P_GB_P2Q3 */
{ 0x36A6, 0x8DF5 }, /* P_GB_P2Q4 */
{ 0x36DE, 0x0B0C }, /* P_GB_P3Q0 */
{ 0x36E0, 0x84CE }, /* P_GB_P3Q1 */
{ 0x36E2, 0x8493 }, /* P_GB_P3Q2 */
{ 0x36E4, 0xA610 }, /* P_GB_P3Q3 */
{ 0x36E6, 0x50B5 }, /* P_GB_P3Q4 */
{ 0x371E, 0x9651 }, /* P_GB_P4Q0 */
{ 0x3720, 0x1EAB }, /* P_GB_P4Q1 */
{ 0x3722, 0xAF76 }, /* P_GB_P4Q2 */
{ 0x3724, 0xE4F4 }, /* P_GB_P4Q3 */
{ 0x3726, 0x79F8 }, /* P_GB_P4Q4 */
{ 0x3782, 0x0410 }, /* POLY_ORIGIN_C */
{ 0x3784, 0x0320 }, /* POLY_ORIGIN_R */
{ 0x3780, 0x8000 } /* POLY_SC_ENABLE */
};
struct mt9t013_reg mt9t013_regs = {
.reg_pat = &mt9t013_reg_pat[0],
.reg_pat_size = ARRAY_SIZE(mt9t013_reg_pat),
.ttbl = &mt9t013_test_tbl[0],
.ttbl_size = ARRAY_SIZE(mt9t013_test_tbl),
.lctbl = &mt9t013_lc_tbl[0],
.lctbl_size = ARRAY_SIZE(mt9t013_lc_tbl),
.rftbl = &mt9t013_lc_tbl[0], /* &mt9t013_rolloff_tbl[0], */
.rftbl_size = ARRAY_SIZE(mt9t013_lc_tbl)
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
/*
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
#ifndef CAMSENSOR_S5K3E2FX
#define CAMSENSOR_S5K3E2FX
#include <mach/board.h>
#endif /* CAMSENSOR_S5K3E2FX */