#define RK29_CAM_EIO_INVALID -1
#define RK29_CAM_EIO_REQUESTFAIL -2
+#define RK29_CAM_SENSOR_OV7675 ov7675
#define RK29_CAM_SENSOR_OV9650 ov9650
#define RK29_CAM_SENSOR_OV2655 ov2655
#define RK29_CAM_SENSOR_OV2659 ov2659
#define RK29_CAM_SENSOR_MT9P111 mt9p111
#define RK29_CAM_SENSOR_GT2005 gt2005
#define RK29_CAM_SENSOR_GC0308 gc0308
+#define RK29_CAM_SENSOR_GC0309 gc0309
+#define RK29_CAM_SENSOR_GC2015 gc2015
#define RK29_CAM_SENSOR_SIV120B siv120b
+#define RK29_CAM_SENSOR_SID130B sid130B
+#define RK29_CAM_SENSOR_HI253 hi253
+#define RK29_CAM_SENSOR_HI704 hi704
+#define RK29_CAM_SENSOR_NT99250 nt99250
+#define RK29_CAM_SENSOR_NAME_OV7675 "ov7675"
#define RK29_CAM_SENSOR_NAME_OV9650 "ov9650"
#define RK29_CAM_SENSOR_NAME_OV2655 "ov2655"
#define RK29_CAM_SENSOR_NAME_OV2659 "ov2659"
#define RK29_CAM_SENSOR_NAME_MT9P111 "mt9p111"
#define RK29_CAM_SENSOR_NAME_GT2005 "gt2005"
#define RK29_CAM_SENSOR_NAME_GC0308 "gc0308"
+#define RK29_CAM_SENSOR_NAME_GC0309 "gc0309"
+#define RK29_CAM_SENSOR_NAME_GC2015 "gc2015"
#define RK29_CAM_SENSOR_NAME_SIV120B "siv120b"
+#define RK29_CAM_SENSOR_NAME_SID130B "sid130B"
+#define RK29_CAM_SENSOR_NAME_HI253 "hi253"
+#define RK29_CAM_SENSOR_NAME_HI704 "hi704"
+#define RK29_CAM_SENSOR_NAME_NT99250 "nt99250"
#define RK29_CAM_POWERACTIVE_BITPOS 0x00
#define RK29_CAM_POWERACTIVE_MASK (1<<RK29_CAM_POWERACTIVE_BITPOS)
#include <linux/delay.h>
#include <linux/string.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
#include <mach/rk29_lightsensor.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend cm3202_early_suspend;
+#endif
+
struct rk29_lsr_platform_data *lightsensor;
static void lsr_report_value(struct input_dev *input_dev, int value)
{
- input_report_abs(input_dev, ABS_X, value);
- //input_sync(input_dev);
+ input_report_abs(input_dev, ABS_MISC/*ABS_X*/, value);
+ input_sync(input_dev);
}
pdata->input_dev->name = "lsensor";
pdata->input_dev->dev.parent = &dev->dev;
pdata->input_dev->evbit[0] = BIT(EV_ABS);
- input_set_abs_params(pdata->input_dev,ABS_X,0,0x3ff,0,0);
+ input_set_abs_params(pdata->input_dev,ABS_MISC/*ABS_X*/,0,9/*0x3ff*/,0,0);
ret = input_register_device(pdata->input_dev);
return ;
init_input_register_device_failed:
input_unregister_device(pdata->input_dev);
input_free_device(pdata->input_dev);
}
+static int lsr_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ set_lsr_timer(0);
+ set_lsr_value(LSR_OFF);
+ return 0;
+}
+static int lsr_resume(struct platform_device *pdev)
+{
+ set_lsr_timer(1);
+ set_lsr_value(LSR_ON);
+ return 0;
+}
static int __devinit lsr_probe(struct platform_device *pdev)
{
lightsensor = kzalloc(sizeof(struct rk29_lsr_platform_data), GFP_KERNEL);
rk29_lsr_adc_init(pdev);
rk29_lsr_timer_init(pdev);
rk29_lsr_input_init(pdev);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ cm3202_early_suspend.suspend = lsr_suspend;
+ cm3202_early_suspend.resume = lsr_resume;
+ register_early_suspend(&cm3202_early_suspend);
+#endif
+
return 0;
err_kzalloc_lightsensor:
return 0;
}
-static int lsr_suspend(struct platform_device *pdev, pm_message_t state)
-{
- set_lsr_timer(0);
- set_lsr_value(LSR_OFF);
- return 0;
-}
-
-static int lsr_resume(struct platform_device *pdev)
-{
- set_lsr_timer(1);
- set_lsr_value(LSR_ON);
- return 0;
-}
-
-
-
static struct platform_driver lsr_device_driver = {
.probe = lsr_probe,
.remove = __devexit_p(lsr_remove),
- .suspend = lsr_suspend,
- .resume = lsr_resume,
+// .suspend = lsr_suspend,
+// .resume = lsr_resume,
.driver = {
.name = LSR_NAME,
.owner = THIS_MODULE,
depends on SOC_CAMERA && I2C
help
This is a ov2655 camera driver
+
config SOC_CAMERA_OV3640
tristate "ov3640 camera support"
depends on SOC_CAMERA && I2C
help
- This is a ov3640 camera driver
+ This is a ov3640 camera driver
+choice
+ prompt "OV3640 Module Focus select"
+ depends on SOC_CAMERA_OV3640
+ default OV3640_AUTOFOCUS
+ ---help---
+
+config OV3640_AUTOFOCUS
+ bool "OV3640 auto focus"
+
+config OV3640_FIXEDFOCUS
+ bool "OV3640 fixed focus"
+endchoice
config SOC_CAMERA_OV5642
tristate "ov5642 camera support"
depends on SOC_CAMERA && I2C
help
This is a GC0308 camera driver
+config SOC_CAMERA_GC0309
+ tristate "GC0309 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a GC0309 camera driver
+config SOC_CAMERA_GC2015
+ tristate "GC2015 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a GC2015 camera driver
+config SOC_CAMERA_HI253
+ tristate "HI253 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a HI253 camera driver
+config SOC_CAMERA_HI704
+ tristate "HI704 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a HI704 camera driver
config SOC_CAMERA_SIV120B
tristate "siv120b support"
depends on SOC_CAMERA && I2C
help
This is a SIV120B camera driver
+
+config SOC_CAMERA_SID130B
+ tristate "sid130b support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a SID130B camera driver
+
+config SOC_CAMERA_NT99250
+ tristate "NT99250 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a NT99250 camera driver
config MX1_VIDEO
bool
obj-$(CONFIG_SOC_CAMERA_S5K6AA) += s5k6aa.o
obj-$(CONFIG_SOC_CAMERA_GT2005) += gt2005.o
obj-$(CONFIG_SOC_CAMERA_GC0308) += gc0308.o
+obj-$(CONFIG_SOC_CAMERA_GC0309) += gc0309.o
+obj-$(CONFIG_SOC_CAMERA_GC2015) += gc2015.o
obj-$(CONFIG_SOC_CAMERA_SIV120B) += siv120b.o
+obj-$(CONFIG_SOC_CAMERA_SID130B) += sid130B.o
+obj-$(CONFIG_SOC_CAMERA_HI253) += hi253.o
+obj-$(CONFIG_SOC_CAMERA_HI704) += hi704.o
+obj-$(CONFIG_SOC_CAMERA_NT99250) += nt99250.o
# And now the v4l2 drivers:
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
--- /dev/null
+/*
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_GC0309
+#define SENSOR_V4L2_IDENT V4L2_IDENT_GC0309
+#define SENSOR_ID 0xa0
+#define SENSOR_MIN_WIDTH 176
+#define SENSOR_MIN_HEIGHT 144
+#define SENSOR_MAX_WIDTH 648
+#define SENSOR_MAX_HEIGHT 488
+#define SENSOR_INIT_WIDTH 648 /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT 488
+#define SENSOR_INIT_WINSEQADR sensor_vga
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY
+
+#define CONFIG_SENSOR_WhiteBalance 1
+#define CONFIG_SENSOR_Brightness 0
+#define CONFIG_SENSOR_Contrast 0
+#define CONFIG_SENSOR_Saturation 0
+#define CONFIG_SENSOR_Effect 1
+#define CONFIG_SENSOR_Scene 1
+#define CONFIG_SENSOR_DigitalZoom 0
+#define CONFIG_SENSOR_Focus 0
+#define CONFIG_SENSOR_Exposure 0
+#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Mirror 0
+#define CONFIG_SENSOR_Flip 0
+
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500
+#define COLOR_TEMPERATURE_OFFICE_DN 3500
+#define COLOR_TEMPERATURE_OFFICE_UP 5000
+#define COLOR_TEMPERATURE_HOME_DN 2500
+#define COLOR_TEMPERATURE_HOME_UP 3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+
+struct reginfo
+{
+ u8 reg;
+ u8 val;
+};
+
+/* init SVGA preview */
+static struct reginfo sensor_init_data[] =
+{
+ /*init registers code.*/
+
+{0xfe,0x80}, // soft reset
+
+// GC0309_SET_PAGE0; // set page0
+
+{0x1a,0x16},
+{0xd2,0x10}, // close AEC
+{0x22,0x55}, // close AWB
+
+{0x5a,0x56},
+{0x5b,0x40},
+{0x5c,0x4a},
+
+{0x22,0x57},
+
+{0x01,0xfa},
+{0x02,0x70},
+{0x0f,0x01},
+
+{0xe2,0x00},
+{0xe3,0x64},
+
+{0x03,0x01},
+{0x04,0x2c},
+
+ /*
+{0x01,0x6a},
+{0x02,0x25},
+{0x0f,0x00},
+
+{0xe2,0x00},
+{0xe3,0x4b},
+
+{0xe4,0x02},
+{0xe5,0x0d},
+{0xe6,0x02},
+{0xe7,0x0d},
+{0xe8,0x02},
+{0xe9,0x0d},
+{0xea,0x05},
+{0xeb,0xdc},
+ */
+
+{0x05,0x00},
+{0x06,0x00},
+{0x07,0x00},
+{0x08,0x00},
+{0x09,0x01},
+{0x0a,0xe8},
+{0x0b,0x02},
+{0x0c,0x88},
+{0x0d,0x02},
+{0x0e,0x02},
+{0x10,0x22},
+{0x11,0x0d},
+{0x12,0x2a},
+{0x13,0x00},
+//{0x14,0x10},
+{0x15,0x0a},
+{0x16,0x05},
+{0x17,0x01},
+
+{0x1b,0x03},
+{0x1c,0xc1},
+{0x1d,0x08},
+{0x1e,0x20},
+{0x1f,0x16},
+
+{0x20,0xff},
+{0x21,0xf8},
+{0x24,0xa0},
+{0x25,0x0f},
+ //output sync_mode
+{0x26,0x03},
+{0x2f,0x01},
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// grab_t ////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0x30,0xf7},
+{0x31,0x40},
+{0x32,0x00},
+{0x39,0x04},
+{0x3a,0x20},
+{0x3b,0x20},
+{0x3c,0x02},
+{0x3d,0x02},
+{0x3e,0x02},
+{0x3f,0x02},
+
+ //gain
+{0x50,0x24},
+
+{0x53,0x82},
+{0x54,0x80},
+{0x55,0x80},
+{0x56,0x82},
+
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// LSC_t ////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0x8b,0x20},
+{0x8c,0x20},
+{0x8d,0x20},
+{0x8e,0x10},
+{0x8f,0x10},
+{0x90,0x10},
+{0x91,0x3c},
+{0x92,0x50},
+{0x5d,0x12},
+{0x5e,0x1a},
+{0x5f,0x24},
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// DNDD_t ///////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0x60,0x07},
+{0x61,0x0e},
+{0x62,0x0c},
+{0x64,0x03},
+{0x66,0xe8},
+{0x67,0x86},
+{0x68,0xa2},
+
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// asde_t ///////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0x69,0x20},
+{0x6a,0x0f},
+{0x6b,0x00},
+{0x6c,0x53},
+{0x6d,0x83},
+{0x6e,0xac},
+{0x6f,0xac},
+{0x70,0x15},
+{0x71,0x33},
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// eeintp_t///////////////////////////////
+};
+
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+{0x45 , 0x0f}, //output enable
+ {0x0,0x0}
+};
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{};
+
+/* 320*240 QVGA */
+static struct reginfo sensor_qvga[] =
+{};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{};
+
+
+static struct reginfo sensor_ClrFmt_YUYV[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_ClrFmt_UYVY[]=
+{
+
+ {0x00, 0x00}
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static struct reginfo sensor_WhiteB_Auto[]=
+{
+
+ {0x00, 0x00}
+};
+/* Cloudy Colour Temperature : 6500K - 8000K */
+static struct reginfo sensor_WhiteB_Cloudy[]=
+{
+
+ {0x00, 0x00}
+};
+/* ClearDay Colour Temperature : 5000K - 6500K */
+static struct reginfo sensor_WhiteB_ClearDay[]=
+{
+ //Sunny
+
+ {0x00, 0x00}
+};
+/* Office Colour Temperature : 3500K - 5000K */
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+ //Office
+
+ {0x00, 0x00}
+
+};
+/* Home Colour Temperature : 2500K - 3500K */
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+ //Home
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static struct reginfo sensor_Brightness0[]=
+{
+ // Brightness -2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness1[]=
+{
+ // Brightness -1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness2[]=
+{
+ // Brightness 0
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness3[]=
+{
+ // Brightness +1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness4[]=
+{
+ // Brightness +2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness5[]=
+{
+ // Brightness +3
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+ sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static struct reginfo sensor_Effect_Normal[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_WandB[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Sepia[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Negative[] =
+{
+ //Negative
+
+ {0x00, 0x00}
+};
+static struct reginfo sensor_Effect_Bluish[] =
+{
+ // Bluish
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Green[] =
+{
+ // Greenish
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static struct reginfo sensor_Exposure0[]=
+{
+ //-3
+
+};
+
+static struct reginfo sensor_Exposure1[]=
+{
+ //-2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure2[]=
+{
+ //-0.3EV
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure3[]=
+{
+ //default
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure4[]=
+{
+ // 1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure5[]=
+{
+ // 2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure6[]=
+{
+ // 3
+
+ {0x00, 0x00}
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static struct reginfo sensor_Saturation0[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Saturation1[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Saturation2[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static struct reginfo sensor_Contrast0[]=
+{
+ //Contrast -3
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast1[]=
+{
+ //Contrast -2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast2[]=
+{
+ // Contrast -1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast3[]=
+{
+ //Contrast 0
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast4[]=
+{
+ //Contrast +1
+
+ {0x00, 0x00}
+};
+
+
+static struct reginfo sensor_Contrast5[]=
+{
+ //Contrast +2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast6[]=
+{
+ //Contrast +3
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static struct reginfo sensor_MirrorOn[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_MirrorOff[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static struct reginfo sensor_FlipOn[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_FlipOff[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static struct reginfo sensor_SceneAuto[] =
+{
+#if 0 /* ddl@rock-chips.com : */
+ {0x3014, 0x04},
+ {0x3015, 0x00},
+ {0x302e, 0x00},
+ {0x302d, 0x00},
+ {0x00, 0x00}
+#else
+
+ {0x00, 0x00}
+#endif
+};
+
+static struct reginfo sensor_SceneNight[] =
+{
+#if 1
+ //30fps ~ 5fps night mode for 60/50Hz light environment, 24Mhz clock input,36Mzh pclk
+
+ {0x00, 0x00}
+#else
+ //15fps ~ 5fps night mode for 60/50Hz light environment, 24Mhz clock input,18Mhz pclk
+ {0x300e, 0x34},
+ {0x3011, 0x01},
+ {0x302c, 0x00},
+ {0x3071, 0x00},
+ {0x3070, 0x5d},
+ {0x301c, 0x05},
+ {0x3073, 0x00},
+ {0x3072, 0x4d},
+ {0x301d, 0x07},
+ {0x3014, 0x0c},
+ {0x3015, 0x50},
+ {0x302e, 0x00},
+ {0x302d, 0x00},
+#endif
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+ {0x0, 0x0},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+ {0x0, 0x0},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},
+ #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White Balance Control",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Brightness
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness Control",
+ .minimum = -3,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ {
+ .id = V4L2_CID_EFFECT,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Effect Control",
+ .minimum = 0,
+ .maximum = 5,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Exposure
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Control",
+ .minimum = 0,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Saturation
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation Control",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Contrast
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast Control",
+ .minimum = -3,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Mirror
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flip
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ {
+ .id = V4L2_CID_SCENE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Scene Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_DigitalZoom
+ {
+ .id = V4L2_CID_ZOOM_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_ZOOM_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Focus
+ {
+ .id = V4L2_CID_FOCUS_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_FOCUS_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 125,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ {
+ .id = V4L2_CID_FLASH,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Flash Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+ .suspend = sensor_suspend,
+ .resume = sensor_resume,
+ .set_bus_param = sensor_set_bus_param,
+ .query_bus_param = sensor_query_bus_param,
+ .controls = sensor_controls,
+ .menus = sensor_menus,
+ .num_controls = ARRAY_SIZE(sensor_controls),
+ .num_menus = ARRAY_SIZE(sensor_menus),
+};
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+
+#define JPG_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+
+static const struct soc_camera_data_format sensor_colour_formats[] = {
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
+};
+
+typedef struct sensor_info_priv_s
+{
+ int whiteBalance;
+ int brightness;
+ int contrast;
+ int saturation;
+ int effect;
+ int scene;
+ int digitalzoom;
+ int focus;
+ int flash;
+ int exposure;
+ bool snap2preview;
+ bool video2preview;
+ unsigned char mirror; /* HFLIP */
+ unsigned char flip; /* VFLIP */
+ unsigned int winseqe_cur_addr;
+ unsigned int pixfmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+ struct v4l2_subdev subdev;
+ struct i2c_client *client;
+ sensor_info_priv_t info_priv;
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+#endif
+ return 0;
+sensor_task_lock_err:
+ return -1;
+}
+
+#if 0
+/* sensor register */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_recv(client, reg, val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_send(client, reg, &val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+#else
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err,cnt;
+ u8 buf[2];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+ buf[1] = val;
+
+ if (reg == 0xfe)
+ mdelay(10);
+
+ msg->addr = client->addr;
+ msg->flags = client->flags;
+ msg->buf = buf;
+ msg->len = sizeof(buf);
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ return 0;
+ } else {
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int err,cnt;
+ u8 buf[1];
+ struct i2c_msg msg[2];
+
+ buf[0] = reg ;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].buf = buf;
+ msg[0].len = sizeof(buf);
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags|I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = 1;
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err >= 0) {
+ *val = buf[0];
+ return 0;
+ } else {
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+#endif
+
+/* write a array of registers */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int err = 0, cnt;
+ int i = 0;
+ int j = 0;
+ char valchk;
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
+ while (regarray[i].reg != 0)
+ {
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);
+ if (err < 0)
+ {
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ //mdelay(5);
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
+ }
+ i++;
+ }
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+ char value;
+ int ret;
+
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ /* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
+ ret = sensor_write(client, 0xfe, 0x80);
+ if (ret != 0)
+ {
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ mdelay(5); //delay 5 microseconds
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x00, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ ret = sensor_write_array(client, sensor_init_data);
+ if (ret != 0)
+ {
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+ goto sensor_INIT_ERR;
+ }
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
+
+ /* sensor sensor information for initialization */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ if (qctrl)
+ sensor->info_priv.whiteBalance = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+ if (qctrl)
+ sensor->info_priv.brightness = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ if (qctrl)
+ sensor->info_priv.effect = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+ if (qctrl)
+ sensor->info_priv.exposure = qctrl->default_value;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+ if (qctrl)
+ sensor->info_priv.saturation = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+ if (qctrl)
+ sensor->info_priv.contrast = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+ if (qctrl)
+ sensor->info_priv.mirror = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+ if (qctrl)
+ sensor->info_priv.flip = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+ if (qctrl)
+ sensor->info_priv.scene = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.digitalzoom = qctrl->default_value;
+
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
+ #if CONFIG_SENSOR_Focus
+ sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.focus = qctrl->default_value;
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+ if (qctrl)
+ sensor->info_priv.flash = qctrl->default_value;
+ #endif
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+ return 0;
+sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
+ return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
+
+static struct reginfo sensor_power_down_sequence[]=
+{
+ {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;
+ if (ret != 0) {
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+ return ret;
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ }
+ } else {
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+ return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+
+ return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ unsigned long flags = SENSOR_BUS_PARAM;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = icd->user_width;
+ pix->height = icd->user_height;
+ pix->pixelformat = sensor->info_priv.pixfmt;
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct reginfo *winseqe_set_addr=NULL;
+ int ret=0, set_w,set_h;
+
+ SENSOR_TR("sensor_s_fmt\n");
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {
+ switch (pix->pixelformat)
+ {
+ case V4L2_PIX_FMT_YUYV:
+ {
+ winseqe_set_addr = sensor_ClrFmt_YUYV;
+ break;
+ }
+ case V4L2_PIX_FMT_UYVY:
+ {
+ winseqe_set_addr = sensor_ClrFmt_UYVY;
+ break;
+ }
+ default:
+ break;
+ }
+ if (winseqe_set_addr != NULL) {
+ sensor_write_array(client, winseqe_set_addr);
+ sensor->info_priv.pixfmt = pix->pixelformat;
+
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ } else {
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ }
+ }
+
+ set_w = pix->width;
+ set_h = pix->height;
+
+ if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[0].reg)
+ {
+ winseqe_set_addr = sensor_qcif;
+ set_w = 176;
+ set_h = 144;
+ }
+ else if (((set_w <= 320) && (set_h <= 240)) && sensor_qvga[0].reg)
+ {
+ winseqe_set_addr = sensor_qvga;
+ set_w = 320;
+ set_h = 240;
+ }
+ else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[0].reg)
+ {
+ winseqe_set_addr = sensor_cif;
+ set_w = 352;
+ set_h = 288;
+ }
+ else if (((set_w <= 640) && (set_h <= 480)) && sensor_vga[0].reg)
+ {
+ winseqe_set_addr = sensor_vga;
+ set_w = 640;
+ set_h = 480;
+ }
+
+ else
+ {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
+ ret = -1;
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
+ }
+
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ ret |= sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ }
+
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+ }
+ else
+ {
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ }
+
+ pix->width = set_w;
+ pix->height = set_h;
+
+sensor_s_fmt_end:
+ return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;
+
+ /*
+ * With Bayer format enforce even side lengths, but let the user play
+ * with the starting pixel
+ */
+
+ if (pix->height > SENSOR_MAX_HEIGHT)
+ pix->height = SENSOR_MAX_HEIGHT;
+ else if (pix->height < SENSOR_MIN_HEIGHT)
+ pix->height = SENSOR_MIN_HEIGHT;
+ else if (bayer)
+ pix->height = ALIGN(pix->height, 2);
+
+ if (pix->width > SENSOR_MAX_WIDTH)
+ pix->width = SENSOR_MAX_WIDTH;
+ else if (pix->width < SENSOR_MIN_WIDTH)
+ pix->width = SENSOR_MIN_WIDTH;
+ else if (bayer)
+ pix->width = ALIGN(pix->width, 2);
+
+ return 0;
+}
+
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+ struct i2c_client *client = sd->priv;
+
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match.addr != client->addr)
+ return -ENODEV;
+
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */
+ id->revision = 0;
+
+ return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ int digitalzoom_cur, digitalzoom_total;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl_info)
+ return -EINVAL;
+
+ digitalzoom_cur = sensor->info_priv.digitalzoom;
+ digitalzoom_total = qctrl_info->maximum;
+
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+ {
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+ {
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+ {
+ *value = digitalzoom_total - digitalzoom_cur;
+ }
+
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+ {
+ *value = 0 - digitalzoom_cur;
+ }
+
+ digitalzoom_cur += *value;
+
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+ case V4L2_CID_BRIGHTNESS:
+ {
+ ctrl->value = sensor->info_priv.brightness;
+ break;
+ }
+ case V4L2_CID_SATURATION:
+ {
+ ctrl->value = sensor->info_priv.saturation;
+ break;
+ }
+ case V4L2_CID_CONTRAST:
+ {
+ ctrl->value = sensor->info_priv.contrast;
+ break;
+ }
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ ctrl->value = sensor->info_priv.whiteBalance;
+ break;
+ }
+ case V4L2_CID_EXPOSURE:
+ {
+ ctrl->value = sensor->info_priv.exposure;
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ ctrl->value = sensor->info_priv.mirror;
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ ctrl->value = sensor->info_priv.flip;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+ const struct v4l2_queryctrl *qctrl;
+
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+#if CONFIG_SENSOR_Brightness
+ case V4L2_CID_BRIGHTNESS:
+ {
+ if (ctrl->value != sensor->info_priv.brightness)
+ {
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.brightness = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Exposure
+ case V4L2_CID_EXPOSURE:
+ {
+ if (ctrl->value != sensor->info_priv.exposure)
+ {
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.exposure = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Saturation
+ case V4L2_CID_SATURATION:
+ {
+ if (ctrl->value != sensor->info_priv.saturation)
+ {
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.saturation = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Contrast
+ case V4L2_CID_CONTRAST:
+ {
+ if (ctrl->value != sensor->info_priv.contrast)
+ {
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.contrast = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ if (ctrl->value != sensor->info_priv.whiteBalance)
+ {
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.whiteBalance = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Mirror
+ case V4L2_CID_HFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.mirror)
+ {
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.mirror = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flip
+ case V4L2_CID_VFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.flip)
+ {
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flip = ctrl->value;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ext_ctrl->id)
+ {
+ case V4L2_CID_SCENE:
+ {
+ ext_ctrl->value = sensor->info_priv.scene;
+ break;
+ }
+ case V4L2_CID_EFFECT:
+ {
+ ext_ctrl->value = sensor->info_priv.effect;
+ break;
+ }
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.digitalzoom;
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.focus;
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FLASH:
+ {
+ ext_ctrl->value = sensor->info_priv.flash;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int val_offset;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ val_offset = 0;
+ switch (ext_ctrl->id)
+ {
+#if CONFIG_SENSOR_Scene
+ case V4L2_CID_SCENE:
+ {
+ if (ext_ctrl->value != sensor->info_priv.scene)
+ {
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.scene = ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Effect
+ case V4L2_CID_EFFECT:
+ {
+ if (ext_ctrl->value != sensor->info_priv.effect)
+ {
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.effect= ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += val_offset;
+
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Focus
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.focus)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+ sensor->info_priv.focus += val_offset;
+ }
+
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ sensor->info_priv.focus += ext_ctrl->value;
+
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flash
+ case V4L2_CID_FLASH:
+ {
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flash = ext_ctrl->value;
+
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
+{
+ char value;
+ int ret;
+ struct sensor *sensor = to_sensor(client);
+
+ /* We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant. */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ /* soft reset */
+ ret = sensor_write(client, 0xfe, 0x80);
+ if (ret != 0)
+ {
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+ return -ENODEV;
+ }
+ mdelay(5); //delay 5 microseconds
+
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x00, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ SENSOR_TR("chip id:0x%x\n",value);
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ icd->formats = sensor_colour_formats;
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
+
+ return 0;
+
+sensor_video_probe_err:
+
+ return ret;
+}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_ioctl_end:
+ return ret;
+
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+ .init = sensor_init,
+ .g_ctrl = sensor_g_control,
+ .s_ctrl = sensor_s_control,
+ .g_ext_ctrls = sensor_g_ext_controls,
+ .s_ext_ctrls = sensor_s_ext_controls,
+ .g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+ .s_fmt = sensor_s_fmt,
+ .g_fmt = sensor_g_fmt,
+ .try_fmt = sensor_try_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+ .core = &sensor_subdev_core_ops,
+ .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct sensor *sensor;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
+ int ret;
+
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+ return -EIO;
+ }
+
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd->ops = &sensor_ops;
+ icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
+
+ ret = sensor_video_probe(icd, client);
+ if (ret < 0) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(sensor);
+ sensor = NULL;
+ }
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+ return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
+ kfree(sensor);
+ sensor = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+ {SENSOR_NAME_STRING(), 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+ .driver = {
+ .name = SENSOR_NAME_STRING(),
+ },
+ .probe = sensor_probe,
+ .remove = sensor_remove,
+ .id_table = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+ return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+ i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("ddl <kernel@rock-chips>");
+MODULE_LICENSE("GPL");
+
+
+
--- /dev/null
+/*
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_GC2015
+#define SENSOR_V4L2_IDENT V4L2_IDENT_GC2015
+#define SENSOR_ID 0x2005
+#define SENSOR_MIN_WIDTH 176
+#define SENSOR_MIN_HEIGHT 144
+#define SENSOR_MAX_WIDTH 1600
+#define SENSOR_MAX_HEIGHT 1200
+#define SENSOR_INIT_WIDTH 1024 /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT 768
+#define SENSOR_INIT_WINSEQADR sensor_svga
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY
+
+#define CONFIG_SENSOR_WhiteBalance 1
+#define CONFIG_SENSOR_Brightness 0
+#define CONFIG_SENSOR_Contrast 0
+#define CONFIG_SENSOR_Saturation 0
+#define CONFIG_SENSOR_Effect 1
+#define CONFIG_SENSOR_Scene 1
+#define CONFIG_SENSOR_DigitalZoom 0
+#define CONFIG_SENSOR_Focus 0
+#define CONFIG_SENSOR_Exposure 0
+#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Mirror 0
+#define CONFIG_SENSOR_Flip 0
+
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500
+#define COLOR_TEMPERATURE_OFFICE_DN 3500
+#define COLOR_TEMPERATURE_OFFICE_UP 5000
+#define COLOR_TEMPERATURE_HOME_DN 2500
+#define COLOR_TEMPERATURE_HOME_UP 3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+
+struct reginfo
+{
+ u8 reg;
+ u8 val;
+};
+
+/* init SVGA preview */
+static struct reginfo sensor_init_data[] =
+{
+//{0xfe , 0x80}, //soft reset
+{0x45 , 0x00}, //output_enable
+ //////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////preview capture switch /////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////
+ //preview
+{0x02 , 0x01}, //preview mode
+{0x2a , 0xca}, //[7]col_binning , 0x[6]even skip
+{0x48 , 0x40}, //manual_gain
+
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////// preview LSC /////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+
+{0xb0 , 0x13}, //[4]Y_LSC_en [3]lsc_compensate [2]signed_b4 [1:0]pixel array select
+{0xb1 , 0x20}, //P_LSC_red_b2
+{0xb2 , 0x20}, //P_LSC_green_b2
+{0xb3 , 0x20}, //P_LSC_blue_b2
+{0xb4 , 0x20}, //P_LSC_red_b4
+{0xb5 , 0x20}, //P_LSC_green_b4
+{0xb6 , 0x20}, //P_LSC_blue_b4
+{0xb7 , 0x00}, //P_LSC_compensate_b2
+{0xb8 , 0x80}, //P_LSC_row_center , 0x344 , 0x (0x600/2-100)/2=100
+{0xb9 , 0x80}, //P_LSC_col_center , 0x544 , 0x (0x800/2-200)/2=100
+
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////// capture LSC ///////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+{0xba , 0x13}, //[4]Y_LSC_en [3]lsc_compensate [2]signed_b4 [1:0]pixel array select
+{0xbb , 0x20}, //C_LSC_red_b2
+{0xbc , 0x20}, //C_LSC_green_b2
+{0xbd , 0x20}, //C_LSC_blue_b2
+{0xbe , 0x20}, //C_LSC_red_b4
+{0xbf , 0x20}, //C_LSC_green_b4
+{0xc0 , 0x20}, //C_LSC_blue_b4
+{0xc1 , 0x00}, //C_Lsc_compensate_b2
+{0xc2 , 0x80}, //C_LSC_row_center , 0x344 , 0x (0x1200/2-344)/2=128
+{0xc3 , 0x80}, //C_LSC_col_center , 0x544 , 0x (0x1600/2-544)/2=128
+
+ //GC2015_SET_PAGE0; //page0
+
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////// analog configure ///////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+{0x29 , 0x00}, //cisctl mode 1
+{0x2b , 0x06}, //cisctl mode 3
+{0x32 , 0x0c}, //analog mode 1
+{0x33 , 0x0f}, //analog mode 2
+{0x34 , 0x00}, //[6:4]da_rsg
+
+{0x35 , 0x88}, //Vref_A25
+{0x37 , 0x16}, //Drive Current
+
+ /////////////////////////////////////////////////////////////////////
+ ///////////////////////////ISP Related//////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0x40 , 0xff},
+{0x41 , 0x24}, //[5]skin_detectionenable[2]auto_gray , 0x[1]y_gamma
+{0x42 , 0x76}, //[7]auto_sa[6]auto_ee[5]auto_dndd[4]auto_lsc[3]na[2]abs , 0x[1]awb
+{0x4b , 0xea}, //[1]AWB_gain_mode , 0x1:atpregain0:atpostgain
+{0x4d , 0x03}, //[1]inbf_en
+{0x4f , 0x01}, //AEC enable
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// BLK ///////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x63 , 0x77}, //BLK mode 1
+{0x66 , 0x00}, //BLK global offset
+{0x6d , 0x04},
+{0x6e , 0x18}, //BLK offset submode,offset R
+{0x6f , 0x10},
+{0x70 , 0x18},
+{0x71 , 0x10},
+{0x73 , 0x03},
+
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// DNDD ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x80 , 0x07}, //[7]dn_inc_or_dec [4]zero_weight_mode[3]share [2]c_weight_adap [1]dn_lsc_mode [0]dn_b
+{0x82 , 0x08}, //DN lilat b base
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// EEINTP ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x8a , 0x7c},
+{0x8c , 0x02},
+{0x8e , 0x02},
+{0x8f , 0x48},
+
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// CC_t ///////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0xb0 , 0x44},
+{0xb1 , 0xfe},
+{0xb2 , 0x00},
+{0xb3 , 0xf8},
+{0xb4 , 0x48},
+{0xb5 , 0xf8},
+{0xb6 , 0x00},
+{0xb7 , 0x04},
+{0xb8 , 0x00},
+
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// GAMMA ///////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+ //RGB_GAMMA
+{0xbf , 0x0e},
+{0xc0 , 0x1c},
+{0xc1 , 0x34},
+{0xc2 , 0x48},
+{0xc3 , 0x5a},
+{0xc4 , 0x6b},
+{0xc5 , 0x7b},
+{0xc6 , 0x95},
+{0xc7 , 0xab},
+{0xc8 , 0xbf},
+{0xc9 , 0xce},
+{0xca , 0xd9},
+{0xcb , 0xe4},
+{0xcc , 0xec},
+{0xcd , 0xf7},
+{0xce , 0xfd},
+{0xcf , 0xff},
+
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////// YCP_t ///////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+{0xd1 , 0x38}, //saturation
+{0xd2 , 0x38}, //saturation
+{0xde , 0x21}, //auto_gray
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// ASDE ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x98 , 0x30},
+{0x99 , 0xf0},
+{0x9b , 0x00},
+
+ //GC2015_SET_PAGE1; //page1
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// AEC ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x10 , 0x45}, //AEC mode 1
+{0x11 , 0x32}, //[7]fix target
+{0x13 , 0x60},
+{0x17 , 0x00},
+{0x1c , 0x96},
+{0x1e , 0x11},
+{0x21 , 0xc0}, //max_post_gain
+{0x22 , 0x40}, //max_pre_gain
+{0x2d , 0x06}, //P_N_AEC_exp_level_1[12:8]
+{0x2e , 0x00}, //P_N_AEC_exp_level_1[7:0]
+{0x1e , 0x32},
+{0x33 , 0x00}, //[6:5]max_exp_level [4:0]min_exp_level
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// AWB ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x57 , 0x40}, //number limit
+{0x5d , 0x44}, //
+{0x5c , 0x35}, //show mode,close dark_mode
+{0x5e , 0x29}, //close color temp
+{0x5f , 0x50},
+{0x60 , 0x50},
+{0x65 , 0xc0},
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// ABS ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x80 , 0x82},
+{0x81 , 0x00},
+{0x83 , 0x00}, //ABS Y stretch limit
+
+ //GC2015_SET_PAGE0;
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////// Crop //////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////
+{0x50 , 0x01},//out window
+{0x51 , 0x00},
+{0x52 , 0x00},
+{0x53 , 0x00},
+{0x54 , 0x00},
+{0x55 , 0x02},
+{0x56 , 0x58},
+{0x57 , 0x03},
+{0x58 , 0x20},
+
+ ////////////////////////////////////////////////////////////////////
+ /////////////////////////// OUT ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+{0x44 , 0xa0}, //YUV sequence
+{0x45 , 0x0f}, //output enable
+{0x46 , 0x02}, //sync mode
+};
+
+/* 1600X1200 UXGA capture */
+static struct reginfo sensor_uxga[] =
+{
+{0x45 , 0x0f}, //output enable
+ {0x0,0x0}
+};
+
+/* 1280X1024 SXGA */
+static struct reginfo sensor_sxga[] =
+{
+ {0x0, 0x0}
+};
+static struct reginfo sensor_xga[] =
+{
+ {0x0, 0x0}
+};
+/* 800X600 SVGA,30fps*/
+static struct reginfo sensor_svga[] =
+{
+{0x45 , 0x0f}, //output enable
+ {0x0,0x0}
+};
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+{0x45 , 0x0f}, //output enable
+ {0x0,0x0}
+};
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{};
+
+/* 320*240 QVGA */
+static struct reginfo sensor_qvga[] =
+{};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{};
+#if 0
+/* 160X120 QQVGA*/
+static struct reginfo ov2655_qqvga[] =
+{
+
+ {0x300E, 0x34},
+ {0x3011, 0x01},
+ {0x3012, 0x10},
+ {0x302a, 0x02},
+ {0x302b, 0xE6},
+ {0x306f, 0x14},
+ {0x3362, 0x90},
+
+ {0x3070, 0x5d},
+ {0x3072, 0x5d},
+ {0x301c, 0x07},
+ {0x301d, 0x07},
+
+ {0x3020, 0x01},
+ {0x3021, 0x18},
+ {0x3022, 0x00},
+ {0x3023, 0x06},
+ {0x3024, 0x06},
+ {0x3025, 0x58},
+ {0x3026, 0x02},
+ {0x3027, 0x61},
+ {0x3088, 0x00},
+ {0x3089, 0xa0},
+ {0x308a, 0x00},
+ {0x308b, 0x78},
+ {0x3316, 0x64},
+ {0x3317, 0x25},
+ {0x3318, 0x80},
+ {0x3319, 0x08},
+ {0x331a, 0x0a},
+ {0x331b, 0x07},
+ {0x331c, 0x80},
+ {0x331d, 0x38},
+ {0x3100, 0x00},
+ {0x3302, 0x11},
+
+ {0x0, 0x0},
+};
+
+
+
+static struct reginfo ov2655_Sharpness_auto[] =
+{
+ {0x3306, 0x00},
+};
+
+static struct reginfo ov2655_Sharpness1[] =
+{
+ {0x3306, 0x08},
+ {0x3371, 0x00},
+};
+
+static struct reginfo ov2655_Sharpness2[][3] =
+{
+ //Sharpness 2
+ {0x3306, 0x08},
+ {0x3371, 0x01},
+};
+
+static struct reginfo ov2655_Sharpness3[] =
+{
+ //default
+ {0x3306, 0x08},
+ {0x332d, 0x02},
+};
+static struct reginfo ov2655_Sharpness4[]=
+{
+ //Sharpness 4
+ {0x3306, 0x08},
+ {0x332d, 0x03},
+};
+
+static struct reginfo ov2655_Sharpness5[] =
+{
+ //Sharpness 5
+ {0x3306, 0x08},
+ {0x332d, 0x04},
+};
+#endif
+
+static struct reginfo sensor_ClrFmt_YUYV[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_ClrFmt_UYVY[]=
+{
+
+ {0x00, 0x00}
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static struct reginfo sensor_WhiteB_Auto[]=
+{
+
+ {0x00, 0x00}
+};
+/* Cloudy Colour Temperature : 6500K - 8000K */
+static struct reginfo sensor_WhiteB_Cloudy[]=
+{
+
+ {0x00, 0x00}
+};
+/* ClearDay Colour Temperature : 5000K - 6500K */
+static struct reginfo sensor_WhiteB_ClearDay[]=
+{
+ //Sunny
+
+ {0x00, 0x00}
+};
+/* Office Colour Temperature : 3500K - 5000K */
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+ //Office
+
+ {0x00, 0x00}
+
+};
+/* Home Colour Temperature : 2500K - 3500K */
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+ //Home
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static struct reginfo sensor_Brightness0[]=
+{
+ // Brightness -2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness1[]=
+{
+ // Brightness -1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness2[]=
+{
+ // Brightness 0
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness3[]=
+{
+ // Brightness +1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness4[]=
+{
+ // Brightness +2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Brightness5[]=
+{
+ // Brightness +3
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+ sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static struct reginfo sensor_Effect_Normal[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_WandB[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Sepia[] =
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Negative[] =
+{
+ //Negative
+
+ {0x00, 0x00}
+};
+static struct reginfo sensor_Effect_Bluish[] =
+{
+ // Bluish
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Effect_Green[] =
+{
+ // Greenish
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static struct reginfo sensor_Exposure0[]=
+{
+ //-3
+
+};
+
+static struct reginfo sensor_Exposure1[]=
+{
+ //-2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure2[]=
+{
+ //-0.3EV
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure3[]=
+{
+ //default
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure4[]=
+{
+ // 1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure5[]=
+{
+ // 2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Exposure6[]=
+{
+ // 3
+
+ {0x00, 0x00}
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static struct reginfo sensor_Saturation0[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Saturation1[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Saturation2[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static struct reginfo sensor_Contrast0[]=
+{
+ //Contrast -3
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast1[]=
+{
+ //Contrast -2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast2[]=
+{
+ // Contrast -1
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast3[]=
+{
+ //Contrast 0
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast4[]=
+{
+ //Contrast +1
+
+ {0x00, 0x00}
+};
+
+
+static struct reginfo sensor_Contrast5[]=
+{
+ //Contrast +2
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_Contrast6[]=
+{
+ //Contrast +3
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static struct reginfo sensor_MirrorOn[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_MirrorOff[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static struct reginfo sensor_FlipOn[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_FlipOff[]=
+{
+
+ {0x00, 0x00}
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static struct reginfo sensor_SceneAuto[] =
+{
+#if 0 /* ddl@rock-chips.com : */
+ {0x3014, 0x04},
+ {0x3015, 0x00},
+ {0x302e, 0x00},
+ {0x302d, 0x00},
+ {0x00, 0x00}
+#else
+
+ {0x00, 0x00}
+#endif
+};
+
+static struct reginfo sensor_SceneNight[] =
+{
+#if 1
+ //30fps ~ 5fps night mode for 60/50Hz light environment, 24Mhz clock input,36Mzh pclk
+
+ {0x00, 0x00}
+#else
+ //15fps ~ 5fps night mode for 60/50Hz light environment, 24Mhz clock input,18Mhz pclk
+ {0x300e, 0x34},
+ {0x3011, 0x01},
+ {0x302c, 0x00},
+ {0x3071, 0x00},
+ {0x3070, 0x5d},
+ {0x301c, 0x05},
+ {0x3073, 0x00},
+ {0x3072, 0x4d},
+ {0x301d, 0x07},
+ {0x3014, 0x0c},
+ {0x3015, 0x50},
+ {0x302e, 0x00},
+ {0x302d, 0x00},
+#endif
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+ {0x0, 0x0},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+ {0x0, 0x0},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},
+ #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White Balance Control",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Brightness
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness Control",
+ .minimum = -3,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ {
+ .id = V4L2_CID_EFFECT,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Effect Control",
+ .minimum = 0,
+ .maximum = 5,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Exposure
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Control",
+ .minimum = 0,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Saturation
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation Control",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Contrast
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast Control",
+ .minimum = -3,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Mirror
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flip
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ {
+ .id = V4L2_CID_SCENE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Scene Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_DigitalZoom
+ {
+ .id = V4L2_CID_ZOOM_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_ZOOM_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Focus
+ {
+ .id = V4L2_CID_FOCUS_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_FOCUS_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 125,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ {
+ .id = V4L2_CID_FLASH,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Flash Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+ .suspend = sensor_suspend,
+ .resume = sensor_resume,
+ .set_bus_param = sensor_set_bus_param,
+ .query_bus_param = sensor_query_bus_param,
+ .controls = sensor_controls,
+ .menus = sensor_menus,
+ .num_controls = ARRAY_SIZE(sensor_controls),
+ .num_menus = ARRAY_SIZE(sensor_menus),
+};
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+
+#define JPG_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+
+static const struct soc_camera_data_format sensor_colour_formats[] = {
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
+};
+
+typedef struct sensor_info_priv_s
+{
+ int whiteBalance;
+ int brightness;
+ int contrast;
+ int saturation;
+ int effect;
+ int scene;
+ int digitalzoom;
+ int focus;
+ int flash;
+ int exposure;
+ bool snap2preview;
+ bool video2preview;
+ unsigned char mirror; /* HFLIP */
+ unsigned char flip; /* VFLIP */
+ unsigned int winseqe_cur_addr;
+ unsigned int pixfmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+ struct v4l2_subdev subdev;
+ struct i2c_client *client;
+ sensor_info_priv_t info_priv;
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+#endif
+ return 0;
+sensor_task_lock_err:
+ return -1;
+}
+
+#if 0
+/* sensor register */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_recv(client, reg, val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_send(client, reg, &val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+#else
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err,cnt;
+ u8 buf[2];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+ buf[1] = val;
+
+ if (reg == 0xfe)
+ mdelay(20);
+
+ msg->addr = client->addr;
+ msg->flags = client->flags;
+ msg->buf = buf;
+ msg->len = sizeof(buf);
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ return 0;
+ } else {
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int err,cnt;
+ u8 buf[1];
+ struct i2c_msg msg[2];
+
+ buf[0] = reg ;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].buf = buf;
+ msg[0].len = sizeof(buf);
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags|I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = 1;
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err >= 0) {
+ *val = buf[0];
+ return 0;
+ } else {
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+#endif
+
+/* write a array of registers */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int err = 0, cnt;
+ int i = 0;
+ int j = 0;
+ char valchk;
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
+ while (regarray[i].reg != 0)
+ {
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);
+ if (err < 0)
+ {
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ //mdelay(5);
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
+ }
+ i++;
+ }
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+ char value;
+ int ret,pid = 0;
+
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ /* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
+ ret = sensor_write(client, 0xfe, 0x80);
+ if (ret != 0)
+ {
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ mdelay(5); //delay 5 microseconds
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x00, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ pid |= (value << 8);
+
+ ret = sensor_read(client, 0x01, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id low byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ pid |= (value & 0xff);
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ if (pid == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ ret = sensor_write_array(client, sensor_init_data);
+ if (ret != 0)
+ {
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+ goto sensor_INIT_ERR;
+ }
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
+
+ /* sensor sensor information for initialization */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ if (qctrl)
+ sensor->info_priv.whiteBalance = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+ if (qctrl)
+ sensor->info_priv.brightness = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ if (qctrl)
+ sensor->info_priv.effect = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+ if (qctrl)
+ sensor->info_priv.exposure = qctrl->default_value;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+ if (qctrl)
+ sensor->info_priv.saturation = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+ if (qctrl)
+ sensor->info_priv.contrast = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+ if (qctrl)
+ sensor->info_priv.mirror = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+ if (qctrl)
+ sensor->info_priv.flip = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+ if (qctrl)
+ sensor->info_priv.scene = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.digitalzoom = qctrl->default_value;
+
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
+ #if CONFIG_SENSOR_Focus
+ sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.focus = qctrl->default_value;
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+ if (qctrl)
+ sensor->info_priv.flash = qctrl->default_value;
+ #endif
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+ return 0;
+sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
+ return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
+
+static struct reginfo sensor_power_down_sequence[]=
+{
+ {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;
+ if (ret != 0) {
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+ return ret;
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ }
+ } else {
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+ return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+
+ return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ unsigned long flags = SENSOR_BUS_PARAM;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = icd->user_width;
+ pix->height = icd->user_height;
+ pix->pixelformat = sensor->info_priv.pixfmt;
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct reginfo *winseqe_set_addr=NULL;
+ int ret=0, set_w,set_h;
+
+ SENSOR_TR("sensor_s_fmt\n");
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {
+ switch (pix->pixelformat)
+ {
+ case V4L2_PIX_FMT_YUYV:
+ {
+ winseqe_set_addr = sensor_ClrFmt_YUYV;
+ break;
+ }
+ case V4L2_PIX_FMT_UYVY:
+ {
+ winseqe_set_addr = sensor_ClrFmt_UYVY;
+ break;
+ }
+ default:
+ break;
+ }
+ if (winseqe_set_addr != NULL) {
+ sensor_write_array(client, winseqe_set_addr);
+ sensor->info_priv.pixfmt = pix->pixelformat;
+
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ } else {
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ }
+ }
+
+ set_w = pix->width;
+ set_h = pix->height;
+
+ if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[0].reg)
+ {
+ winseqe_set_addr = sensor_qcif;
+ set_w = 176;
+ set_h = 144;
+ }
+ else if (((set_w <= 320) && (set_h <= 240)) && sensor_qvga[0].reg)
+ {
+ winseqe_set_addr = sensor_qvga;
+ set_w = 320;
+ set_h = 240;
+ }
+ else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[0].reg)
+ {
+ winseqe_set_addr = sensor_cif;
+ set_w = 352;
+ set_h = 288;
+ }
+ else if (((set_w <= 640) && (set_h <= 480)) && sensor_vga[0].reg)
+ {
+ winseqe_set_addr = sensor_vga;
+ set_w = 640;
+ set_h = 480;
+ }
+ else if (((set_w <= 800) && (set_h <= 600)) && sensor_svga[0].reg)
+ {
+ winseqe_set_addr = sensor_svga;
+ set_w = 800;
+ set_h = 600;
+ }
+ else if (((set_w <= 1024) && (set_h <= 768)) && sensor_xga[0].reg)
+ {
+ winseqe_set_addr = sensor_xga;
+ set_w = 1024;
+ set_h = 768;
+ }
+ else if (((set_w <= 1280) && (set_h <= 1024)) && sensor_sxga[0].reg)
+ {
+ winseqe_set_addr = sensor_sxga;
+ set_w = 1280;
+ set_h = 1024;
+ }
+ else if (((set_w <= 1600) && (set_h <= 1200)) && sensor_uxga[0].reg)
+ {
+ winseqe_set_addr = sensor_uxga;
+ set_w = 1600;
+ set_h = 1200;
+ }
+ else
+ {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
+ ret = -1;
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
+ }
+
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ ret |= sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ }
+
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+ }
+ else
+ {
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ }
+
+ pix->width = set_w;
+ pix->height = set_h;
+
+sensor_s_fmt_end:
+ return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;
+
+ /*
+ * With Bayer format enforce even side lengths, but let the user play
+ * with the starting pixel
+ */
+
+ if (pix->height > SENSOR_MAX_HEIGHT)
+ pix->height = SENSOR_MAX_HEIGHT;
+ else if (pix->height < SENSOR_MIN_HEIGHT)
+ pix->height = SENSOR_MIN_HEIGHT;
+ else if (bayer)
+ pix->height = ALIGN(pix->height, 2);
+
+ if (pix->width > SENSOR_MAX_WIDTH)
+ pix->width = SENSOR_MAX_WIDTH;
+ else if (pix->width < SENSOR_MIN_WIDTH)
+ pix->width = SENSOR_MIN_WIDTH;
+ else if (bayer)
+ pix->width = ALIGN(pix->width, 2);
+
+ return 0;
+}
+
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+ struct i2c_client *client = sd->priv;
+
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match.addr != client->addr)
+ return -ENODEV;
+
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */
+ id->revision = 0;
+
+ return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ int digitalzoom_cur, digitalzoom_total;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl_info)
+ return -EINVAL;
+
+ digitalzoom_cur = sensor->info_priv.digitalzoom;
+ digitalzoom_total = qctrl_info->maximum;
+
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+ {
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+ {
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+ {
+ *value = digitalzoom_total - digitalzoom_cur;
+ }
+
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+ {
+ *value = 0 - digitalzoom_cur;
+ }
+
+ digitalzoom_cur += *value;
+
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+ case V4L2_CID_BRIGHTNESS:
+ {
+ ctrl->value = sensor->info_priv.brightness;
+ break;
+ }
+ case V4L2_CID_SATURATION:
+ {
+ ctrl->value = sensor->info_priv.saturation;
+ break;
+ }
+ case V4L2_CID_CONTRAST:
+ {
+ ctrl->value = sensor->info_priv.contrast;
+ break;
+ }
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ ctrl->value = sensor->info_priv.whiteBalance;
+ break;
+ }
+ case V4L2_CID_EXPOSURE:
+ {
+ ctrl->value = sensor->info_priv.exposure;
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ ctrl->value = sensor->info_priv.mirror;
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ ctrl->value = sensor->info_priv.flip;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+ const struct v4l2_queryctrl *qctrl;
+
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+#if CONFIG_SENSOR_Brightness
+ case V4L2_CID_BRIGHTNESS:
+ {
+ if (ctrl->value != sensor->info_priv.brightness)
+ {
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.brightness = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Exposure
+ case V4L2_CID_EXPOSURE:
+ {
+ if (ctrl->value != sensor->info_priv.exposure)
+ {
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.exposure = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Saturation
+ case V4L2_CID_SATURATION:
+ {
+ if (ctrl->value != sensor->info_priv.saturation)
+ {
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.saturation = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Contrast
+ case V4L2_CID_CONTRAST:
+ {
+ if (ctrl->value != sensor->info_priv.contrast)
+ {
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.contrast = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ if (ctrl->value != sensor->info_priv.whiteBalance)
+ {
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.whiteBalance = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Mirror
+ case V4L2_CID_HFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.mirror)
+ {
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.mirror = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flip
+ case V4L2_CID_VFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.flip)
+ {
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flip = ctrl->value;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ext_ctrl->id)
+ {
+ case V4L2_CID_SCENE:
+ {
+ ext_ctrl->value = sensor->info_priv.scene;
+ break;
+ }
+ case V4L2_CID_EFFECT:
+ {
+ ext_ctrl->value = sensor->info_priv.effect;
+ break;
+ }
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.digitalzoom;
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.focus;
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FLASH:
+ {
+ ext_ctrl->value = sensor->info_priv.flash;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int val_offset;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ val_offset = 0;
+ switch (ext_ctrl->id)
+ {
+#if CONFIG_SENSOR_Scene
+ case V4L2_CID_SCENE:
+ {
+ if (ext_ctrl->value != sensor->info_priv.scene)
+ {
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.scene = ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Effect
+ case V4L2_CID_EFFECT:
+ {
+ if (ext_ctrl->value != sensor->info_priv.effect)
+ {
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.effect= ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += val_offset;
+
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Focus
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.focus)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+ sensor->info_priv.focus += val_offset;
+ }
+
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ sensor->info_priv.focus += ext_ctrl->value;
+
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flash
+ case V4L2_CID_FLASH:
+ {
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flash = ext_ctrl->value;
+
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
+{
+ char value;
+ int ret,pid=0;
+ struct sensor *sensor = to_sensor(client);
+
+ /* We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant. */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ /* soft reset */
+ ret = sensor_write(client, 0xfe, 0x80);
+ if (ret != 0)
+ {
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+ return -ENODEV;
+ }
+ mdelay(5); //delay 5 microseconds
+
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x00, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ pid |= (value << 8);
+
+ ret = sensor_read(client, 0x01, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id low byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ pid |= (value & 0xff);
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ if (pid == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ icd->formats = sensor_colour_formats;
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
+
+ return 0;
+
+sensor_video_probe_err:
+
+ return ret;
+}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_ioctl_end:
+ return ret;
+
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+ .init = sensor_init,
+ .g_ctrl = sensor_g_control,
+ .s_ctrl = sensor_s_control,
+ .g_ext_ctrls = sensor_g_ext_controls,
+ .s_ext_ctrls = sensor_s_ext_controls,
+ .g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+ .s_fmt = sensor_s_fmt,
+ .g_fmt = sensor_g_fmt,
+ .try_fmt = sensor_try_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+ .core = &sensor_subdev_core_ops,
+ .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct sensor *sensor;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
+ int ret;
+
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+ return -EIO;
+ }
+
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd->ops = &sensor_ops;
+ icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
+
+ ret = sensor_video_probe(icd, client);
+ if (ret < 0) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(sensor);
+ sensor = NULL;
+ }
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+ return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
+ kfree(sensor);
+ sensor = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+ {SENSOR_NAME_STRING(), 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+ .driver = {
+ .name = SENSOR_NAME_STRING(),
+ },
+ .probe = sensor_probe,
+ .remove = sensor_remove,
+ .id_table = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+ return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+ i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("ddl <kernel@rock-chips>");
+MODULE_LICENSE("GPL");
+
+
--- /dev/null
+/*
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_HI253
+#define SENSOR_V4L2_IDENT V4L2_IDENT_HI253
+#define SENSOR_ID 0x92
+#define SENSOR_MIN_WIDTH 176
+#define SENSOR_MIN_HEIGHT 144
+#define SENSOR_MAX_WIDTH 1600
+#define SENSOR_MAX_HEIGHT 1200
+#define SENSOR_INIT_WIDTH 1600 /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT 1200
+#define SENSOR_INIT_WINSEQADR sensor_uxga
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY
+
+#define CONFIG_SENSOR_WhiteBalance 1
+#define CONFIG_SENSOR_Brightness 0
+#define CONFIG_SENSOR_Contrast 0
+#define CONFIG_SENSOR_Saturation 0
+#define CONFIG_SENSOR_Effect 1
+#define CONFIG_SENSOR_Scene 1
+#define CONFIG_SENSOR_DigitalZoom 0
+#define CONFIG_SENSOR_Focus 0
+#define CONFIG_SENSOR_Exposure 0
+#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Mirror 0
+#define CONFIG_SENSOR_Flip 0
+
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500
+#define COLOR_TEMPERATURE_OFFICE_DN 3500
+#define COLOR_TEMPERATURE_OFFICE_UP 5000
+#define COLOR_TEMPERATURE_HOME_DN 2500
+#define COLOR_TEMPERATURE_HOME_UP 3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+
+#define END_REG 0xff
+
+struct reginfo
+{
+ u8 reg;
+ u8 val;
+};
+
+/* init SVGA preview */
+static struct reginfo sensor_init_data[] =
+{
+// {0x01, 0xf9},
+ {0x08, 0x0f},
+ {0x01, 0xf8},
+
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+
+ {0x0e, 0x00},
+
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+
+ {0x0e, 0x00},
+ {0x01, 0xf1},
+ {0x08, 0x00},
+ {0x01, 0xf3},
+ {0x01, 0xf1},
+
+ {0x03, 0x20},
+ {0x10, 0x0c},
+ {0x03, 0x22},
+ {0x10, 0x69},
+
+ //Page 00
+ {0x03, 0x00},
+ {0x10, 0x00}, //lxh
+ {0x11, 0x90},
+ {0x12, 0x04},
+ {0x0b, 0xaa},
+ {0x0c, 0xaa},
+ {0x0d, 0xaa},
+ {0x20, 0x00},
+ {0x21, 0x0a}, //lxh
+ {0x22, 0x00},
+ {0x23, 0x0a}, //lxh
+ {0x24, 0x04},
+ {0x25, 0xb0},
+ {0x26, 0x06},
+ {0x27, 0x40},
+
+ {0x40, 0x01},
+ {0x41, 0x98},//lxh
+ {0x42, 0x00},
+ {0x43, 0x14},//lxh
+
+ {0x45, 0x04},
+ {0x46, 0x18},
+ {0x47, 0xd8},
+
+ {0xe1, 0x0f},
+
+ //BLC
+ {0x80, 0x2e},
+ {0x81, 0x7e},
+ {0x82, 0x90},
+ {0x83, 0x00},
+ {0x84, 0x0c},
+ {0x85, 0x00},
+ {0x90, 0x0c},
+ {0x91, 0x0c},
+ {0x92, 0x78},
+ {0x93, 0x70},
+ {0x94, 0x75},
+ {0x95, 0x70},
+ {0x96, 0xdc},
+ {0x97, 0xfe},
+ {0x98, 0x20},
+
+ //OutDoor BLC
+ {0x99,0x42},
+ {0x9a,0x42},
+ {0x9b,0x42},
+ {0x9c,0x42},
+
+ //Dark BLC
+ {0xa0, 0x00},
+ {0xa2, 0x00},
+ {0xa4, 0x00},
+ {0xa6, 0x00},
+
+ //Normal BLC
+ {0xa8, 0x43},
+ {0xaa, 0x43},
+ {0xac, 0x43},
+ {0xae, 0x43},
+
+ //Page 02
+ {0x03, 0x02},
+ {0x12, 0x03},
+ {0x13, 0x03},
+ {0x16, 0x00},
+ {0x17, 0x8C},
+ {0x18, 0x4c},
+ {0x19, 0x00},
+ {0x1a, 0x39},
+ {0x1c, 0x09},
+ {0x1d, 0x40},
+ {0x1e, 0x30},
+ {0x1f, 0x10},
+ {0x20, 0x77},
+ {0x21, 0xde},
+ {0x22, 0xa7},
+ {0x23, 0x30},
+ {0x27, 0x3c},
+ {0x2b, 0x80},
+ {0x2e, 0x00},
+ {0x2f, 0x00},
+ {0x30, 0x05},
+ {0x50, 0x20},
+ {0x52, 0x01},
+ {0x53, 0xc1},
+ {0x55, 0x1c},
+ {0x56, 0x11},
+ {0x5d, 0xA2},
+ {0x5e, 0x5a},
+ {0x60, 0x87},
+ {0x61, 0x99},
+ {0x62, 0x88},
+ {0x63, 0x97},
+ {0x64, 0x88},
+ {0x65, 0x97},
+ {0x67, 0x0c},
+ {0x68, 0x0c},
+ {0x69, 0x0c},
+ {0x72, 0x89},
+ {0x73, 0x96},
+ {0x74, 0x89},
+ {0x75, 0x96},
+ {0x76, 0x89},
+ {0x77, 0x96},
+ {0x7C, 0x85},
+ {0x7d, 0xaf},
+ {0x80, 0x01},
+ {0x81, 0x7f},
+ {0x82, 0x13},
+ {0x83, 0x24},
+ {0x84, 0x7d},
+ {0x85, 0x81},
+ {0x86, 0x7d},
+ {0x87, 0x81},
+ {0x92, 0x48},
+ {0x93, 0x54},
+ {0x94, 0x7d},
+ {0x95, 0x81},
+ {0x96, 0x7d},
+ {0x97, 0x81},
+ {0xa0, 0x02},
+ {0xa1, 0x7b},
+ {0xa2, 0x02},
+ {0xa3, 0x7b},
+ {0xa4, 0x7b},
+ {0xa5, 0x02},
+ {0xa6, 0x7b},
+ {0xa7, 0x02},
+ {0xa8, 0x85},
+ {0xa9, 0x8c},
+ {0xaa, 0x85},
+ {0xab, 0x8c},
+ {0xac, 0x10},
+ {0xad, 0x16},
+ {0xae, 0x10},
+ {0xaf, 0x16},
+ {0xb0, 0x99},
+ {0xb1, 0xa3},
+ {0xb2, 0xa4},
+ {0xb3, 0xae},
+ {0xb4, 0x9b},
+ {0xb5, 0xa2},
+ {0xb6, 0xa6},
+ {0xb7, 0xac},
+ {0xb8, 0x9b},
+ {0xb9, 0x9f},
+ {0xba, 0xa6},
+ {0xbb, 0xaa},
+ {0xbc, 0x9b},
+ {0xbd, 0x9f},
+ {0xbe, 0xa6},
+ {0xbf, 0xaa},
+ {0xc4, 0x2c},
+ {0xc5, 0x43},
+ {0xc6, 0x63},
+ {0xc7, 0x79},
+ {0xc8, 0x2d},
+ {0xc9, 0x42},
+ {0xca, 0x2d},
+ {0xcb, 0x42},
+ {0xcc, 0x64},
+ {0xcd, 0x78},
+ {0xce, 0x64},
+ {0xcf, 0x78},
+ {0xd0, 0x0a},
+ {0xd1, 0x09},
+ {0xd4, 0x0c},
+ {0xd5, 0x0c},
+ {0xd6, 0xd8},
+ {0xd7, 0xd0},//lxh
+ {0xe0, 0xc4},
+ {0xe1, 0xc4},
+ {0xe2, 0xc4},
+ {0xe3, 0xc4},
+ {0xe4, 0x00},
+ {0xe8, 0x80},
+ {0xe9, 0x40},
+ {0xea, 0x7f},
+ {0xf0, 0x01},
+ {0xf1, 0x01},
+ {0xf2, 0x01},
+ {0xf3, 0x01},
+ {0xf4, 0x01},
+
+ //PAGE10
+ {0x03, 0x10},
+ {0x10, 0x01}, //lxh
+ {0x11, 0x03}, //lxh,normal
+ {0x12, 0x00},
+ {0x13, 0x00},
+ {0x20, 0x00},
+
+ {0x40, 0x80},
+ {0x41, 0x00},
+ {0x48, 0x88},// 84
+ {0x50, 0x90},
+ {0x30, 0x00},
+ {0x31, 0x00},
+ {0x32, 0x00},
+ {0x33, 0x00},
+
+ {0x34, 0x30},
+ {0x35, 0x00},
+ {0x36, 0x00},
+ {0x38, 0x00},
+ {0x3e, 0x58},
+ {0x3f, 0x00},
+
+ //Saturation
+ {0x60, 0x6f},
+ {0x61, 0x95},// 74
+ {0x62, 0x95},// 76
+ {0x63, 0x30},
+ {0x64, 0x41},
+
+ {0x66, 0x33},
+ {0x67, 0x00},
+
+ {0x6a, 0x90},
+ {0x6b, 0x80},
+ {0x6c, 0x80},
+ {0x6d, 0xa0},
+
+ {0x76, 0x01},
+ {0x74, 0x66},
+ {0x79, 0x06},
+
+ //Page 11
+ {0x03, 0x11},
+ {0x10, 0x7f},//lxh,3f
+ {0x11, 0x40},
+ {0x12, 0xba},
+ {0x13, 0xcb},
+ {0x26, 0x20},
+ {0x27, 0x22},
+ {0x28, 0x0f},
+ {0x29, 0x10},
+ {0x2b, 0x30},
+ {0x2c, 0x32},
+
+ //Out2 D-LPF th
+ {0x30, 0x70},
+ {0x31, 0x10},
+ {0x32, 0x65},
+ {0x33, 0x09},
+ {0x34, 0x06},
+ {0x35, 0x04},
+
+ //Out1 D-LPF th
+ {0x36, 0x70},
+ {0x37, 0x18},
+ {0x38, 0x65},
+ {0x39, 0x09},
+ {0x3a, 0x06},
+ {0x3b, 0x04},
+
+ //Indoor D-LPF th
+ {0x3c, 0x80},
+ {0x3d, 0x18},
+ {0x3e, 0x80},
+ {0x3f, 0x0c},
+ {0x40, 0x09},
+ {0x41, 0x06},
+
+ {0x42, 0x80},
+ {0x43, 0x18},
+ {0x44, 0x80},
+ {0x45, 0x12},
+ {0x46, 0x10},
+ {0x47, 0x10},
+ {0x48, 0x90},
+ {0x49, 0x40},
+ {0x4a, 0x80},
+ {0x4b, 0x13},
+ {0x4c, 0x10},
+ {0x4d, 0x11},
+ {0x4e, 0x80},
+ {0x4f, 0x30},
+ {0x50, 0x80},
+ {0x51, 0x13},
+ {0x52, 0x10},
+ {0x53, 0x13},
+ {0x54, 0x11},
+ {0x55, 0x17},
+ {0x56, 0x20},
+ {0x57, 0x20},
+ {0x58, 0x20},
+ {0x59, 0x30},
+ {0x5a, 0x18},
+ {0x5b, 0x00},
+ {0x5c, 0x00},
+ {0x60, 0x3f},
+ {0x62, 0x50},
+ {0x70, 0x06},
+
+ //Page 12
+ {0x03, 0x12},
+ {0x20, 0x0f},
+ {0x21, 0x0f},
+ {0x25, 0x30},
+ {0x28, 0x00},
+ {0x29, 0x00},
+ {0x2a, 0x00},
+ {0x30, 0x50},
+ {0x31, 0x18},
+ {0x32, 0x32},
+ {0x33, 0x40},
+ {0x34, 0x50},
+ {0x35, 0x70},
+ {0x36, 0xa0},
+
+ //Out2 th
+ {0x40, 0xa0},
+ {0x41, 0x40},
+ {0x42, 0xa0},
+ {0x43, 0x90},
+ {0x44, 0x90},
+ {0x45, 0x80},
+
+ //Out1 th
+ {0x46, 0xb0},
+ {0x47, 0x55},
+ {0x48, 0xa0},
+ {0x49, 0x90},
+ {0x4a, 0x90},
+ {0x4b, 0x80},
+
+ //In door th
+ {0x4c, 0xb0},
+ {0x4d, 0x40},
+ {0x4e, 0x90},
+ {0x4f, 0x90},
+ {0x50, 0xe6},
+ {0x51, 0x80},
+
+ //Dark1 th
+ {0x52, 0xb0},
+ {0x53, 0x60},
+ {0x54, 0xc0},
+ {0x55, 0xc0},
+ {0x56, 0xc0},
+ {0x57, 0x80},
+
+ //Dark2 th
+ {0x58, 0x90},
+ {0x59, 0x40},
+ {0x5a, 0xd0},
+ {0x5b, 0xd0},
+ {0x5c, 0xe0},
+ {0x5d, 0x80},
+
+ //Dark3 th
+ {0x5e, 0x88},
+ {0x5f, 0x40},
+ {0x60, 0xe0},
+ {0x61, 0xe6},
+ {0x62, 0xe6},
+ {0x63, 0x80},
+
+ {0x70, 0x15},
+ {0x71, 0x01},
+
+ {0x72, 0x18},
+ {0x73, 0x01},
+
+ {0x74, 0x25},
+ {0x75, 0x15},
+ {0x80, 0x30},
+ {0x81, 0x50},
+ {0x82, 0x80},
+ {0x85, 0x1a},
+ {0x88, 0x00},
+ {0x89, 0x00},
+ {0x90, 0x5d},
+
+ {0xc5, 0x30},
+ {0xc6, 0x2a},
+
+ {0xD0, 0x0c},
+ {0xD1, 0x80},
+ {0xD2, 0x67},
+ {0xD3, 0x00},
+ {0xD4, 0x00},
+ {0xD5, 0x02},
+ {0xD6, 0xff},
+ {0xD7, 0x18},
+ {0x3b, 0x06},
+ {0x3c, 0x06},
+
+ {0xc5, 0x30},
+ {0xc6, 0x2a},
+
+ //Page 13
+ {0x03, 0x13},
+ {0x10, 0xcb},
+ {0x11, 0x7b},
+ {0x12, 0x07},
+ {0x14, 0x00},
+
+ {0x20, 0x15},
+ {0x21, 0x13},
+ {0x22, 0x33},
+ {0x23, 0x04},
+ {0x24, 0x09},
+ {0x25, 0x08},
+ {0x26, 0x18},
+ {0x27, 0x30},
+ {0x29, 0x12},
+ {0x2a, 0x50},
+
+ //Low clip th
+ {0x2b, 0x06},
+ {0x2c, 0x06},
+ {0x25, 0x08},
+ {0x2d, 0x0c},
+ {0x2e, 0x12},
+ {0x2f, 0x12},
+
+ //Out2 Edge
+ {0x50, 0x10},
+ {0x51, 0x14},
+ {0x52, 0x10},
+ {0x53, 0x0c},
+ {0x54, 0x0f},
+ {0x55, 0x0c},
+
+ //Out1 Edge
+ {0x56, 0x10},
+ {0x57, 0x13},
+ {0x58, 0x10},
+ {0x59, 0x0c},
+ {0x5a, 0x0f},
+ {0x5b, 0x0c},
+
+ //Indoor Edge
+ {0x5c, 0x0a},
+ {0x5d, 0x0b},
+ {0x5e, 0x0a},
+ {0x5f, 0x08},
+ {0x60, 0x09},
+ {0x61, 0x08},
+
+ //Dark1 Edge
+ {0x62, 0x08},
+ {0x63, 0x08},
+ {0x64, 0x08},
+ {0x65, 0x06},
+ {0x66, 0x06},
+ {0x67, 0x06},
+
+ //Dark2 Edge
+ {0x68, 0x07},
+ {0x69, 0x07},
+ {0x6a, 0x07},
+ {0x6b, 0x05},
+ {0x6c, 0x05},
+ {0x6d, 0x05},
+
+ //Dark3 Edge
+ {0x6e, 0x07},
+ {0x6f, 0x07},
+ {0x70, 0x07},
+ {0x71, 0x05},
+ {0x72, 0x05},
+ {0x73, 0x05},
+
+ //2DY
+ {0x80, 0xfd},
+ {0x81, 0x1f},
+ {0x82, 0x05},
+ {0x83, 0x01},
+
+ {0x90, 0x15},
+ {0x91, 0x15},
+ {0x92, 0x33},
+ {0x93, 0x30},
+ {0x94, 0x03},
+ {0x95, 0x14},
+ {0x97, 0x30},
+ {0x99, 0x30},
+
+ {0xa0, 0x04},
+ {0xa1, 0x05},
+ {0xa2, 0x04},
+ {0xa3, 0x05},
+ {0xa4, 0x07},
+ {0xa5, 0x08},
+ {0xa6, 0x07},
+ {0xa7, 0x08},
+ {0xa8, 0x07},
+ {0xa9, 0x08},
+ {0xaa, 0x07},
+ {0xab, 0x08},
+
+ //Out2
+ {0xb0, 0x22},
+ {0xb1, 0x2a},
+ {0xb2, 0x28},
+ {0xb3, 0x22},
+ {0xb4, 0x2a},
+ {0xb5, 0x28},
+
+ //Out1
+ {0xb6, 0x22},
+ {0xb7, 0x2a},
+ {0xb8, 0x28},
+ {0xb9, 0x22},
+ {0xba, 0x2a},
+ {0xbb, 0x28},
+
+ {0xbc, 0x17},
+ {0xbd, 0x17},
+ {0xbe, 0x17},
+ {0xbf, 0x17},
+ {0xc0, 0x17},
+ {0xc1, 0x17},
+
+ //Dark1
+ {0xc2, 0x1e},
+ {0xc3, 0x12},
+ {0xc4, 0x10},
+ {0xc5, 0x1e},
+ {0xc6, 0x12},
+ {0xc7, 0x10},
+
+ //Dark2
+ {0xc8, 0x18},
+ {0xc9, 0x05},
+ {0xca, 0x05},
+ {0xcb, 0x18},
+ {0xcc, 0x05},
+ {0xcd, 0x05},
+
+ //Dark3
+ {0xce, 0x18},
+ {0xcf, 0x05},
+ {0xd0, 0x05},
+ {0xd1, 0x18},
+ {0xd2, 0x05},
+ {0xd3, 0x05},
+
+ //Page 14
+ {0x03, 0x14},
+ {0x10, 0x11},
+ {0x20, 0x40},
+ {0x21, 0x80},
+ {0x23, 0x80},
+ {0x22, 0x80},
+ {0x23, 0x80},
+ {0x24, 0x80},
+
+ {0x30, 0xc8},
+ {0x31, 0x2b},
+ {0x32, 0x00},
+ {0x33, 0x00},
+ {0x34, 0x90},
+
+ {0x40, 0x42},
+ {0x50, 0x2d},
+ {0x60, 0x28},
+ {0x70, 0x2d},
+
+ //Page 15
+ {0x03, 0x15},
+ {0x10, 0x0f},
+ {0x14, 0x52},
+ {0x15, 0x42},
+ {0x16, 0x32},
+ {0x17, 0x2f},
+
+ //CMC
+ {0x30, 0x8f},
+ {0x31, 0x59},
+ {0x32, 0x0a},
+ {0x33, 0x15},
+ {0x34, 0x5b},
+ {0x35, 0x06},
+ {0x36, 0x07},
+ {0x37, 0x40},
+ {0x38, 0x86},
+
+ //CMC OFS
+ {0x40, 0x95},
+ {0x41, 0x1f},
+ {0x42, 0x8a},
+ {0x43, 0x86},
+ {0x44, 0x0a},
+ {0x45, 0x84},
+ {0x46, 0x87},
+ {0x47, 0x9b},
+ {0x48, 0x23},
+
+ //CMC POFS
+ {0x50, 0x8c},
+ {0x51, 0x0c},
+ {0x52, 0x00},
+ {0x53, 0x07},
+ {0x54, 0x17},
+ {0x55, 0x9d},
+ {0x56, 0x00},
+ {0x57, 0x0b},
+ {0x58, 0x89},
+
+ {0x80, 0x03},
+ {0x85, 0x40},
+ {0x87, 0x02},
+ {0x88, 0x00},
+ {0x89, 0x00},
+ {0x8a, 0x00},
+
+ {0x03, 0x16},
+ {0x10, 0x31},
+ {0x18, 0x37},
+ {0x19, 0x36},
+ {0x1a, 0x0e},
+ {0x1b, 0x01},
+ {0x1c, 0xdc},
+ {0x1d, 0xfe},
+/* original
+ {0x30, 0x00},
+ {0x31, 0x06},
+ {0x32, 0x1d},
+ {0x33, 0x33},
+ {0x34, 0x53},
+ {0x35, 0x6c},
+ {0x36, 0x81},
+ {0x37, 0x94},
+ {0x38, 0xa4},
+ {0x39, 0xb3},
+ {0x3a, 0xc0},
+ {0x3b, 0xcb},
+ {0x3c, 0xd5},
+ {0x3d, 0xde},
+ {0x3e, 0xe6},
+ {0x3f, 0xee},
+ {0x40, 0xf5},
+ {0x41, 0xfc},
+ {0x42, 0xff},
+
+ {0x50, 0x00},
+ {0x51, 0x03},
+ {0x52, 0x19},
+ {0x53, 0x34},
+ {0x54, 0x58},
+ {0x55, 0x75},
+ {0x56, 0x8d},
+ {0x57, 0xa1},
+ {0x58, 0xb2},
+ {0x59, 0xbe},
+ {0x5a, 0xc9},
+ {0x5b, 0xd2},
+ {0x5c, 0xdb},
+ {0x5d, 0xe3},
+ {0x5e, 0xeb},
+ {0x5f, 0xf0},
+ {0x60, 0xf5},
+ {0x61, 0xf7},
+ {0x62, 0xf8},
+
+ {0x70, 0x00},
+ {0x71, 0x08},
+ {0x72, 0x17},
+ {0x73, 0x2f},
+ {0x74, 0x53},
+ {0x75, 0x6c},
+ {0x76, 0x81},
+ {0x77, 0x94},
+ {0x78, 0xa4},
+ {0x79, 0xb3},
+ {0x7a, 0xc0},
+ {0x7b, 0xcb},
+ {0x7c, 0xd5},
+ {0x7d, 0xde},
+ {0x7e, 0xe6},
+ {0x7f, 0xee},
+ {0x80, 0xf4},
+ {0x81, 0xfa},
+ {0x82, 0xff},
+*/
+ {0x30, 0x00},
+ {0x31, 0x08},
+ {0x32, 0x1f},
+ {0x33, 0x35},
+ {0x34, 0x55},
+ {0x35, 0x6e},
+ {0x36, 0x83},
+ {0x37, 0x96},
+ {0x38, 0xa6},
+ {0x39, 0xb5},
+ {0x3a, 0xc2},
+ {0x3b, 0xcd},
+ {0x3c, 0xd7},
+ {0x3d, 0xe0},
+ {0x3e, 0xe8},
+ {0x3f, 0xf0},
+ {0x40, 0xf7},
+ {0x41, 0xfe},
+ {0x42, 0xff},
+
+ {0x50, 0x00},
+ {0x51, 0x05},
+ {0x52, 0x1b},
+ {0x53, 0x36},
+ {0x54, 0x5a},
+ {0x55, 0x77},
+ {0x56, 0x8f},
+ {0x57, 0xa3},
+ {0x58, 0xb4},
+ {0x59, 0xc0},
+ {0x5a, 0xcb},
+ {0x5b, 0xd4},
+ {0x5c, 0xde},
+ {0x5d, 0xe5},
+ {0x5e, 0xed},
+ {0x5f, 0xf2},
+ {0x60, 0xf7},
+ {0x61, 0xf9},
+ {0x62, 0xfa},
+
+ {0x70, 0x00},
+ {0x71, 0x0a},
+ {0x72, 0x19},
+ {0x73, 0x31},
+ {0x74, 0x55},
+ {0x75, 0x6e},
+ {0x76, 0x83},
+ {0x77, 0x96},
+ {0x78, 0xa6},
+ {0x79, 0xb5},
+ {0x7a, 0xc2},
+ {0x7b, 0xcd},
+ {0x7c, 0xd7},
+ {0x7d, 0xe0},
+ {0x7e, 0xe8},
+ {0x7f, 0xf0},
+ {0x80, 0xf6},
+ {0x81, 0xfc},
+ {0x82, 0xff},
+
+
+ {0x03, 0x17},
+ {0xc4, 0x6e},
+ {0xc5, 0x5c},
+
+ {0x03, 0x20},
+ {0x10, 0x1c},
+ {0x18, 0x38},
+ {0x20, 0x01},
+ {0x21, 0x30},
+ {0x22, 0x10},
+ {0x23, 0x00},
+ {0x24, 0x04},
+
+ {0x28, 0xff},
+ {0x29, 0xad},
+
+ {0x2a, 0xf0},
+ {0x2b, 0x34},
+ {0x30, 0x78},
+ {0x2c, 0xc3},
+ {0x2d, 0x5f},
+ {0x2e, 0x33},
+ //{0x30, 0xf8},
+ {0x32, 0x03},
+ {0x33, 0x2e},
+ {0x34, 0x30},
+ {0x35, 0xd4},
+ {0x36, 0xfe},
+ {0x37, 0x32},
+ {0x38, 0x04},
+ {0x47, 0xf0},
+
+ //Y_Frame TH
+ {0x50, 0x45},
+ {0x51, 0x88},
+
+ {0x56, 0x10},
+ {0x57, 0xb7},
+ {0x58, 0x14},
+ {0x59, 0x88},
+ {0x5a, 0x04},
+
+ {0x60, 0x55},
+ {0x61, 0x55},
+ {0x62, 0x6a},
+ {0x63, 0xa9},
+ {0x64, 0x6a},
+ {0x65, 0xa9},
+ {0x66, 0x6a},
+ {0x67, 0xa9},
+ {0x68, 0x6b},
+ {0x69, 0xe9},
+ {0x6a, 0x6a},
+ {0x6b, 0xa9},
+ {0x6c, 0x6a},
+ {0x6d, 0xa9},
+ {0x6e, 0x55},
+ {0x6f, 0x55},
+ {0x70, 0x42},
+ {0x71, 0xBb},
+
+ // haunting control
+ {0x76, 0x21},
+ {0x77, 0x02},
+ {0x78, 0x22},
+ {0x79, 0x2a},
+
+ {0x78, 0x24},
+ {0x79, 0x23},
+ {0x7a, 0x23},
+ {0x7b, 0x22},
+ {0x7d, 0x23},
+ {0x83, 0x01},
+ {0x84, 0x5f},
+ {0x85, 0x6c},
+ {0x86, 0x02},
+ {0x87, 0x00},
+ {0x88, 0x05},
+ {0x89, 0x7c},
+ {0x8a, 0x00},
+ {0x8B, 0x75},
+ {0x8C, 0x00},
+ {0x8D, 0x61},
+ {0x8E, 0x00},
+
+ {0x98, 0xdc},
+ {0x99, 0x45},
+ {0x9a, 0x0d},
+ {0x9b, 0xde},
+ {0x9c, 0x08},
+ {0x9d, 0x0a},
+ {0x9e, 0x01},
+ {0x10, 0x9c},
+ {0x18, 0x30},
+ {0x90, 0x0c},
+ {0x91, 0x0c},
+ {0x92, 0xd8},
+ {0x93, 0xd0},
+
+ {0x9f, 0x26},
+ {0xa0, 0x03},
+ {0xa1, 0xa9},
+ {0xa2, 0x80},
+ {0xb0, 0x1d},
+ {0xb1, 0x1a},
+ {0xb2, 0x60},
+ {0xb3, 0x1a},
+ {0xb4, 0x1a},
+ {0xb5, 0x44},
+ {0xb6, 0x2f},
+ {0xb7, 0x28},
+ {0xb8, 0x25},
+ {0xb9, 0x22},
+ {0xba, 0x21},
+ {0xbb, 0x20},
+ {0xbc, 0x1f},
+ {0xbd, 0x1f},
+ {0xc0, 0x30},
+ {0xc1, 0x20},
+ {0xc2, 0x20},
+ {0xc3, 0x20},
+ {0xc4, 0x08},
+ {0xc8, 0x60},
+ {0xc9, 0x40},
+
+ //Page 22
+ {0x03, 0x22},
+ {0x10, 0x69},//lxh
+ {0x11, 0x2c},
+ {0x19, 0x01},
+ {0x20, 0x30},
+ {0x21, 0x80},
+ {0x23, 0x08},
+ {0x24, 0x01},
+
+ {0x30, 0x80},
+ {0x31, 0x80},
+ {0x38, 0x11},
+ {0x39, 0x34},
+ {0x40, 0xf7},
+
+ {0x41, 0x77},
+ {0x42, 0x55},
+ {0x43, 0xf0},
+ {0x44, 0x43},
+ {0x45, 0x33},
+ {0x46, 0x00},
+
+ {0x47, 0x94},
+
+ {0x50, 0xb2},
+ {0x51, 0x81},
+ {0x52, 0x98},
+
+ {0x80, 0x3d},//lxh
+ {0x81, 0x20},
+ {0x82, 0x32},//lxh
+
+ {0x83, 0x50},
+ {0x84, 0x20},
+ {0x85, 0x50},
+ {0x86, 0x20},
+
+ {0x87, 0x54},
+ {0x88, 0x20},
+ {0x89, 0x45},
+ {0x8a, 0x2a},
+
+ {0x8b, 0x46},
+ {0x8c, 0x3f},
+ {0x8d, 0x34},
+ {0x8e, 0x2c},
+
+ {0x8f, 0x60},
+ {0x90, 0x5f},
+ {0x91, 0x5c},
+ {0x92, 0x4C},
+ {0x93, 0x41},
+ {0x94, 0x3b},
+ {0x95, 0x36},
+ {0x96, 0x30},
+ {0x97, 0x27},
+ {0x98, 0x20},
+ {0x99, 0x1C},
+ {0x9a, 0x19},
+
+ {0x9b, 0x88},
+ {0x9c, 0x88},
+ {0x9d, 0x48},
+ {0x9e, 0x38},
+ {0x9f, 0x30},
+
+ {0xa0, 0x74},
+ {0xa1, 0x35},
+ {0xa2, 0xaf},
+ {0xa3, 0xf7},
+
+ {0xa4, 0x10},
+ {0xa5, 0x50},
+ {0xa6, 0xc4},
+
+ {0xad, 0x40},
+ {0xae, 0x4a},
+
+ {0xaf, 0x2a},
+ {0xb0, 0x29},
+
+ {0xb1, 0x20},
+ {0xb4, 0xff},
+ {0xb8, 0x6b},
+ {0xb9, 0x00},
+
+ {0x03, 0x24},
+ {0x10, 0x01},
+ {0x18, 0x06},
+ {0x30, 0x06},
+ {0x31, 0x90},
+ {0x32, 0x25},
+ {0x33, 0xa2},
+ {0x34, 0x26},
+ {0x35, 0x58},
+ {0x36, 0x60},
+ {0x37, 0x00},
+ {0x38, 0x50},
+ {0x39, 0x00},
+
+ {0x03, 0x20},
+ {0x10, 0x9c},
+ {0x03, 0x22},
+ {0x10, 0xe9},
+
+ //Page 00
+ {0x03, 0x00},
+ {0x0e, 0x03},
+ {0x0e, 0x73},
+
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+ {0x03, 0x00},
+
+ {0x03, 0x00},
+ {0x01, 0xf8},
+
+ {END_REG, END_REG},
+
+};
+
+
+/* 1600X1200 UXGA capture */
+static struct reginfo sensor_uxga[] =
+{
+ {0x03, 0x00},
+ //{0x11, 0xa0},
+
+ {0x20, 0x00},
+ {0x21, 0x0a},
+ {0x22, 0x00},
+ {0x23, 0x0a},
+
+ {0x03, 0x10},
+ {0x3f, 0x00},
+
+ //Page12
+ {0x03, 0x12},
+ {0x20, 0x0f},
+ {0x21, 0x0f},
+ {0x90, 0x5d},
+
+ //Page13
+ {0x03, 0x13},
+ {0x80, 0xfd},
+
+ // 1600*1200
+ {0x03,0x00},
+ {0x10,0x00},
+
+ {END_REG, END_REG},
+};
+
+/* 1280X1024 SXGA */
+static struct reginfo sensor_sxga[] =
+{
+ {END_REG, END_REG},
+};
+static struct reginfo sensor_xga[] =
+{
+ {0x01, 0xf8},
+ {END_REG, END_REG},
+};
+/* 800X600 SVGA,30fps*/
+static struct reginfo sensor_svga[] =
+{
+#if 1
+ {0x03, 0x10},
+ {0x3f, 0x00},
+
+
+ //Page12
+ {0x03, 0x12}, //Function
+ {0x20, 0x0f},
+ {0x21, 0x0f},
+ {0x90, 0x5d},
+
+ //Page13
+ {0x03, 0x13}, //Function
+ {0x80, 0xfd}, //Function
+
+ // 800*600
+ {0x03,0x00},
+ {0x10,0x91},//11
+ {0x20, 0x00},
+ {0x21, 0x04},
+ {0x22, 0x00},
+ {0x23, 0x07},
+ {0x24, 0x04},
+ {0x25, 0xb0},
+ {0x26, 0x06},
+ {0x27, 0x40},
+
+ {0x03, 0x20},
+ {0x8b, 0x1d},
+ {0x8c, 0x4c},
+ {0x8d, 0x18},
+ {0x8e, 0x6a},
+
+ {0x03, 0x20},
+ {0x03, 0x20},
+#endif
+ {END_REG, END_REG},
+};
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+ {END_REG, END_REG},
+};
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{};
+
+/* 320*240 QVGA */
+static struct reginfo sensor_qvga[] =
+{};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{};
+
+
+static struct reginfo sensor_ClrFmt_YUYV[]=
+{
+
+ {0x00, 0x00}
+};
+
+static struct reginfo sensor_ClrFmt_UYVY[]=
+{
+
+ {0x00, 0x00}
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static struct reginfo sensor_WhiteB_Auto[]=
+{
+ {0x03, 0x22},
+ {0x10, 0x69},
+ {0x80, 0x3d},
+ {0x81, 0x20},
+ {0x82, 0x32},
+ {0x83, 0x50},
+ {0x84, 0x20},
+ {0x85, 0x50},
+ {0x86, 0x20},
+ {0x10, 0xe9},
+ {END_REG, END_REG},
+};
+/* Cloudy Colour Temperature : 6500K - 8000K */
+static struct reginfo sensor_WhiteB_Cloudy[]=
+{
+ {0x03, 0x22},
+ {0x10, 0x69},
+ {0x80, 0x49},
+ {0x81, 0x20},
+ {0x82, 0x24},
+ {0x83, 0x50},
+ {0x84, 0x45},
+ {0x85, 0x24},
+ {0x86, 0x1e},
+ {0x10, 0xe9},
+ {END_REG, END_REG},
+};
+/* ClearDay Colour Temperature : 5000K - 6500K */
+static struct reginfo sensor_WhiteB_ClearDay[]=
+{
+ //Sunny
+ {0x03, 0x22},
+ {0x10, 0x69},
+ {0x80, 0x45},
+ {0x81, 0x20},
+ {0x82, 0x27},
+ {0x83, 0x44},
+ {0x84, 0x3f},
+ {0x85, 0x29},
+ {0x86, 0x23},
+ {END_REG, END_REG},
+};
+/* Office Colour Temperature : 3500K - 5000K */
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+ //incandescense
+ {0x03, 0x22},
+ {0x10, 0x69},
+ {0x80, 0x33},
+ {0x81, 0x20},
+ {0x82, 0x3d},
+ {0x83, 0x2e},
+ {0x84, 0x24},
+ {0x85, 0x43},
+ {0x86, 0x3d},
+ {END_REG, END_REG},
+
+};
+/* Home Colour Temperature : 2500K - 3500K */
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+ //Home
+ {0x03, 0x22},
+ {0x10, 0x69},
+ {0x80, 0x45},
+ {0x81, 0x20},
+ {0x82, 0x2f},
+ {0x83, 0x38},
+ {0x84, 0x32},
+ {0x85, 0x39},
+ {0x86, 0x33},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static struct reginfo sensor_Brightness0[]=
+{
+ // Brightness -2
+ {0x03, 0x10},
+ {0x40, 0xa0},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness1[]=
+{
+ // Brightness -1
+ {0x03, 0x10},
+ {0x40, 0x90},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness2[]=
+{
+ // Brightness 0
+ {0x03, 0x10},
+ {0x40, 0x00},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness3[]=
+{
+ // Brightness +1
+ {0x03, 0x10},
+ {0x40, 0x10},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness4[]=
+{
+ // Brightness +2
+ {0x03, 0x10},
+ {0x40, 0x20},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness5[]=
+{
+ // Brightness +3
+ {0x03, 0x10},
+ {0x40, 0x30},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+ sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static struct reginfo sensor_Effect_Normal[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x00},
+ {0x13, 0x00},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_WandB[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x03},
+ {0x13, 0x02},
+ {0x44, 0x80},
+ {0x45, 0x80},
+ {0x47, 0x7f},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Sepia[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x23},
+ {0x13, 0x00},
+ {0x44, 0x70},
+ {0x45, 0x98},
+ {0x47, 0x7f},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Negative[] =
+{
+ //Negative
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x08},
+ {0x13, 0x02},
+ {0x14, 0x00},
+ {0x44, 0x80},
+ {0x45, 0x80},
+ {0x47, 0x7f},
+ {END_REG, END_REG},
+};
+static struct reginfo sensor_Effect_Bluish[] =
+{
+ // Bluish
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x03},
+ {0x13, 0x02},
+ {0x44, 0xb0},
+ {0x45, 0x40},
+ {0x47, 0x7f},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Green[] =
+{
+ // Greenish
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x03},
+ {0x13, 0x02},
+ {0x44, 0x30},
+ {0x45, 0x50},
+ {0x47, 0x7f},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static struct reginfo sensor_Exposure0[]=
+{
+ //-3
+
+};
+
+static struct reginfo sensor_Exposure1[]=
+{
+ //-2
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure2[]=
+{
+ //-0.3EV
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure3[]=
+{
+ //default
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure4[]=
+{
+ // 1
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure5[]=
+{
+ // 2
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure6[]=
+{
+ // 3
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static struct reginfo sensor_Saturation0[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Saturation1[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Saturation2[]=
+{
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static struct reginfo sensor_Contrast0[]=
+{
+ //Contrast -3
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast1[]=
+{
+ //Contrast -2
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast2[]=
+{
+ // Contrast -1
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast3[]=
+{
+ //Contrast 0
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast4[]=
+{
+ //Contrast +1
+
+ {END_REG, END_REG},
+};
+
+
+static struct reginfo sensor_Contrast5[]=
+{
+ //Contrast +2
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast6[]=
+{
+ //Contrast +3
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static struct reginfo sensor_MirrorOn[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_MirrorOff[]=
+{
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static struct reginfo sensor_FlipOn[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_FlipOff[]=
+{
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static struct reginfo sensor_SceneAuto[] =
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_SceneNight[] =
+{
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+ {END_REG, END_REG},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},
+ #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White Balance Control",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Brightness
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness Control",
+ .minimum = -3,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ {
+ .id = V4L2_CID_EFFECT,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Effect Control",
+ .minimum = 0,
+ .maximum = 5,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Exposure
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Control",
+ .minimum = 0,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Saturation
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation Control",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Contrast
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast Control",
+ .minimum = -3,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Mirror
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flip
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ {
+ .id = V4L2_CID_SCENE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Scene Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_DigitalZoom
+ {
+ .id = V4L2_CID_ZOOM_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_ZOOM_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Focus
+ {
+ .id = V4L2_CID_FOCUS_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_FOCUS_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 125,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ {
+ .id = V4L2_CID_FLASH,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Flash Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+ .suspend = sensor_suspend,
+ .resume = sensor_resume,
+ .set_bus_param = sensor_set_bus_param,
+ .query_bus_param = sensor_query_bus_param,
+ .controls = sensor_controls,
+ .menus = sensor_menus,
+ .num_controls = ARRAY_SIZE(sensor_controls),
+ .num_menus = ARRAY_SIZE(sensor_menus),
+};
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+
+#define JPG_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+
+static const struct soc_camera_data_format sensor_colour_formats[] = {
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
+};
+
+typedef struct sensor_info_priv_s
+{
+ int whiteBalance;
+ int brightness;
+ int contrast;
+ int saturation;
+ int effect;
+ int scene;
+ int digitalzoom;
+ int focus;
+ int flash;
+ int exposure;
+ bool snap2preview;
+ bool video2preview;
+ unsigned char mirror; /* HFLIP */
+ unsigned char flip; /* VFLIP */
+ unsigned int winseqe_cur_addr;
+ unsigned int pixfmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+ struct v4l2_subdev subdev;
+ struct i2c_client *client;
+ sensor_info_priv_t info_priv;
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+ return 0;
+sensor_task_lock_err:
+ return -1;
+#else
+ return 0;
+#endif
+}
+
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err,cnt;
+ u8 buf[2];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+ buf[1] = val;
+
+ msg->addr = client->addr;
+ msg->flags = client->flags;
+ msg->buf = buf;
+ msg->len = sizeof(buf);
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ return 0;
+ } else {
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int err,cnt;
+ u8 buf[1];
+ struct i2c_msg msg[2];
+
+ buf[0] = reg ;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].buf = buf;
+ msg[0].len = sizeof(buf);
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags|I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = 1;
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err >= 0) {
+ *val = buf[0];
+ return 0;
+ } else {
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+
+/* write a array of registers */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int err = 0, cnt;
+ int i = 0;
+#if CONFIG_SENSOR_I2C_RDWRCHK
+ char valchk;
+#endif
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
+ while (regarray[i].reg != END_REG)
+ {
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);
+ if (err < 0)
+ {
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ //mdelay(5);
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
+ }
+ i++;
+ }
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+ char value;
+ int ret;
+
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ /* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
+#if 1
+ ret = sensor_write(client, 0x01, 0xF9);
+ if (ret != 0)
+ {
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ mdelay(5); //delay 5 microseconds
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x04, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+#endif
+ ret = sensor_write_array(client, sensor_init_data);
+ if (ret != 0)
+ {
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+ goto sensor_INIT_ERR;
+ }
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
+
+ /* sensor sensor information for initialization */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ if (qctrl)
+ sensor->info_priv.whiteBalance = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+ if (qctrl)
+ sensor->info_priv.brightness = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ if (qctrl)
+ sensor->info_priv.effect = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+ if (qctrl)
+ sensor->info_priv.exposure = qctrl->default_value;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+ if (qctrl)
+ sensor->info_priv.saturation = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+ if (qctrl)
+ sensor->info_priv.contrast = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+ if (qctrl)
+ sensor->info_priv.mirror = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+ if (qctrl)
+ sensor->info_priv.flip = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+ if (qctrl)
+ sensor->info_priv.scene = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.digitalzoom = qctrl->default_value;
+
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
+ #if CONFIG_SENSOR_Focus
+ sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.focus = qctrl->default_value;
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+ if (qctrl)
+ sensor->info_priv.flash = qctrl->default_value;
+ #endif
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+ return 0;
+sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
+ return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
+
+static struct reginfo sensor_power_down_sequence[]=
+{
+ {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;
+ if (ret != 0) {
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+ return ret;
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ }
+ } else {
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+ return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+
+ return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ unsigned long flags = SENSOR_BUS_PARAM;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = icd->user_width;
+ pix->height = icd->user_height;
+ pix->pixelformat = sensor->info_priv.pixfmt;
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct reginfo *winseqe_set_addr=NULL;
+ int ret=0, set_w,set_h;
+
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {
+ switch (pix->pixelformat)
+ {
+ case V4L2_PIX_FMT_YUYV:
+ {
+ winseqe_set_addr = sensor_ClrFmt_YUYV;
+ break;
+ }
+ case V4L2_PIX_FMT_UYVY:
+ {
+ winseqe_set_addr = sensor_ClrFmt_UYVY;
+ break;
+ }
+ default:
+ break;
+ }
+ if (winseqe_set_addr != NULL) {
+ sensor_write_array(client, winseqe_set_addr);
+ sensor->info_priv.pixfmt = pix->pixelformat;
+
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ } else {
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ }
+ }
+
+ set_w = pix->width;
+ set_h = pix->height;
+
+ if (((set_w <= 176) && (set_h <= 144)) && (sensor_qcif[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_qcif;
+ set_w = 176;
+ set_h = 144;
+ }
+ else if (((set_w <= 320) && (set_h <= 240)) && (sensor_qvga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_qvga;
+ set_w = 320;
+ set_h = 240;
+ }
+ else if (((set_w <= 352) && (set_h<= 288)) && (sensor_cif[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_cif;
+ set_w = 352;
+ set_h = 288;
+ }
+ else if (((set_w <= 640) && (set_h <= 480)) && (sensor_vga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_vga;
+ set_w = 640;
+ set_h = 480;
+ }
+ else if (((set_w <= 800) && (set_h <= 600)) && (sensor_svga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_svga;
+ set_w = 800;
+ set_h = 600;
+ }
+ else if (((set_w <= 1024) && (set_h <= 768)) && (sensor_xga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_xga;
+ set_w = 1024;
+ set_h = 768;
+ }
+ else if (((set_w <= 1280) && (set_h <= 1024)) && (sensor_sxga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_sxga;
+ set_w = 1280;
+ set_h = 1024;
+ }
+ else if (((set_w <= 1600) && (set_h <= 1200)) && (sensor_uxga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_uxga;
+ set_w = 1600;
+ set_h = 1200;
+ }
+ else
+ {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
+
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
+ }
+
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ ret |= sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ }
+
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ #endif
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+ }
+ else
+ {
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ }
+
+ pix->width = set_w;
+ pix->height = set_h;
+
+sensor_s_fmt_end:
+ return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;
+
+ /*
+ * With Bayer format enforce even side lengths, but let the user play
+ * with the starting pixel
+ */
+
+ if (pix->height > SENSOR_MAX_HEIGHT)
+ pix->height = SENSOR_MAX_HEIGHT;
+ else if (pix->height < SENSOR_MIN_HEIGHT)
+ pix->height = SENSOR_MIN_HEIGHT;
+ else if (bayer)
+ pix->height = ALIGN(pix->height, 2);
+
+ if (pix->width > SENSOR_MAX_WIDTH)
+ pix->width = SENSOR_MAX_WIDTH;
+ else if (pix->width < SENSOR_MIN_WIDTH)
+ pix->width = SENSOR_MIN_WIDTH;
+ else if (bayer)
+ pix->width = ALIGN(pix->width, 2);
+
+ return 0;
+}
+
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+ struct i2c_client *client = sd->priv;
+
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match.addr != client->addr)
+ return -ENODEV;
+
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */
+ id->revision = 0;
+
+ return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ int digitalzoom_cur, digitalzoom_total;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl_info)
+ return -EINVAL;
+
+ digitalzoom_cur = sensor->info_priv.digitalzoom;
+ digitalzoom_total = qctrl_info->maximum;
+
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+ {
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+ {
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+ {
+ *value = digitalzoom_total - digitalzoom_cur;
+ }
+
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+ {
+ *value = 0 - digitalzoom_cur;
+ }
+
+ digitalzoom_cur += *value;
+
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+ case V4L2_CID_BRIGHTNESS:
+ {
+ ctrl->value = sensor->info_priv.brightness;
+ break;
+ }
+ case V4L2_CID_SATURATION:
+ {
+ ctrl->value = sensor->info_priv.saturation;
+ break;
+ }
+ case V4L2_CID_CONTRAST:
+ {
+ ctrl->value = sensor->info_priv.contrast;
+ break;
+ }
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ ctrl->value = sensor->info_priv.whiteBalance;
+ break;
+ }
+ case V4L2_CID_EXPOSURE:
+ {
+ ctrl->value = sensor->info_priv.exposure;
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ ctrl->value = sensor->info_priv.mirror;
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ ctrl->value = sensor->info_priv.flip;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+ const struct v4l2_queryctrl *qctrl;
+
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+#if CONFIG_SENSOR_Brightness
+ case V4L2_CID_BRIGHTNESS:
+ {
+ if (ctrl->value != sensor->info_priv.brightness)
+ {
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.brightness = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Exposure
+ case V4L2_CID_EXPOSURE:
+ {
+ if (ctrl->value != sensor->info_priv.exposure)
+ {
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.exposure = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Saturation
+ case V4L2_CID_SATURATION:
+ {
+ if (ctrl->value != sensor->info_priv.saturation)
+ {
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.saturation = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Contrast
+ case V4L2_CID_CONTRAST:
+ {
+ if (ctrl->value != sensor->info_priv.contrast)
+ {
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.contrast = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ if (ctrl->value != sensor->info_priv.whiteBalance)
+ {
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.whiteBalance = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Mirror
+ case V4L2_CID_HFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.mirror)
+ {
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.mirror = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flip
+ case V4L2_CID_VFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.flip)
+ {
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flip = ctrl->value;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ext_ctrl->id)
+ {
+ case V4L2_CID_SCENE:
+ {
+ ext_ctrl->value = sensor->info_priv.scene;
+ break;
+ }
+ case V4L2_CID_EFFECT:
+ {
+ ext_ctrl->value = sensor->info_priv.effect;
+ break;
+ }
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.digitalzoom;
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.focus;
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FLASH:
+ {
+ ext_ctrl->value = sensor->info_priv.flash;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int val_offset;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ val_offset = 0;
+ switch (ext_ctrl->id)
+ {
+#if CONFIG_SENSOR_Scene
+ case V4L2_CID_SCENE:
+ {
+ if (ext_ctrl->value != sensor->info_priv.scene)
+ {
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.scene = ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Effect
+ case V4L2_CID_EFFECT:
+ {
+ if (ext_ctrl->value != sensor->info_priv.effect)
+ {
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.effect= ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += val_offset;
+
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Focus
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.focus)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+ sensor->info_priv.focus += val_offset;
+ }
+
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ sensor->info_priv.focus += ext_ctrl->value;
+
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flash
+ case V4L2_CID_FLASH:
+ {
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flash = ext_ctrl->value;
+
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
+{
+ char value;
+ int ret;
+ struct sensor *sensor = to_sensor(client);
+
+ /* We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant. */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ /* soft reset */
+ ret = sensor_write(client, 0x01, 0xf9);
+ if (ret != 0)
+ {
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+ return -ENODEV;
+ }
+ mdelay(5); //delay 5 microseconds
+
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x04, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+
+ icd->formats = sensor_colour_formats;
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
+
+ return 0;
+
+sensor_video_probe_err:
+
+ return ret;
+}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_ioctl_end:
+ return ret;
+
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+ .init = sensor_init,
+ .g_ctrl = sensor_g_control,
+ .s_ctrl = sensor_s_control,
+ .g_ext_ctrls = sensor_g_ext_controls,
+ .s_ext_ctrls = sensor_s_ext_controls,
+ .g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+ .s_fmt = sensor_s_fmt,
+ .g_fmt = sensor_g_fmt,
+ .try_fmt = sensor_try_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+ .core = &sensor_subdev_core_ops,
+ .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct sensor *sensor;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
+ int ret;
+
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+ return -EIO;
+ }
+
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd->ops = &sensor_ops;
+ icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
+
+ ret = sensor_video_probe(icd, client);
+ if (ret < 0) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(sensor);
+ sensor = NULL;
+ }
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+ return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
+ kfree(sensor);
+ sensor = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+ {SENSOR_NAME_STRING(), 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+ .driver = {
+ .name = SENSOR_NAME_STRING(),
+ },
+ .probe = sensor_probe,
+ .remove = sensor_remove,
+ .id_table = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+ return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+ i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("lxh@wisky.com.cn");
+MODULE_LICENSE("GPL");
+
+
+
--- /dev/null
+/*
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_HI704
+#define SENSOR_V4L2_IDENT V4L2_IDENT_HI704
+#define SENSOR_ID 0x96
+#define SENSOR_MIN_WIDTH 176
+#define SENSOR_MIN_HEIGHT 144
+#define SENSOR_MAX_WIDTH 640
+#define SENSOR_MAX_HEIGHT 480
+#define SENSOR_INIT_WIDTH 640 /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT 480
+#define SENSOR_INIT_WINSEQADR sensor_vga
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY
+
+#define CONFIG_SENSOR_WhiteBalance 1
+#define CONFIG_SENSOR_Brightness 0
+#define CONFIG_SENSOR_Contrast 0
+#define CONFIG_SENSOR_Saturation 0
+#define CONFIG_SENSOR_Effect 1
+#define CONFIG_SENSOR_Scene 1
+#define CONFIG_SENSOR_DigitalZoom 0
+#define CONFIG_SENSOR_Focus 0
+#define CONFIG_SENSOR_Exposure 0
+#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Mirror 0
+#define CONFIG_SENSOR_Flip 0
+
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500
+#define COLOR_TEMPERATURE_OFFICE_DN 3500
+#define COLOR_TEMPERATURE_OFFICE_UP 5000
+#define COLOR_TEMPERATURE_HOME_DN 2500
+#define COLOR_TEMPERATURE_HOME_UP 3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+//lxh end of reg flag
+#define END_REG 0xff
+
+struct reginfo
+{
+ u8 reg;
+ u8 val;
+};
+
+/* init SVGA preview */
+static struct reginfo sensor_init_data[] =
+{
+ //PAGE 0
+ //Image Size/Windowing/HSYNC/VSYNC[Type1]
+{0x03, 0x00}, //PAGEMODE(0x03)
+{0x01, 0xf1},
+{0x01, 0xf3}, //PWRCTL(0x01[P0])Bit[1]:Software Reset.
+{0x01, 0xf1},
+{0x10, 0x00},//vga mode
+{0x11, 0x91}, //For No Fixed Framerate Bit[2]
+{0x12, 0x04},
+
+{0x20, 0x00},
+{0x21, 0x04},
+{0x22, 0x00},
+{0x23, 0x04},
+
+{0x24, 0x01},
+{0x25, 0xe0},
+{0x26, 0x02},
+{0x27, 0x80},
+
+{0x40, 0x00}, //HBLANK: 0x70 = 112
+{0x41, 0x70},
+{0x42, 0x00}, //VBLANK: 0x40 = 64
+{0x43, 0x40}, //0x04 -> 0x40: For Max Framerate = 30fps
+
+//BLC
+{0x80, 0x2e},
+{0x81, 0x7e},
+{0x82, 0x90},
+{0x83, 0x30},
+{0x84, 0x2c},
+{0x85, 0x4b},
+{0x89, 0x48},
+
+{0x90, 0x0b},
+{0x91, 0x0b},
+{0x92, 0x48},
+{0x93, 0x48},
+{0x98, 0x38},
+{0x99, 0x40},
+{0xa0, 0x00},
+{0xa8, 0x40},
+
+//PAGE 2
+//Analog Circuit
+{0x03, 0x02},
+{0x13, 0x40},
+{0x14, 0x04},
+{0x1a, 0x00},
+{0x1b, 0x08},
+
+{0x20, 0x33},
+{0x21, 0xaa},
+{0x22, 0xa7},
+{0x23, 0xb1}, //For Sun Pot
+
+{0x3b, 0x48},
+
+{0x50, 0x21},
+{0x52, 0xa2},
+{0x53, 0x0a},
+{0x54, 0x30},
+{0x55, 0x10},
+{0x56, 0x0c},
+{0x59, 0x0F},
+
+{0x60, 0x54},
+{0x61, 0x5d},
+{0x62, 0x56},
+{0x63, 0x5c},
+{0x64, 0x56},
+{0x65, 0x5c},
+{0x72, 0x57},
+{0x73, 0x5b},
+{0x74, 0x57},
+{0x75, 0x5b},
+{0x80, 0x02},
+{0x81, 0x46},
+{0x82, 0x07},
+{0x83, 0x10},
+{0x84, 0x07},
+{0x85, 0x10},
+{0x92, 0x24},
+{0x93, 0x30},
+{0x94, 0x24},
+{0x95, 0x30},
+{0xa0, 0x03},
+{0xa1, 0x45},
+{0xa4, 0x45},
+{0xa5, 0x03},
+{0xa8, 0x12},
+{0xa9, 0x20},
+{0xaa, 0x34},
+{0xab, 0x40},
+{0xb8, 0x55},
+{0xb9, 0x59},
+{0xbc, 0x05},
+{0xbd, 0x09},
+{0xc0, 0x5f},
+{0xc1, 0x67},
+{0xc2, 0x5f},
+{0xc3, 0x67},
+{0xc4, 0x60},
+{0xc5, 0x66},
+{0xc6, 0x60},
+{0xc7, 0x66},
+{0xc8, 0x61},
+{0xc9, 0x65},
+{0xca, 0x61},
+{0xcb, 0x65},
+{0xcc, 0x62},
+{0xcd, 0x64},
+{0xce, 0x62},
+{0xcf, 0x64},
+{0xd0, 0x53},
+{0xd1, 0x68},
+
+ //PAGE 10
+ //Image Format, Image Effect
+{0x03, 0x10},
+{0x10, 0x01},//lxh
+{0x11, 0x43},
+{0x12, 0x30},
+
+{0x40, 0x10},//brightness +1
+{0x41, 0x02},
+{0x48, 0x98},//contrast level +1
+
+{0x50, 0x48},
+
+{0x60, 0x7f},
+{0x61, 0x00}, //Use default
+{0x62, 0xa0}, //SATB (1.4x)
+{0x63, 0xa0}, //SATR (1.2x)
+{0x64, 0x48}, //AGSAT
+{0x66, 0x90}, //wht_th2
+{0x67, 0x36}, //wht_gain Dark (0.4x), Normal (0.75x)
+
+//LPF
+{0x03, 0x11},
+{0x10, 0x25},
+{0x11, 0x1f},
+
+{0x20, 0x00},
+{0x21, 0x38},
+{0x23, 0x0a},
+
+{0x60, 0x10},
+{0x61, 0x82},
+{0x62, 0x00},
+{0x63, 0x83},
+{0x64, 0x83},
+{0x67, 0xF0},
+{0x68, 0x20},//30
+{0x69, 0x10},
+
+ //PAGE 12
+ //2D
+{0x03, 0x12},
+
+{0x40, 0xe9},
+{0x41, 0x09},
+
+{0x50, 0x18},
+{0x51, 0x24},
+
+{0x70, 0x1f},
+{0x71, 0x00},
+{0x72, 0x00},
+{0x73, 0x00},
+{0x74, 0x10},
+{0x75, 0x10},
+{0x76, 0x20},
+{0x77, 0x80},
+{0x78, 0x88},
+{0x79, 0x18},
+
+{0xb0, 0x7d},
+
+//Edge
+{0x03, 0x13},
+{0x10, 0x01},
+{0x11, 0x89},
+{0x12, 0x14},
+{0x13, 0x19},
+{0x14, 0x08}, //Test Setting
+{0x20, 0x06}, //SHARP_Negative
+{0x21, 0x03}, //SHARP_Positive
+{0x23, 0x30}, //SHARP_DY_CTL
+{0x24, 0x33}, //40->33
+{0x25, 0x08}, //SHARP_PGA_TH
+{0x26, 0x18}, //Test Setting
+{0x27, 0x00}, //Test Setting
+{0x28, 0x08}, //Test Setting
+{0x29, 0x50}, //AG_TH
+{0x2a, 0xe0}, //region ratio
+{0x2b, 0x10}, //Test Setting
+{0x2c, 0x28}, //Test Setting
+{0x2d, 0x40}, //Test Setting
+{0x2e, 0x00}, //Test Setting
+{0x2f, 0x00}, //Test Setting
+{0x30, 0x11}, //Test Setting
+{0x80, 0x03}, //SHARP2D_CTL
+{0x81, 0x07}, //Test Setting
+{0x90, 0x04}, //SHARP2D_SLOPE
+{0x91, 0x02}, //SHARP2D_DIFF_CTL
+{0x92, 0x00}, //SHARP2D_HI_CLIP
+{0x93, 0x20}, //SHARP2D_DY_CTL
+{0x94, 0x42}, //Test Setting
+{0x95, 0x60}, //Test Setting
+
+//Shading
+{0x03, 0x14},
+{0x10, 0x01},
+{0x20, 0x60}, //XCEN
+{0x21, 0x60}, //YCEN 80
+{0x22, 0x66}, //76, 34, 2b
+{0x23, 0x50}, //4b, 15, 0d
+{0x24, 0x44}, //3b, 10, 0b
+
+//Page 15 CMC
+{0x03, 0x15},
+{0x10, 0x03},
+
+{0x14, 0x3c},
+{0x16, 0x2c},
+{0x17, 0x2f},
+
+{0x30, 0xcb},
+{0x31, 0x61},
+{0x32, 0x16},
+{0x33, 0x23},
+{0x34, 0xce},
+{0x35, 0x2b},
+{0x36, 0x01},
+{0x37, 0x34},
+{0x38, 0x75},
+
+{0x40, 0x87},
+{0x41, 0x18},
+{0x42, 0x91},
+{0x43, 0x94},
+{0x44, 0x9f},
+{0x45, 0x33},
+{0x46, 0x00},
+{0x47, 0x94},
+{0x48, 0x14},
+
+//Gamma
+//normal
+{0x03,0x16},
+{0x30,0x00},
+{0x31,0x0a},
+{0x32,0x1b},
+{0x33,0x2e},
+{0x34,0x5c},
+{0x35,0x79},
+{0x36,0x95},
+{0x37,0xa4},
+{0x38,0xb1},
+{0x39,0xbd},
+{0x3a,0xc8},
+{0x3b,0xd9},
+{0x3c,0xe8},
+{0x3d,0xf5},
+{0x3e,0xff},
+ //0930
+//{0x03,0x16},
+//{0x30,0x00},
+//{0x31,0x08},
+//{0x32,0x0e},
+//{0x33,0x1b},
+//{0x34,0x33},
+//{0x35,0x4d},
+//{0x36,0x66},
+//{0x37,0x7e},
+//{0x38,0x95},
+//{0x39,0xa9},
+//{0x3a,0xbb},
+//{0x3b,0xd7},
+//{0x3c,0xeb},
+//{0x3d,0xf7},
+//{0x3e,0xff},
+
+//night mode
+//{0x03,0x16},
+//{0x30,0x00},
+//{0x31,0x1c},
+//{0x32,0x2d},
+//{0x33,0x4e},
+//{0x34,0x6d},
+//{0x35,0x8b},
+//{0x36,0xa2},
+//{0x37,0xb5},
+//{0x38,0xc4},
+//{0x39,0xd0},
+//{0x3a,0xda},
+//{0x3b,0xea},
+//{0x3c,0xf4},
+//{0x3d,0xfb},
+//{0x3e,0xff},
+
+//Page 17 AE
+{0x03, 0x17},
+{0xc4, 0x3c},
+{0xc5, 0x32},
+
+//Page 20 AE
+{0x03, 0x20},
+{0x10, 0x0c},
+{0x11, 0x04},
+
+{0x20, 0x01},
+{0x28, 0x27},
+{0x29, 0xa1},
+
+{0x2a, 0xf0},
+{0x2b, 0x34},
+{0x2c, 0x2b}, //23->2b 2010_04_06 hhzin
+
+{0x30, 0xf8},
+
+{0x39, 0x22},
+{0x3a, 0xde},
+{0x3b, 0x22}, //23->22 _10_04_06 hhzin
+{0x3c, 0xde},
+
+{0x60, 0x95}, //d5, 99
+{0x68, 0x3c},
+{0x69, 0x64},
+{0x6A, 0x28},
+{0x6B, 0xc8},
+
+{0x70, 0x42},//Y Target 42
+
+{0x76, 0x22}, //Unlock bnd1
+{0x77, 0x02}, //Unlock bnd2 02->a2 _10_04_06 hhzin
+
+{0x78, 0x12}, //Yth 1
+{0x79, 0x27}, //Yth 2 26->27 _10_04_06 hhzin
+{0x7a, 0x23}, //Yth 3
+
+{0x7c, 0x1d}, //1c->1d _10_04_06 hhzin
+{0x7d, 0x22},
+
+//50Hz
+{0x83, 0x00},//ExpTime 30fps
+{0x84, 0xaf},
+{0x85, 0xc8},
+
+//60Hz
+//{0x83, 0x00},//ExpTime 30fps
+//{0x84, 0xc3},
+//{0x85, 0x50},
+
+{0x86, 0x00},//ExpMin
+{0x87, 0xfa},
+
+//50Hz_8fps
+{0x88, 0x02},//ExpMax 8fps(8fps)
+{0x89, 0xbf},
+{0x8a, 0x20},
+
+//50Hz_5fps
+//{0x88, 0x04},//ExpMax 8fps(8fps)
+//{0x89, 0x93},
+//{0x8a, 0xe0},
+
+//60Hz_8fps
+//{0x88, 0x02},//ExpMax 8fps(8fps)
+//{0x89, 0xdc},
+//{0x8a, 0x6c},
+
+{0x8b, 0x3a},//Exp100
+{0x8c, 0x98},
+
+{0x8d, 0x30},//Exp120
+{0x8e, 0xd4},
+
+{0x91, 0x02},
+{0x92, 0xdc},
+{0x93, 0x6c},
+
+{0x94, 0x01}, //fix_step
+{0x95, 0xb7},
+{0x96, 0x74},
+
+{0x98, 0x8C},
+{0x99, 0x23},
+
+{0x9c, 0x0b}, //4shared limit_10_04_06 hhzin
+{0x9d, 0x3b}, // 0x06d3 --> 0x0b3b
+{0x9e, 0x00}, //4shared Unit_10_04_06 hhzin
+{0x9f, 0xfa}, // 0x01f4 --> 0xfa
+
+{0xb1, 0x14},
+{0xb2, 0x50},
+{0xb4, 0x14},
+{0xb5, 0x38},
+{0xb6, 0x26},
+{0xb7, 0x20},
+{0xb8, 0x1d},
+{0xb9, 0x1b},
+{0xba, 0x1a},
+{0xbb, 0x19},
+{0xbc, 0x19},
+{0xbd, 0x18},
+
+{0xc0, 0x1a},
+{0xc3, 0x48},
+{0xc4, 0x48},
+
+
+//Page 22 AWB
+{0x03, 0x22},
+{0x10, 0xe2},
+{0x11, 0x26},
+{0x21, 0x40},
+
+{0x30, 0x80},
+{0x31, 0x80},
+{0x38, 0x12},
+{0x39, 0x33},
+{0x40, 0xf0},
+{0x41, 0x33},
+{0x42, 0x33},
+{0x43, 0xf3},
+{0x44, 0x55},
+{0x45, 0x44},
+{0x46, 0x02},
+
+{0x80, 0x45},
+{0x81, 0x20},
+{0x82, 0x48},
+{0x83, 0x52}, //RMAX Default : 50 -> 48 -> 52
+{0x84, 0x1b}, //RMIN Default : 20
+{0x85, 0x50}, //BMAX Default : 50, 5a -> 58 -> 55
+{0x86, 0x25}, //BMIN Default : 20
+{0x87, 0x4d}, //RMAXB Default : 50, 4d
+{0x88, 0x38}, //RMINB Default : 3e, 45 --> 42
+{0x89, 0x3e}, //BMAXB Default : 2e, 2d --> 30
+{0x8a, 0x29}, //BMINB Default : 20, 22 --> 26 --> 29
+{0x8b, 0x02}, //OUT TH
+{0x8d, 0x22},
+{0x8e, 0x71},
+
+{0x8f, 0x63},
+{0x90, 0x60},
+{0x91, 0x5c},
+{0x92, 0x56},
+{0x93, 0x52},
+{0x94, 0x4c},
+{0x95, 0x36},
+{0x96, 0x31},
+{0x97, 0x2e},
+{0x98, 0x2a},
+{0x99, 0x29},
+{0x9a, 0x26},
+{0x9b, 0x09},
+
+{0x03, 0x22},
+{0x10, 0xfb},
+
+//PAGE 20
+{0x03, 0x20},
+{0x10, 0x9c},
+
+{0x01, 0xf0},
+
+//PAGE 0
+{0x03, 0x00},
+{0x01, 0x90}, //0xf1 ->0x41 : For Preview Green/Red Line.
+{0xff, 0xff} //End of Initial Setting
+};
+
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+{0x03, 0x00},
+{0x10, 0x00}, //VGA Size
+
+{0x20, 0x00},
+{0x21, 0x04},
+
+{0x40, 0x00}, //HBLANK: 0x70 = 112
+{0x41, 0x70},
+{0x42, 0x00}, //VBLANK: 0x04 = 4
+{0x43, 0x40},
+
+{0x03, 0x11},
+{0x10, 0x25},
+
+{0x03, 0x20},
+{0x83, 0x00},
+{0x84, 0xaf},
+{0x85, 0x80},
+{0x86, 0x00},
+{0x87, 0xc0},
+
+{0x8b, 0x3a},
+{0x8c, 0x80},
+{0x8d, 0x30},
+{0x8e, 0xc0},
+
+{0x9c, 0x08},
+{0x9d, 0xa0},
+{0x9e, 0x00},
+{0x9f, 0xc0},
+{END_REG, END_REG},
+};
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{
+ {END_REG, END_REG},
+};
+
+/* 320*240 QVGA */
+static struct reginfo sensor_qvga[] =
+{
+{0x03, 0x00},
+{0x10, 0x01}, //QVGA Size: 0x10 -> 0x01
+
+{0x20, 0x00},
+{0x21, 0x02},
+
+{0x40, 0x01}, //HBLANK: 0x0158 = 344
+{0x41, 0x58},
+{0x42, 0x00}, //VBLANK: 0x14 = 20
+{0x43, 0x14},
+
+{0x03, 0x11}, //QVGA Fixframerate
+{0x10, 0x21},
+
+{0x03, 0x20},
+
+{0x83, 0x00},
+{0x84, 0xaf},
+{0x85, 0xc8},
+{0x86, 0x00},
+{0x87, 0xfa},
+
+{0x8b, 0x3a},
+{0x8c, 0x98},
+{0x8d, 0x30},
+{0x8e, 0xd4},
+
+{0x9c, 0x0b},
+{0x9d, 0x3b},
+{0x9e, 0x00},
+{0x9f, 0xfa},
+{END_REG, END_REG},
+};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{
+ {END_REG, END_REG},
+};
+
+
+static struct reginfo sensor_ClrFmt_YUYV[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_ClrFmt_UYVY[]=
+{
+
+ {END_REG, END_REG},
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static struct reginfo sensor_WhiteB_Auto[]=
+{
+ {0x03, 0x22},
+ {0x10, 0x6a},
+ {0x80, 0x48},
+ {0x81, 0x20},
+ {0x82, 0x40},
+ {0x83, 0x58},
+ {0x84, 0x10},
+ {0x85, 0x70},
+ {0x86, 0x10},
+ {0x10, 0xea},
+ {END_REG, END_REG},
+};
+/* Cloudy Colour Temperature : 6500K - 8000K */
+static struct reginfo sensor_WhiteB_Cloudy[]=
+{
+ {0x03, 0x22},
+ {0x10, 0x6a},
+ {0x80, 0x62},
+ {0x81, 0x20},
+ {0x82, 0x2e},
+ {0x83, 0x6d},
+ {0x84, 0x65},
+ {0x85, 0x30},
+ {0x86, 0x25},
+ {END_REG, END_REG},
+};
+/* ClearDay Colour Temperature : 5000K - 6500K */
+static struct reginfo sensor_WhiteB_ClearDay[]=
+{
+ //Sunny
+ {0x03, 0x22},
+ {0x10, 0x6a},
+ {0x80, 0x50},
+ {0x81, 0x20},
+ {0x82, 0x2d},
+ {0x83, 0x52},
+ {0x84, 0x40},
+ {0x85, 0x30},
+ {0x86, 0x1c},
+ {END_REG, END_REG},
+};
+/* Office Colour Temperature : 3500K - 5000K */
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+ //Office£¬Ó«¹âµÆ
+ {0x03, 0x22},
+ {0x10, 0x6a},
+ {0x80, 0x40},
+ {0x81, 0x20},
+ {0x82, 0x4f},
+ {0x83, 0x44},
+ {0x84, 0x3a},
+ {0x85, 0x47},
+ {0x86, 0x3a},
+ {END_REG, END_REG},
+
+};
+/* Home Colour Temperature : 2500K - 3500K */
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+ //Home,°×³ãµÆ
+ {0x03, 0x22},
+ {0x10, 0x6a},
+ {0x80, 0x26},
+ {0x81, 0x20},
+ {0x82, 0x55},
+ {0x83, 0x24},
+ {0x84, 0x1e},
+ {0x85, 0x58},
+ {0x86, 0x4a},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static struct reginfo sensor_Brightness0[]=
+{
+ // Brightness -2
+ {0x03, 0x10},
+ {0x40, 0xa0},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness1[]=
+{
+ // Brightness -1
+ {0x03, 0x10},
+ {0x40, 0x90},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness2[]=
+{
+ // Brightness 0
+ {0x03, 0x10},
+ {0x40, 0x00},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness3[]=
+{
+ // Brightness +1
+ {0x03, 0x10},
+ {0x40, 0x10},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness4[]=
+{
+ // Brightness +2
+ {0x03, 0x10},
+ {0x40, 0x20},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Brightness5[]=
+{
+ // Brightness +3
+ {0x03, 0x10},
+ {0x40, 0x30},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+ sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static struct reginfo sensor_Effect_Normal[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x30},
+ {0x13, 0x00},
+ {0x44, 0x80},
+ {0x45, 0x80},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x06},
+ {0x21, 0x04},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_WandB[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x30},
+ {0x13, 0x00},
+ {0x44, 0x80},
+ {0x45, 0x80},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x06},
+ {0x21, 0x04},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Sepia[] =
+{
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x23},
+ {0x13, 0x00},
+ {0x44, 0x70},
+ {0x45, 0x98},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x07},
+ {0x21, 0x03},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Negative[] =
+{
+ //Negative
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x28},
+ {0x13, 0x00},
+ {0x44, 0x80},
+ {0x45, 0x80},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x07},
+ {0x21, 0x03},
+ {END_REG, END_REG},
+};
+static struct reginfo sensor_Effect_Bluish[] =
+{
+ // Bluish
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x33},
+ {0x13, 0x00},
+ {0x44, 0xb0},
+ {0x45, 0x40},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x07},
+ {0x21, 0x03},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Effect_Green[] =
+{
+ // Greenish
+ {0x03, 0x10},
+ {0x11, 0x03},
+ {0x12, 0x33},
+ {0x13, 0x00},
+ {0x44, 0x60},
+ {0x45, 0x60},
+ {0x47, 0x7f},
+ {0x03, 0x13},
+ {0x20, 0x07},
+ {0x21, 0x03},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static struct reginfo sensor_Exposure0[]=
+{
+ //-3
+
+};
+
+static struct reginfo sensor_Exposure1[]=
+{
+ //-2
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure2[]=
+{
+ //-0.3EV
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure3[]=
+{
+ //default
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure4[]=
+{
+ // 1
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure5[]=
+{
+ // 2
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Exposure6[]=
+{
+ // 3
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static struct reginfo sensor_Saturation0[]=
+{
+ //-3 level
+ {0x03, 0x10},
+ {0x62, 0x60},
+ {0x63, 0x60},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Saturation1[]=
+{
+ //00 level
+ {0x03, 0x10},
+ {0x62, 0x90},
+ {0x63, 0x90},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Saturation2[]=
+{
+ //+3 level
+ {0x03, 0x10},
+ {0x62, 0xc0},
+ {0x63, 0xc0},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static struct reginfo sensor_Contrast0[]=
+{
+ //Contrast -3
+ {0x03, 0x10},
+ {0x48, 0x54},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast1[]=
+{
+ //Contrast -2
+ {0x03, 0x10},
+ {0x48, 0x64},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast2[]=
+{
+ // Contrast -1
+ {0x03, 0x10},
+ {0x48, 0x74},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast3[]=
+{
+ //Contrast 0
+ {0x03, 0x10},
+ {0x48, 0x84},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast4[]=
+{
+ //Contrast +1
+ {0x03, 0x10},
+ {0x48, 0x94},
+ {END_REG, END_REG},
+};
+
+
+static struct reginfo sensor_Contrast5[]=
+{
+ //Contrast +2
+ {0x03, 0x10},
+ {0x48, 0xa4},
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Contrast6[]=
+{
+ //Contrast +3
+ {0x03, 0x10},
+ {0x48, 0xb4},
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static struct reginfo sensor_MirrorOn[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_MirrorOff[]=
+{
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static struct reginfo sensor_FlipOn[]=
+{
+
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_FlipOff[]=
+{
+
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static struct reginfo sensor_SceneAuto[] =
+{
+
+};
+
+static struct reginfo sensor_SceneNight[] =
+{
+
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+ {END_REG, END_REG},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+ {END_REG, END_REG},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+ {END_REG, END_REG},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},
+ #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White Balance Control",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Brightness
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness Control",
+ .minimum = -3,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ {
+ .id = V4L2_CID_EFFECT,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Effect Control",
+ .minimum = 0,
+ .maximum = 5,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Exposure
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Control",
+ .minimum = 0,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Saturation
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation Control",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Contrast
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast Control",
+ .minimum = -3,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Mirror
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flip
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ {
+ .id = V4L2_CID_SCENE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Scene Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_DigitalZoom
+ {
+ .id = V4L2_CID_ZOOM_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_ZOOM_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Focus
+ {
+ .id = V4L2_CID_FOCUS_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_FOCUS_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 125,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ {
+ .id = V4L2_CID_FLASH,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Flash Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+ .suspend = sensor_suspend,
+ .resume = sensor_resume,
+ .set_bus_param = sensor_set_bus_param,
+ .query_bus_param = sensor_query_bus_param,
+ .controls = sensor_controls,
+ .menus = sensor_menus,
+ .num_controls = ARRAY_SIZE(sensor_controls),
+ .num_menus = ARRAY_SIZE(sensor_menus),
+};
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+
+#define JPG_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+
+static const struct soc_camera_data_format sensor_colour_formats[] = {
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
+};
+
+typedef struct sensor_info_priv_s
+{
+ int whiteBalance;
+ int brightness;
+ int contrast;
+ int saturation;
+ int effect;
+ int scene;
+ int digitalzoom;
+ int focus;
+ int flash;
+ int exposure;
+ bool snap2preview;
+ bool video2preview;
+ unsigned char mirror; /* HFLIP */
+ unsigned char flip; /* VFLIP */
+ unsigned int winseqe_cur_addr;
+ unsigned int pixfmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+ struct v4l2_subdev subdev;
+ struct i2c_client *client;
+ sensor_info_priv_t info_priv;
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+#endif
+ return 0;
+sensor_task_lock_err:
+ return -1;
+}
+
+#if 0
+/* sensor register */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_recv(client, reg, val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret = 0;
+
+ ret = i2c_master_reg8_send(client, reg, &val, 1, CONFIG_SENSOR_I2C_SPEED);
+
+ return (ret > 0)? 0 : ret;
+}
+#else
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int err,cnt;
+ u8 buf[2];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+ buf[1] = val;
+
+ msg->addr = client->addr;
+ msg->flags = client->flags;
+ msg->buf = buf;
+ msg->len = sizeof(buf);
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ return 0;
+ } else {
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int err,cnt;
+ u8 buf[1];
+ struct i2c_msg msg[2];
+
+ buf[0] = reg ;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].buf = buf;
+ msg[0].len = sizeof(buf);
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags|I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = 1;
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err >= 0) {
+ *val = buf[0];
+ return 0;
+ } else {
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+#endif
+
+/* write a array of registers */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int err = 0, cnt;
+ int i = 0;
+#if CONFIG_SENSOR_I2C_RDWRCHK
+ char valchk;
+#endif
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
+ while (regarray[i].reg != END_REG)
+ {
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);
+ if (err < 0)
+ {
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ //mdelay(5);
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
+ }
+ i++;
+ }
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+ char value;
+ int ret;
+
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ /* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
+#if 1
+ ret = sensor_write(client, 0x01, 0xF3);
+ if (ret != 0)
+ {
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ mdelay(5); //delay 5 microseconds
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x04, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+#endif
+ ret = sensor_write_array(client, sensor_init_data);
+ if (ret != 0)
+ {
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+ goto sensor_INIT_ERR;
+ }
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
+
+ /* sensor sensor information for initialization */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ if (qctrl)
+ sensor->info_priv.whiteBalance = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+ if (qctrl)
+ sensor->info_priv.brightness = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ if (qctrl)
+ sensor->info_priv.effect = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+ if (qctrl)
+ sensor->info_priv.exposure = qctrl->default_value;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+ if (qctrl)
+ sensor->info_priv.saturation = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+ if (qctrl)
+ sensor->info_priv.contrast = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+ if (qctrl)
+ sensor->info_priv.mirror = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+ if (qctrl)
+ sensor->info_priv.flip = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+ if (qctrl)
+ sensor->info_priv.scene = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.digitalzoom = qctrl->default_value;
+
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
+ #if CONFIG_SENSOR_Focus
+ sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.focus = qctrl->default_value;
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+ if (qctrl)
+ sensor->info_priv.flash = qctrl->default_value;
+ #endif
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+ return 0;
+sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
+ return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
+
+static struct reginfo sensor_power_down_sequence[]=
+{
+ {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;
+ if (ret != 0) {
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+ return ret;
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ }
+ } else {
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+ return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+
+ return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ unsigned long flags = SENSOR_BUS_PARAM;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = icd->user_width;
+ pix->height = icd->user_height;
+ pix->pixelformat = sensor->info_priv.pixfmt;
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct reginfo *winseqe_set_addr=NULL;
+ int ret=0, set_w,set_h;
+
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {
+ switch (pix->pixelformat)
+ {
+ case V4L2_PIX_FMT_YUYV:
+ {
+ winseqe_set_addr = sensor_ClrFmt_YUYV;
+ break;
+ }
+ case V4L2_PIX_FMT_UYVY:
+ {
+ winseqe_set_addr = sensor_ClrFmt_UYVY;
+ break;
+ }
+ default:
+ break;
+ }
+ if (winseqe_set_addr != NULL) {
+ sensor_write_array(client, winseqe_set_addr);
+ sensor->info_priv.pixfmt = pix->pixelformat;
+
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ } else {
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ }
+ }
+
+ set_w = pix->width;
+ set_h = pix->height;
+
+ if (((set_w <= 176) && (set_h <= 144)) && (sensor_qcif[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_qcif;
+ set_w = 176;
+ set_h = 144;
+ }
+ else if (((set_w <= 320) && (set_h <= 240)) && (sensor_qvga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_qvga;
+ set_w = 320;
+ set_h = 240;
+ }
+ else if (((set_w <= 352) && (set_h<= 288)) && (sensor_cif[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_cif;
+ set_w = 352;
+ set_h = 288;
+ }
+ else if (((set_w <= 640) && (set_h <= 480)) && (sensor_vga[0].reg != END_REG))
+ {
+ winseqe_set_addr = sensor_vga;
+ set_w = 640;
+ set_h = 480;
+ }
+ else
+ {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
+
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
+ }
+
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ ret |= sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ }
+
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ #endif
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+ }
+ else
+ {
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ }
+
+ pix->width = set_w;
+ pix->height = set_h;
+
+sensor_s_fmt_end:
+ return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;
+
+ /*
+ * With Bayer format enforce even side lengths, but let the user play
+ * with the starting pixel
+ */
+
+ if (pix->height > SENSOR_MAX_HEIGHT)
+ pix->height = SENSOR_MAX_HEIGHT;
+ else if (pix->height < SENSOR_MIN_HEIGHT)
+ pix->height = SENSOR_MIN_HEIGHT;
+ else if (bayer)
+ pix->height = ALIGN(pix->height, 2);
+
+ if (pix->width > SENSOR_MAX_WIDTH)
+ pix->width = SENSOR_MAX_WIDTH;
+ else if (pix->width < SENSOR_MIN_WIDTH)
+ pix->width = SENSOR_MIN_WIDTH;
+ else if (bayer)
+ pix->width = ALIGN(pix->width, 2);
+
+ return 0;
+}
+
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+ struct i2c_client *client = sd->priv;
+
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match.addr != client->addr)
+ return -ENODEV;
+
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */
+ id->revision = 0;
+
+ return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ int digitalzoom_cur, digitalzoom_total;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl_info)
+ return -EINVAL;
+
+ digitalzoom_cur = sensor->info_priv.digitalzoom;
+ digitalzoom_total = qctrl_info->maximum;
+
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+ {
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+ {
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+ {
+ *value = digitalzoom_total - digitalzoom_cur;
+ }
+
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+ {
+ *value = 0 - digitalzoom_cur;
+ }
+
+ digitalzoom_cur += *value;
+
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+ case V4L2_CID_BRIGHTNESS:
+ {
+ ctrl->value = sensor->info_priv.brightness;
+ break;
+ }
+ case V4L2_CID_SATURATION:
+ {
+ ctrl->value = sensor->info_priv.saturation;
+ break;
+ }
+ case V4L2_CID_CONTRAST:
+ {
+ ctrl->value = sensor->info_priv.contrast;
+ break;
+ }
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ ctrl->value = sensor->info_priv.whiteBalance;
+ break;
+ }
+ case V4L2_CID_EXPOSURE:
+ {
+ ctrl->value = sensor->info_priv.exposure;
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ ctrl->value = sensor->info_priv.mirror;
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ ctrl->value = sensor->info_priv.flip;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+ const struct v4l2_queryctrl *qctrl;
+
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+#if CONFIG_SENSOR_Brightness
+ case V4L2_CID_BRIGHTNESS:
+ {
+ if (ctrl->value != sensor->info_priv.brightness)
+ {
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.brightness = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Exposure
+ case V4L2_CID_EXPOSURE:
+ {
+ if (ctrl->value != sensor->info_priv.exposure)
+ {
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.exposure = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Saturation
+ case V4L2_CID_SATURATION:
+ {
+ if (ctrl->value != sensor->info_priv.saturation)
+ {
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.saturation = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Contrast
+ case V4L2_CID_CONTRAST:
+ {
+ if (ctrl->value != sensor->info_priv.contrast)
+ {
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.contrast = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ if (ctrl->value != sensor->info_priv.whiteBalance)
+ {
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.whiteBalance = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Mirror
+ case V4L2_CID_HFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.mirror)
+ {
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.mirror = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flip
+ case V4L2_CID_VFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.flip)
+ {
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flip = ctrl->value;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ext_ctrl->id)
+ {
+ case V4L2_CID_SCENE:
+ {
+ ext_ctrl->value = sensor->info_priv.scene;
+ break;
+ }
+ case V4L2_CID_EFFECT:
+ {
+ ext_ctrl->value = sensor->info_priv.effect;
+ break;
+ }
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.digitalzoom;
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.focus;
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FLASH:
+ {
+ ext_ctrl->value = sensor->info_priv.flash;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int val_offset;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ val_offset = 0;
+ switch (ext_ctrl->id)
+ {
+#if CONFIG_SENSOR_Scene
+ case V4L2_CID_SCENE:
+ {
+ if (ext_ctrl->value != sensor->info_priv.scene)
+ {
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.scene = ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Effect
+ case V4L2_CID_EFFECT:
+ {
+ if (ext_ctrl->value != sensor->info_priv.effect)
+ {
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.effect= ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += val_offset;
+
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Focus
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.focus)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+ sensor->info_priv.focus += val_offset;
+ }
+
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ sensor->info_priv.focus += ext_ctrl->value;
+
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flash
+ case V4L2_CID_FLASH:
+ {
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flash = ext_ctrl->value;
+
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
+{
+ char value;
+ int ret;
+ struct sensor *sensor = to_sensor(client);
+
+ /* We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant. */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ /* soft reset */
+ ret = sensor_write(client, 0x01, 0xf3);
+ if (ret != 0)
+ {
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+ return -ENODEV;
+ }
+ mdelay(5); //delay 5 microseconds
+
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x04, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+
+ if (value == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), value);
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+
+ icd->formats = sensor_colour_formats;
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
+
+ return 0;
+
+sensor_video_probe_err:
+
+ return ret;
+}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_ioctl_end:
+ return ret;
+
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+ .init = sensor_init,
+ .g_ctrl = sensor_g_control,
+ .s_ctrl = sensor_s_control,
+ .g_ext_ctrls = sensor_g_ext_controls,
+ .s_ext_ctrls = sensor_s_ext_controls,
+ .g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+ .s_fmt = sensor_s_fmt,
+ .g_fmt = sensor_g_fmt,
+ .try_fmt = sensor_try_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+ .core = &sensor_subdev_core_ops,
+ .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct sensor *sensor;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
+ int ret;
+
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+ return -EIO;
+ }
+
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd->ops = &sensor_ops;
+ icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
+
+ ret = sensor_video_probe(icd, client);
+ if (ret < 0) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(sensor);
+ sensor = NULL;
+ }
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+ return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
+ kfree(sensor);
+ sensor = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+ {SENSOR_NAME_STRING(), 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+ .driver = {
+ .name = SENSOR_NAME_STRING(),
+ },
+ .probe = sensor_probe,
+ .remove = sensor_remove,
+ .id_table = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+ return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+ i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("lxh@wisky.com.cn");
+MODULE_LICENSE("GPL");
+
+
+
--- /dev/null
+/*
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_NT99250
+#define SENSOR_V4L2_IDENT V4L2_IDENT_NT99250
+#define SENSOR_ID 0x0105
+#define SENSOR_MIN_WIDTH 176
+#define SENSOR_MIN_HEIGHT 144
+#define SENSOR_MAX_WIDTH 1600
+#define SENSOR_MAX_HEIGHT 1200
+#define SENSOR_INIT_WIDTH 800 /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT 600
+#define SENSOR_INIT_WINSEQADR sensor_svga
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY
+
+#define CONFIG_SENSOR_WhiteBalance 0
+#define CONFIG_SENSOR_Brightness 0
+#define CONFIG_SENSOR_Contrast 0
+#define CONFIG_SENSOR_Saturation 0
+#define CONFIG_SENSOR_Effect 0
+#define CONFIG_SENSOR_Scene 0
+#define CONFIG_SENSOR_DigitalZoom 0
+#define CONFIG_SENSOR_Focus 0
+#define CONFIG_SENSOR_Exposure 0
+#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Mirror 0
+#define CONFIG_SENSOR_Flip 0
+
+#define CONFIG_SENSOR_I2C_SPEED 250000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500
+#define COLOR_TEMPERATURE_OFFICE_DN 3500
+#define COLOR_TEMPERATURE_OFFICE_UP 5000
+#define COLOR_TEMPERATURE_HOME_DN 2500
+#define COLOR_TEMPERATURE_HOME_UP 3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+struct reginfo
+{
+ u16 reg;
+ u8 val;
+};
+
+/* init 352X288 SVGA */
+static struct reginfo sensor_init_data[] =
+{
+{0x3024,0x02}, //TG //0x02
+{0x32F0,0x00},//0:UYVY 2:VYUY 1:YUYV 3:YVYU
+{0x301e,0x54},
+{0x301f,0x48},
+//gamma ++++
+{0x3270,0x00},
+{0x3271,0x04},
+{0x3272,0x0E},
+{0x3273,0x28},
+{0x3274,0x3F},
+{0x3275,0x50},
+{0x3276,0x6E},
+{0x3277,0x88},
+{0x3278,0xA0},
+{0x3279,0xB3},
+{0x327A,0xD2},
+{0x327B,0xE8},
+{0x327C,0xF5},
+{0x327D,0xFF},
+{0x327E,0xFF},
+//gamma ----
+//CC ++++
+{0x3302,0x00},
+{0x3303,0x2E},
+{0x3304,0x00},
+{0x3305,0xB7},
+{0x3306,0x00},
+{0x3307,0x1A},
+{0x3308,0x07},
+{0x3309,0xE7},
+{0x330A,0x07},
+{0x330B,0x44},
+{0x330C,0x00},
+{0x330D,0xD6},
+{0x330E,0x01},
+{0x330F,0x01},
+{0x3310,0x07},
+{0x3311,0x1A},
+{0x3312,0x07},
+{0x3313,0xE5},
+//CC ----
+//LSC_+++++
+{0x3250,0x01},
+{0x3251,0x87},
+{0x3252,0x01},
+{0x3253,0x88},
+{0x3254,0x01},
+{0x3255,0x89},
+{0x3256,0x01},
+{0x3257,0x33},
+{0x3258,0x01},
+{0x3259,0x34},
+{0x325A,0x01},
+{0x325B,0x35},
+{0x325C,0x00},
+{0x325D,0x00},
+{0x325E,0x00},
+{0x325F,0x00},
+{0x3260,0x00},
+{0x3261,0x00},
+{0x3262,0x09},
+{0x3263,0x08},
+{0x3264,0x08},
+{0x3265,0x17},
+{0x3266,0x00},
+{0x3200,0x3e},
+//LSC_----
+//analog ++++
+{0x3102,0x0b},
+{0x3103,0x46},
+{0x3105,0x33},
+{0x3107,0x32},
+{0x310A,0x03},
+{0x310B,0x18},
+{0x310f,0x08},
+{0x3110,0x03},
+{0x3113,0x0F},
+{0x3119,0x17},
+{0x3114,0x03},
+{0x3117,0x03},
+{0x3118,0x01},
+{0x3380,0x03},
+//analog ----
+//DAC&DPC ++++
+{0x3044,0x02},
+{0x3045,0xd0},
+{0x3046,0x02},
+{0x3047,0xd0},
+{0x3048,0x02},
+{0x3049,0xd0},
+{0x304a,0x02},
+{0x304b,0xd0},
+{0x303e,0x02},
+{0x303f,0x2b},
+{0x3052,0x80},
+{0x3059,0x10},
+{0x305a,0x28},
+{0x305b,0x20},
+{0x305c,0x04},
+{0x305d,0x28},
+{0x305e,0x04},
+{0x305f,0x52},
+{0x3058,0x01},
+//DAC&DPC ----
+{0x3080,0x80},
+{0x3081,0x80},
+{0x3082,0x80},
+{0x3083,0x40},
+{0x3084,0x80},
+{0x3085,0x40},
+//AEC AGC ++++
+{0x32b0,0x00},
+{0x32b1,0x90},
+{0x32BB,0x0b},
+{0x32bd,0x05},
+{0x32be,0x05},
+{0x32cd,0x01},
+{0x32d3,0x13},
+{0x32d7,0x82},
+{0x32d8,0x3F},
+{0x32d9,0x18},
+{0x32c5,0x18},
+//AEC AGC ----
+{0x32f6,0x0c},//effect function
+{0x3069, 0x00}, //Pix //01 :for M1002 00 :for other
+{0x306d, 0x01}, //pclk //00 :for M1002 01 :for other
+
+ //==============================
+ //Output size
+ //==============================
+ //[800X600]
+ //edge & denoise +++
+ {0x3300,0x30},
+ {0x3301,0x80},
+ {0x3320,0x28},
+ {0x3331,0x04},
+ {0x3332,0x40},
+ {0x3339,0x10},
+ {0x333a,0x1a},
+ //edge & denoise ---
+ //AE AWB mode ++
+ {0x329C,0x4b},
+ {0x32bf,0x52},
+ {0x32c0,0x10},
+ {0x3200,0x3e},
+ {0x3201,0x3f},
+ {0x32b0,0x02},
+ {0x32b1,0xc0},
+ //AE AWB mode ---
+ {0x3052,0x80}, //OB
+ {0x32e0,0x03},
+ {0x32e1,0x20},
+ {0x32e2,0x02},
+ {0x32e3,0x58},
+ {0x32e4,0x01},
+ {0x32e5,0x00},
+ {0x32e6,0x00},
+ {0x32e7,0x00},
+ {0x301e,0x00}, //pll
+ {0x301f,0x20}, //pll
+ {0x3022,0x25},
+ {0x3023,0x64},
+ {0x3002,0x00},
+ {0x3003,0x04},
+ {0x3004,0x00},
+ {0x3005,0x04},
+ {0x3006,0x06},
+ {0x3007,0x43},
+ {0x3008,0x04},
+ {0x3009,0xb3},
+ {0x300a,0x09},
+ {0x300b,0x91},
+ {0x300c,0x02},
+ {0x300d,0x64},
+ {0x300e,0x06},
+ {0x300f,0x40},
+ {0x3010,0x02},
+ {0x3011,0x58},
+ {0x32bb,0x0b},
+ {0x32bc,0x3a},
+ {0x32c1,0x25},
+ {0x32c2,0x5c}, //7.14fps @ 48M
+ {0x32c8,0x62},
+ {0x32c9,0x52},
+ {0x32c4,0x00},
+ {0x3290,0x01}, //awb init ++++
+ {0x3291,0x68},
+ {0x3296,0x01},
+ {0x3297,0x75},
+ {0x32A9,0x11},
+ {0x32AA,0x01},
+ {0x329b,0x01},
+ {0x32a2,0x60},
+ {0x32a4,0xa0},
+ {0x32a6,0x60},
+ {0x32a8,0xa0}, //awb init ----
+ {0x3012,0x02}, //AE init +++
+ {0x3013,0xae},
+ {0x301d,0x08},
+ {0x3201,0x7f}, //AE init ---
+ {0x3021,0x06},
+ {0x3060,0x01},
+ {0x0, 0x0}, //end flag
+
+};
+
+/* 1600X1200 UXGA */
+static struct reginfo sensor_uxga[] =
+{
+ //Output format & size
+ {0x3300, 0x3f},
+ {0x3301, 0xa0},
+ {0x3331, 0x08},
+ {0x3332, 0x80}, //0x20
+ {0x3320, 0x20}, //0x28
+
+ {0x329C, 0x4b},
+ {0x32bf, 0x52},
+ {0x3200, 0x3e},
+
+ {0x32e0,0x06},
+ {0x32e1,0x40},
+ {0x32e2,0x04},
+ {0x32e3,0xb0},
+ {0x32e4,0x00},
+ {0x32e5,0x00},
+ {0x32e6,0x00},
+ {0x32e7,0x00},
+
+ {0x301e, 0x00},
+ {0x301f, 0x20},
+
+ {0x3022, 0x25},
+ {0x3023, 0x24},
+
+ //Capture_1600x1200s
+ {0x3002, 0x00},
+ {0x3003, 0x04},
+ {0x3004, 0x00},
+ {0x3005, 0x04},
+ {0x3006, 0x06},
+ {0x3007, 0x43},
+ {0x3008, 0x00},
+ {0x3009, 0xb3},
+ {0x300a, 0x09},
+ {0x300b, 0x82},
+ {0x300c, 0x07},
+ {0x300d, 0xb4},
+ {0x300e, 0x06},
+ {0x300f, 0x40},
+ {0x3010, 0x04},
+ {0x3011, 0xb0},
+
+ {0x32bb, 0x0b},
+ //{0x32bc, 0x38},
+
+ {0x32c4, 0x00},
+ //{0x3201, 0x3f},
+ {0x3021, 0x06},
+ {0x3060, 0x01},
+
+ {0x0, 0x0},
+};
+
+/* 1280X1024 SXGA */
+static struct reginfo sensor_sxga[] =
+{
+ {0x3300, 0x3f},
+ {0x3301, 0xa0},
+ {0x3331, 0x0c},
+ {0x3332, 0x80},
+ {0x3320, 0x20},
+ {0x329C, 0x4b},
+ {0x32bf, 0x52},
+ {0x3200, 0x3e},
+//1280x1024
+ {0x32e0, 0x05},
+ {0x32e1, 0x00},
+ {0x32e2, 0x04},
+ {0x32e3, 0x00},
+ {0x32e4, 0x00},
+ {0x32e5, 0x40},
+ {0x32e6, 0x00},
+ {0x32e7, 0x2c},
+
+ {0x301e, 0x00},
+ {0x3022, 0x25},
+ {0x3023, 0x24},
+ {0x3002, 0x00},
+ {0x3003, 0x04},
+ {0x3004, 0x00},
+ {0x3005, 0x04},
+ {0x3006, 0x06},
+ {0x3007, 0x43},
+ {0x3008, 0x04},
+ {0x3009, 0xb3},
+ {0x300a, 0x09},
+ {0x300b, 0x82},
+ {0x300c, 0x07},
+ {0x300d, 0xb4},
+ {0x300e, 0x06},
+ {0x300f, 0x40},
+ {0x3010, 0x04},
+ {0x3011, 0xb0},
+ {0x32bb, 0x0b},
+
+ //{0x3201, 0x7f},
+ {0x3021, 0x06},
+ {0x3060, 0x01},
+ {0x0, 0x0},
+};
+
+/* 800X600 SVGA*/
+static struct reginfo sensor_svga[] =
+{
+//edge & denoise +++
+{0x3300,0x30},
+{0x3301,0x80},
+{0x3320,0x30},
+{0x3331,0x0c},
+{0x3332,0x40},
+{0x3339,0x10},
+{0x333a,0x1a},
+//edge & denoise ---
+//AE AWB mode ++
+{0x329C,0x4b},
+{0x32bf,0x52},
+{0x32c0,0x10},
+{0x3200,0x3e},
+//{0x3201,0x3f},
+{0x32b0,0x02},
+{0x32b1,0xc0},
+//AE AWB mode ---
+{0x3052,0x80}, //OB
+ {0x32e0,0x03},
+ {0x32e1,0x20},
+ {0x32e2,0x02},
+ {0x32e3,0x58},
+ {0x32e4,0x01},
+ {0x32e5,0x00},
+ {0x32e6,0x00},
+ {0x32e7,0x00},
+{0x301e,0x00}, //pll
+{0x301f,0x20}, //pll 0x20 48Mhz 0x24 32Mhz
+{0x3022,0x25},
+{0x3023,0x64},
+ {0x3002,0x00},
+ {0x3003,0x04},
+ {0x3004,0x00},
+ {0x3005,0x04},
+ {0x3006,0x06},
+ {0x3007,0x43},
+ {0x3008,0x04},
+ {0x3009,0xb3},
+ {0x300a,0x09},
+ {0x300b,0x91},
+ {0x300c,0x02},
+ {0x300d,0x64},
+ {0x300e,0x06},
+ {0x300f,0x40},
+ {0x3010,0x02},
+ {0x3011,0x58},
+{0x32bb,0x0b},
+{0x32bc,0x30},
+{0x32c1,0x25},
+{0x32c2,0x5c}, //7.14fps @ 48M
+//{0x32c1,0x23},
+//{0x32c2,0xd4}, //10fps @ 48M
+{0x32c8,0x62},
+{0x32c9,0x52},
+{0x32c4,0x00},
+//{0x3290,0x01}, //awb init ++++
+//{0x3291,0x68},
+//{0x3296,0x01},
+//{0x3297,0x75},
+{0x32A9,0x11},
+{0x32AA,0x01},
+{0x329b,0x01},
+{0x32a2,0x60},
+{0x32a4,0xa0},
+{0x32a6,0x60},
+{0x32a8,0xa0}, //awb init ----
+//{0x3012,0x02}, //AE init +++
+//{0x3013,0xae},
+//{0x301d,0x08},
+//{0x3201,0x7f}, //AE init ---
+{0x3021,0x06},
+{0x3060,0x01},
+ {0x0, 0x0},
+ {0x0, 0x0},
+};
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+//[640X480]
+//edge & denoise +++
+{0x3300,0x30},
+{0x3301,0x80},
+{0x3320,0x28},
+{0x3331,0x04},
+{0x3332,0x40},
+{0x3339,0x10},
+{0x333a,0x1a},
+//edge & denoise ---
+//AE AWB mode ++
+{0x329C,0x4b},
+{0x32bf,0x52},
+{0x32c0,0x10},
+{0x3200,0x3e},
+//{0x3201,0x3f},
+{0x32b0,0x02},
+{0x32b1,0xc0},
+//AE AWB mode ---
+{0x3052,0x80}, //OB
+{0x32e0,0x02},
+{0x32e1,0x80},
+{0x32e2,0x01},
+{0x32e3,0xe0},
+{0x32e4,0x01},
+{0x32e5,0x81},
+{0x32e6,0x00},
+{0x32e7,0x40},
+{0x301e,0x00}, //pll
+{0x301f,0x20}, //pll 0x20 48Mhz 0x24 32Mhz
+{0x3022,0x25},
+{0x3023,0x64},
+{0x3002,0x00},
+{0x3003,0x04},
+{0x3004,0x00},
+{0x3005,0x04},
+{0x3006,0x06},
+{0x3007,0x43},
+{0x3008,0x04},
+{0x3009,0xb3},
+{0x300a,0x09},
+{0x300b,0x91},
+{0x300c,0x02},
+{0x300d,0x91},
+{0x300e,0x06},
+{0x300f,0x40},
+{0x3010,0x02},
+{0x3011,0x58},
+{0x32bb,0x0b},
+{0x32bc,0x30},
+//{0x32c1,0x25},
+//{0x32c2,0x5c}, //7.14fps @ 48M
+{0x32c1,0x23},
+{0x32c2,0xd4}, //10fps @ 48M
+{0x32c8,0x62},
+{0x32c9,0x52},
+{0x32c4,0x00},
+//{0x3290,0x01}, //awb init ++++
+//{0x3291,0x68},
+//{0x3296,0x01},
+//{0x3297,0x75},
+{0x32A9,0x11},
+{0x32AA,0x01},
+{0x329b,0x01},
+{0x32a2,0x60},
+{0x32a4,0xa0},
+{0x32a6,0x60},
+{0x32a8,0xa0}, //awb init ----
+//{0x3012,0x02}, //AE init +++
+//{0x3013,0xae},
+//{0x301d,0x08},
+//{0x3201,0x7f}, //AE init ---
+{0x3021,0x06},
+{0x3060,0x01},
+ {0x0, 0x0},
+};
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{
+ {0x0, 0x0},
+};
+
+/* 320*240 QVGA */
+static struct reginfo sensor_qvga[] =
+{
+ {0x0, 0x0},
+};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{
+ {0x0, 0x0},
+};
+
+
+static struct reginfo sensor_ClrFmt_YUYV[]=
+{
+ {0x32f0, 0x00}, //0:UYVY 2:VYUY 1:YUYV 3:YVYU
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_ClrFmt_UYVY[]=
+{
+ {0x32F0, 0x00}, //0:UYVY 2:VYUY 1:YUYV 3:YVYU
+ {0x0000, 0x00}
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static struct reginfo sensor_WhiteB_Auto[]=
+{
+ {0x3201, 0x3f}, //AWB auto, bit[1]:0,auto
+ {0x0000, 0x00}
+};
+/* Cloudy Colour Temperature : 6500K - 8000K */
+static struct reginfo sensor_WhiteB_Cloudy[]=
+{
+ {0x3201, 0x2f},
+ {0x3290, 0x01},
+ {0x3291, 0x48},
+ {0x3296, 0x01},
+ {0x3297, 0x58},
+ {0x0000, 0x00}
+};
+/* ClearDay Colour Temperature : 5000K - 6500K */
+static struct reginfo sensor_WhiteB_ClearDay[]=
+{
+ //Sunny
+ {0x3201, 0x2f},
+ {0x3290, 0x01},
+ {0x3291, 0x38},
+ {0x3296, 0x01},
+ {0x3297, 0x68},
+ {0x0000, 0x00}
+
+};
+/* Office Colour Temperature : 3500K - 5000K */
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+ //Office
+ {0x3201, 0x2f},
+ {0x3290, 0x01},
+ {0x3291, 0x24},
+ {0x3296, 0x01},
+ {0x3297, 0x78},
+ {0x0000, 0x00}
+
+};
+/* Home Colour Temperature : 2500K - 3500K */
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+ //Home
+ {0x3201, 0x2f},
+ {0x3290, 0x01},
+ {0x3291, 0x30},
+ {0x3296, 0x01},
+ {0x3297, 0x70},
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static struct reginfo sensor_Brightness0[]=
+{
+ // Brightness -2
+ {0x32f1, 0x05},
+ {0x32f2, 0x60},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Brightness1[]=
+{
+ // Brightness -1
+ {0x32f1, 0x05},
+ {0x32f2, 0x70},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Brightness2[]=
+{
+ // Brightness 0
+ {0x32f1, 0x05},
+ {0x32f2, 0x80},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Brightness3[]=
+{
+ // Brightness +1
+ {0x32f1, 0x05},
+ {0x32f2, 0x90},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Brightness4[]=
+{
+ // Brightness +2
+ {0x32f1, 0x05},
+ {0x32f2, 0xa0},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Brightness5[]=
+{
+ // Brightness +3
+ {0x32f1, 0x05},
+ {0x32f2, 0xb0},
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+ sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static struct reginfo sensor_Effect_Normal[] =
+{
+ {0x32f1, 0x00},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Effect_WandB[] =
+{
+ {0x32f1, 0x01},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Effect_Sepia[] =
+{
+ {0x32f1, 0x02},
+ {0x32f6, 0x20},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Effect_Negative[] =
+{
+ //Negative
+ {0x32f1, 0x03},
+ {0x32f6, 0x10},
+ {0x0000, 0x00}
+};
+static struct reginfo sensor_Effect_Bluish[] =
+{
+ // Bluish
+ {0x32f1, 0x05},
+ {0x32f6, 0x04},
+ {0x32f4, 0x80},
+ {0x32f6, 0x0c},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Effect_Green[] =
+{
+ // Greenish
+ {0x32f1, 0x05},
+ {0x32f4, 0x60},
+ {0x32f5, 0x20},
+ {0x32f6, 0x0c},
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static struct reginfo sensor_Exposure0[]=
+{
+ //-3
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure1[]=
+{
+ //-2
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure2[]=
+{
+ //-0.3EV
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure3[]=
+{
+ //default
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure4[]=
+{
+ // 1
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure5[]=
+{
+ // 2
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Exposure6[]=
+{
+ // 3
+ {0x0000, 0x00}
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static struct reginfo sensor_Saturation0[]=
+{
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Saturation1[]=
+{
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Saturation2[]=
+{
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static struct reginfo sensor_Contrast0[]=
+{
+ //Contrast -3
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Contrast1[]=
+{
+ //Contrast -2
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Contrast2[]=
+{
+ // Contrast -1
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Contrast3[]=
+{
+ //Contrast 0
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Contrast4[]=
+{
+ //Contrast +1
+ {0x0000, 0x00}
+};
+
+
+static struct reginfo sensor_Contrast5[]=
+{
+ //Contrast +2
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_Contrast6[]=
+{
+ //Contrast +3
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static struct reginfo sensor_MirrorOn[]=
+{
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_MirrorOff[]=
+{
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static struct reginfo sensor_FlipOn[]=
+{
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_FlipOff[]=
+{
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static struct reginfo sensor_SceneAuto[] =
+{
+ {0x301e, 0x00},
+ {0x0000, 0x00}
+};
+
+static struct reginfo sensor_SceneNight[] =
+{
+ //30fps ~ 5fps night mode for 60/50Hz light environment, 24Mhz clock input,36Mzh pclk
+ {0x301e, 0x04},
+ {0x0000, 0x00}
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+ {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+ {0x0, 0x0},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+ {0x0, 0x0},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},
+ #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+ #if CONFIG_SENSOR_WhiteBalance
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White Balance Control",
+ .minimum = 0,
+ .maximum = 4,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Brightness
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness Control",
+ .minimum = -3,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Effect
+ {
+ .id = V4L2_CID_EFFECT,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Effect Control",
+ .minimum = 0,
+ .maximum = 5,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Exposure
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure Control",
+ .minimum = 0,
+ .maximum = 6,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Saturation
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation Control",
+ .minimum = 0,
+ .maximum = 2,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Contrast
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast Control",
+ .minimum = -3,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Mirror
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flip
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Flip Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Scene
+ {
+ .id = V4L2_CID_SCENE,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Scene Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_DigitalZoom
+ {
+ .id = V4L2_CID_ZOOM_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_ZOOM_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "DigitalZoom Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Focus
+ {
+ .id = V4L2_CID_FOCUS_RELATIVE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = -1,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_FOCUS_ABSOLUTE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 125,
+ },
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ {
+ .id = V4L2_CID_FLASH,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Flash Control",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ },
+ #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+ .suspend = sensor_suspend,
+ .resume = sensor_resume,
+ .set_bus_param = sensor_set_bus_param,
+ .query_bus_param = sensor_query_bus_param,
+ .controls = sensor_controls,
+ .menus = sensor_menus,
+ .num_controls = ARRAY_SIZE(sensor_controls),
+ .num_menus = ARRAY_SIZE(sensor_menus),
+};
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+ .colorspace = _colorspace }
+
+#define JPG_FMT(_name, _depth, _fourcc) \
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+
+static const struct soc_camera_data_format sensor_colour_formats[] = {
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
+};
+
+typedef struct sensor_info_priv_s
+{
+ int whiteBalance;
+ int brightness;
+ int contrast;
+ int saturation;
+ int effect;
+ int scene;
+ int digitalzoom;
+ int focus;
+ int flash;
+ int exposure;
+ bool snap2preview;
+ bool video2preview;
+ unsigned char mirror; /* HFLIP */
+ unsigned char flip; /* VFLIP */
+ unsigned int winseqe_cur_addr;
+ unsigned int pixfmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+ struct v4l2_subdev subdev;
+ struct i2c_client *client;
+ sensor_info_priv_t info_priv;
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+ return 0;
+sensor_task_lock_err:
+ return -1;
+#else
+ return 0;
+#endif
+
+}
+
+/* sensor register write */
+static int sensor_write(struct i2c_client *client, u16 reg, u8 val)
+{
+ int err,cnt;
+ u8 buf[3];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+ buf[2] = val;
+
+ msg->addr = client->addr;
+ msg->flags = client->flags;
+ msg->buf = buf;
+ msg->len = sizeof(buf);
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 8;
+ err = -EAGAIN;
+
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0) {
+ return 0;
+ } else {
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+ int err,cnt;
+ u8 buf[2];
+ struct i2c_msg msg[2];
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].buf = buf;
+ msg[0].len = sizeof(buf);
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags|I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = 1;
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+ cnt = 3;
+ err = -EAGAIN;
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ if (err >= 0) {
+ *val = buf[0];
+ return 0;
+ } else {
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+ udelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* write a array of registers */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int err = 0, cnt;
+ int i = 0;
+#if CONFIG_SENSOR_I2C_RDWRCHK
+ char valchk;
+#endif
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
+
+ while (regarray[i].reg != 0)
+ {
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);
+ if (err < 0)
+ {
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
+ }
+ i++;
+ }
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
+ return 0;
+}
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+ char value;
+ int ret,pid = 0;
+
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ /* soft reset */
+ sensor_task_lock(client,1);
+ ret = sensor_write(client, 0x3021, 0x61);
+ if (ret != 0)
+ {
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ mdelay(5); //delay 5 microseconds
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x307e, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ pid |= (value << 8);
+
+ ret = sensor_read(client, 0x307f, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id low byte failed\n");
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
+ pid |= (value & 0xff);
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ #if 1
+ if (pid == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+ #endif
+
+ ret = sensor_write_array(client, sensor_init_data);
+ if (ret != 0)
+ {
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+ goto sensor_INIT_ERR;
+ }
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
+
+ /* sensor sensor information for initialization */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ if (qctrl)
+ sensor->info_priv.whiteBalance = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+ if (qctrl)
+ sensor->info_priv.brightness = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ if (qctrl)
+ sensor->info_priv.effect = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+ if (qctrl)
+ sensor->info_priv.exposure = qctrl->default_value;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+ if (qctrl)
+ sensor->info_priv.saturation = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+ if (qctrl)
+ sensor->info_priv.contrast = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+ if (qctrl)
+ sensor->info_priv.mirror = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+ if (qctrl)
+ sensor->info_priv.flip = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+ if (qctrl)
+ sensor->info_priv.scene = qctrl->default_value;
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.digitalzoom = qctrl->default_value;
+
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
+ #if CONFIG_SENSOR_Focus
+ sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (qctrl)
+ sensor->info_priv.focus = qctrl->default_value;
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+ if (qctrl)
+ sensor->info_priv.flash = qctrl->default_value;
+ #endif
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+ return 0;
+sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
+ return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+ //u8 reg_val;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
+
+static struct reginfo sensor_power_down_sequence[]=
+{
+ //{0x30ab, 0x00},
+ //{0x30ad, 0x0a},
+ //{0x30ae,0x27},
+ //{0x363b,0x01},
+ {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;
+ if (ret != 0) {
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+ return ret;
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ }
+ } else {
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+ int ret;
+
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+ return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+
+ return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ unsigned long flags = SENSOR_BUS_PARAM;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = icd->user_width;
+ pix->height = icd->user_height;
+ pix->pixelformat = sensor->info_priv.pixfmt;
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct reginfo *winseqe_set_addr=NULL;
+ char readval;
+ int ret=0, set_w,set_h;
+
+u16 AE_reg, AGC_reg;
+ u8 temp_reg12,temp_reg13;
+ u16 shutter,reg_1, reg;
+
+ //turn on scaler for preivew
+ sensor_read(client ,0x3201, ®_1);
+ sensor_write(client, 0x3201, (reg_1|0x40) );
+ //for preview
+ sensor_read(client ,0x32f1, ®);
+ sensor_write(client, 0x32f1, (reg|0x10) );
+
+ #if 0 //preview_fastmode
+ // turn off AE for preview
+ sensor_read(client ,0x3201, &AE_reg);
+ sensor_write(client, 0x3201, (AE_reg|0x20) );
+ // turn off AGC for preview
+ sensor_read(client ,0x32bb, &AGC_reg);
+ sensor_write(client, 0x32bb, (AGC_reg|0x01) );
+
+ sensor_read(client, 0x3012, &temp_reg12);
+ sensor_read(client, 0x3013, &temp_reg13);
+ shutter = (temp_reg13 & 0x00FF) | (temp_reg12 << 8);
+ #endif
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {
+ switch (pix->pixelformat)
+ {
+ case V4L2_PIX_FMT_YUYV:
+ {
+ winseqe_set_addr = sensor_ClrFmt_YUYV;
+ break;
+ }
+ case V4L2_PIX_FMT_UYVY:
+ {
+ winseqe_set_addr = sensor_ClrFmt_UYVY;
+ break;
+ }
+ default:
+ break;
+ }
+ if (winseqe_set_addr != NULL) {
+ sensor_write_array(client, winseqe_set_addr);
+ sensor->info_priv.pixfmt = pix->pixelformat;
+
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ } else {
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);
+ }
+ }
+
+ set_w = pix->width;
+ set_h = pix->height;
+
+ if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[0].reg)
+ {
+ winseqe_set_addr = sensor_qcif;
+ set_w = 176;
+ set_h = 144;
+ }
+ else if (((set_w <= 320) && (set_h <= 240)) && sensor_qvga[0].reg)
+ {
+ winseqe_set_addr = sensor_qvga;
+ set_w = 320;
+ set_h = 240;
+ }
+ else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[0].reg)
+ {
+ winseqe_set_addr = sensor_cif;
+ set_w = 352;
+ set_h = 288;
+ }
+ else if (((set_w <= 640) && (set_h <= 480)) && sensor_vga[0].reg)
+ {
+ winseqe_set_addr = sensor_vga;
+ set_w = 640;
+ set_h = 480;
+ }
+ else if (((set_w <= 800) && (set_h <= 600)) && sensor_svga[0].reg)
+ {
+ winseqe_set_addr = sensor_svga;
+ set_w = 800;
+ set_h = 600;
+ }
+ else if (((set_w <= 1280) && (set_h <= 1024)) && sensor_sxga[0].reg)
+ {
+ winseqe_set_addr = sensor_sxga;
+ set_w = 1280;
+ set_h = 1024;
+ }
+ else if (((set_w <= 1600) && (set_h <= 1200)) && sensor_uxga[0].reg)
+ {
+ winseqe_set_addr = sensor_uxga;
+ set_w = 1600;
+ set_h = 1200;
+ }
+ else
+ {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
+ ret = -1;
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
+ }
+
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ ret |= sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ }
+
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+
+ if ((set_w <= 640) && (set_h <= 480))
+ {
+ shutter = shutter;
+ }
+ else
+ {
+ //for capture
+ sensor_read(client ,0x32f1, ®);
+ sensor_write(client, 0x32f1, (reg&(~0x10)) );
+ if ((set_w <= 1600) && (set_h <= 1200))
+ {
+ //turn off scaler for UXGA capture
+ sensor_read(client ,0x3201, ®_1);
+ sensor_write(client, 0x3201, (reg_1&(~0x40)) );
+ }
+ #if 0 //preview_fastmode
+ // turn off AE
+ sensor_read(client ,0x3201, &AE_reg);
+ sensor_write(client, 0x3201, (AE_reg&(~0x20)) );
+ // turn off AGC
+ sensor_read(client ,0x32bb, &AGC_reg);
+ sensor_write(client, 0x32bb, (AGC_reg&(~0x01)) );
+ if ((set_w <= 800) && (set_h <= 600))
+ {
+ shutter = shutter*1984/2434;
+ }
+ else if ((set_w <= 2434) && (set_h <= 1024))
+ {
+ shutter = shutter*1984/2434;
+ }
+ else if ((set_w <= 1600) && (set_h <= 1200))
+ {
+ shutter = shutter*1984/2434;
+ }
+ if (shutter < 1)
+ {
+ shutter = 1;
+ }
+ sensor_write(client, 0x3012, sizeof((shutter >> 8) & 0xff) );
+ sensor_write(client, 0x3013, sizeof(shutter & 0xFF) );
+ #endif
+ }
+ mdelay(250);
+
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+ }
+ else
+ {
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ }
+
+ pix->width = set_w;
+ pix->height = set_h;
+
+sensor_s_fmt_end:
+ return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;
+
+ /*
+ * With Bayer format enforce even side lengths, but let the user play
+ * with the starting pixel
+ */
+
+ if (pix->height > SENSOR_MAX_HEIGHT)
+ pix->height = SENSOR_MAX_HEIGHT;
+ else if (pix->height < SENSOR_MIN_HEIGHT)
+ pix->height = SENSOR_MIN_HEIGHT;
+ else if (bayer)
+ pix->height = ALIGN(pix->height, 2);
+
+ if (pix->width > SENSOR_MAX_WIDTH)
+ pix->width = SENSOR_MAX_WIDTH;
+ else if (pix->width < SENSOR_MIN_WIDTH)
+ pix->width = SENSOR_MIN_WIDTH;
+ else if (bayer)
+ pix->width = ALIGN(pix->width, 2);
+/*not support 720p video*/
+ if(pix->height == 720 && pix->width == 1280){
+ pix->height = 480;
+ pix->width = 640;
+ }
+ return 0;
+}
+
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+ struct i2c_client *client = sd->priv;
+
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+ return -EINVAL;
+
+ if (id->match.addr != client->addr)
+ return -ENODEV;
+
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */
+ id->revision = 0;
+
+ return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+ {
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+ {
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+ }
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ int digitalzoom_cur, digitalzoom_total;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+ if (qctrl_info)
+ return -EINVAL;
+
+ digitalzoom_cur = sensor->info_priv.digitalzoom;
+ digitalzoom_total = qctrl_info->maximum;
+
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+ {
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+ {
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+ return -EINVAL;
+ }
+
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+ {
+ *value = digitalzoom_total - digitalzoom_cur;
+ }
+
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+ {
+ *value = 0 - digitalzoom_cur;
+ }
+
+ digitalzoom_cur += *value;
+
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+ {
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+ {
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+ return -EINVAL;
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+ case V4L2_CID_BRIGHTNESS:
+ {
+ ctrl->value = sensor->info_priv.brightness;
+ break;
+ }
+ case V4L2_CID_SATURATION:
+ {
+ ctrl->value = sensor->info_priv.saturation;
+ break;
+ }
+ case V4L2_CID_CONTRAST:
+ {
+ ctrl->value = sensor->info_priv.contrast;
+ break;
+ }
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ ctrl->value = sensor->info_priv.whiteBalance;
+ break;
+ }
+ case V4L2_CID_EXPOSURE:
+ {
+ ctrl->value = sensor->info_priv.exposure;
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ {
+ ctrl->value = sensor->info_priv.mirror;
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ {
+ ctrl->value = sensor->info_priv.flip;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+ const struct v4l2_queryctrl *qctrl;
+
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ctrl->id)
+ {
+#if CONFIG_SENSOR_Brightness
+ case V4L2_CID_BRIGHTNESS:
+ {
+ if (ctrl->value != sensor->info_priv.brightness)
+ {
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.brightness = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Exposure
+ case V4L2_CID_EXPOSURE:
+ {
+ if (ctrl->value != sensor->info_priv.exposure)
+ {
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.exposure = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Saturation
+ case V4L2_CID_SATURATION:
+ {
+ if (ctrl->value != sensor->info_priv.saturation)
+ {
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.saturation = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Contrast
+ case V4L2_CID_CONTRAST:
+ {
+ if (ctrl->value != sensor->info_priv.contrast)
+ {
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.contrast = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+ case V4L2_CID_DO_WHITE_BALANCE:
+ {
+ if (ctrl->value != sensor->info_priv.whiteBalance)
+ {
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+ {
+ return -EINVAL;
+ }
+ sensor->info_priv.whiteBalance = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Mirror
+ case V4L2_CID_HFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.mirror)
+ {
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.mirror = ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flip
+ case V4L2_CID_VFLIP:
+ {
+ if (ctrl->value != sensor->info_priv.flip)
+ {
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flip = ctrl->value;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ switch (ext_ctrl->id)
+ {
+ case V4L2_CID_SCENE:
+ {
+ ext_ctrl->value = sensor->info_priv.scene;
+ break;
+ }
+ case V4L2_CID_EFFECT:
+ {
+ ext_ctrl->value = sensor->info_priv.effect;
+ break;
+ }
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.digitalzoom;
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ ext_ctrl->value = sensor->info_priv.focus;
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ return -EINVAL;
+ }
+ case V4L2_CID_FLASH:
+ {
+ ext_ctrl->value = sensor->info_priv.flash;
+ break;
+ }
+ default :
+ break;
+ }
+ return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+ const struct v4l2_queryctrl *qctrl;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int val_offset;
+
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+ if (!qctrl)
+ {
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ return -EINVAL;
+ }
+
+ val_offset = 0;
+ switch (ext_ctrl->id)
+ {
+#if CONFIG_SENSOR_Scene
+ case V4L2_CID_SCENE:
+ {
+ if (ext_ctrl->value != sensor->info_priv.scene)
+ {
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.scene = ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Effect
+ case V4L2_CID_EFFECT:
+ {
+ if (ext_ctrl->value != sensor->info_priv.effect)
+ {
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.effect= ext_ctrl->value;
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+ case V4L2_CID_ZOOM_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += val_offset;
+
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+
+ break;
+ }
+ case V4L2_CID_ZOOM_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Focus
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ {
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
+
+ if (ext_ctrl->value != sensor->info_priv.focus)
+ {
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+ sensor->info_priv.focus += val_offset;
+ }
+
+ break;
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
+ {
+ if (ext_ctrl->value)
+ {
+ sensor->info_priv.focus += ext_ctrl->value;
+
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+ }
+ break;
+ }
+#endif
+#if CONFIG_SENSOR_Flash
+ case V4L2_CID_FLASH:
+ {
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
+ sensor->info_priv.flash = ext_ctrl->value;
+
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ int i, error_cnt=0, error_idx=-1;
+
+
+ for (i=0; i<ext_ctrl->count; i++) {
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+ error_cnt++;
+ error_idx = i;
+ }
+ }
+
+ if (error_cnt > 1)
+ error_idx = ext_ctrl->count;
+
+ if (error_idx != -1) {
+ ext_ctrl->error_idx = error_idx;
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
+{
+ char value;
+ int ret,pid = 0;
+ struct sensor *sensor = to_sensor(client);
+
+ /* We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant. */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ /* soft reset */
+ ret = sensor_write(client, 0x3021, 0x61);
+ if (ret != 0)
+ {
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+ return -ENODEV;
+ }
+ mdelay(5); //delay 5 microseconds
+
+ /* check if it is an sensor sensor */
+ ret = sensor_read(client, 0x307e, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id high byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ pid |= (value << 8);
+
+ ret = sensor_read(client, 0x307f, &value);
+ if (ret != 0) {
+ SENSOR_TR("read chip id low byte failed\n");
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ pid |= (value & 0xff);
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ if (pid == SENSOR_ID) {
+ sensor->model = SENSOR_V4L2_IDENT;
+ } else {
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
+
+ icd->formats = sensor_colour_formats;
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);
+
+ return 0;
+
+sensor_video_probe_err:
+
+ return ret;
+}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_ioctl_end:
+ return ret;
+
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+ .init = sensor_init,
+ .g_ctrl = sensor_g_control,
+ .s_ctrl = sensor_s_control,
+ .g_ext_ctrls = sensor_g_ext_controls,
+ .s_ext_ctrls = sensor_s_ext_controls,
+ .g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+ .s_fmt = sensor_s_fmt,
+ .g_fmt = sensor_g_fmt,
+ .try_fmt = sensor_try_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+ .core = &sensor_subdev_core_ops,
+ .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+{
+ struct sensor *sensor;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
+ int ret;
+
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ dev_warn(&adapter->dev,
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+ return -EIO;
+ }
+
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+ if (!sensor)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+ /* Second stage probe - when a capture adapter is there */
+ icd->ops = &sensor_ops;
+ icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
+
+ ret = sensor_video_probe(icd, client);
+ if (ret < 0) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(sensor);
+ sensor = NULL;
+ }
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+ return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
+ kfree(sensor);
+ sensor = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+ {SENSOR_NAME_STRING(), 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+ .driver = {
+ .name = SENSOR_NAME_STRING(),
+ },
+ .probe = sensor_probe,
+ .remove = sensor_remove,
+ .id_table = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+ return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+ i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("ddl <kernel@rock-chips>");
+MODULE_LICENSE("GPL");
#include <linux/delay.h>
#include <linux/circ_buf.h>
#include <linux/miscdevice.h>
-
-
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+#include "ov3640.h"
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
#define _CONS(a,b) a##b
#define CONS(a,b) _CONS(a,b)
#define _STR(x) __STR(x)
#define STR(x) _STR(x)
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
/* Sensor Driver Configuration */
-#define SENSOR_NAME ov3640
+#define SENSOR_NAME RK29_CAM_SENSOR_OV3640
#define SENSOR_V4L2_IDENT V4L2_IDENT_OV3640
#define SENSOR_ID 0x364c
#define SENSOR_MIN_WIDTH 176
#define CONFIG_SENSOR_Effect 1
#define CONFIG_SENSOR_Scene 1
#define CONFIG_SENSOR_DigitalZoom 0
-#define CONFIG_SENSOR_Focus 0
#define CONFIG_SENSOR_Exposure 0
-#define CONFIG_SENSOR_Flash 0
+#define CONFIG_SENSOR_Flash 1
#define CONFIG_SENSOR_Mirror 0
#define CONFIG_SENSOR_Flip 0
-#define CONFIG_SENSOR_I2C_SPEED 200000 /* Hz */
-
-#define CONFIG_SENSOR_TR 1
-#define CONFIG_SENSOR_DEBUG 1
-
-#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
-#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
-
-#define MIN(x,y) ((x<y) ? x: y)
-#define MAX(x,y) ((x>y) ? x: y)
-
-#if (CONFIG_SENSOR_TR)
- #define SENSOR_TR(format, ...) printk(format, ## __VA_ARGS__)
- #if (CONFIG_SENSOR_DEBUG)
- #define SENSOR_DG(format, ...) printk(format, ## __VA_ARGS__)
- #else
- #define SENSOR_DG(format, ...)
- #endif
+#ifdef CONFIG_OV3640_AUTOFOCUS
+#define CONFIG_SENSOR_Focus 1
+#include "ov3640_af_firmware.c"
#else
- #define SENSOR_TR(format, ...)
+#define CONFIG_SENSOR_Focus 0
#endif
+#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
+
+
#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)
#define COLOR_TEMPERATURE_HOME_DN 2500
#define COLOR_TEMPERATURE_HOME_UP 3500
-struct reginfo
-{
- u16 reg;
- u8 val;
-};
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+#define SENSOR_AF_IS_ERR (0x00<<0)
+#define SENSOR_AF_IS_OK (0x01<<0)
+
+#if CONFIG_SENSOR_Focus
+#define SENSOR_AF_MODE_INFINITY 0
+#define SENSOR_AF_MODE_MACRO 1
+#define SENSOR_AF_MODE_FIXED 2
+#define SENSOR_AF_MODE_AUTO 3
+#define SENSOR_AF_MODE_CONTINUOUS 4
+#define SENSOR_AF_MODE_CLOSE 5
+
+#endif
+
+#define VCM_FIRMWARE 1
+
+#define VCM_STARTADDR 0x8000
+
+#define S_IDLE 0x00
+#if (VCM_FIRMWARE==1)
+#define S_FOCUSING 0x01
+#define S_FOCUSED 0x02
+#define S_CAPTURE 0x12
+#define STA_FOCUS 0x3f07
+#elif (VCM_FIRMWARE==2)
+#define S_FOCUSING 0x01
+#define S_FOCUSED 0x02
+#define S_CAPTURE 0x12
+#define STA_FOCUS 0x3f01
+#else
+#define S_FOCUSING 0x65
+#define S_FOCUSED 0x46
+#define S_CAPTURE 0x47
+#define STA_FOCUS 0x3f01
+#endif
+
+
+#if CONFIG_SENSOR_Focus
+/* ov3640 VCM Command and Status Registers */
+#define CMD_MAIN_Reg 0x3F00
+#define CMD_TAG_Reg 0x3F01
+#define CMD_PARA0_Reg 0x3F05
+#define CMD_PARA1_Reg 0x3F04
+#define CMD_PARA2_Reg 0x3F03
+#define CMD_PARA3_Reg 0x3F02
+#define STA_ZONE_Reg 0x3F06
+#define STA_FOCUS_Reg 0x3F07
+
+/* ov3640 VCM Command */
+#define OverlayEn_Cmd 0x01
+#define OverlayDis_Cmd 0x02
+#define SingleFocus_Cmd 0x03
+#define ConstFocus_Cmd 0x04
+#define StepMode_Cmd 0x05
+#define PauseFocus_Cmd 0x06
+#define ReturnIdle_Cmd 0x08
+#define SetZone_Cmd 0x10
+#define UpdateZone_Cmd 0x12
+#define SetMotor_Cmd 0x20
+
+/* ov3640 Focus State */
+#define S_FIRWRE 0xFF
+#define S_STARTUP 0xFA
+#define S_ERROR 0xFE
+#define S_DRVICERR 0xEE
+#define S_IDLE 0x00
+#define S_FOCUSING 0x01
+#define S_FOCUSED 0x02
+#define S_CAPTURE 0x12
+#define S_STEP 0x20
+
+/* ovxxxx Zone State */
+#define Zone_Is_Focused(a, zone_val) (zone_val&(1<<(a-3)))
+#define Zone_Get_ID(zone_val) (zone_val&0x03)
+
+#define Zone_CenterMode 0x01
+#define Zone_5xMode 0x02
+#define Zone_5PlusMode 0x03
+#define Zone_4fMode 0x04
+
+#define ZoneSel_Auto 0x0b
+#define ZoneSel_SemiAuto 0x0c
+#define ZoneSel_Manual 0x0d
+#define ZoneSel_Rotate 0x0e
+
+/* ovxxxx Step Focus Commands */
+#define StepFocus_Near_Tag 0x01
+#define StepFocus_Far_Tag 0x02
+#define StepFocus_Furthest_Tag 0x03
+#define StepFocus_Nearest_Tag 0x04
+#define StepFocus_Spec_Tag 0x10
+#endif
/* init VGA 640*480 */
static struct reginfo sensor_init_data[] =
{
+#if 1
{0x3078, 0x02},
{0x304d, 0x45},
{0x30a7, 0x5e},
{0x30aa, 0x42},
{0x30b0, 0xff},
{0x30b1, 0xff},
- {0x30b2, 0x10},
+ //{0x30b2, 0x10},
+ {0x30b2, 0x18}, // by FAE
{0x300e, 0x39},
{0x300f, 0x21},
{0x3010, 0x20},
{0x3018, 0x48},
{0x3019, 0x40},
{0x301a, 0x82},
+
+ {0x30a9, 0xbd},//disable internal DVDD, by FAE.
+
{0x307d, 0x00},
{0x3087, 0x02},
{0x3082, 0x20},
{0x332e, 0x04},
{0x332f, 0x06},
{0x3331, 0x03},
-
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror ,by FAE.
+ {0x3090, 0xc8},
+#else
+//640 480 ;XGA->XGA;;
+ {0x3012, 0x10},
+ {0x3023, 0x06},
+ {0x3026, 0x03},
+ {0x3027, 0x04},
+ {0x302a, 0x03},
+ {0x302b, 0x10},
+ {0x3075, 0x24},
+ {0x300d, 0x01},
+ {0x30d7, 0x90},
+ {0x3069, 0x04},
+ {0x303e, 0x00},
+ {0x303f, 0xc0},
+ {0x3302, 0xef},
+ {0x335f, 0x34},
+ {0x3360, 0x0c},
+ {0x3361, 0x04},
+ {0x3362, 0x34},
+ {0x3363, 0x08},
+ {0x3364, 0x04},
+ {0x3403, 0x42},
+ {0x3088, 0x04},
+ {0x3089, 0x00},
+ {0x308a, 0x03},
+ {0x308b, 0x00},
+ {0x300e, 0x32},
+ {0x300f, 0x21},
+ {0x3010, 0x20},
+ {0x3011, 0x01},
+ {0x304c, 0x82},
+
+//;XGA->VGA
+ {0x3302, 0xef},
+ {0x335f, 0x34},
+ {0x3360, 0x0c},
+ {0x3361, 0x04},
+ {0x3362, 0x12},
+ {0x3363, 0x88},
+ {0x3364, 0xe4},
+ {0x3403, 0x42},
+ {0x3088, 0x12},
+ {0x3089, 0x80},
+ {0x308a, 0x01},
+ {0x308b, 0xe0},
+ {0x304c, 0x85},
+#endif
{0x0000 ,0x00},
};
/* 2048X1536 QXGA */
static struct reginfo sensor_qxga_preview[] =
{
+#if 1
{0x3012, 0x00},
{0x3366, 0x10},
{0x3020, 0x01},
{0x3010, 0x20},
{0x3011, 0x01},
{0x304c, 0x81},
-
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
+
+#else
+//[Sensor.YUV.2048x1536] XGA->QXGA
+ {0x3012, 0x00},
+ {0x3020, 0x01},
+ {0x3021, 0x1d},
+ {0x3022, 0x00},
+ {0x3023, 0x0a},
+ {0x3024, 0x08},
+ {0x3025, 0x18},
+ {0x3026, 0x06},
+ {0x3027, 0x0c},
+ {0x302a, 0x06},
+ {0x302b, 0x20},
+ {0x3075, 0x44},
+ {0x300d, 0x00},
+ {0x30d7, 0x10},
+ {0x3069, 0x44},
+ {0x303e, 0x01},
+ {0x303f, 0x80},
+ {0x3302, 0xcf},
+ {0x335f, 0x68},
+ {0x3360, 0x18},
+ {0x3361, 0x0c},
+ {0x3362, 0x68},
+ {0x3363, 0x08},
+ {0x3364, 0x04},
+ {0x3403, 0x42},
+ {0x3088, 0x08},
+ {0x3089, 0x00},
+ {0x308a, 0x06},
+ {0x308b, 0x00},
+ {0x300e, 0x39},
+ {0x300f, 0x21},
+ {0x3010, 0x20},
+ {0x3011, 0x01},
+ {0x304c, 0x81},
+#endif
{0x0000 ,0x00}
};
static struct reginfo sensor_qxga_capture[] = {
{0x302a, 0x06},
{0x302b, 0x20},
{0x3075, 0x44},
+ //{0x307C, 0x13}, // by FAE.
{0x300d, 0x00},
{0x30d7, 0x10},
{0x3069, 0x44},
{0x3010, 0x20},
{0x3011, 0x01},
{0x304c, 0x81},
+
+ //{0x307c, 0x13},// flip && mirror
+ {0x307c, 0x11},// flip && mirror , by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00}
};
{0x308a, 0x04},
{0x308b, 0xb0},
{0x304c, 0x81},//56Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x04},
{0x308b, 0xb0},
{0x304c, 0x81},//56Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror, by FAE.
+ {0x307c, 0x11},
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x03},
{0x308b, 0xc0},
{0x304c, 0x81},//56Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x03},
{0x308b, 0xc0},
{0x304c, 0x81},//56Mhz PCLK output
-
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo *sensor_sxga[2] = {
{0x308a, 0x03},
{0x308b, 0x00},
{0x304c, 0x82},//28Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11},// by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x03},
{0x308b, 0x00},
{0x304c, 0x82},//28Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308b, 0x58},
{0x304c, 0x83},//28Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo sensor_svga_capture[] =
{0x308b, 0x58},
{0x304c, 0x82},//28Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo * sensor_svga[2] = {
{0x3364, 0xe4},
{0x3403, 0x42},
{0x3088, 0x02},
- {0x3089, 0x80},
+ {0x3089, 0x88},// 0x80, by FAE.
{0x308a, 0x01},
- {0x308b, 0xe0},
- {0x304c, 0x83}, //85
+ {0x308b, 0xe4},// 0xe0, by FAE.
+ {0x304c, 0x84}, //0x83, by FAE.
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
+// by FAE.
+//AWB short
+ // {0x33a7, 0x60},
+ //{0x33a8, 0x40},
+ //{0x33a9, 0x68},
+ //{0x332b, 0x08},
+ //{0x330a, 0x22},
+
+ //{0x332b, 0x00},
+ //{0x330a, 0x02},
+//end
+
{0x0000 ,0x00},
};
+
static struct reginfo sensor_vga_capture[] =
{
{0x3302, 0xef},
{0x308a, 0x01},
{0x308b, 0xe0},
{0x304c, 0x82},//14Mhz PCLK output 84
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11},// by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x3010, 0x20},
{0x3011, 0x01},
//XGA->CIF(352*288)
+#if 0 // by FAE.
{0x3302, 0xef},
{0x335f, 0x34},
{0x3360, 0x0c},
{0x308a, 0x01},
{0x308b, 0x20},
{0x304c, 0x82}, //89
+#else
+ {0x3302, 0xef},
+ {0x335f, 0x34},
+ {0x3360, 0x0c},
+ {0x3361, 0x04},
+ {0x3362, 0x11},
+ {0x3363, 0x68}, //?
+ {0x3364, 0x24},//?
+ {0x3403, 0x42},
+ {0x3088, 0x01},
+ {0x3089, 0x68},
+ {0x308a, 0x01},
+ {0x308b, 0x24},
+ {0x304c, 0x85}, //89
+#endif
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // flip && mirror, by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x01},
{0x308b, 0x20},
{0x304c, 0x84},//14Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11},//by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308a, 0x00},
{0x308b, 0xf0},
{0x304c, 0x89},//14Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
{0x308b, 0xf0},
{0x304c, 0x84},//14Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11},// by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo *sensor_qvga[2] = {
{0x308a, 0x00},
{0x308b, 0x90},
{0x304c, 0x82},//14Mhz PCLK output 89
-
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11},// by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo sensor_qcif_capture[] =
{0x308b, 0x90},
{0x304c, 0x84},//14Mhz PCLK output
+ //{0x307c, 0x13}, // flip && mirror
+ {0x307c, 0x11}, // by FAE.
+ {0x3090, 0xc8},
{0x0000 ,0x00},
};
static struct reginfo *sensor_qcif[2] = {
.step = 1,
.default_value = 125,
},
+ {
+ .id = V4L2_CID_FOCUS_AUTO,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+#if 0 //IF CONTINOUS IS SUPPORT, SET TO 1
+ {
+ .id = V4L2_CID_FOCUS_CONTINUOUS,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Focus Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+#endif
#endif
#if CONFIG_SENSOR_Flash
static int sensor_resume(struct soc_camera_device *icd);
static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
-static int sensor_set_flashLed(struct soc_camera_device *icd, int value);
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+static int sensor_deactivate(struct i2c_client *client);
static struct soc_camera_ops sensor_ops =
{
JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),
};
+
+enum sensor_work_state
+{
+ sensor_work_ready = 0,
+ sensor_working,
+};
+struct sensor_work
+{
+ struct i2c_client *client;
+ struct delayed_work dwork;
+ enum sensor_work_state state;
+};
+
typedef struct sensor_info_priv_s
{
int whiteBalance;
int scene;
int digitalzoom;
int focus;
+ int auto_focus;
+ int affm_reinit;
int flash;
int exposure;
+ bool snap2preview;
+ bool video2preview;
unsigned char mirror; /* HFLIP */
unsigned char flip; /* VFLIP */
unsigned int winseqe_cur_addr;
unsigned int pixfmt;
+ unsigned int enable;
+ unsigned int funmodule_state;
} sensor_info_priv_t;
struct sensor
struct v4l2_subdev subdev;
struct i2c_client *client;
sensor_info_priv_t info_priv;
+ struct workqueue_struct *sensor_wq;
+ struct sensor_work sensor_wk;
+ struct mutex wq_lock;
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
};
static struct sensor* to_sensor(const struct i2c_client *client)
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
}
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+ return 0;
+sensor_task_lock_err:
+ return -1;
+#else
+ return 0;
+#endif
+
+}
+
/* sensor register write */
static int sensor_write(struct i2c_client *client, u16 reg, u8 val)
{
cnt = 1;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
return 0;
} else {
- SENSOR_TR("\n %s write reg failed, try to write again! reg:0x%x val:0x%x ,err=%d\n",SENSOR_NAME_STRING(), reg, val,err);
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
udelay(10);
}
}
cnt = 1;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 2);
if (err >= 0) {
*val = buf[0];
return 0;
} else {
- SENSOR_TR("\n %s read reg failed, try to read again! reg:0x%x \n",SENSOR_NAME_STRING(),*val);
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
udelay(10);
}
}
/* write a array of registers */
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
{
- int err, cnt;
+ int err=0, cnt;
int i = 0;
+#if CONFIG_SENSOR_Focus
+ struct sensor *sensor = to_sensor(client);
+#endif
+#if CONFIG_SENSOR_I2C_RDWRCHK
+ char valchk;
+#endif
cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
while (regarray[i].reg != 0)
{
+ #if CONFIG_SENSOR_Focus
+ if ((regarray == sensor_af_firmware) && (sensor->info_priv.enable == 0)) {
+ SENSOR_DG("%s disable, Download af firmware terminated!\n",SENSOR_NAME_STRING());
+ err = -EINVAL;
+ goto sensor_write_array_end;
+ }
+ #endif
+
err = sensor_write(client, regarray[i].reg, regarray[i].val);
if (err < 0)
{
continue;
} else {
SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
- return -EPERM;
+
+ err = -EPERM;
+ goto sensor_write_array_end;
}
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
}
i++;
}
+
+ #if CONFIG_SENSOR_Focus
+ if (((regarray->reg == SEQUENCE_PROPERTY) && (regarray->val == SEQUENCE_INIT))
+ || (regarray == sensor_init_data)) {
+ sensor->info_priv.affm_reinit = 1;
+ }
+ #endif
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
+}
+#if CONFIG_SENSOR_I2C_RDWRCHK
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+ int cnt;
+ int i = 0;
+ char valchk;
+
+ cnt = 0;
+ valchk = 0;
+ while (regarray[i].reg != 0)
+ {
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+ i++;
+ }
return 0;
}
+#endif
+#if CONFIG_SENSOR_Focus
+struct af_cmdinfo
+{
+ char cmd_tag;
+ char cmd_para[4];
+ char validate_bit;
+};
+static int sensor_af_cmdset(struct i2c_client *client, int cmd_main, struct af_cmdinfo *cmdinfo)
+{
+ int i;
+ char read_tag=0xff,cnt;
+
+ if (cmdinfo) {
+ if (cmdinfo->validate_bit & 0x80) {
+ if (sensor_write(client, CMD_TAG_Reg, cmdinfo->cmd_tag)) {
+ SENSOR_TR("%s write CMD_TAG_Reg(main:0x%x tag:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
+ goto sensor_af_cmdset_err;
+ }
+ SENSOR_DG("%s write CMD_TAG_Reg(main:0x%x tag:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
+ }
+ for (i=0; i<4; i++) {
+ if (cmdinfo->validate_bit & (1<<i)) {
+ if (sensor_write(client, CMD_PARA0_Reg-i, cmdinfo->cmd_para[i])) {
+ SENSOR_TR("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
+ goto sensor_af_cmdset_err;
+ }
+ SENSOR_DG("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
+ }
+ }
+ } else {
+ if (sensor_write(client, CMD_TAG_Reg, 0xff)) {
+ SENSOR_TR("%s write CMD_TAG_Reg(main:0x%x no tag) error!\n",SENSOR_NAME_STRING(),cmd_main);
+ goto sensor_af_cmdset_err;
+ }
+ SENSOR_DG("%s write CMD_TAG_Reg(main:0x%x no tag) success!\n",SENSOR_NAME_STRING(),cmd_main);
+ }
+
+ if (sensor_write(client, CMD_MAIN_Reg, cmd_main)) {
+ SENSOR_TR("%s write CMD_MAIN_Reg(main:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main);
+ goto sensor_af_cmdset_err;
+ }
+
+ cnt = 0;
+ do
+ {
+ msleep(5);
+ if (sensor_read(client,CMD_TAG_Reg,&read_tag)){
+ SENSOR_TR("%s[%d] read TAG failed\n",SENSOR_NAME_STRING(),__LINE__);
+ break;
+ }
+ } while((read_tag != 0x00)&& (cnt++<100));
+
+ SENSOR_DG("%s write CMD_MAIN_Reg(main:0x%x read tag:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,read_tag);
+ return 0;
+sensor_af_cmdset_err:
+ return -1;
+}
+
+static int sensor_af_idlechk(struct i2c_client *client)
+{
+ int ret = 0;
+ char state,cnt;
+
+ cnt = 0;
+ do
+ {
+ ret = sensor_read(client, STA_FOCUS_Reg, &state);
+ if (ret != 0){
+ SENSOR_TR("%s[%d] read focus_status failed\n",SENSOR_NAME_STRING(),__LINE__);
+ ret = -1;
+ goto sensor_af_idlechk_end;
+ }
+
+ if (state != S_IDLE) {
+ sensor_af_cmdset(client, ReturnIdle_Cmd, NULL);
+ msleep(1);
+ cnt++;
+ }
+ } while((state != S_IDLE)&& (cnt<100));
+
+ ret = (state == S_IDLE) ? 0 : -1;
+
+sensor_af_idlechk_end:
+ return ret;
+}
+
+static int sensor_af_single(struct i2c_client *client)
+{
+ int ret = 0;
+ char state,cnt;
+
+ if (sensor_af_idlechk(client))
+ goto sensor_af_single_end;
+
+ if (sensor_af_cmdset(client, SingleFocus_Cmd, NULL)) {
+ SENSOR_TR("%s single focus mode set error!\n",SENSOR_NAME_STRING());
+ ret = -1;
+ goto sensor_af_single_end;
+ }
+
+ cnt = 0;
+ do
+ {
+ if (cnt != 0) {
+ msleep(1);
+ }
+ cnt++;
+ ret = sensor_read(client, STA_FOCUS_Reg, &state);
+ if (ret != 0){
+ SENSOR_TR("%s[%d] read focus_status failed\n",SENSOR_NAME_STRING(),__LINE__);
+ ret = -1;
+ goto sensor_af_single_end;
+ }
+ }while((state == S_FOCUSING) && (cnt<100));
+
+ if (state != S_FOCUSED) {
+ SENSOR_TR("%s[%d] focus state(0x%x) is error!\n",SENSOR_NAME_STRING(),__LINE__,state);
+ ret = -1;
+ goto sensor_af_single_end;
+ }
+
+ //sensor_af_cmdset(client, ReturnIdle_Cmd, NULL); // by duanyp. fix af blur when taking pictures
+sensor_af_single_end:
+ return ret;
+}
+
+static int sensor_af_const(struct i2c_client *client)
+{
+ int ret = 0;
+
+ if (sensor_af_idlechk(client))
+ goto sensor_af_const_end;
+
+ if (sensor_af_cmdset(client, ConstFocus_Cmd, NULL)) {
+ SENSOR_TR("%s const focus mode set error!\n",SENSOR_NAME_STRING());
+ ret = -1;
+ goto sensor_af_const_end;
+ }
+sensor_af_const_end:
+ return ret;
+}
+static int sensor_af_pause2capture(struct i2c_client *client)
+{
+ int ret = 0;
+ char state,cnt;
+
+ if (sensor_af_cmdset(client, PauseFocus_Cmd, NULL)) {
+ SENSOR_TR("%s pause focus mode set error!\n",SENSOR_NAME_STRING());
+ ret = -1;
+ goto sensor_af_pause_end;
+ }
+
+ cnt = 0;
+ do
+ {
+ if (cnt != 0) {
+ msleep(1);
+ }
+ cnt++;
+ ret = sensor_read(client, STA_FOCUS_Reg, &state);
+ if (ret != 0){
+ SENSOR_TR("%s[%d] read focus_status failed\n",SENSOR_NAME_STRING(),__LINE__);
+ ret = -1;
+ goto sensor_af_pause_end;
+ }
+ }while((state != S_CAPTURE) && (cnt<100));
+
+ if (state != S_CAPTURE) {
+ SENSOR_TR("%s[%d] focus state(0x%x) is error!\n",SENSOR_NAME_STRING(),__LINE__,state);
+ ret = -1;
+ goto sensor_af_pause_end;
+ }
+sensor_af_pause_end:
+ return ret;
+}
+static int sensor_af_zoneupdate(struct i2c_client *client)
+{
+ int ret = 0;
+
+ if (sensor_af_idlechk(client))
+ goto sensor_af_zoneupdate_end;
+
+ if (sensor_af_cmdset(client, UpdateZone_Cmd, NULL)) {
+ SENSOR_TR("%s update zone fail!\n",SENSOR_NAME_STRING());
+ ret = -1;
+ goto sensor_af_zoneupdate_end;
+ }
+
+sensor_af_zoneupdate_end:
+ return ret;
+}
+static int sensor_af_init(struct i2c_client *client)
+{
+ int ret = 0;
+ char state,cnt;
+
+ ret = sensor_write_array(client, sensor_af_firmware);
+ if (ret != 0) {
+ SENSOR_TR("%s Download firmware failed\n",SENSOR_NAME_STRING());
+ ret = -1;
+ goto sensor_af_init_end;
+ }
+
+ cnt = 0;
+ do
+ {
+ if (cnt != 0) {
+ msleep(1);
+ }
+ cnt++;
+ ret = sensor_read(client, STA_FOCUS_Reg, &state);
+ if (ret != 0){
+ SENSOR_TR("%s[%d] read focus_status failed\n",SENSOR_NAME_STRING(),__LINE__);
+ ret = -1;
+ goto sensor_af_init_end;
+ }
+ }while((state == S_STARTUP) && (cnt<100));
+
+ if (state != S_IDLE) {
+ SENSOR_TR("%s focus state(0x%x) is error!\n",SENSOR_NAME_STRING(),state);
+ ret = -1;
+ goto sensor_af_init_end;
+ }
+
+sensor_af_init_end:
+ SENSOR_DG("%s %s ret:0x%x \n",SENSOR_NAME_STRING(),__FUNCTION__,ret);
+ return ret;
+}
+
+static int sensor_af_wq_function(struct i2c_client *client)
+{
+ struct sensor *sensor = to_sensor(client);
+ struct af_cmdinfo cmdinfo;
+ int ret=0, focus_pos = 0xfe;
+
+ SENSOR_DG("%s %s Enter\n",SENSOR_NAME_STRING(), __FUNCTION__);
+
+ mutex_lock(&sensor->wq_lock);
+ if (sensor_af_init(client)) {
+ sensor->info_priv.funmodule_state &= (~SENSOR_AF_IS_OK);
+ ret = -1;
+ } else {
+ sensor->info_priv.funmodule_state |= SENSOR_AF_IS_OK;
+
+ switch (sensor->info_priv.auto_focus)
+ {
+ case SENSOR_AF_MODE_INFINITY:
+ {
+ focus_pos = 0x00;
+ }
+ case SENSOR_AF_MODE_MACRO:
+ {
+ if (focus_pos != 0x00)
+ focus_pos = 0xff;
+
+ sensor_af_idlechk(client);
+ cmdinfo.cmd_tag = StepFocus_Spec_Tag;
+ cmdinfo.cmd_para[0] = focus_pos;
+ cmdinfo.validate_bit = 0x81;
+ ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
+ break;
+ }
+ case SENSOR_AF_MODE_AUTO:
+ {
+ ret = sensor_af_single(client);
+ break;
+ }
+ case SENSOR_AF_MODE_CONTINUOUS:
+ {
+ ret = sensor_af_const(client);
+ break;
+ }
+ case SENSOR_AF_MODE_CLOSE:
+ {
+ ret = 0;
+ break;
+ }
+ default:
+ {
+ SENSOR_DG("%s focus mode(0x%x) is unkonwn\n",SENSOR_NAME_STRING(),sensor->info_priv.auto_focus);
+ goto sensor_af_wq_function_end;
+ }
+ }
+
+ SENSOR_DG("%s sensor_af_wq_function set focus mode(0x%x) ret:0x%x\n",SENSOR_NAME_STRING(), sensor->info_priv.auto_focus,ret);
+ }
+
+sensor_af_wq_function_end:
+ sensor->sensor_wk.state = sensor_work_ready;
+ mutex_unlock(&sensor->wq_lock);
+ return ret;
+}
+static void sensor_af_workqueue(struct work_struct *work)
+{
+ struct sensor_work *sensor_work = container_of(work, struct sensor_work, dwork.work);
+ struct i2c_client *client = sensor_work->client;
+
+ if (sensor_af_wq_function(client) < 0) {
+ SENSOR_TR("%s af workqueue return false\n",SENSOR_NAME_STRING());
+ }
+}
+#endif
+
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
struct i2c_client *client = sd->priv;
int ret,pid = 0;
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
-
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
/* ddl@rock-chips.com : ov3640_powerOn have hardware reset */
#if 0
/* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
ret = sensor_write(client, 0x3012, 0x80);
if (ret != 0)
{
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
goto sensor_INIT_ERR;
}
-
- icd->user_width = SENSOR_INIT_WIDTH;
- icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
/* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */
#if CONFIG_SENSOR_Focus
- sensor_set_focus();
- qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ // sensor_set_focus();
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);//?,JYK
if (qctrl)
sensor->info_priv.focus = qctrl->default_value;
#endif
sensor->info_priv.flash = qctrl->default_value;
#endif
- SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
return 0;
sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
return ret;
}
+static int sensor_deactivate(struct i2c_client *client)
+{
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
+ return 0;
+}
static struct reginfo sensor_power_down_sequence[]=
{
{0x361e, 0x00},
{
int ret;
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- struct soc_camera_link *icl;
-
- if (pm_msg.event == PM_EVENT_SUSPEND)
- {
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
ret = sensor_write_array(client, sensor_power_down_sequence) ;
- if (ret != 0)
- {
+ if (ret != 0) {
SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
return ret;
- }
- else
- {
- icl = to_soc_camera_link(icd);
- if (icl->power) {
- ret = icl->power(icd->pdev, 0);
- if (ret < 0) {
- SENSOR_TR("\n %s suspend fail for turn on power!\n",__FUNCTION__);
- return -EINVAL;
- }
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
}
}
- }
- else
- {
+ } else {
SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
return -EINVAL;
}
+
return 0;
}
static int sensor_resume(struct soc_camera_device *icd)
{
- struct soc_camera_link *icl;
- int ret;
+ int ret;
- icl = to_soc_camera_link(icd);
- if (icl->power) {
- ret = icl->power(icd->pdev, 1);
- if (ret < 0) {
- SENSOR_TR("\n %s resume fail for turn on power!\n",__FUNCTION__);
- return -EINVAL;
- }
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
}
SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
-
- return 0;
-
+ return 0;
}
static int sensor_set_bus_param(struct soc_camera_device *icd,
return 0;
}
-static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct i2c_client *client = sd->priv;
- struct soc_camera_device *icd = client->dev.platform_data;
- if (!enable) {
- sensor_set_flashLed(icd,0);
- return 0;
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
}
- return 0;
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
}
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
struct i2c_client *client = sd->priv;
struct soc_camera_device *icd = client->dev.platform_data;
struct sensor *sensor = to_sensor(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
struct reginfo *winseqe_set_addr=NULL;
- int ret, set_w,set_h;
- int isCapture = 0; // 1--ÅÄÕÕÐòÁÐ 0--Ô¤ÀÀÐòÁÐ
+ int ret=0, set_w,set_h;
+ int isCapture = 0;
if (sensor->info_priv.pixfmt != pix->pixelformat) {
switch (pix->pixelformat)
set_w = pix->width;
set_h = pix->height;
- isCapture = pix->priv;
-
- if(isCapture)
- sensor_set_flashLed(icd,1);
-
- SENSOR_DG("%s %c,%c,%c,%c\n", SENSOR_NAME_STRING(),
- ((pix->pixelformat) & 0xff),((pix->pixelformat>>8) & 0xff),
- ((pix->pixelformat>>16) & 0xff),((pix->pixelformat>>24) & 0xff));
+ isCapture = sensor_fmt_capturechk(sd, f);
if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[isCapture][0].reg)
{
}
else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[isCapture][0].reg)
{
+ //printk("===> isCapture: %d!\n", isCapture);
winseqe_set_addr = sensor_cif[isCapture];
set_w = 352;
set_h = 288;
set_w = 2048;
set_h = 1536;
}
- else if (sensor_qcif[isCapture][0].reg)
+ else
{
- winseqe_set_addr = sensor_qcif[isCapture]; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
- set_w = 176;
- set_h = 144;
- }
- else
- {
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */
+ set_w = SENSOR_INIT_WIDTH;
+ set_h = SENSOR_INIT_HEIGHT;
SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
- return -EINVAL;
- }
+ }
if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr)
{
{
SENSOR_DG("%s write sensor_qxga[1]\n", SENSOR_NAME_STRING());
ret = sensor_write_array(client, sensor_qxga[isCapture]);
- if (ret != 0)
- {
- SENSOR_TR("%s write sensor_qxga[1] failed\n", SENSOR_NAME_STRING());
- return ret;
- }
+ if (ret != 0)
+ {
+ SENSOR_TR("%s write sensor_qxga[1] failed\n", SENSOR_NAME_STRING());
+ return ret;
+ }
}
+
+ #if CONFIG_SENSOR_Focus
+ //sensor_af_idlechk(client);
+ if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_CONTINUOUS)
+ {
+ sensor_af_idlechk(client); // by duanyp
+ sensor_af_cmdset(client, PauseFocus_Cmd, NULL);
+ }
+ #endif
+
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
- ret = sensor_write_array(client, winseqe_set_addr);
- if (ret != 0)
- {
+ ret = sensor_write_array(client, winseqe_set_addr);
+ if (ret != 0) {
SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
- return ret;
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ goto sensor_s_fmt_end;
+ } else {
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
+ mdelay(100); // by FAE.
}
-
- sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
- //mdelay(250);
-
SENSOR_DG("\n%s..%s.. icd->width=%d..icd->height=%d..isCapture=%d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h,isCapture);
}
else
SENSOR_TR("\n %s .. Current Format is validate. icd->width=%d..icd->height=%d..isCapture=%d\n",SENSOR_NAME_STRING(),set_w,set_h,isCapture);
}
- return 0;
+ //add by duanyp. Improve the green phenomenon when startup camera every time.
+ //mdelay(500);
+
+sensor_s_fmt_end:
+ return ret;
}
static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
return 0;
}
-
-
-static int sensor_set_flashLed(struct soc_camera_device *icd, int value)
-{
-#if CONFIG_SENSOR_Flash
- struct soc_camera_link *icl = to_soc_camera_link(icd);
- struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- struct sensor *sensor = to_sensor(client);
- int ret;
-
- SENSOR_DG("sensor_set_flashLed - %d,%d\n", sensor->info_priv.flash,value);
-
- if(icl->flash_led == NULL)
- {
- SENSOR_TR("icl->flash_led == NULL\n ");
- return -1;
- }
-
- switch(sensor->info_priv.flash)
- {
- case 0: // off
- {
- ret = icl->flash_led(icd->pdev, 0);
- break;
- }
- case 1: //auto
- {
- ret = icl->flash_led(icd->pdev,value);
- break;
- }
- case 2: // on
- {
- ret = icl->flash_led(icd->pdev,1);
- break;
- }
- default: // off
- {
- ret = icl->flash_led(icd->pdev,0);
- break;
- }
-
- }
-
- if(ret)
- {
- SENSOR_TR("icl->flash_led failed\n ");
- }
-#endif
-
- return 0;
-}
-
#if CONFIG_SENSOR_Brightness
static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
{
return -EINVAL;
}
#endif
+
+#if CONFIG_SENSOR_Focus
+static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ struct af_cmdinfo cmdinfo;
+ int ret = 0;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+ if (!qctrl_info)
+ return -EINVAL;
+
+ if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
+ if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
+
+ if (sensor_af_idlechk(client))
+ goto sensor_set_focus_absolute_end;
+
+ cmdinfo.cmd_tag = StepFocus_Spec_Tag;
+ cmdinfo.cmd_para[0] = value;
+ cmdinfo.validate_bit = 0x81;
+ ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
+ //ret |= sensor_af_cmdset(client, ReturnIdle_Cmd, NULL);
+ SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
+ } else {
+ ret = -EINVAL;
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ }
+ } else {
+ ret = -EACCES;
+ SENSOR_TR("\n %s..%s AF module state(0x%x, 0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,
+ sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
+ }
+
+sensor_set_focus_absolute_end:
+ return ret;
+}
+static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ const struct v4l2_queryctrl *qctrl_info;
+ struct af_cmdinfo cmdinfo;
+ int ret = 0;
+
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_RELATIVE);
+ if (!qctrl_info)
+ return -EINVAL;
+
+ if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
+ if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
+
+ if (sensor_af_idlechk(client))
+ goto sensor_set_focus_relative_end;
+
+ if (value > 0) {
+ cmdinfo.cmd_tag = StepFocus_Near_Tag;
+ } else if (value < 0) {
+ cmdinfo.cmd_tag = StepFocus_Far_Tag;
+ }
+ cmdinfo.validate_bit = 0x80;
+ ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
+
+ SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
+ } else {
+ ret = -EINVAL;
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ }
+ } else {
+ ret = -EACCES;
+ SENSOR_TR("\n %s..%s AF module state(0x%x, 0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,
+ sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
+ }
+sensor_set_focus_relative_end:
+ return ret;
+}
+
+static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+
+ if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
+ switch (value)
+ {
+ case SENSOR_AF_MODE_AUTO:
+ {
+ ret = sensor_af_single(client);
+ break;
+ }
+
+ case SENSOR_AF_MODE_MACRO:
+ {
+ ret = sensor_set_focus_absolute(icd, qctrl, 0xff);
+ break;
+ }
+
+ case SENSOR_AF_MODE_INFINITY:
+ {
+ ret = sensor_set_focus_absolute(icd, qctrl, 0x00);
+ break;
+ }
+
+ case SENSOR_AF_MODE_CONTINUOUS:
+ {
+ ret = sensor_af_const(client);
+ break;
+ }
+ default:
+ SENSOR_TR("\n %s..%s AF value(0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ break;
+
+ }
+
+ SENSOR_DG("%s..%s : %d ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
+ } else {
+ ret = -EACCES;
+ SENSOR_TR("\n %s..%s AF module state(0x%x, 0x%x) is error!\n",SENSOR_NAME_STRING(),__FUNCTION__,
+ sensor->info_priv.funmodule_state,sensor->info_priv.affm_reinit);
+ }
+
+ return ret;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %d\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct i2c_client *client = sd->priv;
if (!qctrl)
{
- SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ SENSOR_TR("\n %s ioctrl id = 0x%x is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
return -EINVAL;
}
if (!qctrl)
{
- SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+ SENSOR_TR("\n %s ioctrl id = 0x%x is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
return -EINVAL;
}
if (!qctrl)
{
- SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ SENSOR_TR("\n %s ioctrl id = 0x%x is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
return -EINVAL;
}
if (!qctrl)
{
- SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+ SENSOR_TR("\n %s ioctrl id = 0x%x is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
return -EINVAL;
}
if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
return -EINVAL;
- if (ext_ctrl->value != sensor->info_priv.focus)
- {
- val_offset = ext_ctrl->value -sensor->info_priv.focus;
-
- sensor->info_priv.focus += val_offset;
- }
+ if (sensor_set_focus_absolute(icd, qctrl,ext_ctrl->value) == 0) {
+ if (ext_ctrl->value == qctrl->minimum) {
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_INFINITY;
+ } else if (ext_ctrl->value == qctrl->maximum) {
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_MACRO;
+ } else {
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_FIXED;
+ }
+ }
break;
- }
- case V4L2_CID_FOCUS_RELATIVE:
+ }
+ case V4L2_CID_FOCUS_RELATIVE:
{
- if (ext_ctrl->value)
- {
- sensor->info_priv.focus += ext_ctrl->value;
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+ return -EINVAL;
- SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
- }
+ sensor_set_focus_relative(icd, qctrl,ext_ctrl->value);
break;
}
+ case V4L2_CID_FOCUS_AUTO:
+ {
+ if (ext_ctrl->value == 1) {
+ if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_AUTO) != 0)
+ return -EINVAL;
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_AUTO;
+ } else if (SENSOR_AF_MODE_AUTO == sensor->info_priv.auto_focus){
+ if (ext_ctrl->value == 0)
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_CLOSE;
+ }
+ break;
+ }
+ /*
+ case V4L2_CID_FOCUS_CONTINUOUS:
+ {
+ if (SENSOR_AF_MODE_CONTINUOUS != sensor->info_priv.auto_focus) {
+ if (ext_ctrl->value == 1) {
+ if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_CONTINUOUS) != 0)
+ return -EINVAL;
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_CONTINUOUS;
+ }
+ } else {
+ if (ext_ctrl->value == 0)
+ sensor->info_priv.auto_focus = SENSOR_AF_MODE_CLOSE;
+ }
+ break;
+ }*/
#endif
#if CONFIG_SENSOR_Flash
case V4L2_CID_FLASH:
{
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
sensor->info_priv.flash = ext_ctrl->value;
- sensor_set_flashLed(icd,0);
+
SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
break;
}
}
}
+static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct i2c_client *client = sd->priv;
+ struct sensor *sensor = to_sensor(client);
+ #if CONFIG_SENSOR_Focus
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct v4l2_format fmt;
+ #endif
+
+ if (enable == 1) {
+ sensor->info_priv.enable = 1;
+ #if CONFIG_SENSOR_Focus
+ fmt.fmt.pix.width = icd->user_width;
+ fmt.fmt.pix.height = icd->user_height;
+ /* If auto focus firmware haven't download success, must download firmware again when in video or preview stream on */
+ if (sensor_fmt_capturechk(sd, &fmt) == false) {
+ if ((sensor->info_priv.affm_reinit == 1) || ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)==0)) {
+ if (sensor->sensor_wq != NULL) {
+ mutex_lock(&sensor->wq_lock);
+ if (sensor->sensor_wk.state == sensor_working) {
+ SENSOR_DG("%s sensor af firmware thread is runing, Ingore current work",SENSOR_NAME_STRING());
+ mutex_unlock(&sensor->wq_lock);
+ goto sensor_s_stream_end;
+ }
+ sensor->sensor_wk.state = sensor_working;
+ mutex_unlock(&sensor->wq_lock);
+ sensor->sensor_wk.client = client;
+ INIT_WORK(&(sensor->sensor_wk.dwork.work), sensor_af_workqueue);
+ queue_delayed_work(sensor->sensor_wq,&(sensor->sensor_wk.dwork), 0);
+ }
+ sensor->info_priv.affm_reinit = 0;
+ }
+ }
+ #endif
+ } else if (enable == 0) {
+ sensor->info_priv.enable = 0;
+ #if CONFIG_SENSOR_Focus
+ flush_work(&(sensor->sensor_wk.dwork.work));
+ mutex_lock(&sensor->wq_lock);
+ sensor->sensor_wk.state = sensor_work_ready;
+ mutex_unlock(&sensor->wq_lock);
+ #endif
+ }
+
+sensor_s_stream_end:
+ return 0;
+}
+
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
static int sensor_video_probe(struct soc_camera_device *icd,
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
/* soft reset */
ret = sensor_write(client, 0x3012, 0x80);
- if (ret != 0)
- {
+ if (ret != 0) {
SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
- return -ENODEV;
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
}
mdelay(5); //delay 5 microseconds
return 0;
sensor_video_probe_err:
-
return ret;
}
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0,i;
+
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ switch (cmd)
+ {
+ case RK29_CAM_SUBDEV_DEACTIVATE:
+ {
+ sensor_deactivate(client);
+ break;
+ }
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ printk("flash io:%d\n",sensor->sensor_gpio_res->gpio_flash);
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+
+sensor_ioctl_end:
+ return ret;
+
+}
static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
.init = sensor_init,
.g_ext_ctrls = sensor_g_ext_controls,
.s_ext_ctrls = sensor_s_ext_controls,
.g_chip_ident = sensor_g_chip_ident,
+ .ioctl = sensor_ioctl,
};
static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
- .s_stream = sensor_s_stream,
.s_fmt = sensor_s_fmt,
.g_fmt = sensor_g_fmt,
.try_fmt = sensor_try_fmt,
+ .s_stream = sensor_s_stream,
};
static struct v4l2_subdev_ops sensor_subdev_ops = {
/* Second stage probe - when a capture adapter is there */
icd->ops = &sensor_ops;
icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
ret = sensor_video_probe(icd, client);
- if (ret) {
+ if (ret < 0) {
icd->ops = NULL;
i2c_set_clientdata(client, NULL);
kfree(sensor);
+ sensor = NULL;
+ } else {
+ #if CONFIG_SENSOR_Focus
+ sensor->sensor_wq = create_workqueue(SENSOR_NAME_STRING( wq));
+ if (sensor->sensor_wq == NULL)
+ SENSOR_TR("%s workqueue create fail!", SENSOR_NAME_STRING( wq));
+ mutex_init(&sensor->wq_lock);
+ sensor->sensor_wk.state = sensor_work_ready;
+ #endif
}
SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
return ret;
struct sensor *sensor = to_sensor(client);
struct soc_camera_device *icd = client->dev.platform_data;
+ #if CONFIG_SENSOR_Focus
+ if (sensor->sensor_wq) {
+ destroy_workqueue(sensor->sensor_wq);
+ sensor->sensor_wq = NULL;
+ }
+ #endif
+
icd->ops = NULL;
i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(sensor);
-
+ sensor = NULL;
return 0;
}
module_exit(sensor_mod_exit);
MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
-MODULE_AUTHOR("srt <kernel@rock-chips>");
+MODULE_AUTHOR("ddl <kernel@rock-chips>");
MODULE_LICENSE("GPL");
--- /dev/null
+/*\r
+ * Driver for OV5642 CMOS Image Sensor from OmniVision\r
+ *\r
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ */\r
+\r
+#ifndef __OV3640_H__\r
+#define __OV3640_H__\r
+struct reginfo\r
+{\r
+ u16 reg;\r
+ u8 val;\r
+};\r
+\r
+#define SEQUENCE_INIT 0x00\r
+#define SEQUENCE_NORMAL 0x01\r
+\r
+#define SEQUENCE_PROPERTY 0xFFFD\r
+#define SEQUENCE_WAIT_MS 0xFFFE\r
+#define SEQUENCE_END 0xFFFF\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ * Driver for OV5642 CMOS Image Sensor from OmniVision\r
+ *\r
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ */\r
+\r
+#define VCM_DRIVER_A3907 0\r
+#define VCM_DRIVER_AD5820 1\r
+#define VCM_DRIVER_DW9710 2\r
+#define VCM_DRIVER VCM_DRIVER_AD5820\r
+\r
+\r
+#if (VCM_DRIVER == VCM_DRIVER_AD5820)\r
+static struct reginfo sensor_af_firmware[ ]=\r
+{\r
+ {0x308c,0x00},\r
+ {0x3104,0x02},\r
+ {0x3105,0xff},\r
+ {0x3106,0x00},\r
+ {0x3107,0xff},\r
+ {0x8000,0x02},\r
+ {0x8001,0x00},\r
+ {0x8002,0x06},\r
+ {0x8003,0x02},\r
+ {0x8004,0x07},\r
+ {0x8005,0xa9},\r
+ {0x8006,0x78},\r
+ {0x8007,0x7f},\r
+ {0x8008,0xe4},\r
+ {0x8009,0xf6},\r
+ {0x800a,0xd8},\r
+ {0x800b,0xfd},\r
+ {0x800c,0x75},\r
+ {0x800d,0x81},\r
+ {0x800e,0x45},\r
+ {0x800f,0x02},\r
+ {0x8010,0x0a},\r
+ {0x8011,0xdf},\r
+ {0x8012,0x32},\r
+ {0x8013,0x02},\r
+ {0x8014,0x00},\r
+ {0x8015,0x12},\r
+ {0x8016,0xe8},\r
+ {0x8017,0x8f},\r
+ {0x8018,0xf0},\r
+ {0x8019,0xa4},\r
+ {0x801a,0xcc},\r
+ {0x801b,0x8b},\r
+ {0x801c,0xf0},\r
+ {0x801d,0xa4},\r
+ {0x801e,0x2c},\r
+ {0x801f,0xfc},\r
+ {0x8020,0xe9},\r
+ {0x8021,0x8e},\r
+ {0x8022,0xf0},\r
+ {0x8023,0xa4},\r
+ {0x8024,0x2c},\r
+ {0x8025,0xfc},\r
+ {0x8026,0x8a},\r
+ {0x8027,0xf0},\r
+ {0x8028,0xed},\r
+ {0x8029,0xa4},\r
+ {0x802a,0x2c},\r
+ {0x802b,0xfc},\r
+ {0x802c,0xea},\r
+ {0x802d,0x8e},\r
+ {0x802e,0xf0},\r
+ {0x802f,0xa4},\r
+ {0x8030,0xcd},\r
+ {0x8031,0xa8},\r
+ {0x8032,0xf0},\r
+ {0x8033,0x8b},\r
+ {0x8034,0xf0},\r
+ {0x8035,0xa4},\r
+ {0x8036,0x2d},\r
+ {0x8037,0xcc},\r
+ {0x8038,0x38},\r
+ {0x8039,0x25},\r
+ {0x803a,0xf0},\r
+ {0x803b,0xfd},\r
+ {0x803c,0xe9},\r
+ {0x803d,0x8f},\r
+ {0x803e,0xf0},\r
+ {0x803f,0xa4},\r
+ {0x8040,0x2c},\r
+ {0x8041,0xcd},\r
+ {0x8042,0x35},\r
+ {0x8043,0xf0},\r
+ {0x8044,0xfc},\r
+ {0x8045,0xeb},\r
+ {0x8046,0x8e},\r
+ {0x8047,0xf0},\r
+ {0x8048,0xa4},\r
+ {0x8049,0xfe},\r
+ {0x804a,0xa9},\r
+ {0x804b,0xf0},\r
+ {0x804c,0xeb},\r
+ {0x804d,0x8f},\r
+ {0x804e,0xf0},\r
+ {0x804f,0xa4},\r
+ {0x8050,0xcf},\r
+ {0x8051,0xc5},\r
+ {0x8052,0xf0},\r
+ {0x8053,0x2e},\r
+ {0x8054,0xcd},\r
+ {0x8055,0x39},\r
+ {0x8056,0xfe},\r
+ {0x8057,0xe4},\r
+ {0x8058,0x3c},\r
+ {0x8059,0xfc},\r
+ {0x805a,0xea},\r
+ {0x805b,0xa4},\r
+ {0x805c,0x2d},\r
+ {0x805d,0xce},\r
+ {0x805e,0x35},\r
+ {0x805f,0xf0},\r
+ {0x8060,0xfd},\r
+ {0x8061,0xe4},\r
+ {0x8062,0x3c},\r
+ {0x8063,0xfc},\r
+ {0x8064,0x22},\r
+ {0x8065,0x75},\r
+ {0x8066,0xf0},\r
+ {0x8067,0x08},\r
+ {0x8068,0x75},\r
+ {0x8069,0x82},\r
+ {0x806a,0x00},\r
+ {0x806b,0xef},\r
+ {0x806c,0x2f},\r
+ {0x806d,0xff},\r
+ {0x806e,0xee},\r
+ {0x806f,0x33},\r
+ {0x8070,0xfe},\r
+ {0x8071,0xcd},\r
+ {0x8072,0x33},\r
+ {0x8073,0xcd},\r
+ {0x8074,0xcc},\r
+ {0x8075,0x33},\r
+ {0x8076,0xcc},\r
+ {0x8077,0xc5},\r
+ {0x8078,0x82},\r
+ {0x8079,0x33},\r
+ {0x807a,0xc5},\r
+ {0x807b,0x82},\r
+ {0x807c,0x9b},\r
+ {0x807d,0xed},\r
+ {0x807e,0x9a},\r
+ {0x807f,0xec},\r
+ {0x8080,0x99},\r
+ {0x8081,0xe5},\r
+ {0x8082,0x82},\r
+ {0x8083,0x98},\r
+ {0x8084,0x40},\r
+ {0x8085,0x0c},\r
+ {0x8086,0xf5},\r
+ {0x8087,0x82},\r
+ {0x8088,0xee},\r
+ {0x8089,0x9b},\r
+ {0x808a,0xfe},\r
+ {0x808b,0xed},\r
+ {0x808c,0x9a},\r
+ {0x808d,0xfd},\r
+ {0x808e,0xec},\r
+ {0x808f,0x99},\r
+ {0x8090,0xfc},\r
+ {0x8091,0x0f},\r
+ {0x8092,0xd5},\r
+ {0x8093,0xf0},\r
+ {0x8094,0xd6},\r
+ {0x8095,0xe4},\r
+ {0x8096,0xce},\r
+ {0x8097,0xfb},\r
+ {0x8098,0xe4},\r
+ {0x8099,0xcd},\r
+ {0x809a,0xfa},\r
+ {0x809b,0xe4},\r
+ {0x809c,0xcc},\r
+ {0x809d,0xf9},\r
+ {0x809e,0xa8},\r
+ {0x809f,0x82},\r
+ {0x80a0,0x22},\r
+ {0x80a1,0xb8},\r
+ {0x80a2,0x00},\r
+ {0x80a3,0xc1},\r
+ {0x80a4,0xb9},\r
+ {0x80a5,0x00},\r
+ {0x80a6,0x59},\r
+ {0x80a7,0xba},\r
+ {0x80a8,0x00},\r
+ {0x80a9,0x2d},\r
+ {0x80aa,0xec},\r
+ {0x80ab,0x8b},\r
+ {0x80ac,0xf0},\r
+ {0x80ad,0x84},\r
+ {0x80ae,0xcf},\r
+ {0x80af,0xce},\r
+ {0x80b0,0xcd},\r
+ {0x80b1,0xfc},\r
+ {0x80b2,0xe5},\r
+ {0x80b3,0xf0},\r
+ {0x80b4,0xcb},\r
+ {0x80b5,0xf9},\r
+ {0x80b6,0x78},\r
+ {0x80b7,0x18},\r
+ {0x80b8,0xef},\r
+ {0x80b9,0x2f},\r
+ {0x80ba,0xff},\r
+ {0x80bb,0xee},\r
+ {0x80bc,0x33},\r
+ {0x80bd,0xfe},\r
+ {0x80be,0xed},\r
+ {0x80bf,0x33},\r
+ {0x80c0,0xfd},\r
+ {0x80c1,0xec},\r
+ {0x80c2,0x33},\r
+ {0x80c3,0xfc},\r
+ {0x80c4,0xeb},\r
+ {0x80c5,0x33},\r
+ {0x80c6,0xfb},\r
+ {0x80c7,0x10},\r
+ {0x80c8,0xd7},\r
+ {0x80c9,0x03},\r
+ {0x80ca,0x99},\r
+ {0x80cb,0x40},\r
+ {0x80cc,0x04},\r
+ {0x80cd,0xeb},\r
+ {0x80ce,0x99},\r
+ {0x80cf,0xfb},\r
+ {0x80d0,0x0f},\r
+ {0x80d1,0xd8},\r
+ {0x80d2,0xe5},\r
+ {0x80d3,0xe4},\r
+ {0x80d4,0xf9},\r
+ {0x80d5,0xfa},\r
+ {0x80d6,0x22},\r
+ {0x80d7,0x78},\r
+ {0x80d8,0x18},\r
+ {0x80d9,0xef},\r
+ {0x80da,0x2f},\r
+ {0x80db,0xff},\r
+ {0x80dc,0xee},\r
+ {0x80dd,0x33},\r
+ {0x80de,0xfe},\r
+ {0x80df,0xed},\r
+ {0x80e0,0x33},\r
+ {0x80e1,0xfd},\r
+ {0x80e2,0xec},\r
+ {0x80e3,0x33},\r
+ {0x80e4,0xfc},\r
+ {0x80e5,0xc9},\r
+ {0x80e6,0x33},\r
+ {0x80e7,0xc9},\r
+ {0x80e8,0x10},\r
+ {0x80e9,0xd7},\r
+ {0x80ea,0x05},\r
+ {0x80eb,0x9b},\r
+ {0x80ec,0xe9},\r
+ {0x80ed,0x9a},\r
+ {0x80ee,0x40},\r
+ {0x80ef,0x07},\r
+ {0x80f0,0xec},\r
+ {0x80f1,0x9b},\r
+ {0x80f2,0xfc},\r
+ {0x80f3,0xe9},\r
+ {0x80f4,0x9a},\r
+ {0x80f5,0xf9},\r
+ {0x80f6,0x0f},\r
+ {0x80f7,0xd8},\r
+ {0x80f8,0xe0},\r
+ {0x80f9,0xe4},\r
+ {0x80fa,0xc9},\r
+ {0x80fb,0xfa},\r
+ {0x80fc,0xe4},\r
+ {0x80fd,0xcc},\r
+ {0x80fe,0xfb},\r
+ {0x80ff,0x22},\r
+ {0x8100,0x75},\r
+ {0x8101,0xf0},\r
+ {0x8102,0x10},\r
+ {0x8103,0xef},\r
+ {0x8104,0x2f},\r
+ {0x8105,0xff},\r
+ {0x8106,0xee},\r
+ {0x8107,0x33},\r
+ {0x8108,0xfe},\r
+ {0x8109,0xed},\r
+ {0x810a,0x33},\r
+ {0x810b,0xfd},\r
+ {0x810c,0xcc},\r
+ {0x810d,0x33},\r
+ {0x810e,0xcc},\r
+ {0x810f,0xc8},\r
+ {0x8110,0x33},\r
+ {0x8111,0xc8},\r
+ {0x8112,0x10},\r
+ {0x8113,0xd7},\r
+ {0x8114,0x07},\r
+ {0x8115,0x9b},\r
+ {0x8116,0xec},\r
+ {0x8117,0x9a},\r
+ {0x8118,0xe8},\r
+ {0x8119,0x99},\r
+ {0x811a,0x40},\r
+ {0x811b,0x0a},\r
+ {0x811c,0xed},\r
+ {0x811d,0x9b},\r
+ {0x811e,0xfd},\r
+ {0x811f,0xec},\r
+ {0x8120,0x9a},\r
+ {0x8121,0xfc},\r
+ {0x8122,0xe8},\r
+ {0x8123,0x99},\r
+ {0x8124,0xf8},\r
+ {0x8125,0x0f},\r
+ {0x8126,0xd5},\r
+ {0x8127,0xf0},\r
+ {0x8128,0xda},\r
+ {0x8129,0xe4},\r
+ {0x812a,0xcd},\r
+ {0x812b,0xfb},\r
+ {0x812c,0xe4},\r
+ {0x812d,0xcc},\r
+ {0x812e,0xfa},\r
+ {0x812f,0xe4},\r
+ {0x8130,0xc8},\r
+ {0x8131,0xf9},\r
+ {0x8132,0x22},\r
+ {0x8133,0xe8},\r
+ {0x8134,0x60},\r
+ {0x8135,0x0f},\r
+ {0x8136,0xef},\r
+ {0x8137,0xc3},\r
+ {0x8138,0x33},\r
+ {0x8139,0xff},\r
+ {0x813a,0xee},\r
+ {0x813b,0x33},\r
+ {0x813c,0xfe},\r
+ {0x813d,0xed},\r
+ {0x813e,0x33},\r
+ {0x813f,0xfd},\r
+ {0x8140,0xec},\r
+ {0x8141,0x33},\r
+ {0x8142,0xfc},\r
+ {0x8143,0xd8},\r
+ {0x8144,0xf1},\r
+ {0x8145,0x22},\r
+ {0x8146,0xa4},\r
+ {0x8147,0x25},\r
+ {0x8148,0x82},\r
+ {0x8149,0xf5},\r
+ {0x814a,0x82},\r
+ {0x814b,0xe5},\r
+ {0x814c,0xf0},\r
+ {0x814d,0x35},\r
+ {0x814e,0x83},\r
+ {0x814f,0xf5},\r
+ {0x8150,0x83},\r
+ {0x8151,0x22},\r
+ {0x8152,0xd0},\r
+ {0x8153,0x83},\r
+ {0x8154,0xd0},\r
+ {0x8155,0x82},\r
+ {0x8156,0xf8},\r
+ {0x8157,0xe4},\r
+ {0x8158,0x93},\r
+ {0x8159,0x70},\r
+ {0x815a,0x12},\r
+ {0x815b,0x74},\r
+ {0x815c,0x01},\r
+ {0x815d,0x93},\r
+ {0x815e,0x70},\r
+ {0x815f,0x0d},\r
+ {0x8160,0xa3},\r
+ {0x8161,0xa3},\r
+ {0x8162,0x93},\r
+ {0x8163,0xf8},\r
+ {0x8164,0x74},\r
+ {0x8165,0x01},\r
+ {0x8166,0x93},\r
+ {0x8167,0xf5},\r
+ {0x8168,0x82},\r
+ {0x8169,0x88},\r
+ {0x816a,0x83},\r
+ {0x816b,0xe4},\r
+ {0x816c,0x73},\r
+ {0x816d,0x74},\r
+ {0x816e,0x02},\r
+ {0x816f,0x93},\r
+ {0x8170,0x68},\r
+ {0x8171,0x60},\r
+ {0x8172,0xef},\r
+ {0x8173,0xa3},\r
+ {0x8174,0xa3},\r
+ {0x8175,0xa3},\r
+ {0x8176,0x80},\r
+ {0x8177,0xdf},\r
+ {0x8178,0x75},\r
+ {0x8179,0x0c},\r
+ {0x817a,0x0a},\r
+ {0x817b,0xa2},\r
+ {0x817c,0xaf},\r
+ {0x817d,0x92},\r
+ {0x817e,0x22},\r
+ {0x817f,0xc2},\r
+ {0x8180,0xaf},\r
+ {0x8181,0xc2},\r
+ {0x8182,0x23},\r
+ {0x8183,0x12},\r
+ {0x8184,0x04},\r
+ {0x8185,0x07},\r
+ {0x8186,0x12},\r
+ {0x8187,0x04},\r
+ {0x8188,0x4d},\r
+ {0x8189,0x12},\r
+ {0x818a,0x04},\r
+ {0x818b,0x07},\r
+ {0x818c,0x75},\r
+ {0x818d,0x32},\r
+ {0x818e,0x05},\r
+ {0x818f,0xaf},\r
+ {0x8190,0x32},\r
+ {0x8191,0x15},\r
+ {0x8192,0x32},\r
+ {0x8193,0xef},\r
+ {0x8194,0x70},\r
+ {0x8195,0xf9},\r
+ {0x8196,0xd2},\r
+ {0x8197,0x18},\r
+ {0x8198,0x12},\r
+ {0x8199,0x04},\r
+ {0x819a,0x09},\r
+ {0x819b,0x75},\r
+ {0x819c,0x32},\r
+ {0x819d,0x0a},\r
+ {0x819e,0xaf},\r
+ {0x819f,0x32},\r
+ {0x81a0,0x15},\r
+ {0x81a1,0x32},\r
+ {0x81a2,0xef},\r
+ {0x81a3,0x70},\r
+ {0x81a4,0xf9},\r
+ {0x81a5,0xc2},\r
+ {0x81a6,0x19},\r
+ {0x81a7,0x12},\r
+ {0x81a8,0x04},\r
+ {0x81a9,0x09},\r
+ {0x81aa,0x75},\r
+ {0x81ab,0x32},\r
+ {0x81ac,0x05},\r
+ {0x81ad,0xaf},\r
+ {0x81ae,0x32},\r
+ {0x81af,0x15},\r
+ {0x81b0,0x32},\r
+ {0x81b1,0xef},\r
+ {0x81b2,0x70},\r
+ {0x81b3,0xf9},\r
+ {0x81b4,0xc2},\r
+ {0x81b5,0x18},\r
+ {0x81b6,0x12},\r
+ {0x81b7,0x04},\r
+ {0x81b8,0x09},\r
+ {0x81b9,0x75},\r
+ {0x81ba,0x32},\r
+ {0x81bb,0x05},\r
+ {0x81bc,0xaf},\r
+ {0x81bd,0x32},\r
+ {0x81be,0x15},\r
+ {0x81bf,0x32},\r
+ {0x81c0,0xef},\r
+ {0x81c1,0x70},\r
+ {0x81c2,0xf9},\r
+ {0x81c3,0x75},\r
+ {0x81c4,0x0d},\r
+ {0x81c5,0x18},\r
+ {0x81c6,0x12},\r
+ {0x81c7,0x02},\r
+ {0x81c8,0xb8},\r
+ {0x81c9,0x75},\r
+ {0x81ca,0x32},\r
+ {0x81cb,0x0a},\r
+ {0x81cc,0xaf},\r
+ {0x81cd,0x32},\r
+ {0x81ce,0x15},\r
+ {0x81cf,0x32},\r
+ {0x81d0,0xef},\r
+ {0x81d1,0x70},\r
+ {0x81d2,0xf9},\r
+ {0x81d3,0xd2},\r
+ {0x81d4,0x18},\r
+ {0x81d5,0x12},\r
+ {0x81d6,0x04},\r
+ {0x81d7,0x09},\r
+ {0x81d8,0x12},\r
+ {0x81d9,0x04},\r
+ {0x81da,0x97},\r
+ {0x81db,0xaf},\r
+ {0x81dc,0x32},\r
+ {0x81dd,0x15},\r
+ {0x81de,0x32},\r
+ {0x81df,0xef},\r
+ {0x81e0,0x70},\r
+ {0x81e1,0xf9},\r
+ {0x81e2,0xc2},\r
+ {0x81e3,0x18},\r
+ {0x81e4,0x12},\r
+ {0x81e5,0x04},\r
+ {0x81e6,0x09},\r
+ {0x81e7,0x75},\r
+ {0x81e8,0x32},\r
+ {0x81e9,0x0a},\r
+ {0x81ea,0xaf},\r
+ {0x81eb,0x32},\r
+ {0x81ec,0x15},\r
+ {0x81ed,0x32},\r
+ {0x81ee,0xef},\r
+ {0x81ef,0x70},\r
+ {0x81f0,0xf9},\r
+ {0x81f1,0x30},\r
+ {0x81f2,0x11},\r
+ {0x81f3,0x03},\r
+ {0x81f4,0x02},\r
+ {0x81f5,0x02},\r
+ {0x81f6,0x6f},\r
+ {0x81f7,0x12},\r
+ {0x81f8,0x04},\r
+ {0x81f9,0x07},\r
+ {0x81fa,0x12},\r
+ {0x81fb,0x04},\r
+ {0x81fc,0x4d},\r
+ {0x81fd,0xe5},\r
+ {0x81fe,0x0a},\r
+ {0x81ff,0xf5},\r
+ {0x8200,0x0d},\r
+ {0x8201,0x12},\r
+ {0x8202,0x02},\r
+ {0x8203,0xb8},\r
+ {0x8204,0x75},\r
+ {0x8205,0x32},\r
+ {0x8206,0x0a},\r
+ {0x8207,0xaf},\r
+ {0x8208,0x32},\r
+ {0x8209,0x15},\r
+ {0x820a,0x32},\r
+ {0x820b,0xef},\r
+ {0x820c,0x70},\r
+ {0x820d,0xf9},\r
+ {0x820e,0xd2},\r
+ {0x820f,0x18},\r
+ {0x8210,0x12},\r
+ {0x8211,0x04},\r
+ {0x8212,0x09},\r
+ {0x8213,0x12},\r
+ {0x8214,0x04},\r
+ {0x8215,0x97},\r
+ {0x8216,0xaf},\r
+ {0x8217,0x32},\r
+ {0x8218,0x15},\r
+ {0x8219,0x32},\r
+ {0x821a,0xef},\r
+ {0x821b,0x70},\r
+ {0x821c,0xf9},\r
+ {0x821d,0xc2},\r
+ {0x821e,0x18},\r
+ {0x821f,0x12},\r
+ {0x8220,0x04},\r
+ {0x8221,0x09},\r
+ {0x8222,0x75},\r
+ {0x8223,0x32},\r
+ {0x8224,0x0a},\r
+ {0x8225,0xaf},\r
+ {0x8226,0x32},\r
+ {0x8227,0x15},\r
+ {0x8228,0x32},\r
+ {0x8229,0xef},\r
+ {0x822a,0x70},\r
+ {0x822b,0xf9},\r
+ {0x822c,0x30},\r
+ {0x822d,0x11},\r
+ {0x822e,0x04},\r
+ {0x822f,0x15},\r
+ {0x8230,0x0c},\r
+ {0x8231,0x80},\r
+ {0x8232,0x45},\r
+ {0x8233,0x12},\r
+ {0x8234,0x04},\r
+ {0x8235,0x07},\r
+ {0x8236,0x12},\r
+ {0x8237,0x04},\r
+ {0x8238,0x4d},\r
+ {0x8239,0x85},\r
+ {0x823a,0x0b},\r
+ {0x823b,0x0d},\r
+ {0x823c,0x12},\r
+ {0x823d,0x0a},\r
+ {0x823e,0x9b},\r
+ {0x823f,0xc2},\r
+ {0x8240,0x0f},\r
+ {0x8241,0x12},\r
+ {0x8242,0x04},\r
+ {0x8243,0x4f},\r
+ {0x8244,0x75},\r
+ {0x8245,0x32},\r
+ {0x8246,0x0a},\r
+ {0x8247,0xaf},\r
+ {0x8248,0x32},\r
+ {0x8249,0x15},\r
+ {0x824a,0x32},\r
+ {0x824b,0xef},\r
+ {0x824c,0x70},\r
+ {0x824d,0xf9},\r
+ {0x824e,0xd2},\r
+ {0x824f,0x18},\r
+ {0x8250,0x12},\r
+ {0x8251,0x04},\r
+ {0x8252,0x09},\r
+ {0x8253,0x12},\r
+ {0x8254,0x04},\r
+ {0x8255,0x97},\r
+ {0x8256,0xaf},\r
+ {0x8257,0x32},\r
+ {0x8258,0x15},\r
+ {0x8259,0x32},\r
+ {0x825a,0xef},\r
+ {0x825b,0x70},\r
+ {0x825c,0xf9},\r
+ {0x825d,0xc2},\r
+ {0x825e,0x18},\r
+ {0x825f,0x12},\r
+ {0x8260,0x04},\r
+ {0x8261,0x09},\r
+ {0x8262,0x75},\r
+ {0x8263,0x32},\r
+ {0x8264,0x0a},\r
+ {0x8265,0xaf},\r
+ {0x8266,0x32},\r
+ {0x8267,0x15},\r
+ {0x8268,0x32},\r
+ {0x8269,0xef},\r
+ {0x826a,0x70},\r
+ {0x826b,0xf9},\r
+ {0x826c,0x30},\r
+ {0x826d,0x11},\r
+ {0x826e,0x06},\r
+ {0x826f,0x15},\r
+ {0x8270,0x0c},\r
+ {0x8271,0xd2},\r
+ {0x8272,0x23},\r
+ {0x8273,0x80},\r
+ {0x8274,0x03},\r
+ {0x8275,0xe4},\r
+ {0x8276,0xf5},\r
+ {0x8277,0x0c},\r
+ {0x8278,0x12},\r
+ {0x8279,0x04},\r
+ {0x827a,0x07},\r
+ {0x827b,0x12},\r
+ {0x827c,0x04},\r
+ {0x827d,0x4d},\r
+ {0x827e,0xc2},\r
+ {0x827f,0x19},\r
+ {0x8280,0x12},\r
+ {0x8281,0x04},\r
+ {0x8282,0x09},\r
+ {0x8283,0x75},\r
+ {0x8284,0x32},\r
+ {0x8285,0x05},\r
+ {0x8286,0xaf},\r
+ {0x8287,0x32},\r
+ {0x8288,0x15},\r
+ {0x8289,0x32},\r
+ {0x828a,0xef},\r
+ {0x828b,0x70},\r
+ {0x828c,0xf9},\r
+ {0x828d,0xd2},\r
+ {0x828e,0x18},\r
+ {0x828f,0x12},\r
+ {0x8290,0x04},\r
+ {0x8291,0x09},\r
+ {0x8292,0x75},\r
+ {0x8293,0x32},\r
+ {0x8294,0x05},\r
+ {0x8295,0xaf},\r
+ {0x8296,0x32},\r
+ {0x8297,0x15},\r
+ {0x8298,0x32},\r
+ {0x8299,0xef},\r
+ {0x829a,0x70},\r
+ {0x829b,0xf9},\r
+ {0x829c,0x12},\r
+ {0x829d,0x04},\r
+ {0x829e,0x07},\r
+ {0x829f,0x75},\r
+ {0x82a0,0x32},\r
+ {0x82a1,0x05},\r
+ {0x82a2,0xaf},\r
+ {0x82a3,0x32},\r
+ {0x82a4,0x15},\r
+ {0x82a5,0x32},\r
+ {0x82a6,0xef},\r
+ {0x82a7,0x70},\r
+ {0x82a8,0xf9},\r
+ {0x82a9,0xa2},\r
+ {0x82aa,0x22},\r
+ {0x82ab,0x92},\r
+ {0x82ac,0xaf},\r
+ {0x82ad,0xe5},\r
+ {0x82ae,0x0c},\r
+ {0x82af,0xd3},\r
+ {0x82b0,0x94},\r
+ {0x82b1,0x00},\r
+ {0x82b2,0x40},\r
+ {0x82b3,0x03},\r
+ {0x82b4,0x02},\r
+ {0x82b5,0x01},\r
+ {0x82b6,0x7f},\r
+ {0x82b7,0x22},\r
+ {0x82b8,0x12},\r
+ {0x82b9,0x0a},\r
+ {0x82ba,0x9b},\r
+ {0x82bb,0xc2},\r
+ {0x82bc,0x0f},\r
+ {0x82bd,0x90},\r
+ {0x82be,0x30},\r
+ {0x82bf,0xb1},\r
+ {0x82c0,0xe5},\r
+ {0x82c1,0x21},\r
+ {0x82c2,0xf0},\r
+ {0x82c3,0x22},\r
+ {0x82c4,0x90},\r
+ {0x82c5,0x33},\r
+ {0x82c6,0x5f},\r
+ {0x82c7,0xe0},\r
+ {0x82c8,0x54},\r
+ {0x82c9,0x0f},\r
+ {0x82ca,0xfe},\r
+ {0x82cb,0xa3},\r
+ {0x82cc,0xe0},\r
+ {0x82cd,0xfd},\r
+ {0x82ce,0xed},\r
+ {0x82cf,0xff},\r
+ {0x82d0,0xee},\r
+ {0x82d1,0x54},\r
+ {0x82d2,0x0f},\r
+ {0x82d3,0xf5},\r
+ {0x82d4,0x0d},\r
+ {0x82d5,0x8f},\r
+ {0x82d6,0x0e},\r
+ {0x82d7,0x90},\r
+ {0x82d8,0x33},\r
+ {0x82d9,0x5f},\r
+ {0x82da,0xe0},\r
+ {0x82db,0x54},\r
+ {0x82dc,0x70},\r
+ {0x82dd,0x75},\r
+ {0x82de,0xf0},\r
+ {0x82df,0x10},\r
+ {0x82e0,0xa4},\r
+ {0x82e1,0xff},\r
+ {0x82e2,0x90},\r
+ {0x82e3,0x33},\r
+ {0x82e4,0x61},\r
+ {0x82e5,0xe0},\r
+ {0x82e6,0xfd},\r
+ {0x82e7,0xef},\r
+ {0x82e8,0x4d},\r
+ {0x82e9,0xff},\r
+ {0x82ea,0xe5},\r
+ {0x82eb,0xf0},\r
+ {0x82ec,0x54},\r
+ {0x82ed,0x07},\r
+ {0x82ee,0xf5},\r
+ {0x82ef,0x0f},\r
+ {0x82f0,0x8f},\r
+ {0x82f1,0x10},\r
+ {0x82f2,0xe5},\r
+ {0x82f3,0x0e},\r
+ {0x82f4,0xae},\r
+ {0x82f5,0x0d},\r
+ {0x82f6,0x78},\r
+ {0x82f7,0x05},\r
+ {0x82f8,0xce},\r
+ {0x82f9,0xc3},\r
+ {0x82fa,0x13},\r
+ {0x82fb,0xce},\r
+ {0x82fc,0x13},\r
+ {0x82fd,0xd8},\r
+ {0x82fe,0xf9},\r
+ {0x82ff,0xf5},\r
+ {0x8300,0x0e},\r
+ {0x8301,0x8e},\r
+ {0x8302,0x0d},\r
+ {0x8303,0xe5},\r
+ {0x8304,0x10},\r
+ {0x8305,0xae},\r
+ {0x8306,0x0f},\r
+ {0x8307,0x78},\r
+ {0x8308,0x03},\r
+ {0x8309,0xce},\r
+ {0x830a,0xc3},\r
+ {0x830b,0x13},\r
+ {0x830c,0xce},\r
+ {0x830d,0x13},\r
+ {0x830e,0xd8},\r
+ {0x830f,0xf9},\r
+ {0x8310,0xf5},\r
+ {0x8311,0x10},\r
+ {0x8312,0x8e},\r
+ {0x8313,0x0f},\r
+ {0x8314,0x85},\r
+ {0x8315,0x2a},\r
+ {0x8316,0x11},\r
+ {0x8317,0x85},\r
+ {0x8318,0x2b},\r
+ {0x8319,0x13},\r
+ {0x831a,0x85},\r
+ {0x831b,0x2c},\r
+ {0x831c,0x12},\r
+ {0x831d,0x85},\r
+ {0x831e,0x2d},\r
+ {0x831f,0x14},\r
+ {0x8320,0x12},\r
+ {0x8321,0x04},\r
+ {0x8322,0xab},\r
+ {0x8323,0xaf},\r
+ {0x8324,0x11},\r
+ {0x8325,0x12},\r
+ {0x8326,0x03},\r
+ {0x8327,0xdf},\r
+ {0x8328,0x8f},\r
+ {0x8329,0x11},\r
+ {0x832a,0x12},\r
+ {0x832b,0x04},\r
+ {0x832c,0xab},\r
+ {0x832d,0xaf},\r
+ {0x832e,0x12},\r
+ {0x832f,0x12},\r
+ {0x8330,0x03},\r
+ {0x8331,0xdf},\r
+ {0x8332,0x8f},\r
+ {0x8333,0x12},\r
+ {0x8334,0x12},\r
+ {0x8335,0x04},\r
+ {0x8336,0x56},\r
+ {0x8337,0xaf},\r
+ {0x8338,0x13},\r
+ {0x8339,0xfc},\r
+ {0x833a,0xfd},\r
+ {0x833b,0xfe},\r
+ {0x833c,0x12},\r
+ {0x833d,0x00},\r
+ {0x833e,0x16},\r
+ {0x833f,0x12},\r
+ {0x8340,0x03},\r
+ {0x8341,0xfe},\r
+ {0x8342,0x7b},\r
+ {0x8343,0x1e},\r
+ {0x8344,0x12},\r
+ {0x8345,0x03},\r
+ {0x8346,0xf7},\r
+ {0x8347,0x8f},\r
+ {0x8348,0x13},\r
+ {0x8349,0x12},\r
+ {0x834a,0x04},\r
+ {0x834b,0x56},\r
+ {0x834c,0xaf},\r
+ {0x834d,0x14},\r
+ {0x834e,0xfc},\r
+ {0x834f,0xfd},\r
+ {0x8350,0xfe},\r
+ {0x8351,0x12},\r
+ {0x8352,0x00},\r
+ {0x8353,0x16},\r
+ {0x8354,0x12},\r
+ {0x8355,0x03},\r
+ {0x8356,0xfe},\r
+ {0x8357,0xe4},\r
+ {0x8358,0x7b},\r
+ {0x8359,0x1e},\r
+ {0x835a,0x12},\r
+ {0x835b,0x03},\r
+ {0x835c,0xf8},\r
+ {0x835d,0x8f},\r
+ {0x835e,0x14},\r
+ {0x835f,0xc3},\r
+ {0x8360,0xe5},\r
+ {0x8361,0x12},\r
+ {0x8362,0x95},\r
+ {0x8363,0x11},\r
+ {0x8364,0xff},\r
+ {0x8365,0x0f},\r
+ {0x8366,0xef},\r
+ {0x8367,0xc3},\r
+ {0x8368,0x13},\r
+ {0x8369,0xff},\r
+ {0x836a,0xc3},\r
+ {0x836b,0x94},\r
+ {0x836c,0x02},\r
+ {0x836d,0x50},\r
+ {0x836e,0x27},\r
+ {0x836f,0xe5},\r
+ {0x8370,0x11},\r
+ {0x8371,0x9f},\r
+ {0x8372,0x40},\r
+ {0x8373,0x06},\r
+ {0x8374,0xe5},\r
+ {0x8375,0x11},\r
+ {0x8376,0x9f},\r
+ {0x8377,0xfe},\r
+ {0x8378,0x80},\r
+ {0x8379,0x02},\r
+ {0x837a,0x7e},\r
+ {0x837b,0x00},\r
+ {0x837c,0x8e},\r
+ {0x837d,0x11},\r
+ {0x837e,0xef},\r
+ {0x837f,0xfd},\r
+ {0x8380,0xe5},\r
+ {0x8381,0x12},\r
+ {0x8382,0x2d},\r
+ {0x8383,0xfd},\r
+ {0x8384,0xe4},\r
+ {0x8385,0x33},\r
+ {0x8386,0xfc},\r
+ {0x8387,0xc3},\r
+ {0x8388,0xed},\r
+ {0x8389,0x95},\r
+ {0x838a,0x0e},\r
+ {0x838b,0xec},\r
+ {0x838c,0x95},\r
+ {0x838d,0x0d},\r
+ {0x838e,0x50},\r
+ {0x838f,0x02},\r
+ {0x8390,0x80},\r
+ {0x8391,0x02},\r
+ {0x8392,0xad},\r
+ {0x8393,0x0e},\r
+ {0x8394,0x8d},\r
+ {0x8395,0x12},\r
+ {0x8396,0xc3},\r
+ {0x8397,0xe5},\r
+ {0x8398,0x14},\r
+ {0x8399,0x95},\r
+ {0x839a,0x13},\r
+ {0x839b,0xff},\r
+ {0x839c,0xc3},\r
+ {0x839d,0x94},\r
+ {0x839e,0x08},\r
+ {0x839f,0x50},\r
+ {0x83a0,0x29},\r
+ {0x83a1,0xe5},\r
+ {0x83a2,0x13},\r
+ {0x83a3,0x9f},\r
+ {0x83a4,0x40},\r
+ {0x83a5,0x06},\r
+ {0x83a6,0xe5},\r
+ {0x83a7,0x13},\r
+ {0x83a8,0x9f},\r
+ {0x83a9,0xfe},\r
+ {0x83aa,0x80},\r
+ {0x83ab,0x02},\r
+ {0x83ac,0x7e},\r
+ {0x83ad,0x00},\r
+ {0x83ae,0x8e},\r
+ {0x83af,0x13},\r
+ {0x83b0,0xef},\r
+ {0x83b1,0xfd},\r
+ {0x83b2,0xe5},\r
+ {0x83b3,0x14},\r
+ {0x83b4,0x2d},\r
+ {0x83b5,0xfd},\r
+ {0x83b6,0xe4},\r
+ {0x83b7,0x33},\r
+ {0x83b8,0xfc},\r
+ {0x83b9,0xc3},\r
+ {0x83ba,0xed},\r
+ {0x83bb,0x95},\r
+ {0x83bc,0x10},\r
+ {0x83bd,0xec},\r
+ {0x83be,0x95},\r
+ {0x83bf,0x0f},\r
+ {0x83c0,0x50},\r
+ {0x83c1,0x04},\r
+ {0x83c2,0xaf},\r
+ {0x83c3,0x05},\r
+ {0x83c4,0x80},\r
+ {0x83c5,0x02},\r
+ {0x83c6,0xaf},\r
+ {0x83c7,0x10},\r
+ {0x83c8,0x8f},\r
+ {0x83c9,0x14},\r
+ {0x83ca,0x90},\r
+ {0x83cb,0x39},\r
+ {0x83cc,0x0a},\r
+ {0x83cd,0xe5},\r
+ {0x83ce,0x11},\r
+ {0x83cf,0xf0},\r
+ {0x83d0,0xa3},\r
+ {0x83d1,0xe5},\r
+ {0x83d2,0x13},\r
+ {0x83d3,0xf0},\r
+ {0x83d4,0xa3},\r
+ {0x83d5,0xe5},\r
+ {0x83d6,0x12},\r
+ {0x83d7,0xf0},\r
+ {0x83d8,0xa3},\r
+ {0x83d9,0xe5},\r
+ {0x83da,0x14},\r
+ {0x83db,0xf0},\r
+ {0x83dc,0xc2},\r
+ {0x83dd,0x20},\r
+ {0x83de,0x22},\r
+ {0x83df,0xab},\r
+ {0x83e0,0x0c},\r
+ {0x83e1,0xaa},\r
+ {0x83e2,0x0b},\r
+ {0x83e3,0xa9},\r
+ {0x83e4,0x0a},\r
+ {0x83e5,0xa8},\r
+ {0x83e6,0x09},\r
+ {0x83e7,0xfc},\r
+ {0x83e8,0xfd},\r
+ {0x83e9,0xfe},\r
+ {0x83ea,0x12},\r
+ {0x83eb,0x00},\r
+ {0x83ec,0x16},\r
+ {0x83ed,0x8f},\r
+ {0x83ee,0x0c},\r
+ {0x83ef,0x8e},\r
+ {0x83f0,0x0b},\r
+ {0x83f1,0x8d},\r
+ {0x83f2,0x0a},\r
+ {0x83f3,0x8c},\r
+ {0x83f4,0x09},\r
+ {0x83f5,0x7b},\r
+ {0x83f6,0x28},\r
+ {0x83f7,0xe4},\r
+ {0x83f8,0xfa},\r
+ {0x83f9,0xf9},\r
+ {0x83fa,0xf8},\r
+ {0x83fb,0x12},\r
+ {0x83fc,0x00},\r
+ {0x83fd,0xa1},\r
+ {0x83fe,0x8f},\r
+ {0x83ff,0x0c},\r
+ {0x8400,0x8e},\r
+ {0x8401,0x0b},\r
+ {0x8402,0x8d},\r
+ {0x8403,0x0a},\r
+ {0x8404,0x8c},\r
+ {0x8405,0x09},\r
+ {0x8406,0x22},\r
+ {0x8407,0xd2},\r
+ {0x8408,0x19},\r
+ {0x8409,0x90},\r
+ {0x840a,0x30},\r
+ {0x840b,0xb4},\r
+ {0x840c,0xe5},\r
+ {0x840d,0x23},\r
+ {0x840e,0xf0},\r
+ {0x840f,0x22},\r
+ {0x8410,0x85},\r
+ {0x8411,0x2f},\r
+ {0x8412,0x82},\r
+ {0x8413,0x85},\r
+ {0x8414,0x2e},\r
+ {0x8415,0x83},\r
+ {0x8416,0xe5},\r
+ {0x8417,0x43},\r
+ {0x8418,0x75},\r
+ {0x8419,0xf0},\r
+ {0x841a,0x02},\r
+ {0x841b,0x12},\r
+ {0x841c,0x01},\r
+ {0x841d,0x46},\r
+ {0x841e,0xe4},\r
+ {0x841f,0x93},\r
+ {0x8420,0xfe},\r
+ {0x8421,0x74},\r
+ {0x8422,0x01},\r
+ {0x8423,0x93},\r
+ {0x8424,0xff},\r
+ {0x8425,0x85},\r
+ {0x8426,0x2f},\r
+ {0x8427,0x82},\r
+ {0x8428,0x85},\r
+ {0x8429,0x2e},\r
+ {0x842a,0x83},\r
+ {0x842b,0xe4},\r
+ {0x842c,0x93},\r
+ {0x842d,0xfc},\r
+ {0x842e,0x74},\r
+ {0x842f,0x01},\r
+ {0x8430,0x93},\r
+ {0x8431,0xfd},\r
+ {0x8432,0xc3},\r
+ {0x8433,0xef},\r
+ {0x8434,0x9d},\r
+ {0x8435,0xff},\r
+ {0x8436,0xee},\r
+ {0x8437,0x9c},\r
+ {0x8438,0x22},\r
+ {0x8439,0x12},\r
+ {0x843a,0x00},\r
+ {0x843b,0x16},\r
+ {0x843c,0x8f},\r
+ {0x843d,0x3c},\r
+ {0x843e,0x8e},\r
+ {0x843f,0x3b},\r
+ {0x8440,0x8d},\r
+ {0x8441,0x3a},\r
+ {0x8442,0x8c},\r
+ {0x8443,0x39},\r
+ {0x8444,0xaf},\r
+ {0x8445,0x3c},\r
+ {0x8446,0xae},\r
+ {0x8447,0x3b},\r
+ {0x8448,0xad},\r
+ {0x8449,0x3a},\r
+ {0x844a,0xac},\r
+ {0x844b,0x39},\r
+ {0x844c,0x22},\r
+ {0x844d,0xd2},\r
+ {0x844e,0x0f},\r
+ {0x844f,0x90},\r
+ {0x8450,0x30},\r
+ {0x8451,0xb1},\r
+ {0x8452,0xe5},\r
+ {0x8453,0x21},\r
+ {0x8454,0xf0},\r
+ {0x8455,0x22},\r
+ {0x8456,0xe4},\r
+ {0x8457,0x85},\r
+ {0x8458,0x10},\r
+ {0x8459,0x0c},\r
+ {0x845a,0x85},\r
+ {0x845b,0x0f},\r
+ {0x845c,0x0b},\r
+ {0x845d,0xf5},\r
+ {0x845e,0x0a},\r
+ {0x845f,0xf5},\r
+ {0x8460,0x09},\r
+ {0x8461,0xab},\r
+ {0x8462,0x0c},\r
+ {0x8463,0xaa},\r
+ {0x8464,0x0b},\r
+ {0x8465,0xa9},\r
+ {0x8466,0x0a},\r
+ {0x8467,0xa8},\r
+ {0x8468,0x09},\r
+ {0x8469,0x22},\r
+ {0x846a,0x85},\r
+ {0x846b,0x2f},\r
+ {0x846c,0x82},\r
+ {0x846d,0x85},\r
+ {0x846e,0x2e},\r
+ {0x846f,0x83},\r
+ {0x8470,0x22},\r
+ {0x8471,0xff},\r
+ {0x8472,0xe4},\r
+ {0x8473,0x94},\r
+ {0x8474,0x00},\r
+ {0x8475,0xfe},\r
+ {0x8476,0xe4},\r
+ {0x8477,0xfc},\r
+ {0x8478,0xfd},\r
+ {0x8479,0x02},\r
+ {0x847a,0x01},\r
+ {0x847b,0x33},\r
+ {0x847c,0xc2},\r
+ {0x847d,0x07},\r
+ {0x847e,0xc2},\r
+ {0x847f,0x06},\r
+ {0x8480,0xc2},\r
+ {0x8481,0x02},\r
+ {0x8482,0xc2},\r
+ {0x8483,0x01},\r
+ {0x8484,0xc2},\r
+ {0x8485,0x00},\r
+ {0x8486,0xc2},\r
+ {0x8487,0x03},\r
+ {0x8488,0xd2},\r
+ {0x8489,0x04},\r
+ {0x848a,0x22},\r
+ {0x848b,0x90},\r
+ {0x848c,0x33},\r
+ {0x848d,0xb3},\r
+ {0x848e,0xe4},\r
+ {0x848f,0xf0},\r
+ {0x8490,0xa3},\r
+ {0x8491,0xf0},\r
+ {0x8492,0xa3},\r
+ {0x8493,0xf0},\r
+ {0x8494,0xa3},\r
+ {0x8495,0xf0},\r
+ {0x8496,0x22},\r
+ {0x8497,0xa3},\r
+ {0x8498,0xe0},\r
+ {0x8499,0xf5},\r
+ {0x849a,0x22},\r
+ {0x849b,0x75},\r
+ {0x849c,0x32},\r
+ {0x849d,0x0a},\r
+ {0x849e,0x22},\r
+ {0x849f,0x12},\r
+ {0x84a0,0x00},\r
+ {0x84a1,0xa1},\r
+ {0x84a2,0x8f},\r
+ {0x84a3,0x3c},\r
+ {0x84a4,0x8e},\r
+ {0x84a5,0x3b},\r
+ {0x84a6,0x8d},\r
+ {0x84a7,0x3a},\r
+ {0x84a8,0x8c},\r
+ {0x84a9,0x39},\r
+ {0x84aa,0x22},\r
+ {0x84ab,0xe4},\r
+ {0x84ac,0x85},\r
+ {0x84ad,0x0e},\r
+ {0x84ae,0x0c},\r
+ {0x84af,0x85},\r
+ {0x84b0,0x0d},\r
+ {0x84b1,0x0b},\r
+ {0x84b2,0xf5},\r
+ {0x84b3,0x0a},\r
+ {0x84b4,0xf5},\r
+ {0x84b5,0x09},\r
+ {0x84b6,0x22},\r
+ {0x84b7,0xe4},\r
+ {0x84b8,0xfc},\r
+ {0x84b9,0xfd},\r
+ {0x84ba,0xfe},\r
+ {0x84bb,0x02},\r
+ {0x84bc,0x01},\r
+ {0x84bd,0x33},\r
+ {0x84be,0x90},\r
+ {0x84bf,0x0b},\r
+ {0x84c0,0x4c},\r
+ {0x84c1,0xe4},\r
+ {0x84c2,0x93},\r
+ {0x84c3,0xff},\r
+ {0x84c4,0x90},\r
+ {0x84c5,0x30},\r
+ {0x84c6,0x0a},\r
+ {0x84c7,0xe0},\r
+ {0x84c8,0x22},\r
+ {0x84c9,0xc2},\r
+ {0x84ca,0x02},\r
+ {0x84cb,0xc2},\r
+ {0x84cc,0x01},\r
+ {0x84cd,0xd2},\r
+ {0x84ce,0x00},\r
+ {0x84cf,0xc2},\r
+ {0x84d0,0x03},\r
+ {0x84d1,0xc2},\r
+ {0x84d2,0x04},\r
+ {0x84d3,0x22},\r
+ {0x84d4,0x75},\r
+ {0x84d5,0xf0},\r
+ {0x84d6,0x02},\r
+ {0x84d7,0x02},\r
+ {0x84d8,0x01},\r
+ {0x84d9,0x46},\r
+ {0x84da,0xe4},\r
+ {0x84db,0x93},\r
+ {0x84dc,0xf5},\r
+ {0x84dd,0x43},\r
+ {0x84de,0xa3},\r
+ {0x84df,0xe4},\r
+ {0x84e0,0x93},\r
+ {0x84e1,0xf5},\r
+ {0x84e2,0x28},\r
+ {0x84e3,0x22},\r
+ {0x84e4,0xd2},\r
+ {0x84e5,0x02},\r
+ {0x84e6,0xd2},\r
+ {0x84e7,0x01},\r
+ {0x84e8,0xc2},\r
+ {0x84e9,0x00},\r
+ {0x84ea,0x22},\r
+ {0x84eb,0xd3},\r
+ {0x84ec,0xe5},\r
+ {0x84ed,0x3c},\r
+ {0x84ee,0x94},\r
+ {0x84ef,0xff},\r
+ {0x84f0,0xe5},\r
+ {0x84f1,0x3b},\r
+ {0x84f2,0x94},\r
+ {0x84f3,0x03},\r
+ {0x84f4,0x22},\r
+ {0x84f5,0x30},\r
+ {0x84f6,0x04},\r
+ {0x84f7,0x03},\r
+ {0x84f8,0x02},\r
+ {0x84f9,0x05},\r
+ {0x84fa,0xd5},\r
+ {0x84fb,0xd2},\r
+ {0x84fc,0x04},\r
+ {0x84fd,0xe5},\r
+ {0x84fe,0x45},\r
+ {0x84ff,0xb4},\r
+ {0x8500,0x01},\r
+ {0x8501,0x06},\r
+ {0x8502,0x12},\r
+ {0x8503,0x0c},\r
+ {0x8504,0xfe},\r
+ {0x8505,0x02},\r
+ {0x8506,0x05},\r
+ {0x8507,0xce},\r
+ {0x8508,0xe5},\r
+ {0x8509,0x45},\r
+ {0x850a,0xb4},\r
+ {0x850b,0x02},\r
+ {0x850c,0x06},\r
+ {0x850d,0x12},\r
+ {0x850e,0x0d},\r
+ {0x850f,0x0f},\r
+ {0x8510,0x02},\r
+ {0x8511,0x05},\r
+ {0x8512,0xce},\r
+ {0x8513,0xe5},\r
+ {0x8514,0x45},\r
+ {0x8515,0xb4},\r
+ {0x8516,0x03},\r
+ {0x8517,0x05},\r
+ {0x8518,0xe4},\r
+ {0x8519,0xf5},\r
+ {0x851a,0x09},\r
+ {0x851b,0x80},\r
+ {0x851c,0x08},\r
+ {0x851d,0xe5},\r
+ {0x851e,0x45},\r
+ {0x851f,0xb4},\r
+ {0x8520,0x04},\r
+ {0x8521,0x09},\r
+ {0x8522,0x85},\r
+ {0x8523,0x43},\r
+ {0x8524,0x09},\r
+ {0x8525,0x12},\r
+ {0x8526,0x09},\r
+ {0x8527,0xee},\r
+ {0x8528,0x02},\r
+ {0x8529,0x05},\r
+ {0x852a,0xce},\r
+ {0x852b,0xe5},\r
+ {0x852c,0x45},\r
+ {0x852d,0x64},\r
+ {0x852e,0x0f},\r
+ {0x852f,0x70},\r
+ {0x8530,0x15},\r
+ {0x8531,0x12},\r
+ {0x8532,0x04},\r
+ {0x8533,0xeb},\r
+ {0x8534,0x40},\r
+ {0x8535,0x06},\r
+ {0x8536,0x7e},\r
+ {0x8537,0x03},\r
+ {0x8538,0x7f},\r
+ {0x8539,0xff},\r
+ {0x853a,0x80},\r
+ {0x853b,0x04},\r
+ {0x853c,0xae},\r
+ {0x853d,0x3b},\r
+ {0x853e,0xaf},\r
+ {0x853f,0x3c},\r
+ {0x8540,0x12},\r
+ {0x8541,0x05},\r
+ {0x8542,0xd6},\r
+ {0x8543,0x02},\r
+ {0x8544,0x05},\r
+ {0x8545,0xce},\r
+ {0x8546,0xe5},\r
+ {0x8547,0x45},\r
+ {0x8548,0x64},\r
+ {0x8549,0x10},\r
+ {0x854a,0x60},\r
+ {0x854b,0x03},\r
+ {0x854c,0x02},\r
+ {0x854d,0x05},\r
+ {0x854e,0xce},\r
+ {0x854f,0xf5},\r
+ {0x8550,0x39},\r
+ {0x8551,0xf5},\r
+ {0x8552,0x3a},\r
+ {0x8553,0xf5},\r
+ {0x8554,0x3b},\r
+ {0x8555,0xab},\r
+ {0x8556,0x3c},\r
+ {0x8557,0xaa},\r
+ {0x8558,0x3b},\r
+ {0x8559,0xa9},\r
+ {0x855a,0x3a},\r
+ {0x855b,0xa8},\r
+ {0x855c,0x39},\r
+ {0x855d,0x12},\r
+ {0x855e,0x04},\r
+ {0x855f,0x10},\r
+ {0x8560,0xfe},\r
+ {0x8561,0xe4},\r
+ {0x8562,0xfc},\r
+ {0x8563,0xfd},\r
+ {0x8564,0x12},\r
+ {0x8565,0x04},\r
+ {0x8566,0x39},\r
+ {0x8567,0xe4},\r
+ {0x8568,0x7b},\r
+ {0x8569,0xff},\r
+ {0x856a,0xfa},\r
+ {0x856b,0xf9},\r
+ {0x856c,0xf8},\r
+ {0x856d,0x12},\r
+ {0x856e,0x04},\r
+ {0x856f,0x9f},\r
+ {0x8570,0x12},\r
+ {0x8571,0x04},\r
+ {0x8572,0x6a},\r
+ {0x8573,0xe4},\r
+ {0x8574,0x93},\r
+ {0x8575,0xfe},\r
+ {0x8576,0x74},\r
+ {0x8577,0x01},\r
+ {0x8578,0x93},\r
+ {0x8579,0xff},\r
+ {0x857a,0xe4},\r
+ {0x857b,0xfc},\r
+ {0x857c,0xfd},\r
+ {0x857d,0xe5},\r
+ {0x857e,0x3c},\r
+ {0x857f,0x2f},\r
+ {0x8580,0xf5},\r
+ {0x8581,0x3c},\r
+ {0x8582,0xe5},\r
+ {0x8583,0x3b},\r
+ {0x8584,0x3e},\r
+ {0x8585,0xf5},\r
+ {0x8586,0x3b},\r
+ {0x8587,0xed},\r
+ {0x8588,0x35},\r
+ {0x8589,0x3a},\r
+ {0x858a,0xf5},\r
+ {0x858b,0x3a},\r
+ {0x858c,0xec},\r
+ {0x858d,0x35},\r
+ {0x858e,0x39},\r
+ {0x858f,0xf5},\r
+ {0x8590,0x39},\r
+ {0x8591,0x12},\r
+ {0x8592,0x04},\r
+ {0x8593,0xeb},\r
+ {0x8594,0x40},\r
+ {0x8595,0x06},\r
+ {0x8596,0x7e},\r
+ {0x8597,0x03},\r
+ {0x8598,0x7f},\r
+ {0x8599,0xff},\r
+ {0x859a,0x80},\r
+ {0x859b,0x04},\r
+ {0x859c,0xae},\r
+ {0x859d,0x3b},\r
+ {0x859e,0xaf},\r
+ {0x859f,0x3c},\r
+ {0x85a0,0x12},\r
+ {0x85a1,0x05},\r
+ {0x85a2,0xd6},\r
+ {0x85a3,0xe4},\r
+ {0x85a4,0xf5},\r
+ {0x85a5,0x3a},\r
+ {0x85a6,0xf5},\r
+ {0x85a7,0x3a},\r
+ {0x85a8,0xe5},\r
+ {0x85a9,0x3a},\r
+ {0x85aa,0xd3},\r
+ {0x85ab,0x95},\r
+ {0x85ac,0x43},\r
+ {0x85ad,0x50},\r
+ {0x85ae,0x1c},\r
+ {0x85af,0x12},\r
+ {0x85b0,0x04},\r
+ {0x85b1,0x6a},\r
+ {0x85b2,0xaf},\r
+ {0x85b3,0x3a},\r
+ {0x85b4,0x75},\r
+ {0x85b5,0xf0},\r
+ {0x85b6,0x02},\r
+ {0x85b7,0xef},\r
+ {0x85b8,0x12},\r
+ {0x85b9,0x01},\r
+ {0x85ba,0x46},\r
+ {0x85bb,0xc3},\r
+ {0x85bc,0x74},\r
+ {0x85bd,0x01},\r
+ {0x85be,0x93},\r
+ {0x85bf,0x95},\r
+ {0x85c0,0x3c},\r
+ {0x85c1,0xe4},\r
+ {0x85c2,0x93},\r
+ {0x85c3,0x95},\r
+ {0x85c4,0x3b},\r
+ {0x85c5,0x50},\r
+ {0x85c6,0x04},\r
+ {0x85c7,0x05},\r
+ {0x85c8,0x3a},\r
+ {0x85c9,0x80},\r
+ {0x85ca,0xdd},\r
+ {0x85cb,0x85},\r
+ {0x85cc,0x3a},\r
+ {0x85cd,0x44},\r
+ {0x85ce,0x90},\r
+ {0x85cf,0x3f},\r
+ {0x85d0,0x01},\r
+ {0x85d1,0xe4},\r
+ {0x85d2,0xf0},\r
+ {0x85d3,0xd2},\r
+ {0x85d4,0x25},\r
+ {0x85d5,0x22},\r
+ {0x85d6,0x8e},\r
+ {0x85d7,0x3b},\r
+ {0x85d8,0x8f},\r
+ {0x85d9,0x3c},\r
+ {0x85da,0x85},\r
+ {0x85db,0x3b},\r
+ {0x85dc,0x37},\r
+ {0x85dd,0x85},\r
+ {0x85de,0x3c},\r
+ {0x85df,0x38},\r
+ {0x85e0,0xe5},\r
+ {0x85e1,0x3c},\r
+ {0x85e2,0xc4},\r
+ {0x85e3,0xf8},\r
+ {0x85e4,0x54},\r
+ {0x85e5,0x0f},\r
+ {0x85e6,0xc8},\r
+ {0x85e7,0x68},\r
+ {0x85e8,0xf5},\r
+ {0x85e9,0x3c},\r
+ {0x85ea,0xe5},\r
+ {0x85eb,0x3b},\r
+ {0x85ec,0xc4},\r
+ {0x85ed,0x54},\r
+ {0x85ee,0xf0},\r
+ {0x85ef,0x48},\r
+ {0x85f0,0xf5},\r
+ {0x85f1,0x3b},\r
+ {0x85f2,0x85},\r
+ {0x85f3,0x3b},\r
+ {0x85f4,0x0a},\r
+ {0x85f5,0x85},\r
+ {0x85f6,0x3c},\r
+ {0x85f7,0x0b},\r
+ {0x85f8,0x12},\r
+ {0x85f9,0x01},\r
+ {0x85fa,0x78},\r
+ {0x85fb,0x22},\r
+ {0x85fc,0xe5},\r
+ {0x85fd,0x29},\r
+ {0x85fe,0x70},\r
+ {0x85ff,0x03},\r
+ {0x8600,0x02},\r
+ {0x8601,0x06},\r
+ {0x8602,0xd4},\r
+ {0x8603,0xc2},\r
+ {0x8604,0xaf},\r
+ {0x8605,0xaf},\r
+ {0x8606,0x29},\r
+ {0x8607,0xe4},\r
+ {0x8608,0xf5},\r
+ {0x8609,0x29},\r
+ {0x860a,0xd2},\r
+ {0x860b,0xaf},\r
+ {0x860c,0x90},\r
+ {0x860d,0x3f},\r
+ {0x860e,0x01},\r
+ {0x860f,0xe0},\r
+ {0x8610,0xf5},\r
+ {0x8611,0x45},\r
+ {0x8612,0xa3},\r
+ {0x8613,0xe0},\r
+ {0x8614,0xf5},\r
+ {0x8615,0x39},\r
+ {0x8616,0xa3},\r
+ {0x8617,0xe0},\r
+ {0x8618,0xf5},\r
+ {0x8619,0x3a},\r
+ {0x861a,0xa3},\r
+ {0x861b,0xe0},\r
+ {0x861c,0xf5},\r
+ {0x861d,0x3b},\r
+ {0x861e,0xa3},\r
+ {0x861f,0xe0},\r
+ {0x8620,0xf5},\r
+ {0x8621,0x3c},\r
+ {0x8622,0xef},\r
+ {0x8623,0x12},\r
+ {0x8624,0x01},\r
+ {0x8625,0x52},\r
+ {0x8626,0x06},\r
+ {0x8627,0x4b},\r
+ {0x8628,0x03},\r
+ {0x8629,0x06},\r
+ {0x862a,0x5a},\r
+ {0x862b,0x05},\r
+ {0x862c,0x06},\r
+ {0x862d,0x81},\r
+ {0x862e,0x06},\r
+ {0x862f,0x06},\r
+ {0x8630,0x6f},\r
+ {0x8631,0x08},\r
+ {0x8632,0x06},\r
+ {0x8633,0xa2},\r
+ {0x8634,0x09},\r
+ {0x8635,0x06},\r
+ {0x8636,0x8e},\r
+ {0x8637,0x10},\r
+ {0x8638,0x06},\r
+ {0x8639,0xa2},\r
+ {0x863a,0x12},\r
+ {0x863b,0x06},\r
+ {0x863c,0xa7},\r
+ {0x863d,0x20},\r
+ {0x863e,0x06},\r
+ {0x863f,0xb5},\r
+ {0x8640,0x21},\r
+ {0x8641,0x06},\r
+ {0x8642,0xba},\r
+ {0x8643,0x30},\r
+ {0x8644,0x06},\r
+ {0x8645,0xc5},\r
+ {0x8646,0xd0},\r
+ {0x8647,0x00},\r
+ {0x8648,0x00},\r
+ {0x8649,0x06},\r
+ {0x864a,0xc9},\r
+ {0x864b,0x30},\r
+ {0x864c,0x05},\r
+ {0x864d,0x7b},\r
+ {0x864e,0x20},\r
+ {0x864f,0x00},\r
+ {0x8650,0x78},\r
+ {0x8651,0xd2},\r
+ {0x8652,0x07},\r
+ {0x8653,0xc2},\r
+ {0x8654,0x06},\r
+ {0x8655,0x12},\r
+ {0x8656,0x04},\r
+ {0x8657,0xc9},\r
+ {0x8658,0x80},\r
+ {0x8659,0x21},\r
+ {0x865a,0x30},\r
+ {0x865b,0x05},\r
+ {0x865c,0x6c},\r
+ {0x865d,0x20},\r
+ {0x865e,0x00},\r
+ {0x865f,0x69},\r
+ {0x8660,0xc2},\r
+ {0x8661,0x07},\r
+ {0x8662,0xd2},\r
+ {0x8663,0x06},\r
+ {0x8664,0xc2},\r
+ {0x8665,0x03},\r
+ {0x8666,0x12},\r
+ {0x8667,0x04},\r
+ {0x8668,0xe4},\r
+ {0x8669,0xc2},\r
+ {0x866a,0x04},\r
+ {0x866b,0xc2},\r
+ {0x866c,0x21},\r
+ {0x866d,0x80},\r
+ {0x866e,0x5a},\r
+ {0x866f,0x12},\r
+ {0x8670,0x04},\r
+ {0x8671,0x7c},\r
+ {0x8672,0x30},\r
+ {0x8673,0x05},\r
+ {0x8674,0x06},\r
+ {0x8675,0xe4},\r
+ {0x8676,0xf5},\r
+ {0x8677,0x09},\r
+ {0x8678,0x12},\r
+ {0x8679,0x09},\r
+ {0x867a,0xee},\r
+ {0x867b,0xc2},\r
+ {0x867c,0x21},\r
+ {0x867d,0xd2},\r
+ {0x867e,0x25},\r
+ {0x867f,0x80},\r
+ {0x8680,0x48},\r
+ {0x8681,0x30},\r
+ {0x8682,0x07},\r
+ {0x8683,0x45},\r
+ {0x8684,0x30},\r
+ {0x8685,0x06},\r
+ {0x8686,0x42},\r
+ {0x8687,0x12},\r
+ {0x8688,0x04},\r
+ {0x8689,0xc9},\r
+ {0x868a,0xd2},\r
+ {0x868b,0x21},\r
+ {0x868c,0x80},\r
+ {0x868d,0x3b},\r
+ {0x868e,0x20},\r
+ {0x868f,0x07},\r
+ {0x8690,0x03},\r
+ {0x8691,0x30},\r
+ {0x8692,0x06},\r
+ {0x8693,0x09},\r
+ {0x8694,0xe5},\r
+ {0x8695,0x45},\r
+ {0x8696,0x64},\r
+ {0x8697,0x0e},\r
+ {0x8698,0x70},\r
+ {0x8699,0x2f},\r
+ {0x869a,0x20},\r
+ {0x869b,0x00},\r
+ {0x869c,0x2c},\r
+ {0x869d,0x12},\r
+ {0x869e,0x06},\r
+ {0x869f,0xd5},\r
+ {0x86a0,0x80},\r
+ {0x86a1,0x27},\r
+ {0x86a2,0x12},\r
+ {0x86a3,0x02},\r
+ {0x86a4,0xc4},\r
+ {0x86a5,0x80},\r
+ {0x86a6,0x22},\r
+ {0x86a7,0x30},\r
+ {0x86a8,0x05},\r
+ {0x86a9,0x1f},\r
+ {0x86aa,0x20},\r
+ {0x86ab,0x07},\r
+ {0x86ac,0x1c},\r
+ {0x86ad,0x20},\r
+ {0x86ae,0x06},\r
+ {0x86af,0x19},\r
+ {0x86b0,0x12},\r
+ {0x86b1,0x0c},\r
+ {0x86b2,0xa6},\r
+ {0x86b3,0x80},\r
+ {0x86b4,0x14},\r
+ {0x86b5,0x12},\r
+ {0x86b6,0x09},\r
+ {0x86b7,0x85},\r
+ {0x86b8,0x80},\r
+ {0x86b9,0x0f},\r
+ {0x86ba,0x20},\r
+ {0x86bb,0x07},\r
+ {0x86bc,0x0c},\r
+ {0x86bd,0x20},\r
+ {0x86be,0x06},\r
+ {0x86bf,0x09},\r
+ {0x86c0,0x12},\r
+ {0x86c1,0x0d},\r
+ {0x86c2,0x3c},\r
+ {0x86c3,0x80},\r
+ {0x86c4,0x04},\r
+ {0x86c5,0xd2},\r
+ {0x86c6,0x26},\r
+ {0x86c7,0xc2},\r
+ {0x86c8,0x26},\r
+ {0x86c9,0x20},\r
+ {0x86ca,0x07},\r
+ {0x86cb,0x03},\r
+ {0x86cc,0x20},\r
+ {0x86cd,0x06},\r
+ {0x86ce,0x05},\r
+ {0x86cf,0x90},\r
+ {0x86d0,0x3f},\r
+ {0x86d1,0x01},\r
+ {0x86d2,0xe4},\r
+ {0x86d3,0xf0},\r
+ {0x86d4,0x22},\r
+ {0x86d5,0xe5},\r
+ {0x86d6,0x45},\r
+ {0x86d7,0x24},\r
+ {0x86d8,0xfe},\r
+ {0x86d9,0x60},\r
+ {0x86da,0x19},\r
+ {0x86db,0x14},\r
+ {0x86dc,0x60},\r
+ {0x86dd,0x2c},\r
+ {0x86de,0x24},\r
+ {0x86df,0x02},\r
+ {0x86e0,0x60},\r
+ {0x86e1,0x03},\r
+ {0x86e2,0x02},\r
+ {0x86e3,0x07},\r
+ {0x86e4,0xa8},\r
+ {0x86e5,0xe5},\r
+ {0x86e6,0x3c},\r
+ {0x86e7,0xd3},\r
+ {0x86e8,0x94},\r
+ {0x86e9,0x03},\r
+ {0x86ea,0x40},\r
+ {0x86eb,0x03},\r
+ {0x86ec,0x75},\r
+ {0x86ed,0x3c},\r
+ {0x86ee,0x03},\r
+ {0x86ef,0xe4},\r
+ {0x86f0,0xf5},\r
+ {0x86f1,0x09},\r
+ {0x86f2,0x80},\r
+ {0x86f3,0x0d},\r
+ {0x86f4,0xe5},\r
+ {0x86f5,0x3c},\r
+ {0x86f6,0xd3},\r
+ {0x86f7,0x94},\r
+ {0x86f8,0x05},\r
+ {0x86f9,0x40},\r
+ {0x86fa,0x03},\r
+ {0x86fb,0x75},\r
+ {0x86fc,0x3c},\r
+ {0x86fd,0x05},\r
+ {0x86fe,0x75},\r
+ {0x86ff,0x09},\r
+ {0x8700,0x01},\r
+ {0x8701,0x85},\r
+ {0x8702,0x3c},\r
+ {0x8703,0x0a},\r
+ {0x8704,0x12},\r
+ {0x8705,0x08},\r
+ {0x8706,0xfa},\r
+ {0x8707,0xd2},\r
+ {0x8708,0x20},\r
+ {0x8709,0x22},\r
+ {0x870a,0xe5},\r
+ {0x870b,0x39},\r
+ {0x870c,0xd3},\r
+ {0x870d,0x94},\r
+ {0x870e,0x28},\r
+ {0x870f,0x40},\r
+ {0x8710,0x04},\r
+ {0x8711,0x7f},\r
+ {0x8712,0x28},\r
+ {0x8713,0x80},\r
+ {0x8714,0x02},\r
+ {0x8715,0xaf},\r
+ {0x8716,0x39},\r
+ {0x8717,0x8f},\r
+ {0x8718,0x39},\r
+ {0x8719,0xe5},\r
+ {0x871a,0x3a},\r
+ {0x871b,0xd3},\r
+ {0x871c,0x94},\r
+ {0x871d,0x1e},\r
+ {0x871e,0x40},\r
+ {0x871f,0x04},\r
+ {0x8720,0x7f},\r
+ {0x8721,0x1e},\r
+ {0x8722,0x80},\r
+ {0x8723,0x02},\r
+ {0x8724,0xaf},\r
+ {0x8725,0x3a},\r
+ {0x8726,0x8f},\r
+ {0x8727,0x3a},\r
+ {0x8728,0xe5},\r
+ {0x8729,0x3b},\r
+ {0x872a,0xd3},\r
+ {0x872b,0x94},\r
+ {0x872c,0x28},\r
+ {0x872d,0x40},\r
+ {0x872e,0x04},\r
+ {0x872f,0x7f},\r
+ {0x8730,0x28},\r
+ {0x8731,0x80},\r
+ {0x8732,0x02},\r
+ {0x8733,0xaf},\r
+ {0x8734,0x3b},\r
+ {0x8735,0x8f},\r
+ {0x8736,0x3b},\r
+ {0x8737,0xe5},\r
+ {0x8738,0x3c},\r
+ {0x8739,0xd3},\r
+ {0x873a,0x94},\r
+ {0x873b,0x1e},\r
+ {0x873c,0x40},\r
+ {0x873d,0x04},\r
+ {0x873e,0x7f},\r
+ {0x873f,0x1e},\r
+ {0x8740,0x80},\r
+ {0x8741,0x02},\r
+ {0x8742,0xaf},\r
+ {0x8743,0x3c},\r
+ {0x8744,0x8f},\r
+ {0x8745,0x3c},\r
+ {0x8746,0xaf},\r
+ {0x8747,0x3a},\r
+ {0x8748,0x78},\r
+ {0x8749,0x10},\r
+ {0x874a,0x12},\r
+ {0x874b,0x04},\r
+ {0x874c,0xb7},\r
+ {0x874d,0xc0},\r
+ {0x874e,0x04},\r
+ {0x874f,0xc0},\r
+ {0x8750,0x05},\r
+ {0x8751,0xc0},\r
+ {0x8752,0x06},\r
+ {0x8753,0xc0},\r
+ {0x8754,0x07},\r
+ {0x8755,0xaf},\r
+ {0x8756,0x39},\r
+ {0x8757,0x78},\r
+ {0x8758,0x18},\r
+ {0x8759,0x12},\r
+ {0x875a,0x04},\r
+ {0x875b,0xb7},\r
+ {0x875c,0xd0},\r
+ {0x875d,0x03},\r
+ {0x875e,0xd0},\r
+ {0x875f,0x02},\r
+ {0x8760,0xd0},\r
+ {0x8761,0x01},\r
+ {0x8762,0xd0},\r
+ {0x8763,0x00},\r
+ {0x8764,0xef},\r
+ {0x8765,0x4b},\r
+ {0x8766,0xff},\r
+ {0x8767,0xee},\r
+ {0x8768,0x4a},\r
+ {0x8769,0xfe},\r
+ {0x876a,0xed},\r
+ {0x876b,0x49},\r
+ {0x876c,0xfd},\r
+ {0x876d,0xec},\r
+ {0x876e,0x48},\r
+ {0x876f,0xfc},\r
+ {0x8770,0xc0},\r
+ {0x8771,0x04},\r
+ {0x8772,0xc0},\r
+ {0x8773,0x05},\r
+ {0x8774,0xc0},\r
+ {0x8775,0x06},\r
+ {0x8776,0xc0},\r
+ {0x8777,0x07},\r
+ {0x8778,0xaf},\r
+ {0x8779,0x3b},\r
+ {0x877a,0xe4},\r
+ {0x877b,0xfc},\r
+ {0x877c,0xfd},\r
+ {0x877d,0xfe},\r
+ {0x877e,0x78},\r
+ {0x877f,0x08},\r
+ {0x8780,0x12},\r
+ {0x8781,0x01},\r
+ {0x8782,0x33},\r
+ {0x8783,0xd0},\r
+ {0x8784,0x03},\r
+ {0x8785,0xd0},\r
+ {0x8786,0x02},\r
+ {0x8787,0xd0},\r
+ {0x8788,0x01},\r
+ {0x8789,0xd0},\r
+ {0x878a,0x00},\r
+ {0x878b,0xef},\r
+ {0x878c,0x4b},\r
+ {0x878d,0xfb},\r
+ {0x878e,0xee},\r
+ {0x878f,0x4a},\r
+ {0x8790,0xfa},\r
+ {0x8791,0xed},\r
+ {0x8792,0x49},\r
+ {0x8793,0xf9},\r
+ {0x8794,0xec},\r
+ {0x8795,0x48},\r
+ {0x8796,0xf8},\r
+ {0x8797,0xaf},\r
+ {0x8798,0x3c},\r
+ {0x8799,0xeb},\r
+ {0x879a,0x4f},\r
+ {0x879b,0xf5},\r
+ {0x879c,0x2d},\r
+ {0x879d,0xea},\r
+ {0x879e,0xf5},\r
+ {0x879f,0x2c},\r
+ {0x87a0,0xe9},\r
+ {0x87a1,0xf5},\r
+ {0x87a2,0x2b},\r
+ {0x87a3,0xe8},\r
+ {0x87a4,0xf5},\r
+ {0x87a5,0x2a},\r
+ {0x87a6,0xd2},\r
+ {0x87a7,0x20},\r
+ {0x87a8,0x22},\r
+ {0x87a9,0xc0},\r
+ {0x87aa,0xe0},\r
+ {0x87ab,0xc0},\r
+ {0x87ac,0x83},\r
+ {0x87ad,0xc0},\r
+ {0x87ae,0x82},\r
+ {0x87af,0xc0},\r
+ {0x87b0,0xd0},\r
+ {0x87b1,0x75},\r
+ {0x87b2,0xd0},\r
+ {0x87b3,0x00},\r
+ {0x87b4,0xc0},\r
+ {0x87b5,0x00},\r
+ {0x87b6,0xc0},\r
+ {0x87b7,0x06},\r
+ {0x87b8,0xc0},\r
+ {0x87b9,0x07},\r
+ {0x87ba,0x90},\r
+ {0x87bb,0x37},\r
+ {0x87bc,0x08},\r
+ {0x87bd,0xe0},\r
+ {0x87be,0xf5},\r
+ {0x87bf,0x08},\r
+ {0x87c0,0xe5},\r
+ {0x87c1,0x08},\r
+ {0x87c2,0x30},\r
+ {0x87c3,0xe3},\r
+ {0x87c4,0x23},\r
+ {0x87c5,0x20},\r
+ {0x87c6,0x26},\r
+ {0x87c7,0x20},\r
+ {0x87c8,0x90},\r
+ {0x87c9,0x3a},\r
+ {0x87ca,0x00},\r
+ {0x87cb,0x74},\r
+ {0x87cc,0x81},\r
+ {0x87cd,0xf0},\r
+ {0x87ce,0x90},\r
+ {0x87cf,0x3a},\r
+ {0x87d0,0x03},\r
+ {0x87d1,0xe0},\r
+ {0x87d2,0xf5},\r
+ {0x87d3,0x3e},\r
+ {0x87d4,0xe0},\r
+ {0x87d5,0xf5},\r
+ {0x87d6,0x3d},\r
+ {0x87d7,0x90},\r
+ {0x87d8,0x3a},\r
+ {0x87d9,0x00},\r
+ {0x87da,0x74},\r
+ {0x87db,0x85},\r
+ {0x87dc,0xf0},\r
+ {0x87dd,0x90},\r
+ {0x87de,0x3a},\r
+ {0x87df,0x03},\r
+ {0x87e0,0xe0},\r
+ {0x87e1,0xf5},\r
+ {0x87e2,0x40},\r
+ {0x87e3,0xe0},\r
+ {0x87e4,0xf5},\r
+ {0x87e5,0x3f},\r
+ {0x87e6,0xd2},\r
+ {0x87e7,0x2f},\r
+ {0x87e8,0xe5},\r
+ {0x87e9,0x08},\r
+ {0x87ea,0x30},\r
+ {0x87eb,0xe5},\r
+ {0x87ec,0x56},\r
+ {0x87ed,0x90},\r
+ {0x87ee,0x30},\r
+ {0x87ef,0x1b},\r
+ {0x87f0,0xe0},\r
+ {0x87f1,0xf5},\r
+ {0x87f2,0x42},\r
+ {0x87f3,0xe5},\r
+ {0x87f4,0x41},\r
+ {0x87f5,0x24},\r
+ {0x87f6,0x02},\r
+ {0x87f7,0xff},\r
+ {0x87f8,0xe4},\r
+ {0x87f9,0x33},\r
+ {0x87fa,0xfe},\r
+ {0x87fb,0xc3},\r
+ {0x87fc,0xef},\r
+ {0x87fd,0x95},\r
+ {0x87fe,0x42},\r
+ {0x87ff,0x74},\r
+ {0x8800,0x80},\r
+ {0x8801,0xf8},\r
+ {0x8802,0x6e},\r
+ {0x8803,0x98},\r
+ {0x8804,0x50},\r
+ {0x8805,0x02},\r
+ {0x8806,0x80},\r
+ {0x8807,0x01},\r
+ {0x8808,0xc3},\r
+ {0x8809,0x92},\r
+ {0x880a,0x24},\r
+ {0x880b,0xe5},\r
+ {0x880c,0x42},\r
+ {0x880d,0x24},\r
+ {0x880e,0x02},\r
+ {0x880f,0xff},\r
+ {0x8810,0xe4},\r
+ {0x8811,0x33},\r
+ {0x8812,0xfe},\r
+ {0x8813,0xc3},\r
+ {0x8814,0xef},\r
+ {0x8815,0x95},\r
+ {0x8816,0x41},\r
+ {0x8817,0x74},\r
+ {0x8818,0x80},\r
+ {0x8819,0xf8},\r
+ {0x881a,0x6e},\r
+ {0x881b,0x98},\r
+ {0x881c,0x50},\r
+ {0x881d,0x02},\r
+ {0x881e,0x80},\r
+ {0x881f,0x02},\r
+ {0x8820,0xa2},\r
+ {0x8821,0x24},\r
+ {0x8822,0x92},\r
+ {0x8823,0x24},\r
+ {0x8824,0x30},\r
+ {0x8825,0x24},\r
+ {0x8826,0x04},\r
+ {0x8827,0xaf},\r
+ {0x8828,0x42},\r
+ {0x8829,0x80},\r
+ {0x882a,0x02},\r
+ {0x882b,0xaf},\r
+ {0x882c,0x41},\r
+ {0x882d,0x8f},\r
+ {0x882e,0x41},\r
+ {0x882f,0x30},\r
+ {0x8830,0x27},\r
+ {0x8831,0x11},\r
+ {0x8832,0x90},\r
+ {0x8833,0x33},\r
+ {0x8834,0x00},\r
+ {0x8835,0xe0},\r
+ {0x8836,0x30},\r
+ {0x8837,0x29},\r
+ {0x8838,0x05},\r
+ {0x8839,0x44},\r
+ {0x883a,0x40},\r
+ {0x883b,0xf0},\r
+ {0x883c,0x80},\r
+ {0x883d,0x03},\r
+ {0x883e,0x54},\r
+ {0x883f,0xbf},\r
+ {0x8840,0xf0},\r
+ {0x8841,0xc2},\r
+ {0x8842,0x27},\r
+ {0x8843,0xe5},\r
+ {0x8844,0x08},\r
+ {0x8845,0x30},\r
+ {0x8846,0xe1},\r
+ {0x8847,0x08},\r
+ {0x8848,0x90},\r
+ {0x8849,0x3f},\r
+ {0x884a,0x00},\r
+ {0x884b,0xe0},\r
+ {0x884c,0xf5},\r
+ {0x884d,0x29},\r
+ {0x884e,0xe4},\r
+ {0x884f,0xf0},\r
+ {0x8850,0x90},\r
+ {0x8851,0x37},\r
+ {0x8852,0x08},\r
+ {0x8853,0xe5},\r
+ {0x8854,0x08},\r
+ {0x8855,0xf0},\r
+ {0x8856,0xd0},\r
+ {0x8857,0x07},\r
+ {0x8858,0xd0},\r
+ {0x8859,0x06},\r
+ {0x885a,0xd0},\r
+ {0x885b,0x00},\r
+ {0x885c,0xd0},\r
+ {0x885d,0xd0},\r
+ {0x885e,0xd0},\r
+ {0x885f,0x82},\r
+ {0x8860,0xd0},\r
+ {0x8861,0x83},\r
+ {0x8862,0xd0},\r
+ {0x8863,0xe0},\r
+ {0x8864,0x32},\r
+ {0x8865,0x12},\r
+ {0x8866,0x04},\r
+ {0x8867,0xbe},\r
+ {0x8868,0xb5},\r
+ {0x8869,0x07},\r
+ {0x886a,0x03},\r
+ {0x886b,0xd3},\r
+ {0x886c,0x80},\r
+ {0x886d,0x01},\r
+ {0x886e,0xc3},\r
+ {0x886f,0x40},\r
+ {0x8870,0x03},\r
+ {0x8871,0x02},\r
+ {0x8872,0x08},\r
+ {0x8873,0xf9},\r
+ {0x8874,0x90},\r
+ {0x8875,0x31},\r
+ {0x8876,0x00},\r
+ {0x8877,0xe0},\r
+ {0x8878,0x54},\r
+ {0x8879,0xfe},\r
+ {0x887a,0xf0},\r
+ {0x887b,0xe0},\r
+ {0x887c,0x54},\r
+ {0x887d,0xfd},\r
+ {0x887e,0xf0},\r
+ {0x887f,0xa3},\r
+ {0x8880,0xe4},\r
+ {0x8881,0xf0},\r
+ {0x8882,0x90},\r
+ {0x8883,0x33},\r
+ {0x8884,0x00},\r
+ {0x8885,0xe0},\r
+ {0x8886,0x54},\r
+ {0x8887,0xbf},\r
+ {0x8888,0xf0},\r
+ {0x8889,0x12},\r
+ {0x888a,0x04},\r
+ {0x888b,0x8b},\r
+ {0x888c,0x90},\r
+ {0x888d,0x33},\r
+ {0x888e,0xb0},\r
+ {0x888f,0xf0},\r
+ {0x8890,0xa3},\r
+ {0x8891,0xf0},\r
+ {0x8892,0xa3},\r
+ {0x8893,0xf0},\r
+ {0x8894,0x90},\r
+ {0x8895,0x30},\r
+ {0x8896,0xb2},\r
+ {0x8897,0xe0},\r
+ {0x8898,0x44},\r
+ {0x8899,0x08},\r
+ {0x889a,0xf0},\r
+ {0x889b,0x90},\r
+ {0x889c,0x30},\r
+ {0x889d,0xb0},\r
+ {0x889e,0xe0},\r
+ {0x889f,0x44},\r
+ {0x88a0,0x01},\r
+ {0x88a1,0xf0},\r
+ {0x88a2,0xa3},\r
+ {0x88a3,0xe0},\r
+ {0x88a4,0x44},\r
+ {0x88a5,0x0c},\r
+ {0x88a6,0xf0},\r
+ {0x88a7,0x90},\r
+ {0x88a8,0x30},\r
+ {0x88a9,0xb4},\r
+ {0x88aa,0xe0},\r
+ {0x88ab,0x44},\r
+ {0x88ac,0x07},\r
+ {0x88ad,0xf0},\r
+ {0x88ae,0xe0},\r
+ {0x88af,0xf5},\r
+ {0x88b0,0x23},\r
+ {0x88b1,0x90},\r
+ {0x88b2,0x30},\r
+ {0x88b3,0xb1},\r
+ {0x88b4,0xe0},\r
+ {0x88b5,0xf5},\r
+ {0x88b6,0x21},\r
+ {0x88b7,0x90},\r
+ {0x88b8,0x39},\r
+ {0x88b9,0x01},\r
+ {0x88ba,0x74},\r
+ {0x88bb,0x35},\r
+ {0x88bc,0xf0},\r
+ {0x88bd,0x90},\r
+ {0x88be,0x39},\r
+ {0x88bf,0x00},\r
+ {0x88c0,0x74},\r
+ {0x88c1,0x20},\r
+ {0x88c2,0xf0},\r
+ {0x88c3,0x90},\r
+ {0x88c4,0x37},\r
+ {0x88c5,0x00},\r
+ {0x88c6,0x74},\r
+ {0x88c7,0xff},\r
+ {0x88c8,0xf0},\r
+ {0x88c9,0xa3},\r
+ {0x88ca,0xf0},\r
+ {0x88cb,0x90},\r
+ {0x88cc,0x37},\r
+ {0x88cd,0x00},\r
+ {0x88ce,0xe0},\r
+ {0x88cf,0x54},\r
+ {0x88d0,0xf7},\r
+ {0x88d1,0xf0},\r
+ {0x88d2,0xe0},\r
+ {0x88d3,0x54},\r
+ {0x88d4,0xdf},\r
+ {0x88d5,0xf0},\r
+ {0x88d6,0x90},\r
+ {0x88d7,0x31},\r
+ {0x88d8,0x0f},\r
+ {0x88d9,0x74},\r
+ {0x88da,0x3f},\r
+ {0x88db,0xf0},\r
+ {0x88dc,0xa3},\r
+ {0x88dd,0xe4},\r
+ {0x88de,0xf0},\r
+ {0x88df,0xa3},\r
+ {0x88e0,0x74},\r
+ {0x88e1,0x3f},\r
+ {0x88e2,0xf0},\r
+ {0x88e3,0xa3},\r
+ {0x88e4,0x74},\r
+ {0x88e5,0x01},\r
+ {0x88e6,0xf0},\r
+ {0x88e7,0x90},\r
+ {0x88e8,0x37},\r
+ {0x88e9,0x00},\r
+ {0x88ea,0xe0},\r
+ {0x88eb,0x54},\r
+ {0x88ec,0xfd},\r
+ {0x88ed,0xf0},\r
+ {0x88ee,0x90},\r
+ {0x88ef,0x37},\r
+ {0x88f0,0x08},\r
+ {0x88f1,0x74},\r
+ {0x88f2,0xff},\r
+ {0x88f3,0xf0},\r
+ {0x88f4,0xa3},\r
+ {0x88f5,0xf0},\r
+ {0x88f6,0x75},\r
+ {0x88f7,0xa8},\r
+ {0x88f8,0x01},\r
+ {0x88f9,0x22},\r
+ {0x88fa,0xe5},\r
+ {0x88fb,0x0a},\r
+ {0x88fc,0x25},\r
+ {0x88fd,0xe0},\r
+ {0x88fe,0x25},\r
+ {0x88ff,0xe0},\r
+ {0x8900,0xf5},\r
+ {0x8901,0x0b},\r
+ {0x8902,0xe5},\r
+ {0x8903,0x09},\r
+ {0x8904,0x60},\r
+ {0x8905,0x09},\r
+ {0x8906,0xe5},\r
+ {0x8907,0x0a},\r
+ {0x8908,0x75},\r
+ {0x8909,0xf0},\r
+ {0x890a,0x03},\r
+ {0x890b,0xa4},\r
+ {0x890c,0xff},\r
+ {0x890d,0x80},\r
+ {0x890e,0x02},\r
+ {0x890f,0xaf},\r
+ {0x8910,0x0b},\r
+ {0x8911,0x8f},\r
+ {0x8912,0x0c},\r
+ {0x8913,0xc3},\r
+ {0x8914,0x74},\r
+ {0x8915,0x0f},\r
+ {0x8916,0x9f},\r
+ {0x8917,0x78},\r
+ {0x8918,0x10},\r
+ {0x8919,0x12},\r
+ {0x891a,0x04},\r
+ {0x891b,0x71},\r
+ {0x891c,0xc0},\r
+ {0x891d,0x04},\r
+ {0x891e,0xc0},\r
+ {0x891f,0x05},\r
+ {0x8920,0xc0},\r
+ {0x8921,0x06},\r
+ {0x8922,0xc0},\r
+ {0x8923,0x07},\r
+ {0x8924,0xc3},\r
+ {0x8925,0x74},\r
+ {0x8926,0x14},\r
+ {0x8927,0x95},\r
+ {0x8928,0x0b},\r
+ {0x8929,0x78},\r
+ {0x892a,0x18},\r
+ {0x892b,0x12},\r
+ {0x892c,0x04},\r
+ {0x892d,0x71},\r
+ {0x892e,0xd0},\r
+ {0x892f,0x03},\r
+ {0x8930,0xd0},\r
+ {0x8931,0x02},\r
+ {0x8932,0xd0},\r
+ {0x8933,0x01},\r
+ {0x8934,0xd0},\r
+ {0x8935,0x00},\r
+ {0x8936,0xef},\r
+ {0x8937,0x4b},\r
+ {0x8938,0xff},\r
+ {0x8939,0xee},\r
+ {0x893a,0x4a},\r
+ {0x893b,0xfe},\r
+ {0x893c,0xed},\r
+ {0x893d,0x49},\r
+ {0x893e,0xfd},\r
+ {0x893f,0xec},\r
+ {0x8940,0x48},\r
+ {0x8941,0xfc},\r
+ {0x8942,0xc0},\r
+ {0x8943,0x04},\r
+ {0x8944,0xc0},\r
+ {0x8945,0x05},\r
+ {0x8946,0xc0},\r
+ {0x8947,0x06},\r
+ {0x8948,0xc0},\r
+ {0x8949,0x07},\r
+ {0x894a,0xe5},\r
+ {0x894b,0x0b},\r
+ {0x894c,0x24},\r
+ {0x894d,0x14},\r
+ {0x894e,0xff},\r
+ {0x894f,0xe4},\r
+ {0x8950,0x33},\r
+ {0x8951,0xfe},\r
+ {0x8952,0xe4},\r
+ {0x8953,0xfc},\r
+ {0x8954,0xfd},\r
+ {0x8955,0x78},\r
+ {0x8956,0x08},\r
+ {0x8957,0x12},\r
+ {0x8958,0x01},\r
+ {0x8959,0x33},\r
+ {0x895a,0xd0},\r
+ {0x895b,0x03},\r
+ {0x895c,0xd0},\r
+ {0x895d,0x02},\r
+ {0x895e,0xd0},\r
+ {0x895f,0x01},\r
+ {0x8960,0xd0},\r
+ {0x8961,0x00},\r
+ {0x8962,0xef},\r
+ {0x8963,0x4b},\r
+ {0x8964,0xfb},\r
+ {0x8965,0xee},\r
+ {0x8966,0x4a},\r
+ {0x8967,0xfa},\r
+ {0x8968,0xed},\r
+ {0x8969,0x49},\r
+ {0x896a,0xf9},\r
+ {0x896b,0xec},\r
+ {0x896c,0x48},\r
+ {0x896d,0xf8},\r
+ {0x896e,0xe5},\r
+ {0x896f,0x0c},\r
+ {0x8970,0x24},\r
+ {0x8971,0x0f},\r
+ {0x8972,0xff},\r
+ {0x8973,0xe4},\r
+ {0x8974,0x33},\r
+ {0x8975,0xfe},\r
+ {0x8976,0xeb},\r
+ {0x8977,0x4f},\r
+ {0x8978,0xf5},\r
+ {0x8979,0x2d},\r
+ {0x897a,0xea},\r
+ {0x897b,0x4e},\r
+ {0x897c,0xf5},\r
+ {0x897d,0x2c},\r
+ {0x897e,0xe9},\r
+ {0x897f,0xf5},\r
+ {0x8980,0x2b},\r
+ {0x8981,0xe8},\r
+ {0x8982,0xf5},\r
+ {0x8983,0x2a},\r
+ {0x8984,0x22},\r
+ {0x8985,0xe5},\r
+ {0x8986,0x45},\r
+ {0x8987,0x64},\r
+ {0x8988,0x01},\r
+ {0x8989,0x70},\r
+ {0x898a,0x50},\r
+ {0x898b,0x12},\r
+ {0x898c,0x04},\r
+ {0x898d,0x6a},\r
+ {0x898e,0xe5},\r
+ {0x898f,0x44},\r
+ {0x8990,0x12},\r
+ {0x8991,0x04},\r
+ {0x8992,0x18},\r
+ {0x8993,0xfe},\r
+ {0x8994,0xe4},\r
+ {0x8995,0x8f},\r
+ {0x8996,0x3c},\r
+ {0x8997,0x8e},\r
+ {0x8998,0x3b},\r
+ {0x8999,0xf5},\r
+ {0x899a,0x3a},\r
+ {0x899b,0xf5},\r
+ {0x899c,0x39},\r
+ {0x899d,0x12},\r
+ {0x899e,0x04},\r
+ {0x899f,0x44},\r
+ {0x89a0,0x7b},\r
+ {0x89a1,0xff},\r
+ {0x89a2,0xfa},\r
+ {0x89a3,0xf9},\r
+ {0x89a4,0xf8},\r
+ {0x89a5,0x12},\r
+ {0x89a6,0x04},\r
+ {0x89a7,0x39},\r
+ {0x89a8,0xc0},\r
+ {0x89a9,0x04},\r
+ {0x89aa,0xc0},\r
+ {0x89ab,0x05},\r
+ {0x89ac,0xc0},\r
+ {0x89ad,0x06},\r
+ {0x89ae,0xc0},\r
+ {0x89af,0x07},\r
+ {0x89b0,0x12},\r
+ {0x89b1,0x04},\r
+ {0x89b2,0x10},\r
+ {0x89b3,0xab},\r
+ {0x89b4,0x07},\r
+ {0x89b5,0xfa},\r
+ {0x89b6,0xe4},\r
+ {0x89b7,0xf9},\r
+ {0x89b8,0xf8},\r
+ {0x89b9,0xd0},\r
+ {0x89ba,0x07},\r
+ {0x89bb,0xd0},\r
+ {0x89bc,0x06},\r
+ {0x89bd,0xd0},\r
+ {0x89be,0x05},\r
+ {0x89bf,0xd0},\r
+ {0x89c0,0x04},\r
+ {0x89c1,0x12},\r
+ {0x89c2,0x04},\r
+ {0x89c3,0x9f},\r
+ {0x89c4,0x85},\r
+ {0x89c5,0x3c},\r
+ {0x89c6,0x39},\r
+ {0x89c7,0x85},\r
+ {0x89c8,0x44},\r
+ {0x89c9,0x3a},\r
+ {0x89ca,0x12},\r
+ {0x89cb,0x04},\r
+ {0x89cc,0x6a},\r
+ {0x89cd,0xe5},\r
+ {0x89ce,0x44},\r
+ {0x89cf,0x12},\r
+ {0x89d0,0x04},\r
+ {0x89d1,0xd4},\r
+ {0x89d2,0xe4},\r
+ {0x89d3,0x93},\r
+ {0x89d4,0xf5},\r
+ {0x89d5,0x3b},\r
+ {0x89d6,0x74},\r
+ {0x89d7,0x01},\r
+ {0x89d8,0x93},\r
+ {0x89d9,0xf5},\r
+ {0x89da,0x3c},\r
+ {0x89db,0x90},\r
+ {0x89dc,0x3f},\r
+ {0x89dd,0x02},\r
+ {0x89de,0xe5},\r
+ {0x89df,0x39},\r
+ {0x89e0,0xf0},\r
+ {0x89e1,0xa3},\r
+ {0x89e2,0xe5},\r
+ {0x89e3,0x3a},\r
+ {0x89e4,0xf0},\r
+ {0x89e5,0xa3},\r
+ {0x89e6,0xe5},\r
+ {0x89e7,0x3b},\r
+ {0x89e8,0xf0},\r
+ {0x89e9,0xa3},\r
+ {0x89ea,0xe5},\r
+ {0x89eb,0x3c},\r
+ {0x89ec,0xf0},\r
+ {0x89ed,0x22},\r
+ {0x89ee,0xe5},\r
+ {0x89ef,0x09},\r
+ {0x89f0,0xd3},\r
+ {0x89f1,0x95},\r
+ {0x89f2,0x43},\r
+ {0x89f3,0x40},\r
+ {0x89f4,0x01},\r
+ {0x89f5,0x22},\r
+ {0x89f6,0x12},\r
+ {0x89f7,0x04},\r
+ {0x89f8,0x6a},\r
+ {0x89f9,0xe5},\r
+ {0x89fa,0x09},\r
+ {0x89fb,0x12},\r
+ {0x89fc,0x04},\r
+ {0x89fd,0xd4},\r
+ {0x89fe,0xe4},\r
+ {0x89ff,0x93},\r
+ {0x8a00,0xfe},\r
+ {0x8a01,0x74},\r
+ {0x8a02,0x01},\r
+ {0x8a03,0x93},\r
+ {0x8a04,0xff},\r
+ {0x8a05,0x4e},\r
+ {0x8a06,0x60},\r
+ {0x8a07,0x21},\r
+ {0x8a08,0x8e},\r
+ {0x8a09,0x37},\r
+ {0x8a0a,0x8f},\r
+ {0x8a0b,0x38},\r
+ {0x8a0c,0xef},\r
+ {0x8a0d,0xc4},\r
+ {0x8a0e,0xf8},\r
+ {0x8a0f,0x54},\r
+ {0x8a10,0x0f},\r
+ {0x8a11,0xc8},\r
+ {0x8a12,0x68},\r
+ {0x8a13,0xff},\r
+ {0x8a14,0xee},\r
+ {0x8a15,0xc4},\r
+ {0x8a16,0x54},\r
+ {0x8a17,0xf0},\r
+ {0x8a18,0x48},\r
+ {0x8a19,0xfe},\r
+ {0x8a1a,0x43},\r
+ {0x8a1b,0x07},\r
+ {0x8a1c,0x0d},\r
+ {0x8a1d,0x8e},\r
+ {0x8a1e,0x0a},\r
+ {0x8a1f,0x8f},\r
+ {0x8a20,0x0b},\r
+ {0x8a21,0x12},\r
+ {0x8a22,0x01},\r
+ {0x8a23,0x78},\r
+ {0x8a24,0x30},\r
+ {0x8a25,0x23},\r
+ {0x8a26,0x22},\r
+ {0x8a27,0xc3},\r
+ {0x8a28,0x22},\r
+ {0x8a29,0x75},\r
+ {0x8a2a,0x0a},\r
+ {0x8a2b,0x00},\r
+ {0x8a2c,0x75},\r
+ {0x8a2d,0x0b},\r
+ {0x8a2e,0x0d},\r
+ {0x8a2f,0x12},\r
+ {0x8a30,0x01},\r
+ {0x8a31,0x78},\r
+ {0x8a32,0x30},\r
+ {0x8a33,0x23},\r
+ {0x8a34,0x02},\r
+ {0x8a35,0xc3},\r
+ {0x8a36,0x22},\r
+ {0x8a37,0x75},\r
+ {0x8a38,0x0a},\r
+ {0x8a39,0x00},\r
+ {0x8a3a,0x75},\r
+ {0x8a3b,0x0b},\r
+ {0x8a3c,0x64},\r
+ {0x8a3d,0x12},\r
+ {0x8a3e,0x0c},\r
+ {0x8a3f,0x67},\r
+ {0x8a40,0x75},\r
+ {0x8a41,0x0a},\r
+ {0x8a42,0x80},\r
+ {0x8a43,0x75},\r
+ {0x8a44,0x0b},\r
+ {0x8a45,0x00},\r
+ {0x8a46,0x12},\r
+ {0x8a47,0x01},\r
+ {0x8a48,0x78},\r
+ {0x8a49,0x85},\r
+ {0x8a4a,0x09},\r
+ {0x8a4b,0x44},\r
+ {0x8a4c,0xd3},\r
+ {0x8a4d,0x22},\r
+ {0x8a4e,0xc2},\r
+ {0x8a4f,0x25},\r
+ {0x8a50,0x20},\r
+ {0x8a51,0x05},\r
+ {0x8a52,0x05},\r
+ {0x8a53,0x75},\r
+ {0x8a54,0x09},\r
+ {0x8a55,0xee},\r
+ {0x8a56,0x80},\r
+ {0x8a57,0x36},\r
+ {0x8a58,0x20},\r
+ {0x8a59,0x07},\r
+ {0x8a5a,0x08},\r
+ {0x8a5b,0x20},\r
+ {0x8a5c,0x06},\r
+ {0x8a5d,0x05},\r
+ {0x8a5e,0xe4},\r
+ {0x8a5f,0xf5},\r
+ {0x8a60,0x09},\r
+ {0x8a61,0x80},\r
+ {0x8a62,0x2b},\r
+ {0x8a63,0x20},\r
+ {0x8a64,0x07},\r
+ {0x8a65,0x08},\r
+ {0x8a66,0x30},\r
+ {0x8a67,0x06},\r
+ {0x8a68,0x05},\r
+ {0x8a69,0x75},\r
+ {0x8a6a,0x09},\r
+ {0x8a6b,0x20},\r
+ {0x8a6c,0x80},\r
+ {0x8a6d,0x20},\r
+ {0x8a6e,0x30},\r
+ {0x8a6f,0x00},\r
+ {0x8a70,0x05},\r
+ {0x8a71,0x75},\r
+ {0x8a72,0x09},\r
+ {0x8a73,0x01},\r
+ {0x8a74,0x80},\r
+ {0x8a75,0x18},\r
+ {0x8a76,0xe5},\r
+ {0x8a77,0x20},\r
+ {0x8a78,0x54},\r
+ {0x8a79,0x07},\r
+ {0x8a7a,0xff},\r
+ {0x8a7b,0xbf},\r
+ {0x8a7c,0x06},\r
+ {0x8a7d,0x0d},\r
+ {0x8a7e,0x30},\r
+ {0x8a7f,0x21},\r
+ {0x8a80,0x04},\r
+ {0x8a81,0x7f},\r
+ {0x8a82,0x12},\r
+ {0x8a83,0x80},\r
+ {0x8a84,0x02},\r
+ {0x8a85,0x7f},\r
+ {0x8a86,0x02},\r
+ {0x8a87,0x8f},\r
+ {0x8a88,0x09},\r
+ {0x8a89,0x80},\r
+ {0x8a8a,0x03},\r
+ {0x8a8b,0x75},\r
+ {0x8a8c,0x09},\r
+ {0x8a8d,0xfe},\r
+ {0x8a8e,0x90},\r
+ {0x8a8f,0x3f},\r
+ {0x8a90,0x07},\r
+ {0x8a91,0xe5},\r
+ {0x8a92,0x09},\r
+ {0x8a93,0xf0},\r
+ {0x8a94,0x90},\r
+ {0x8a95,0x3f},\r
+ {0x8a96,0x06},\r
+ {0x8a97,0xe5},\r
+ {0x8a98,0x44},\r
+ {0x8a99,0xf0},\r
+ {0x8a9a,0x22},\r
+ {0x8a9b,0x85},\r
+ {0x8a9c,0x0d},\r
+ {0x8a9d,0x0e},\r
+ {0x8a9e,0x7f},\r
+ {0x8a9f,0x08},\r
+ {0x8aa0,0xe5},\r
+ {0x8aa1,0x0e},\r
+ {0x8aa2,0x30},\r
+ {0x8aa3,0xe7},\r
+ {0x8aa4,0x04},\r
+ {0x8aa5,0xd2},\r
+ {0x8aa6,0x19},\r
+ {0x8aa7,0x80},\r
+ {0x8aa8,0x02},\r
+ {0x8aa9,0xc2},\r
+ {0x8aaa,0x19},\r
+ {0x8aab,0x12},\r
+ {0x8aac,0x04},\r
+ {0x8aad,0x09},\r
+ {0x8aae,0x75},\r
+ {0x8aaf,0x32},\r
+ {0x8ab0,0x0a},\r
+ {0x8ab1,0xae},\r
+ {0x8ab2,0x32},\r
+ {0x8ab3,0x15},\r
+ {0x8ab4,0x32},\r
+ {0x8ab5,0xee},\r
+ {0x8ab6,0x70},\r
+ {0x8ab7,0xf9},\r
+ {0x8ab8,0xe5},\r
+ {0x8ab9,0x0e},\r
+ {0x8aba,0x25},\r
+ {0x8abb,0xe0},\r
+ {0x8abc,0xf5},\r
+ {0x8abd,0x0e},\r
+ {0x8abe,0xd2},\r
+ {0x8abf,0x18},\r
+ {0x8ac0,0x12},\r
+ {0x8ac1,0x04},\r
+ {0x8ac2,0x09},\r
+ {0x8ac3,0x75},\r
+ {0x8ac4,0x32},\r
+ {0x8ac5,0x0a},\r
+ {0x8ac6,0xae},\r
+ {0x8ac7,0x32},\r
+ {0x8ac8,0x15},\r
+ {0x8ac9,0x32},\r
+ {0x8aca,0xee},\r
+ {0x8acb,0x70},\r
+ {0x8acc,0xf9},\r
+ {0x8acd,0xc2},\r
+ {0x8ace,0x18},\r
+ {0x8acf,0x12},\r
+ {0x8ad0,0x04},\r
+ {0x8ad1,0x09},\r
+ {0x8ad2,0x75},\r
+ {0x8ad3,0x32},\r
+ {0x8ad4,0x05},\r
+ {0x8ad5,0xae},\r
+ {0x8ad6,0x32},\r
+ {0x8ad7,0x15},\r
+ {0x8ad8,0x32},\r
+ {0x8ad9,0xee},\r
+ {0x8ada,0x70},\r
+ {0x8adb,0xf9},\r
+ {0x8adc,0xdf},\r
+ {0x8add,0xc2},\r
+ {0x8ade,0x22},\r
+ {0x8adf,0x90},\r
+ {0x8ae0,0x3f},\r
+ {0x8ae1,0x07},\r
+ {0x8ae2,0x74},\r
+ {0x8ae3,0xfa},\r
+ {0x8ae4,0xf0},\r
+ {0x8ae5,0x12},\r
+ {0x8ae6,0x08},\r
+ {0x8ae7,0x65},\r
+ {0x8ae8,0x12},\r
+ {0x8ae9,0x0b},\r
+ {0x8aea,0xfb},\r
+ {0x8aeb,0xe4},\r
+ {0x8aec,0xf5},\r
+ {0x8aed,0x29},\r
+ {0x8aee,0xd2},\r
+ {0x8aef,0xaf},\r
+ {0x8af0,0x12},\r
+ {0x8af1,0x05},\r
+ {0x8af2,0xfc},\r
+ {0x8af3,0x30},\r
+ {0x8af4,0x20},\r
+ {0x8af5,0x03},\r
+ {0x8af6,0x12},\r
+ {0x8af7,0x02},\r
+ {0x8af8,0xc4},\r
+ {0x8af9,0x30},\r
+ {0x8afa,0x25},\r
+ {0x8afb,0x03},\r
+ {0x8afc,0x12},\r
+ {0x8afd,0x0a},\r
+ {0x8afe,0x4e},\r
+ {0x8aff,0x30},\r
+ {0x8b00,0x2f},\r
+ {0x8b01,0xee},\r
+ {0x8b02,0xc2},\r
+ {0x8b03,0x2f},\r
+ {0x8b04,0xd2},\r
+ {0x8b05,0x26},\r
+ {0x8b06,0x30},\r
+ {0x8b07,0x00},\r
+ {0x8b08,0x05},\r
+ {0x8b09,0x12},\r
+ {0x8b0a,0x0b},\r
+ {0x8b0b,0x7b},\r
+ {0x8b0c,0x80},\r
+ {0x8b0d,0x09},\r
+ {0x8b0e,0x20},\r
+ {0x8b0f,0x07},\r
+ {0x8b10,0x06},\r
+ {0x8b11,0x30},\r
+ {0x8b12,0x06},\r
+ {0x8b13,0x03},\r
+ {0x8b14,0x12},\r
+ {0x8b15,0x04},\r
+ {0x8b16,0xf5},\r
+ {0x8b17,0xc2},\r
+ {0x8b18,0x26},\r
+ {0x8b19,0x80},\r
+ {0x8b1a,0xd5},\r
+ {0x8b1b,0xe5},\r
+ {0x8b1c,0x44},\r
+ {0x8b1d,0x70},\r
+ {0x8b1e,0x19},\r
+ {0x8b1f,0x12},\r
+ {0x8b20,0x0d},\r
+ {0x8b21,0x4b},\r
+ {0x8b22,0xc2},\r
+ {0x8b23,0x30},\r
+ {0x8b24,0x12},\r
+ {0x8b25,0x0b},\r
+ {0x8b26,0xd2},\r
+ {0x8b27,0xc2},\r
+ {0x8b28,0x30},\r
+ {0x8b29,0x12},\r
+ {0x8b2a,0x0c},\r
+ {0x8b2b,0x89},\r
+ {0x8b2c,0xc2},\r
+ {0x8b2d,0x03},\r
+ {0x8b2e,0x12},\r
+ {0x8b2f,0x0c},\r
+ {0x8b30,0xfe},\r
+ {0x8b31,0xd2},\r
+ {0x8b32,0x02},\r
+ {0x8b33,0xd2},\r
+ {0x8b34,0x01},\r
+ {0x8b35,0xd2},\r
+ {0x8b36,0x00},\r
+ {0x8b37,0x22},\r
+ {0x8b38,0x30},\r
+ {0x8b39,0x03},\r
+ {0x8b3a,0x08},\r
+ {0x8b3b,0xc2},\r
+ {0x8b3c,0x03},\r
+ {0x8b3d,0xc2},\r
+ {0x8b3e,0x04},\r
+ {0x8b3f,0x12},\r
+ {0x8b40,0x04},\r
+ {0x8b41,0xe4},\r
+ {0x8b42,0x22},\r
+ {0x8b43,0xe4},\r
+ {0x8b44,0xf5},\r
+ {0x8b45,0x09},\r
+ {0x8b46,0x12},\r
+ {0x8b47,0x09},\r
+ {0x8b48,0xee},\r
+ {0x8b49,0xd2},\r
+ {0x8b4a,0x03},\r
+ {0x8b4b,0x22},\r
+ {0x8b4c,0x36},\r
+ {0x8b4d,0x0c},\r
+ {0x8b4e,0x04},\r
+ {0x8b4f,0x00},\r
+ {0x8b50,0x00},\r
+ {0x8b51,0x00},\r
+ {0x8b52,0xc8},\r
+ {0x8b53,0x01},\r
+ {0x8b54,0x2c},\r
+ {0x8b55,0x01},\r
+ {0x8b56,0x5e},\r
+ {0x8b57,0x01},\r
+ {0x8b58,0x8b},\r
+ {0x8b59,0x01},\r
+ {0x8b5a,0xb8},\r
+ {0x8b5b,0x01},\r
+ {0x8b5c,0xe5},\r
+ {0x8b5d,0x02},\r
+ {0x8b5e,0x12},\r
+ {0x8b5f,0x02},\r
+ {0x8b60,0x3f},\r
+ {0x8b61,0x02},\r
+ {0x8b62,0x6c},\r
+ {0x8b63,0x02},\r
+ {0x8b64,0x99},\r
+ {0x8b65,0x02},\r
+ {0x8b66,0xc6},\r
+ {0x8b67,0x02},\r
+ {0x8b68,0xf3},\r
+ {0x8b69,0x07},\r
+ {0x8b6a,0x00},\r
+ {0x8b6b,0x02},\r
+ {0x8b6c,0x4e},\r
+ {0x8b6d,0x02},\r
+ {0x8b6e,0x6c},\r
+ {0x8b6f,0x02},\r
+ {0x8b70,0x8a},\r
+ {0x8b71,0x02},\r
+ {0x8b72,0xa8},\r
+ {0x8b73,0x02},\r
+ {0x8b74,0xc6},\r
+ {0x8b75,0x02},\r
+ {0x8b76,0xe4},\r
+ {0x8b77,0x03},\r
+ {0x8b78,0x02},\r
+ {0x8b79,0x03},\r
+ {0x8b7a,0x20},\r
+ {0x8b7b,0xe5},\r
+ {0x8b7c,0x20},\r
+ {0x8b7d,0x54},\r
+ {0x8b7e,0x07},\r
+ {0x8b7f,0xff},\r
+ {0x8b80,0xbf},\r
+ {0x8b81,0x01},\r
+ {0x8b82,0x03},\r
+ {0x8b83,0x02},\r
+ {0x8b84,0x0b},\r
+ {0x8b85,0x1b},\r
+ {0x8b86,0xe5},\r
+ {0x8b87,0x20},\r
+ {0x8b88,0x54},\r
+ {0x8b89,0x07},\r
+ {0x8b8a,0xff},\r
+ {0x8b8b,0xbf},\r
+ {0x8b8c,0x07},\r
+ {0x8b8d,0x03},\r
+ {0x8b8e,0x02},\r
+ {0x8b8f,0x0c},\r
+ {0x8b90,0x44},\r
+ {0x8b91,0xe5},\r
+ {0x8b92,0x20},\r
+ {0x8b93,0x54},\r
+ {0x8b94,0x07},\r
+ {0x8b95,0xff},\r
+ {0x8b96,0xbf},\r
+ {0x8b97,0x03},\r
+ {0x8b98,0x03},\r
+ {0x8b99,0x02},\r
+ {0x8b9a,0x0b},\r
+ {0x8b9b,0xa8},\r
+ {0x8b9c,0xe5},\r
+ {0x8b9d,0x20},\r
+ {0x8b9e,0x54},\r
+ {0x8b9f,0x07},\r
+ {0x8ba0,0xff},\r
+ {0x8ba1,0xbf},\r
+ {0x8ba2,0x05},\r
+ {0x8ba3,0x03},\r
+ {0x8ba4,0x12},\r
+ {0x8ba5,0x0d},\r
+ {0x8ba6,0x59},\r
+ {0x8ba7,0x22},\r
+ {0x8ba8,0x12},\r
+ {0x8ba9,0x0c},\r
+ {0x8baa,0x21},\r
+ {0x8bab,0xd2},\r
+ {0x8bac,0x30},\r
+ {0x8bad,0x12},\r
+ {0x8bae,0x0b},\r
+ {0x8baf,0xd2},\r
+ {0x8bb0,0xd2},\r
+ {0x8bb1,0x30},\r
+ {0x8bb2,0x12},\r
+ {0x8bb3,0x0c},\r
+ {0x8bb4,0x89},\r
+ {0x8bb5,0xe5},\r
+ {0x8bb6,0x43},\r
+ {0x8bb7,0xd3},\r
+ {0x8bb8,0x95},\r
+ {0x8bb9,0x44},\r
+ {0x8bba,0x40},\r
+ {0x8bbb,0x03},\r
+ {0x8bbc,0xd3},\r
+ {0x8bbd,0x80},\r
+ {0x8bbe,0x01},\r
+ {0x8bbf,0xc3},\r
+ {0x8bc0,0x50},\r
+ {0x8bc1,0x0c},\r
+ {0x8bc2,0x20},\r
+ {0x8bc3,0x28},\r
+ {0x8bc4,0x06},\r
+ {0x8bc5,0x30},\r
+ {0x8bc6,0x2d},\r
+ {0x8bc7,0x03},\r
+ {0x8bc8,0x20},\r
+ {0x8bc9,0x2e},\r
+ {0x8bca,0x03},\r
+ {0x8bcb,0x02},\r
+ {0x8bcc,0x0c},\r
+ {0x8bcd,0xfe},\r
+ {0x8bce,0x12},\r
+ {0x8bcf,0x0c},\r
+ {0x8bd0,0xbf},\r
+ {0x8bd1,0x22},\r
+ {0x8bd2,0x30},\r
+ {0x8bd3,0x30},\r
+ {0x8bd4,0x09},\r
+ {0x8bd5,0x30},\r
+ {0x8bd6,0x2d},\r
+ {0x8bd7,0x06},\r
+ {0x8bd8,0xae},\r
+ {0x8bd9,0x33},\r
+ {0x8bda,0xaf},\r
+ {0x8bdb,0x34},\r
+ {0x8bdc,0x80},\r
+ {0x8bdd,0x04},\r
+ {0x8bde,0xae},\r
+ {0x8bdf,0x3d},\r
+ {0x8be0,0xaf},\r
+ {0x8be1,0x3e},\r
+ {0x8be2,0x8e},\r
+ {0x8be3,0x33},\r
+ {0x8be4,0x8f},\r
+ {0x8be5,0x34},\r
+ {0x8be6,0x30},\r
+ {0x8be7,0x30},\r
+ {0x8be8,0x09},\r
+ {0x8be9,0x30},\r
+ {0x8bea,0x2e},\r
+ {0x8beb,0x06},\r
+ {0x8bec,0xae},\r
+ {0x8bed,0x35},\r
+ {0x8bee,0xaf},\r
+ {0x8bef,0x36},\r
+ {0x8bf0,0x80},\r
+ {0x8bf1,0x04},\r
+ {0x8bf2,0xae},\r
+ {0x8bf3,0x3f},\r
+ {0x8bf4,0xaf},\r
+ {0x8bf5,0x40},\r
+ {0x8bf6,0x8e},\r
+ {0x8bf7,0x35},\r
+ {0x8bf8,0x8f},\r
+ {0x8bf9,0x36},\r
+ {0x8bfa,0x22},\r
+ {0x8bfb,0x12},\r
+ {0x8bfc,0x0c},\r
+ {0x8bfd,0xec},\r
+ {0x8bfe,0x12},\r
+ {0x8bff,0x0d},\r
+ {0x8c00,0x67},\r
+ {0x8c01,0x50},\r
+ {0x8c02,0x04},\r
+ {0x8c03,0xd2},\r
+ {0x8c04,0x05},\r
+ {0x8c05,0x80},\r
+ {0x8c06,0x02},\r
+ {0x8c07,0xc2},\r
+ {0x8c08,0x05},\r
+ {0x8c09,0x12},\r
+ {0x8c0a,0x04},\r
+ {0x8c0b,0x7c},\r
+ {0x8c0c,0xc2},\r
+ {0x8c0d,0x28},\r
+ {0x8c0e,0xc2},\r
+ {0x8c0f,0x21},\r
+ {0x8c10,0xd2},\r
+ {0x8c11,0x25},\r
+ {0x8c12,0x12},\r
+ {0x8c13,0x04},\r
+ {0x8c14,0xbe},\r
+ {0x8c15,0xb5},\r
+ {0x8c16,0x07},\r
+ {0x8c17,0x03},\r
+ {0x8c18,0xd3},\r
+ {0x8c19,0x80},\r
+ {0x8c1a,0x01},\r
+ {0x8c1b,0xc3},\r
+ {0x8c1c,0x40},\r
+ {0x8c1d,0x02},\r
+ {0x8c1e,0xc2},\r
+ {0x8c1f,0x05},\r
+ {0x8c20,0x22},\r
+ {0x8c21,0xd3},\r
+ {0x8c22,0xe5},\r
+ {0x8c23,0x34},\r
+ {0x8c24,0x95},\r
+ {0x8c25,0x3e},\r
+ {0x8c26,0xe5},\r
+ {0x8c27,0x33},\r
+ {0x8c28,0x95},\r
+ {0x8c29,0x3d},\r
+ {0x8c2a,0x40},\r
+ {0x8c2b,0x03},\r
+ {0x8c2c,0xd3},\r
+ {0x8c2d,0x80},\r
+ {0x8c2e,0x01},\r
+ {0x8c2f,0xc3},\r
+ {0x8c30,0x92},\r
+ {0x8c31,0x2d},\r
+ {0x8c32,0xd3},\r
+ {0x8c33,0xe5},\r
+ {0x8c34,0x36},\r
+ {0x8c35,0x95},\r
+ {0x8c36,0x40},\r
+ {0x8c37,0xe5},\r
+ {0x8c38,0x35},\r
+ {0x8c39,0x95},\r
+ {0x8c3a,0x3f},\r
+ {0x8c3b,0x40},\r
+ {0x8c3c,0x03},\r
+ {0x8c3d,0xd3},\r
+ {0x8c3e,0x80},\r
+ {0x8c3f,0x01},\r
+ {0x8c40,0xc3},\r
+ {0x8c41,0x92},\r
+ {0x8c42,0x2e},\r
+ {0x8c43,0x22},\r
+ {0x8c44,0x12},\r
+ {0x8c45,0x0c},\r
+ {0x8c46,0x21},\r
+ {0x8c47,0xd2},\r
+ {0x8c48,0x30},\r
+ {0x8c49,0x12},\r
+ {0x8c4a,0x0b},\r
+ {0x8c4b,0xd2},\r
+ {0x8c4c,0xd2},\r
+ {0x8c4d,0x30},\r
+ {0x8c4e,0x12},\r
+ {0x8c4f,0x0c},\r
+ {0x8c50,0x89},\r
+ {0x8c51,0x12},\r
+ {0x8c52,0x0c},\r
+ {0x8c53,0xfe},\r
+ {0x8c54,0xe5},\r
+ {0x8c55,0x28},\r
+ {0x8c56,0xd3},\r
+ {0x8c57,0x95},\r
+ {0x8c58,0x44},\r
+ {0x8c59,0x40},\r
+ {0x8c5a,0x05},\r
+ {0x8c5b,0xe4},\r
+ {0x8c5c,0x95},\r
+ {0x8c5d,0x44},\r
+ {0x8c5e,0x40},\r
+ {0x8c5f,0x06},\r
+ {0x8c60,0xc2},\r
+ {0x8c61,0x02},\r
+ {0x8c62,0xd2},\r
+ {0x8c63,0x01},\r
+ {0x8c64,0xd2},\r
+ {0x8c65,0x00},\r
+ {0x8c66,0x22},\r
+ {0x8c67,0xe4},\r
+ {0x8c68,0xff},\r
+ {0x8c69,0xfe},\r
+ {0x8c6a,0xc3},\r
+ {0x8c6b,0xef},\r
+ {0x8c6c,0x95},\r
+ {0x8c6d,0x0b},\r
+ {0x8c6e,0xee},\r
+ {0x8c6f,0x95},\r
+ {0x8c70,0x0a},\r
+ {0x8c71,0x50},\r
+ {0x8c72,0x15},\r
+ {0x8c73,0x7d},\r
+ {0x8c74,0x8a},\r
+ {0x8c75,0x7c},\r
+ {0x8c76,0x02},\r
+ {0x8c77,0xed},\r
+ {0x8c78,0x1d},\r
+ {0x8c79,0xaa},\r
+ {0x8c7a,0x04},\r
+ {0x8c7b,0x70},\r
+ {0x8c7c,0x01},\r
+ {0x8c7d,0x1c},\r
+ {0x8c7e,0x4a},\r
+ {0x8c7f,0x70},\r
+ {0x8c80,0xf6},\r
+ {0x8c81,0x0f},\r
+ {0x8c82,0xbf},\r
+ {0x8c83,0x00},\r
+ {0x8c84,0x01},\r
+ {0x8c85,0x0e},\r
+ {0x8c86,0x80},\r
+ {0x8c87,0xe2},\r
+ {0x8c88,0x22},\r
+ {0x8c89,0x30},\r
+ {0x8c8a,0x30},\r
+ {0x8c8b,0x07},\r
+ {0x8c8c,0x30},\r
+ {0x8c8d,0x2d},\r
+ {0x8c8e,0x04},\r
+ {0x8c8f,0xaf},\r
+ {0x8c90,0x30},\r
+ {0x8c91,0x80},\r
+ {0x8c92,0x02},\r
+ {0x8c93,0xaf},\r
+ {0x8c94,0x44},\r
+ {0x8c95,0x8f},\r
+ {0x8c96,0x30},\r
+ {0x8c97,0x30},\r
+ {0x8c98,0x30},\r
+ {0x8c99,0x07},\r
+ {0x8c9a,0x30},\r
+ {0x8c9b,0x2e},\r
+ {0x8c9c,0x04},\r
+ {0x8c9d,0xaf},\r
+ {0x8c9e,0x31},\r
+ {0x8c9f,0x80},\r
+ {0x8ca0,0x02},\r
+ {0x8ca1,0xaf},\r
+ {0x8ca2,0x44},\r
+ {0x8ca3,0x8f},\r
+ {0x8ca4,0x31},\r
+ {0x8ca5,0x22},\r
+ {0x8ca6,0xe5},\r
+ {0x8ca7,0x45},\r
+ {0x8ca8,0xb4},\r
+ {0x8ca9,0x01},\r
+ {0x8caa,0x05},\r
+ {0x8cab,0x12},\r
+ {0x8cac,0x0d},\r
+ {0x8cad,0x1e},\r
+ {0x8cae,0x80},\r
+ {0x8caf,0x08},\r
+ {0x8cb0,0xe5},\r
+ {0x8cb1,0x45},\r
+ {0x8cb2,0xb4},\r
+ {0x8cb3,0x02},\r
+ {0x8cb4,0x09},\r
+ {0x8cb5,0x12},\r
+ {0x8cb6,0x0d},\r
+ {0x8cb7,0x2d},\r
+ {0x8cb8,0xe4},\r
+ {0x8cb9,0xf5},\r
+ {0x8cba,0x09},\r
+ {0x8cbb,0x12},\r
+ {0x8cbc,0x09},\r
+ {0x8cbd,0xee},\r
+ {0x8cbe,0x22},\r
+ {0x8cbf,0xaf},\r
+ {0x8cc0,0x31},\r
+ {0x8cc1,0xe5},\r
+ {0x8cc2,0x44},\r
+ {0x8cc3,0xb5},\r
+ {0x8cc4,0x07},\r
+ {0x8cc5,0x03},\r
+ {0x8cc6,0x02},\r
+ {0x8cc7,0x0c},\r
+ {0x8cc8,0xd8},\r
+ {0x8cc9,0x8f},\r
+ {0x8cca,0x09},\r
+ {0x8ccb,0x12},\r
+ {0x8ccc,0x09},\r
+ {0x8ccd,0xee},\r
+ {0x8cce,0xd2},\r
+ {0x8ccf,0x02},\r
+ {0x8cd0,0xc2},\r
+ {0x8cd1,0x01},\r
+ {0x8cd2,0xd2},\r
+ {0x8cd3,0x00},\r
+ {0x8cd4,0x75},\r
+ {0x8cd5,0x27},\r
+ {0x8cd6,0x03},\r
+ {0x8cd7,0x22},\r
+ {0x8cd8,0xc2},\r
+ {0x8cd9,0x03},\r
+ {0x8cda,0xd2},\r
+ {0x8cdb,0x04},\r
+ {0x8cdc,0x12},\r
+ {0x8cdd,0x04},\r
+ {0x8cde,0xe4},\r
+ {0x8cdf,0xc2},\r
+ {0x8ce0,0x30},\r
+ {0x8ce1,0x12},\r
+ {0x8ce2,0x0b},\r
+ {0x8ce3,0xd2},\r
+ {0x8ce4,0xc2},\r
+ {0x8ce5,0x30},\r
+ {0x8ce6,0x12},\r
+ {0x8ce7,0x0c},\r
+ {0x8ce8,0x89},\r
+ {0x8ce9,0xd2},\r
+ {0x8cea,0x25},\r
+ {0x8ceb,0x22},\r
+ {0x8cec,0x12},\r
+ {0x8ced,0x04},\r
+ {0x8cee,0x8b},\r
+ {0x8cef,0xf5},\r
+ {0x8cf0,0x09},\r
+ {0x8cf1,0x75},\r
+ {0x8cf2,0x0a},\r
+ {0x8cf3,0x01},\r
+ {0x8cf4,0x12},\r
+ {0x8cf5,0x08},\r
+ {0x8cf6,0xfa},\r
+ {0x8cf7,0xd2},\r
+ {0x8cf8,0x20},\r
+ {0x8cf9,0xc2},\r
+ {0x8cfa,0x26},\r
+ {0x8cfb,0xc2},\r
+ {0x8cfc,0x2f},\r
+ {0x8cfd,0x22},\r
+ {0x8cfe,0xe5},\r
+ {0x8cff,0x44},\r
+ {0x8d00,0xc3},\r
+ {0x8d01,0x95},\r
+ {0x8d02,0x43},\r
+ {0x8d03,0x40},\r
+ {0x8d04,0x01},\r
+ {0x8d05,0x22},\r
+ {0x8d06,0xe5},\r
+ {0x8d07,0x44},\r
+ {0x8d08,0x04},\r
+ {0x8d09,0xf5},\r
+ {0x8d0a,0x09},\r
+ {0x8d0b,0x12},\r
+ {0x8d0c,0x09},\r
+ {0x8d0d,0xee},\r
+ {0x8d0e,0x22},\r
+ {0x8d0f,0xe5},\r
+ {0x8d10,0x44},\r
+ {0x8d11,0x70},\r
+ {0x8d12,0x02},\r
+ {0x8d13,0xc3},\r
+ {0x8d14,0x22},\r
+ {0x8d15,0xe5},\r
+ {0x8d16,0x44},\r
+ {0x8d17,0x14},\r
+ {0x8d18,0xf5},\r
+ {0x8d19,0x09},\r
+ {0x8d1a,0x12},\r
+ {0x8d1b,0x09},\r
+ {0x8d1c,0xee},\r
+ {0x8d1d,0x22},\r
+ {0x8d1e,0x75},\r
+ {0x8d1f,0x2e},\r
+ {0x8d20,0x0b},\r
+ {0x8d21,0x75},\r
+ {0x8d22,0x2f},\r
+ {0x8d23,0x4f},\r
+ {0x8d24,0x90},\r
+ {0x8d25,0x0b},\r
+ {0x8d26,0x4d},\r
+ {0x8d27,0x12},\r
+ {0x8d28,0x04},\r
+ {0x8d29,0xda},\r
+ {0x8d2a,0xc2},\r
+ {0x8d2b,0x2c},\r
+ {0x8d2c,0x22},\r
+ {0x8d2d,0x75},\r
+ {0x8d2e,0x2e},\r
+ {0x8d2f,0x0b},\r
+ {0x8d30,0x75},\r
+ {0x8d31,0x2f},\r
+ {0x8d32,0x6b},\r
+ {0x8d33,0x90},\r
+ {0x8d34,0x0b},\r
+ {0x8d35,0x69},\r
+ {0x8d36,0x12},\r
+ {0x8d37,0x04},\r
+ {0x8d38,0xda},\r
+ {0x8d39,0xd2},\r
+ {0x8d3a,0x2c},\r
+ {0x8d3b,0x22},\r
+ {0x8d3c,0xe5},\r
+ {0x8d3d,0x45},\r
+ {0x8d3e,0x24},\r
+ {0x8d3f,0xfe},\r
+ {0x8d40,0x60},\r
+ {0x8d41,0x06},\r
+ {0x8d42,0x04},\r
+ {0x8d43,0x70},\r
+ {0x8d44,0x05},\r
+ {0x8d45,0xd2},\r
+ {0x8d46,0x28},\r
+ {0x8d47,0x22},\r
+ {0x8d48,0xc2},\r
+ {0x8d49,0x28},\r
+ {0x8d4a,0x22},\r
+ {0x8d4b,0xe4},\r
+ {0x8d4c,0xf5},\r
+ {0x8d4d,0x33},\r
+ {0x8d4e,0xf5},\r
+ {0x8d4f,0x34},\r
+ {0x8d50,0xf5},\r
+ {0x8d51,0x35},\r
+ {0x8d52,0xf5},\r
+ {0x8d53,0x36},\r
+ {0x8d54,0xc2},\r
+ {0x8d55,0x2d},\r
+ {0x8d56,0xc2},\r
+ {0x8d57,0x2e},\r
+ {0x8d58,0x22},\r
+ {0x8d59,0xe5},\r
+ {0x8d5a,0x27},\r
+ {0x8d5b,0xd3},\r
+ {0x8d5c,0x94},\r
+ {0x8d5d,0x00},\r
+ {0x8d5e,0x40},\r
+ {0x8d5f,0x03},\r
+ {0x8d60,0x15},\r
+ {0x8d61,0x27},\r
+ {0x8d62,0x22},\r
+ {0x8d63,0x12},\r
+ {0x8d64,0x0c},\r
+ {0x8d65,0xd8},\r
+ {0x8d66,0x22},\r
+ {0x8d67,0x12},\r
+ {0x8d68,0x0d},\r
+ {0x8d69,0x1e},\r
+ {0x8d6a,0xe4},\r
+ {0x8d6b,0xf5},\r
+ {0x8d6c,0x09},\r
+ {0x8d6d,0x12},\r
+ {0x8d6e,0x09},\r
+ {0x8d6f,0xee},\r
+ {0x8d70,0x22},\r
+ {0x3F00,0x00},\r
+ {0x3F01,0x00},\r
+ {0x3F02,0x00},\r
+ {0x3F03,0x00},\r
+ {0x3F04,0x00},\r
+ {0x3F05,0x00},\r
+ {0x3F06,0x00},\r
+ {0x3F07,0xFF},\r
+ {0x3104,0x00},\r
+ {0x0000,0x00}\r
+};\r
+#endif
\ No newline at end of file
#include <media/soc_camera.h>
#include <mach/rk29_camera.h>
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do { \
+ if (debug >= level) \
+ printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(0, format, ## __VA_ARGS__)
+
+
#define _CONS(a,b) a##b
#define CONS(a,b) _CONS(a,b)
#define _STR(x) __STR(x)
#define STR(x) _STR(x)
+#define MIN(x,y) ((x<y) ? x: y)
+#define MAX(x,y) ((x>y) ? x: y)
+
/* Sensor Driver Configuration */
-#define SENSOR_NAME ov7675
+#define SENSOR_NAME RK29_CAM_SENSOR_OV7675
#define SENSOR_V4L2_IDENT V4L2_IDENT_OV7675
#define SENSOR_ID 0x76
#define SENSOR_MIN_WIDTH 640//176
#define CONFIG_SENSOR_Mirror 0
#define CONFIG_SENSOR_Flip 0
-#define CONFIG_SENSOR_I2C_SPEED 100000 /* Hz */
-
-#define CONFIG_SENSOR_TR 1
-#define CONFIG_SENSOR_DEBUG 1
-
-#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
-#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
-
-#define MIN(x,y) ((x<y) ? x: y)
-#define MAX(x,y) ((x>y) ? x: y)
-
-#if (CONFIG_SENSOR_TR)
- #define SENSOR_TR(format, ...) printk(format, ## __VA_ARGS__)
- #if (CONFIG_SENSOR_DEBUG)
- #define SENSOR_DG(format, ...) printk(format, ## __VA_ARGS__)
- #else
- #define SENSOR_DG(format, ...)
- #endif
-#else
- #define SENSOR_TR(format, ...)
-#endif
+#define CONFIG_SENSOR_I2C_SPEED 250000 /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED 0
+#define CONFIG_SENSOR_I2C_RDWRCHK 0
#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
#define COLOR_TEMPERATURE_HOME_DN 2500
#define COLOR_TEMPERATURE_HOME_UP 3500
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
struct reginfo
{
u8 reg;
{0x0e, 0x61},
{0x0f, 0x4b},
{0x16, 0x02},
- {0x1e, 0x07},
+ {0x1e, 0x07}, //0x27
{0x21, 0x02},
{0x22, 0x91},
{0x29, 0x07},
static int sensor_resume(struct soc_camera_device *icd);
static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+static int sensor_deactivate(struct i2c_client *client);
+
static struct soc_camera_ops sensor_ops =
{
int focus;
int flash;
int exposure;
+ bool snap2preview;
+ bool video2preview;
unsigned char mirror; /* HFLIP */
unsigned char flip; /* VFLIP */
unsigned int winseqe_cur_addr;
struct i2c_client *client;
sensor_info_priv_t info_priv;
int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_t tasklock_cnt;
+#endif
+ struct rk29camera_platform_data *sensor_io_request;
+ struct rk29camera_gpio_res *sensor_gpio_res;
};
static struct sensor* to_sensor(const struct i2c_client *client)
return container_of(i2c_get_clientdata(client), struct sensor, subdev);
}
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+ int cnt = 3;
+ struct sensor *sensor = to_sensor(client);
+
+ if (lock) {
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+ msleep(35);
+ cnt--;
+ }
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+ goto sensor_task_lock_err;
+ }
+ preempt_disable();
+ }
+
+ atomic_add(1, &sensor->tasklock_cnt);
+ } else {
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {
+ atomic_sub(1, &sensor->tasklock_cnt);
+
+ if (atomic_read(&sensor->tasklock_cnt) == 0)
+ preempt_enable();
+ }
+ }
+ return 0;
+sensor_task_lock_err:
+ return -1;
+#else
+ return 0;
+#endif
+
+}
+
/* sensor register write */
static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
{
cnt = 3;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
return 0;
} else {
- SENSOR_TR("\n %s write reg failed, try to write again!\n",SENSOR_NAME_STRING());
- udelay(10);
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+ udelay(10);
}
}
cnt = 1;
err = -EAGAIN;
- while ((cnt--) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */
err = i2c_transfer(client->adapter, msg, 2);
if (err >= 0) {
*val = buf[0];
return 0;
} else {
- SENSOR_TR("\n %s read reg failed, try to read again! reg:0x%x \n",SENSOR_NAME_STRING(),(unsigned int)val);
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
udelay(10);
}
}
#if 1
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
{
- int err;
+ int err = 0, cnt;
int i = 0;
+#if CONFIG_SENSOR_I2C_RDWRCHK
+ char valchk;
+#endif
+
+ cnt = 0;
+ if (sensor_task_lock(client, 1) < 0)
+ goto sensor_write_array_end;
while (regarray[i].reg != 0)
{
err = sensor_write(client, regarray[i].reg, regarray[i].val);
- if (err != 0)
+ if (err < 0)
{
- SENSOR_TR("%s..write failed current i = %d\n", SENSOR_NAME_STRING(),i);
- return err;
+ if (cnt-- > 0) {
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+ i = 0;
+ continue;
+ } else {
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+ err = -EPERM;
+ goto sensor_write_array_end;
+ }
+ } else {
+ #if CONFIG_SENSOR_I2C_RDWRCHK
+ sensor_read(client, regarray[i].reg, &valchk);
+ if (valchk != regarray[i].val)
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+ #endif
}
i++;
}
- return 0;
+
+sensor_write_array_end:
+ sensor_task_lock(client,0);
+ return err;
}
#else
static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
return 0;
}
#endif
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ int ret = 0;
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+ switch (cmd)
+ {
+ case Sensor_PowerDown:
+ {
+ if (icl->powerdown) {
+ ret = icl->powerdown(icd->pdev, on);
+ if (ret == RK29_CAM_IO_SUCCESS) {
+ if (on == 0) {
+ mdelay(2);
+ if (icl->reset)
+ icl->reset(icd->pdev);
+ }
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+ ret = -ENODEV;
+ goto sensor_power_end;
+ }
+ }
+ break;
+ }
+ case Sensor_Flash:
+ {
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct sensor *sensor = to_sensor(client);
+
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+ }
+ break;
+ }
+ default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+ break;
+ }
+ }
+sensor_power_end:
+ return ret;
+}
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
struct i2c_client *client = sd->priv;
SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_INIT_ERR;
+ }
+
/* soft reset */
+ if (sensor_task_lock(client,1)<0)
+ goto sensor_INIT_ERR;
ret = sensor_write(client, 0x12, 0x80);
if (ret != 0)
{
SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
goto sensor_INIT_ERR;
}
-
- icd->user_width = SENSOR_INIT_WIDTH;
- icd->user_height = SENSOR_INIT_HEIGHT;
+ sensor_task_lock(client,0);
+ //icd->user_width = SENSOR_INIT_WIDTH;
+ //icd->user_height = SENSOR_INIT_HEIGHT;
sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;
sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;
sensor->info_priv.focus = qctrl->default_value;
#endif
- #if CONFIG_SENSOR_Flash
- sensor_set_flash();
+ #if CONFIG_SENSOR_Flash
qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
if (qctrl)
sensor->info_priv.flash = qctrl->default_value;
#endif
- SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,icd->user_width,icd->user_height);
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
return 0;
sensor_INIT_ERR:
+ sensor_task_lock(client,0);
+ sensor_deactivate(client);
return ret;
}
-static int sensor_deactivate(struct v4l2_subdev *sd)
+static int sensor_deactivate(struct i2c_client *client)
{
- //struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
//u8 reg_val;
- SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
/* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);
-
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+ icd->user_width = SENSOR_INIT_WIDTH;
+ icd->user_height = SENSOR_INIT_HEIGHT;
+ msleep(100);
return 0;
}
static struct reginfo sensor_power_down_sequence[]=
{
int ret;
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- struct soc_camera_link *icl;
-
- if (pm_msg.event == PM_EVENT_SUSPEND)
- {
+ if (pm_msg.event == PM_EVENT_SUSPEND) {
SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
ret = sensor_write_array(client, sensor_power_down_sequence) ;
- if (ret != 0)
- {
+ if (ret != 0) {
SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
return ret;
- }
- else
- {
- icl = to_soc_camera_link(icd);
- if (icl->power) {
- ret = icl->power(icd->pdev, 0);
- if (ret < 0) {
- SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
- return -EINVAL;
- }
+ } else {
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+ if (ret < 0) {
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
}
}
- }
- else
- {
+ } else {
SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
return -EINVAL;
}
static int sensor_resume(struct soc_camera_device *icd)
{
- struct soc_camera_link *icl;
- int ret;
+ int ret;
- icl = to_soc_camera_link(icd);
- if (icl->power) {
- ret = icl->power(icd->pdev, 1);
- if (ret < 0) {
- SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
- return -EINVAL;
- }
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+ if (ret < 0) {
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+ return -EINVAL;
}
SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
return 0;
}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+ bool ret = false;
+
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {
+ ret = true;
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {
+ ret = true;
+ }
+
+ if (ret == true)
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
+ return ret;
+}
static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
struct i2c_client *client = sd->priv;
struct sensor *sensor = to_sensor(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct v4l2_queryctrl *qctrl;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct reginfo *winseqe_set_addr=NULL;
char readval;
int ret=0, set_w,set_h;
SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);
}
- if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr)
- {
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+ }
+ } else { /* ddl@rock-chips.com : Video */
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
ret |= sensor_write_array(client, winseqe_set_addr);
if (ret != 0) {
SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+ #if CONFIG_SENSOR_Flash
+ if (sensor_fmt_capturechk(sd,f) == true) {
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+ }
+ }
+ #endif
goto sensor_s_fmt_end;
}
sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ if (sensor->info_priv.whiteBalance != 0) {
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ }
+ #endif
+ sensor->info_priv.snap2preview = true;
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = true;
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+ #if CONFIG_SENSOR_Effect
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+ #endif
+ #if CONFIG_SENSOR_WhiteBalance
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+ #endif
+ sensor->info_priv.video2preview = false;
+ sensor->info_priv.snap2preview = false;
+ }
SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
}
else
{
- SENSOR_TR("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
}
pix->width = set_w;
return -EINVAL;
}
#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+ if (value == 3) { /* ddl@rock-chips.com: torch */
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */
+ } else {
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+ }
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+ return 0;
+ }
+
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+ return -EINVAL;
+}
+#endif
+
static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct i2c_client *client = sd->priv;
#if CONFIG_SENSOR_Flash
case V4L2_CID_FLASH:
{
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+ return -EINVAL;
sensor->info_priv.flash = ext_ctrl->value;
SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+ ret = -ENODEV;
+ goto sensor_video_probe_err;
+ }
/* soft reset */
ret = sensor_write(client, 0x12, 0x80);
if (ret != 0)
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
+ struct i2c_client *client = sd->priv;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct sensor *sensor = to_sensor(client);
+ int ret = 0;
+#if CONFIG_SENSOR_Flash
+ int i;
+#endif
+
SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
switch (cmd)
{
case RK29_CAM_SUBDEV_DEACTIVATE:
{
- sensor_deactivate(sd);
+ sensor_deactivate(client);
+ break;
+ }
+
+ case RK29_CAM_SUBDEV_IOREQUEST:
+ {
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;
+ if (sensor->sensor_io_request != NULL) {
+ if (sensor->sensor_io_request->gpio_res[0].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name &&
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+ }
+ } else {
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+ ret = -EINVAL;
+ goto sensor_ioctl_end;
+ }
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control
+ for this project */
+ #if CONFIG_SENSOR_Flash
+ if (sensor->sensor_gpio_res) {
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+ for (i = 0; i < icd->ops->num_controls; i++) {
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));
+ }
+ }
+ sensor->info_priv.flash = 0xff;
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+ }
+ }
+ #endif
break;
}
default:
+ {
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
break;
+ }
}
-
- return 0;
+sensor_ioctl_end:
+ return ret;
}
static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
/* Second stage probe - when a capture adapter is there */
icd->ops = &sensor_ops;
icd->y_skip_top = 0;
+ #if CONFIG_SENSOR_I2C_NOSCHED
+ atomic_set(&sensor->tasklock_cnt,0);
+ #endif
ret = sensor_video_probe(icd, client);
- if (ret) {
+ if (ret < 0) {
icd->ops = NULL;
i2c_set_clientdata(client, NULL);
kfree(sensor);
+ sensor = NULL;
}
SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
return ret;
i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(sensor);
-
+ sensor = NULL;
return 0;
}
--- /dev/null
+/*\r
+o* Driver for MT9M001 CMOS Image Sensor from Micron\r
+ *\r
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 as\r
+ * published by the Free Software Foundation.\r
+ */\r
+\r
+#include <linux/videodev2.h>\r
+#include <linux/slab.h>\r
+#include <linux/i2c.h>\r
+#include <linux/log2.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/delay.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/miscdevice.h>\r
+#include <media/v4l2-common.h>\r
+#include <media/v4l2-chip-ident.h>\r
+#include <media/soc_camera.h>\r
+#include <mach/rk29_camera.h>\r
+\r
+static int debug;\r
+module_param(debug, int, S_IRUGO|S_IWUSR);\r
+\r
+#define dprintk(level, fmt, arg...) do { \\r
+ if (debug >= level) \\r
+ printk(KERN_WARNING fmt , ## arg); } while (0)\r
+\r
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)\r
+#define SENSOR_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)\r
+\r
+\r
+#define _CONS(a,b) a##b\r
+#define CONS(a,b) _CONS(a,b)\r
+\r
+#define __STR(x) #x\r
+#define _STR(x) __STR(x)\r
+#define STR(x) _STR(x)\r
+\r
+#define MIN(x,y) ((x<y) ? x: y)\r
+#define MAX(x,y) ((x>y) ? x: y)\r
+\r
+/* Sensor Driver Configuration */\r
+#define SENSOR_NAME sid130B\r
+#define SENSOR_V4L2_IDENT V4L2_IDENT_SID130B\r
+#define SENSOR_ID 0x1B\r
+#define SENSOR_MIN_WIDTH 176\r
+#define SENSOR_MIN_HEIGHT 144\r
+#define SENSOR_MAX_WIDTH 1600\r
+#define SENSOR_MAX_HEIGHT 1200\r
+#define SENSOR_INIT_WIDTH 640 /* Sensor pixel size for sensor_init_data array */\r
+#define SENSOR_INIT_HEIGHT 480\r
+#define SENSOR_INIT_WINSEQADR sensor_vga\r
+#define SENSOR_INIT_PIXFMT V4L2_PIX_FMT_UYVY\r
+\r
+#define CONFIG_SENSOR_WhiteBalance 1\r
+#define CONFIG_SENSOR_Brightness 0\r
+#define CONFIG_SENSOR_Contrast 0\r
+#define CONFIG_SENSOR_Saturation 0\r
+#define CONFIG_SENSOR_Effect 1\r
+#define CONFIG_SENSOR_Scene 0\r
+#define CONFIG_SENSOR_DigitalZoom 0\r
+#define CONFIG_SENSOR_Focus 0\r
+#define CONFIG_SENSOR_Exposure 0\r
+#define CONFIG_SENSOR_Flash 0\r
+#define CONFIG_SENSOR_Mirror 0\r
+#define CONFIG_SENSOR_Flip 0\r
+\r
+#define CONFIG_SENSOR_I2C_SPEED 80000 /* Hz */\r
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */\r
+#define CONFIG_SENSOR_I2C_NOSCHED 0\r
+#define CONFIG_SENSOR_I2C_RDWRCHK 0\r
+\r
+#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\\r
+ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW|\\r
+ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)\r
+\r
+#define COLOR_TEMPERATURE_CLOUDY_DN 6500\r
+#define COLOR_TEMPERATURE_CLOUDY_UP 8000\r
+#define COLOR_TEMPERATURE_CLEARDAY_DN 5000\r
+#define COLOR_TEMPERATURE_CLEARDAY_UP 6500\r
+#define COLOR_TEMPERATURE_OFFICE_DN 3500\r
+#define COLOR_TEMPERATURE_OFFICE_UP 5000\r
+#define COLOR_TEMPERATURE_HOME_DN 2500\r
+#define COLOR_TEMPERATURE_HOME_UP 3500\r
+\r
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))\r
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)\r
+\r
+struct reginfo\r
+{\r
+ u8 reg;\r
+ u8 val;\r
+};\r
+\r
+/* init 352X288 SVGA */\r
+static struct reginfo sensor_init_data[] =\r
+{\r
+ {0x00, 0x00}, \r
+ {0x04, 0x00}, //Group A 0x10\r
+ {0x05, 0x0F}, //UXGA Output\r
+ {0x06, 0x86}, \r
+ {0x07, 0x08}, \r
+\r
+\r
+ {0x08, 0xa2}, //PLL off\r
+ {0x09, 0x12}, \r
+ {0x0A, 0x12}, \r
+ {0x10, 0x17}, \r
+ {0x11, 0x01}, \r
+ {0x12, 0x8A}, \r
+ {0x13, 0x1a}, \r
+ {0x14, 0x27}, \r
+ {0x15, 0x22}, \r
+\r
+ {0x17, 0xCb}, \r
+ {0x18, 0x38}, \r
+ \r
+ {0x40, 0x0f}, \r
+ {0x41, 0x17}, \r
+ {0x42, 0x52}, \r
+ {0x43, 0x80}, \r
+ {0x44, 0x00}, \r
+ {0x45, 0x00}, \r
+\r
+//Flicker - 50Hz - Still mode , \r
+ {0x00, 0x00}, \r
+ {0x20, 0x00}, \r
+ {0x21, 0x02}, \r
+ {0x23, 0x29},//15}, \r
+ {0x00, 0x01}, \r
+ {0x35, 0x50},//3c}, \r
+\r
+//Flicker - 50Hz - Preview mode 24MHz MCLK\r
+ {0x00, 0x00}, \r
+ {0x24, 0x00}, \r
+ {0x25, 0xe6},//10}, \r
+ {0x27, 0x0d},//4b}, \r
+ {0x00, 0x01}, \r
+ {0x34, 0x80},//64}, \r
+\r
+\r
+//AE Block \r
+ {0x00, 0x01}, \r
+ {0x10, 0x00}, \r
+ {0x11, 0x0a}, //.0c\r
+ {0x12, 0x78}, \r
+ {0x13, 0x78}, \r
+ {0x14, 0x78}, \r
+ {0x17, 0xC4}, \r
+ {0x1c, 0x05}, \r
+\r
+ {0x36, 0x28}, //26\r
+\r
+ {0x40, 0x40}, //Max Again //anyuan\r
+ //{0x41, 0x20}, \r
+ //{0x42, 0x20}, \r
+ //{0x43, 0x00}, \r
+ //{0x44, 0x00}, \r
+ //{0x45, 0x01}, \r
+ //{0x46, 0x1c}, \r
+ //{0x47, 0x11}, \r
+ //{0x48, 0x15}, \r
+ //{0x49, 0x17}, \r
+ //{0x4A, 0x1a}, \r
+ //{0x4B, 0x1c}, \r
+ //{0x4C, 0x1e}, \r
+ //{0x4D, 0x1e}, \r
+ //{0x4E, 0x0f}, \r
+ //{0x4F, 0x09}, \r
+ //{0x50, 0x07}, \r
+ //{0x51, 0x05}, \r
+ //{0x52, 0x04}, \r
+ //{0x53, 0x03}, \r
+ //{0x54, 0x02}, \r
+ //{0x55, 0x01}, \r
+ //{0x66, 0x00}, \r
+ //{0x67, 0x00}, \r
+ //{0x68, 0x00}, \r
+ //{0x69, 0x00}, \r
+ //{0x6a, 0x00}, \r
+ //{0x6b, 0x00},\r
+\r
+ {0x70, 0xc4}, \r
+ {0x73, 0x22}, \r
+ {0x74, 0x07}, \r
+ {0x77, 0xd0}, \r
+ {0x78, 0xd8}, \r
+ {0x79, 0x70}, \r
+ //\r
+ {0x90, 0x00}, \r
+ {0x92, 0x0c}, //0bank 0x11 °ú µ¿ÀÏ \r
+ {0x95, 0x40}, //0 bank 0x40 °ú µ¿ÀÏ \r
+ //AWB Block\r
+\r
+ {0x00, 0x02}, \r
+ {0x10, 0xD3}, \r
+ {0x11, 0x11}, \r
+ {0x13, 0x7e}, \r
+ {0x14, 0x7c}, \r
+ {0x15, 0xee}, \r
+ {0x16, 0x80}, \r
+ {0x17, 0xd0}, \r
+ {0x18, 0x80}, \r
+ {0x19, 0x98}, \r
+ {0x1A, 0x68}, \r
+ {0x1B, 0x98}, \r
+ {0x1C, 0x68}, \r
+ {0x1D, 0x90}, \r
+ {0x1E, 0x74}, \r
+ {0x20, 0xF0}, \r
+ {0x21, 0x85}, \r
+ {0x22, 0xB4}, \r
+ {0x23, 0x20}, \r
+ {0x25, 0x20}, \r
+ {0x26, 0x05}, \r
+ {0x27, 0x78}, \r
+ {0x28, 0xd8}, \r
+ {0x29, 0xb8}, \r
+ {0x2A, 0x88}, \r
+ {0x30, 0x00}, \r
+ {0x31, 0x10}, \r
+ {0x32, 0x00}, \r
+ {0x33, 0x10}, \r
+ {0x34, 0x06}, \r
+ {0x35, 0x30}, \r
+ {0x36, 0x04}, \r
+ {0x37, 0xA0}, \r
+ {0x40, 0x01}, \r
+ {0x41, 0x04}, \r
+ {0x42, 0x08}, \r
+ {0x43, 0x10}, \r
+ {0x44, 0x13}, \r
+ {0x45, 0x6B}, \r
+ {0x46, 0x82}, \r
+\r
+\r
+\r
+//CMA change -D65~A\r
+ {0x53, 0xa1}, //AWB R Gain for D30 to D20\r
+ {0x54, 0xc0}, //AWB B Gain for D30 to D20\r
+ {0x55, 0xa1}, //AWB R Gain for D20 to D30\r
+ {0x56, 0xc0}, //AWB B Gain for D20 to D30\r
+ {0x57, 0xc8}, //AWB R Gain for D65 to D30\r
+ {0x58, 0xa0}, //AWB B Gain for D65 to D30\r
+ {0x59, 0xc8}, //AWB R Gain for D30 to D65\r
+ {0x5A, 0xa0}, //AWB B Gain for D30 to D65\r
+\r
+ {0x64, 0x00},\r
+ {0x65, 0x00},\r
+ {0x66, 0x00},\r
+ {0x67, 0x00},\r
+ {0x68, 0xa5},\r
+ {0x69, 0xb4},\r
+ {0x6a, 0xb3},\r
+ {0x6b, 0xac},\r
+ {0x6c, 0xb7},\r
+ {0x6d, 0x98},\r
+ {0x6e, 0xba},\r
+ {0x6f, 0x90},\r
+ \r
+ {0x70, 0xbf},\r
+ {0x71, 0x9b},\r
+ {0x72, 0xce},\r
+ {0x73, 0x8c},\r
+ {0x74, 0x7f},\r
+ {0x75, 0x8c},\r
+ {0x76, 0xad},\r
+ {0x77, 0xba},\r
+ {0x78, 0x8f},\r
+ {0x79, 0x9a},\r
+ {0x7A, 0xa3},\r
+ {0x7B, 0xac},\r
+ {0x7C, 0xa0},\r
+ {0x7D, 0xa9},\r
+ {0x7E, 0x95},\r
+ {0x7F, 0xac},\r
+ {0x80, 0xad},\r
+ {0x81, 0xbc},\r
+ {0x82, 0x98},\r
+ {0x83, 0xa4},\r
+ {0x84, 0x00},\r
+ {0x85, 0x00},\r
+ {0x86, 0x00},\r
+ {0x87, 0x00},\r
+ {0x88, 0xc9},\r
+ {0x89, 0xd5},\r
+ {0x8a, 0x70},\r
+ {0x8b, 0x7b},\r
+ {0x8c, 0xd0},\r
+ {0x8d, 0xe5},\r
+ {0x8e, 0x58},\r
+ {0x8f, 0x70},\r
+ \r
+ {0xB4, 0x05}, \r
+ {0xB5, 0x0F}, \r
+ {0xB6, 0x06}, \r
+ {0xB7, 0x06}, \r
+ {0xB8, 0x40}, \r
+ {0xB9, 0x10}, \r
+ {0xBA, 0x06}, \r
+\r
+//IDP\r
+ {0x00, 0x03}, \r
+ {0x10, 0xFF}, \r
+ {0x11, 0x1D}, \r
+ {0x12, 0x1D}, \r
+ {0x13, 0xFF}, \r
+ {0x14, 0x00}, \r
+ {0x15, 0xc0}, \r
+\r
+//DPC\r
+ {0x30, 0x88}, //DPCNRCTRL\r
+ {0x31, 0x14}, //DPTHR @ AGAIN = 00\r
+ {0x32, 0x10}, //DPTHR @ AGAIN = 20\r
+ {0x33, 0x0c}, //DPTHR @ AGAIN = 40\r
+ {0x34, 0x08}, //DPTHR @ AGAIN = 60\r
+ {0x35, 0x04}, //DPTHR @ AGAIN = 80\r
+ {0x36, 0x44}, //DPTHVRNG\r
+ {0x37, 0x66}, //DPNUMBER\r
+ {0x38, 0x00}, //0x00 // NRTHR0 @ AGAIN = 00\r
+ {0x39, 0x04}, //0x0C // NRTHR1 @ AGAIN = 20\r
+ {0x3A, 0x04}, //0x18 // NRTHR2 @ AGAIN = 40\r
+ {0x3B, 0x2c}, //0x30 // NRTHR3 @ AGAIN = 60\r
+ {0x3C, 0x3c}, // NRTHR4 @ AGAIN = 80\r
+ {0x3D, 0x04}, //NRTHVRNG0 @ AGAIN = 00\r
+ {0x3E, 0x04}, //NRTHVRNG1 @ AGAIN = 20\r
+ {0x3F, 0x04}, //NRTHVRNG2 @ AGAIN = 40\r
+ {0x40, 0x2c}, //NRTHVRNG3 @ AGAIN = 60\r
+ {0x41, 0x3c}, //NRTHVRNG4 @ AGAIN = 80\r
+ {0x42, 0xff}, //NRTHVRNGMAX\r
+ {0x43, 0x40}, //NRTHRWGT\r
+ {0x44, 0x40}, //BASELVL\r
+ {0x45, 0x06}, //SHUMAXH\r
+ {0x46, 0x40}, //SHUMAXL\r
+ {0x47, 0x30}, //ILLUMITHDRK\r
+\r
+// shading\r
+ {0x50, 0x0a}, //0x00 \r
+ {0x51, 0x20}, //0x45 \r
+ {0x52, 0x12}, //0x24 \r
+ {0x53, 0x12}, //0x24 \r
+ \r
+ {0x54, 0x22}, //0x00 \r
+ {0x55, 0x18}, //0x40 \r
+ {0x56, 0x08}, //0x10 \r
+ {0x57, 0x10}, //0x20 \r
+ \r
+ {0x58, 0x22}, //0x00 \r
+ {0x59, 0x18}, //0x40 \r
+ {0x5A, 0x08}, //0x10 \r
+ {0x5B, 0x10}, //0x20 \r
+ \r
+ {0x5C, 0x25}, //0x04 \r
+ {0x5D, 0x1a}, //0x55 \r
+ {0x5E, 0x12}, //0x25 \r
+ {0x5F, 0x10}, //0x20 \r
+ \r
+ {0x60, 0x32}, //0x32 \r
+ {0x61, 0x20}, //20//\r
+ {0x62, 0x58}, //67\r
+// {0x63, 0x89 //8c R Center start gain\r
+// {0x66, 0x79 //B Center start gain 73 \r
+ {0x6B, 0x00}, //01 //01 \r
+ {0x6C, 0x01}, //22 \r
+ {0x6D, 0x23}, //22 \r
+ {0x6E, 0x55}, //55 \r
+ {0x6F, 0x55}, //77 \r
+ {0x70, 0x55}, //65 \r
+ {0x71, 0x00}, //01 //AB (6) \r
+ {0x72, 0x01}, //23 (5) \r
+ {0x73, 0x23}, //33 (4) \r
+ {0x74, 0x44}, //45 (3) \r
+ {0x75, 0x45}, //55 (2) \r
+ {0x76, 0x66}, //55 (1) \r
+ {0x77, 0x00}, //01 //AB (6) \r
+ {0x78, 0x01}, //23 (5) \r
+ {0x79, 0x23}, //33 (4) \r
+ {0x7A, 0x44}, //45 (3) \r
+ {0x7B, 0x45}, //55 (2) \r
+ {0x7C, 0x66}, //55 (1) \r
+ {0x7D, 0x00}, //00 //00 \r
+ {0x7E, 0x00}, //00 //00 \r
+ {0x7F, 0x12}, //11 //12 \r
+ {0x80, 0x33}, //33 //33 //44 \r
+ {0x81, 0x44}, //33 //33 //44 \r
+ {0x82, 0x55}, //22 //44 //45 \r
+ //{0x83, 0x14}, \r
+ //{0x84, 0x0f}, \r
+\r
+ {0x94,0x02},\r
+ {0x95,0x80},\r
+ {0x96,0x01},\r
+ {0x97,0xe0}, \r
+\r
+//Interpolation\r
+ {0xA0, 0x3F},\r
+ {0xA1, 0x05},\r
+ {0xA2, 0xB7},\r
+ {0xA3, 0xB7},\r
+ {0xA4, 0x04},\r
+ {0xA5, 0xFF},\r
+ {0xA6, 0x04},\r
+ {0xA7, 0xFF},\r
+ {0xA8, 0x00},\r
+ {0xA9, 0x00},\r
+ {0xAA, 0x00},\r
+ {0xAB, 0x00},\r
+ {0xAC, 0x60},\r
+ {0xAD, 0x18},\r
+ {0xAE, 0x10},\r
+ {0xAF, 0x20},\r
+ {0xB0, 0x08},\r
+ {0xB1, 0x00},\r
+\r
+//Color Matrix for D65\r
+#if 0\r
+ {0xC0, 0x2F}, // CMASB D20 or D30 or Dark Condition Color Matrix Selection\r
+ {0xC1, 0x66}, \r
+ {0xC2, 0xd4}, \r
+ {0xC3, 0x05}, \r
+ {0xC4, 0xf0}, \r
+ {0xC5, 0x5a}, \r
+ {0xC6, 0xf5}, \r
+ {0xC7, 0xf9}, \r
+ {0xC8, 0xbf}, \r
+ {0xC9, 0x88}, \r
+ {0xCA, 0xa0}, \r
+ {0xCB, 0x50}, \r
+ {0xCC, 0xe2}, \r
+ {0xCD, 0x00}, \r
+ {0xCE, 0x00}, \r
+#else\r
+{0xC0, 0x2F}, // CMASB D20 or D30 or Dark Condition Color Matrix Selection\r
+{0xC1, 0x71}, \r
+{0xC2, 0xcc}, \r
+{0xC3, 0x01}, \r
+{0xC4, 0xe8}, \r
+{0xC5, 0x68}, \r
+{0xC6, 0xef}, \r
+{0xC7, 0xfa}, \r
+{0xC8, 0xc6}, \r
+{0xC9, 0x7e}, \r
+{0xCA, 0xec}, \r
+{0xCB, 0x67}, \r
+{0xCC, 0x34}, \r
+{0xCD, 0x3a}, \r
+{0xCE, 0x08},\r
+\r
+#endif\r
+//Color Matrix for CWF\r
+ {0xD0, 0x2F}, \r
+ {0xD1, 0x66}, \r
+ {0xD2, 0xd4}, \r
+ {0xD3, 0x05}, \r
+ {0xD4, 0xf0}, \r
+ {0xD5, 0x5a}, \r
+ {0xD6, 0xf5}, \r
+ {0xD7, 0xe9}, \r
+ {0xD8, 0xbf}, \r
+ {0xD9, 0x88},\r
+ {0xDA, 0xa0}, \r
+ {0xDB, 0x50}, \r
+ {0xDC, 0xe2}, \r
+ {0xDD, 0x00}, \r
+ {0xDE, 0x00}, \r
+\r
+//Color Matrix for A\r
+ {0xE0, 0x2F}, \r
+ {0xE1, 0x6e}, \r
+ {0xE2, 0xc7}, \r
+ {0xE3, 0x0d}, \r
+ {0xE4, 0xe3}, \r
+ {0xE5, 0x61}, \r
+ {0xE6, 0xfa}, \r
+ {0xE7, 0xe5}, \r
+ {0xE8, 0xcb}, \r
+ {0xE9, 0x8e}, \r
+ {0xEA, 0xc4}, \r
+ {0xEB, 0x04}, \r
+ {0xEC, 0xf3}, \r
+ {0xED, 0xdd}, \r
+ {0xEE, 0x06}, \r
+\r
+//IDP 4\r
+ {0x00, 0x04}, \r
+\r
+//Gamma - r \r
+ {0x10, 0x00}, \r
+ {0x11, 0x04}, \r
+ {0x12, 0x10},\r
+ {0x13, 0x20},\r
+ {0x14, 0x40},\r
+ {0x15, 0x5c},\r
+ {0x16, 0x74},\r
+ {0x17, 0x84},\r
+ {0x18, 0x98},\r
+ {0x19, 0xa4},\r
+ {0x1A, 0xb0},\r
+ {0x1B, 0xc8},\r
+ {0x1C, 0xdc},\r
+ {0x1D, 0xf0},\r
+ {0x1E, 0xf8},\r
+ {0x1F, 0xFF},\r
+ \r
+//Gamma - G \r
+ {0x20, 0x00}, \r
+ {0x21, 0x04}, \r
+ {0x22, 0x10},\r
+ {0x23, 0x20},\r
+ {0x24, 0x40},\r
+ {0x25, 0x5c},\r
+ {0x26, 0x74},\r
+ {0x27, 0x84},\r
+ {0x28, 0x98},\r
+ {0x29, 0xa4},\r
+ {0x2A, 0xb0},\r
+ {0x2B, 0xc8},\r
+ {0x2C, 0xdc},\r
+ {0x2D, 0xf0},\r
+ {0x2E, 0xf8},\r
+ {0x2F, 0xFF},\r
+ \r
+//Gamma - B \r
+ {0x30, 0x00}, \r
+ {0x31, 0x04}, \r
+ {0x32, 0x10},\r
+ {0x33, 0x20},\r
+ {0x34, 0x40},\r
+ {0x35, 0x5c},\r
+ {0x36, 0x74},\r
+ {0x37, 0x84},\r
+ {0x38, 0x98},\r
+ {0x39, 0xa4},\r
+ {0x3A, 0xb0},\r
+ {0x3B, 0xc8},\r
+ {0x3C, 0xdc},\r
+ {0x3D, 0xf0},\r
+ {0x3E, 0xf8},\r
+ {0x3F, 0xFF},\r
+\r
+//DARK GAMMA\r
+ {0x40, 0x00}, \r
+ {0x41, 0x0b}, \r
+ {0x42, 0x15},\r
+ {0x43, 0x29},\r
+ {0x44, 0x47},\r
+ {0x45, 0x5D},\r
+ {0x46, 0x72},\r
+ {0x47, 0x83},\r
+ {0x48, 0x92},\r
+ {0x49, 0xA0},\r
+ {0x4A, 0xac},\r
+ {0x4B, 0xc6},\r
+ {0x4C, 0xdA},\r
+ {0x4D, 0xeC},\r
+ {0x4E, 0xf6},\r
+ {0x4F, 0xFF},\r
+ \r
+ {0x50, 0x00}, //DARK GAMMA on/off\r
+ \r
+//CSC \r
+ {0x60, 0x33}, \r
+ {0x61, 0x20}, \r
+ {0x62, 0xE4}, \r
+ {0x63, 0xFA}, \r
+ {0x64, 0x13}, \r
+ {0x65, 0x25}, \r
+ {0x66, 0x07}, \r
+ {0x67, 0xF5}, \r
+ {0x68, 0xEA}, \r
+ {0x69, 0x20}, \r
+ {0x6A, 0xC8}, \r
+ {0x6B, 0xC4}, \r
+ {0x6C, 0x84}, \r
+ {0x6D, 0x04}, \r
+ {0x6E, 0x0C}, \r
+ {0x6F, 0x00}, \r
+ \r
+//Edge \r
+// {0x70, 0x00},\r
+// {0x71, 0x18},\r
+// {0x72, 0x18},\r
+// {0x73, 0x04},\r
+// {0x74, 0x08},\r
+// {0x76, 0x20},\r
+// {0x77, 0x04},\r
+// {0x78, 0x08},\r
+// {0x7a, 0x20},\r
+// {0x7d, 0x08},\r
+// {0X7e, 0x30},\r
+\r
+ {0x80, 0x22}, \r
+ {0x81, 0x14}, \r
+ {0x82, 0x14}, \r
+ {0x83, 0x04}, \r
+ {0x84, 0x06}, \r
+ {0x85, 0x06}, \r
+ {0x87, 0x04},\r
+ {0x88, 0x10},\r
+ {0x89, 0x06},\r
+ {0X90, 0x06},\r
+ {0x91, 0x03},\r
+ {0x93, 0xe0},\r
+\r
+//Cr/Cb Coring\r
+ {0x94, 0x00}, \r
+ {0x95, 0x00}, \r
+ {0x96, 0x4C}, \r
+ {0x97, 0x76}, \r
+ {0x9A, 0xf5}, \r
+\r
+ {0xA1, 0x08}, //@ 0\r
+ {0xA2, 0x10}, //@ 20\r
+ {0xA3, 0x16}, //@ 40\r
+ {0xA4, 0x20}, //@ 60\r
+ {0xA5, 0x30}, //@ 80\r
+ {0xA6, 0xa0}, \r
+ {0xA7, 0x06}, \r
+ {0xA8, 0x40}, \r
+\r
+ {0xA9, 0x38}, \r
+ {0xAa, 0x35}, \r
+\r
+ {0xAc, 0xff}, \r
+ {0xAd, 0x09}, \r
+ {0xAe, 0x96}, \r
+ {0xAf, 0x18}, \r
+\r
+ {0xB2, 0x38}, //color suppression start\r
+ {0xB3, 0x53}, \r
+ {0xB6, 0x00}, \r
+ \r
+//Color Saturation\r
+ {0xBC, 0x10}, \r
+ {0xBD, 0x10}, \r
+ {0xBE, 0x10}, \r
+ {0xBF, 0x10}, \r
+ {0xc0, 0x10}, \r
+ {0xc1, 0x10}, \r
+ {0xc2, 0x10}, \r
+ {0xc3, 0x10}, \r
+ {0xc4, 0x10}, \r
+ {0xc5, 0x10}, \r
+\r
+ {0xcc, 0x04}, \r
+ {0xcd, 0x40}, \r
+ {0xce, 0x00}, \r
+ \r
+//IDP 3 \r
+ {0x00, 0x05}, \r
+ \r
+//Memory \r
+ {0x40, 0x15}, \r
+ {0x41, 0x28}, \r
+ {0x42, 0x04}, \r
+ {0x43, 0x15}, \r
+ {0x44, 0x28}, \r
+ {0x45, 0x04}, \r
+ {0x46, 0x15}, \r
+ {0x47, 0x28}, \r
+ {0x48, 0x04}, \r
+ \r
+//Knee \r
+ {0x90, 0xca}, //\r
+ {0x91, 0x81}, //knee function selection/knee point H\r
+ {0x92, 0x00}, //knee point L\r
+ {0x93, 0x50}, //Knee gain\r
+ {0x94, 0x41}, //[6:4]knee start H/[2:0]Knee END H\r
+ {0x95, 0x7e}, //knee start L\r
+ {0x96, 0x48}, //knee END L\r
+ \r
+//ADG \r
+ {0x99, 0xC0}, \r
+ {0xA0, 0x10}, \r
+ {0xA1, 0x22}, \r
+ {0xA2, 0x36}, \r
+ {0xA3, 0x49}, \r
+ {0xA4, 0x5D}, \r
+ {0xA5, 0x70}, \r
+ {0xA6, 0x82}, \r
+ {0xA7, 0x94}, \r
+ {0xA8, 0xA5}, \r
+ {0xA9, 0xB5}, \r
+ {0xAA, 0xC3}, \r
+ {0xAB, 0xD1}, \r
+ {0xAC, 0xDE}, \r
+ {0xAD, 0xEA}, \r
+ {0xAE, 0xF5}, \r
+ {0xAF, 0xFF}, \r
+ \r
+//YXGMA \r
+ {0xB0, 0xc0}, //YGMACTRL\r
+ {0xB1, 0x04}, //YGMASLOP\r
+ {0xB8, 0x0f}, //DRKTHR1\r
+ {0xB9, 0x10}, //DRKTHR2\r
+ //{0xBA, 0x38}, //DRKTHR3\r
+ //{0xBB, 0x39}, //DRKTHR4\r
+ {0xC0, 0x03}, \r
+ {0xC1, 0x0E}, \r
+ {0xC2, 0x16}, \r
+ {0xC3, 0x24}, \r
+ {0xC4, 0x3F}, \r
+ {0xC5, 0x56}, \r
+ {0xC6, 0x6A}, \r
+ {0xC7, 0x7C}, \r
+ {0xC8, 0x8C}, \r
+ {0xC9, 0x98}, \r
+ {0xCA, 0xA2}, \r
+ {0xCB, 0xB8}, \r
+ {0xCC, 0xCD}, \r
+ {0xCD, 0xE2}, \r
+ {0xCE, 0xF0}, \r
+ {0xCF, 0xFF}, \r
+\r
+\r
+// edge value adjustment\r
+ {0xe0, 0x81}, \r
+ {0xe1, 0x83}, \r
+ {0xe2, 0x07}, \r
+ {0xe3, 0x0c}, \r
+ {0xe4, 0x14}, \r
+ {0xe5, 0x1c}, \r
+\r
+\r
+//Sensor on\r
+ {0x00, 0x00}, \r
+ {0x03, 0xc5}, \r
+ {0x00, 0x01}, \r
+ {0x10, 0x84}, \r
+ {0x00, 0x02}, \r
+ {0x10, 0xd3}, \r
+ {0xff, 0xff}, \r
+\r
+\r
+};\r
+\r
+/* 1600X1200 UXGA */\r
+static struct reginfo sensor_uxga[] =\r
+{\r
+ {0x00,0x00},\r
+ {0x04,0x10},\r
+ {0x05,0x8f},\r
+ {0x00,0x03},\r
+ {0x94,0x06},\r
+ {0x95,0x40},\r
+ {0x96,0x04},\r
+ {0x97,0xb0}, \r
+ {0xff, 0xff},\r
+};\r
+\r
+/* 1280X1024 SXGA */\r
+static struct reginfo sensor_sxga[] =\r
+{\r
+ {0x00,0x00},\r
+ {0x04,0x10},\r
+ {0x05,0x8b},\r
+ {0x00,0x03},\r
+ {0x94,0x05},\r
+ {0x95,0x00},\r
+ {0x96,0x04},\r
+ {0x97,0x00}, \r
+ {0xff, 0xff}, \r
+};\r
+static struct reginfo sensor_xga[] =\r
+{\r
+ {0xff, 0xff}\r
+};\r
+/* 800X600 SVGA*/\r
+static struct reginfo sensor_svga[] =\r
+{\r
+ {0x00,0x03},\r
+ {0x94,0x03},\r
+ {0x95,0x20},\r
+ {0x96,0x02},\r
+ {0x97,0x58}, \r
+ {0xff, 0xff}\r
+};\r
+\r
+/* 640X480 VGA */\r
+static struct reginfo sensor_vga[] =\r
+{\r
+ {0x00,0x00},\r
+ {0x04,0x00},\r
+ {0x05,0x0f},\r
+ {0x00,0x03},\r
+ {0x94,0x02}, //0x02\r
+ {0x95,0x80}, //0x80\r
+ {0x96,0x01},//0x01\r
+ {0x97,0xe0}, //0xe0\r
+ {0xff, 0xff}, \r
+};\r
+\r
+/* 352X288 CIF */\r
+static struct reginfo sensor_cif[] =\r
+{\r
+ {0x00,0x03},\r
+ {0x94,0x01},\r
+ {0x95,0x60},\r
+ {0x96,0x01},\r
+ {0x97,0x20}, \r
+ {0xff, 0xff}, \r
+};\r
+\r
+/* 320*240 QVGA */\r
+static struct reginfo sensor_qvga[] =\r
+{\r
+ {0x00,0x03},\r
+ {0x94,0x01},\r
+ {0x95,0x40},\r
+ {0x96,0x00},\r
+ {0x97,0xf0}, \r
+ {0xff, 0xff}, \r
+};\r
+\r
+/* 176X144 QCIF*/\r
+static struct reginfo sensor_qcif[] =\r
+{\r
+ {0x00,0x03},\r
+ {0x94,0x00},\r
+ {0x95,0xB0},\r
+ {0x96,0x00},\r
+ {0x97,0x90}, \r
+ {0xff, 0xff},\r
+};\r
+\r
+static struct reginfo sensor_ClrFmt_YUYV[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_ClrFmt_UYVY[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+#if CONFIG_SENSOR_WhiteBalance\r
+static struct reginfo sensor_WhiteB_Auto[]={\r
+ {0x00, 0x02},\r
+ {0x10, 0xd3},\r
+ {0xff, 0xff}\r
+};\r
+/* Cloudy Colour Temperature : 6500K - 8000K */\r
+static struct reginfo sensor_WhiteB_Cloudy[]=\r
+{\r
+ {0x00, 0x02},\r
+ {0x10, 0x00},\r
+ {0x50, 0xd0},\r
+ {0x51, 0x88},\r
+ {0xff, 0xff}\r
+};\r
+/* ClearDay Colour Temperature : 5000K - 6500K */\r
+static struct reginfo sensor_WhiteB_ClearDay[]=\r
+{\r
+ {0x00, 0x02},\r
+ {0x10, 0x00},\r
+ {0x50, 0xaa},\r
+ {0x51, 0x90},\r
+ {0xff, 0xff}\r
+\r
+};\r
+/* Office Colour Temperature : 3500K - 5000K */\r
+static struct reginfo sensor_WhiteB_TungstenLamp1[]=\r
+{\r
+ {0x00, 0x02},\r
+ {0x10, 0x00},\r
+ {0x50, 0xc2},\r
+ {0x51, 0x9e},\r
+ {0xff, 0xff}\r
+};\r
+/* Home Colour Temperature : 2500K - 3500K */\r
+static struct reginfo sensor_WhiteB_TungstenLamp2[]=\r
+{\r
+ {0x00, 0x02},\r
+ {0x10, 0x00},\r
+ {0x50, 0xaa},\r
+ {0x51, 0xbe},\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,\r
+ sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,\r
+};\r
+#endif\r
+\r
+#if CONFIG_SENSOR_Brightness\r
+static struct reginfo sensor_Brightness0[]=\r
+{\r
+ // Brightness -2\r
+ {0x00, 0x04},\r
+ {0xb6, 0xa0},\r
+ {0xff, 0xff}\r
+\r
+};\r
+\r
+static struct reginfo sensor_Brightness1[]=\r
+{\r
+ // Brightness -1\r
+ {0x00, 0x04},\r
+ {0xb6, 0x90},\r
+ {0xff, 0xff}\r
+\r
+};\r
+\r
+static struct reginfo sensor_Brightness2[]=\r
+{\r
+ // Brightness 0\r
+ {0x00, 0x04},\r
+ {0xb6, 0x00},\r
+ {0xff, 0xff}\r
+\r
+};\r
+\r
+static struct reginfo sensor_Brightness3[]=\r
+{\r
+ // Brightness +1\r
+ {0x00, 0x04},\r
+ {0xb6, 0x10},\r
+ {0xff, 0xff}\r
+\r
+};\r
+\r
+static struct reginfo sensor_Brightness4[]=\r
+{\r
+ // Brightness +2\r
+ {0x00, 0x04},\r
+ {0xb6, 0x20},\r
+ {0xff, 0xff}\r
+\r
+};\r
+\r
+static struct reginfo sensor_Brightness5[]=\r
+{\r
+ {0x00, 0x04},\r
+ {0xb6, 0x30},\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,\r
+ sensor_Brightness4, sensor_Brightness5,NULL,\r
+};\r
+\r
+#endif\r
+\r
+#if CONFIG_SENSOR_Effect\r
+static struct reginfo sensor_Effect_Normal[] =\r
+{\r
+ {0x00, 0x04},\r
+ {0xd9, 0x00},\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Effect_WandB[] =\r
+{\r
+ {0x00, 0x04},\r
+ {0xd9, 0x40},\r
+ {0x00, 0x00},\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Effect_Sepia[] =\r
+{\r
+ {0x00, 0x04},\r
+ {0xd9, 0x80},\r
+ {0xda, 0x60},\r
+ {0xdb, 0xa0},\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Effect_Negative[] =\r
+{\r
+ {0x00, 0x04},\r
+ {0xd9, 0x20},\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo sensor_Effect_Bluish[] =\r
+{\r
+ // Bluish\r
+ {0x00, 0x04},\r
+ {0xd9, 0x80},\r
+ {0xda, 0xc0},\r
+ {0xdb, 0x60},\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Effect_Green[] =\r
+{\r
+ // Greenish\r
+ {0x00, 0x04},\r
+ {0xd9, 0x80},\r
+ {0xda, 0x50},\r
+ {0xdb, 0x50},\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,\r
+ sensor_Effect_Bluish, sensor_Effect_Green,NULL,\r
+};\r
+#endif\r
+#if CONFIG_SENSOR_Exposure\r
+static struct reginfo sensor_Exposure0[]=\r
+{\r
+ //-3\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure1[]=\r
+{\r
+ //-2\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure2[]=\r
+{\r
+ //-0.3EV\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure3[]=\r
+{\r
+ //default\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure4[]=\r
+{\r
+ // 1\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure5[]=\r
+{\r
+ // 2\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Exposure6[]=\r
+{\r
+ // 3\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,\r
+ sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,\r
+};\r
+#endif\r
+#if CONFIG_SENSOR_Saturation\r
+static struct reginfo sensor_Saturation0[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Saturation1[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Saturation2[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};\r
+\r
+#endif\r
+#if CONFIG_SENSOR_Contrast\r
+static struct reginfo sensor_Contrast0[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Contrast1[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Contrast2[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Contrast3[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Contrast4[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+\r
+static struct reginfo sensor_Contrast5[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Contrast6[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,\r
+ sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,\r
+};\r
+\r
+#endif\r
+#if CONFIG_SENSOR_Mirror\r
+static struct reginfo sensor_MirrorOn[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_MirrorOff[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};\r
+#endif\r
+#if CONFIG_SENSOR_Flip\r
+static struct reginfo sensor_FlipOn[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_FlipOff[]=\r
+{\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};\r
+\r
+#endif\r
+#if CONFIG_SENSOR_Scene\r
+static struct reginfo sensor_SceneAuto[] =\r
+{\r
+ {0x00, 0x01},\r
+ {0x11, 0x0a},\r
+ {0x00, 0x04},\r
+ {0xb6, 0x00},\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_SceneNight[] =\r
+{\r
+ {0x00, 0x01},\r
+ {0x11, 0x14},\r
+ {0x00, 0x04},\r
+ {0xb6, 0x10},\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};\r
+\r
+#endif\r
+#if CONFIG_SENSOR_DigitalZoom\r
+static struct reginfo sensor_Zoom0[] =\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Zoom1[] =\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+static struct reginfo sensor_Zoom2[] =\r
+{\r
+ {0xff, 0xff}\r
+};\r
+\r
+\r
+static struct reginfo sensor_Zoom3[] =\r
+{\r
+ {0xff, 0xff}\r
+};\r
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};\r
+#endif\r
+static const struct v4l2_querymenu sensor_menus[] =\r
+{\r
+ #if CONFIG_SENSOR_WhiteBalance\r
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 0, .name = "auto", .reserved = 0, }, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 1, .name = "incandescent", .reserved = 0,},\r
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 2, .name = "fluorescent", .reserved = 0,}, { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3, .name = "daylight", .reserved = 0,},\r
+ { .id = V4L2_CID_DO_WHITE_BALANCE, .index = 4, .name = "cloudy-daylight", .reserved = 0,},\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Effect\r
+ { .id = V4L2_CID_EFFECT, .index = 0, .name = "none", .reserved = 0, }, { .id = V4L2_CID_EFFECT, .index = 1, .name = "mono", .reserved = 0,},\r
+ { .id = V4L2_CID_EFFECT, .index = 2, .name = "negative", .reserved = 0,}, { .id = V4L2_CID_EFFECT, .index = 3, .name = "sepia", .reserved = 0,},\r
+ { .id = V4L2_CID_EFFECT, .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT, .index = 5, .name = "aqua", .reserved = 0,},\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Scene\r
+ { .id = V4L2_CID_SCENE, .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE, .index = 1, .name = "night", .reserved = 0,},\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Flash\r
+ { .id = V4L2_CID_FLASH, .index = 0, .name = "off", .reserved = 0, }, { .id = V4L2_CID_FLASH, .index = 1, .name = "auto", .reserved = 0,},\r
+ { .id = V4L2_CID_FLASH, .index = 2, .name = "on", .reserved = 0,}, { .id = V4L2_CID_FLASH, .index = 3, .name = "torch", .reserved = 0,},\r
+ #endif\r
+};\r
+\r
+static const struct v4l2_queryctrl sensor_controls[] =\r
+{\r
+ #if CONFIG_SENSOR_WhiteBalance\r
+ {\r
+ .id = V4L2_CID_DO_WHITE_BALANCE,\r
+ .type = V4L2_CTRL_TYPE_MENU,\r
+ .name = "White Balance Control",\r
+ .minimum = 0,\r
+ .maximum = 4,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Brightness\r
+ {\r
+ .id = V4L2_CID_BRIGHTNESS,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Brightness Control",\r
+ .minimum = -3,\r
+ .maximum = 2,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Effect\r
+ {\r
+ .id = V4L2_CID_EFFECT,\r
+ .type = V4L2_CTRL_TYPE_MENU,\r
+ .name = "Effect Control",\r
+ .minimum = 0,\r
+ .maximum = 5,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Exposure\r
+ {\r
+ .id = V4L2_CID_EXPOSURE,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Exposure Control",\r
+ .minimum = 0,\r
+ .maximum = 6,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Saturation\r
+ {\r
+ .id = V4L2_CID_SATURATION,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Saturation Control",\r
+ .minimum = 0,\r
+ .maximum = 2,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Contrast\r
+ {\r
+ .id = V4L2_CID_CONTRAST,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Contrast Control",\r
+ .minimum = -3,\r
+ .maximum = 3,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Mirror\r
+ {\r
+ .id = V4L2_CID_HFLIP,\r
+ .type = V4L2_CTRL_TYPE_BOOLEAN,\r
+ .name = "Mirror Control",\r
+ .minimum = 0,\r
+ .maximum = 1,\r
+ .step = 1,\r
+ .default_value = 1,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Flip\r
+ {\r
+ .id = V4L2_CID_VFLIP,\r
+ .type = V4L2_CTRL_TYPE_BOOLEAN,\r
+ .name = "Flip Control",\r
+ .minimum = 0,\r
+ .maximum = 1,\r
+ .step = 1,\r
+ .default_value = 1,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Scene\r
+ {\r
+ .id = V4L2_CID_SCENE,\r
+ .type = V4L2_CTRL_TYPE_MENU,\r
+ .name = "Scene Control",\r
+ .minimum = 0,\r
+ .maximum = 1,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_DigitalZoom\r
+ {\r
+ .id = V4L2_CID_ZOOM_RELATIVE,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "DigitalZoom Control",\r
+ .minimum = -1,\r
+ .maximum = 1,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ }, {\r
+ .id = V4L2_CID_ZOOM_ABSOLUTE,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "DigitalZoom Control",\r
+ .minimum = 0,\r
+ .maximum = 3,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Focus\r
+ {\r
+ .id = V4L2_CID_FOCUS_RELATIVE,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Focus Control",\r
+ .minimum = -1,\r
+ .maximum = 1,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ }, {\r
+ .id = V4L2_CID_FOCUS_ABSOLUTE,\r
+ .type = V4L2_CTRL_TYPE_INTEGER,\r
+ .name = "Focus Control",\r
+ .minimum = 0,\r
+ .maximum = 255,\r
+ .step = 1,\r
+ .default_value = 125,\r
+ },\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Flash\r
+ {\r
+ .id = V4L2_CID_FLASH,\r
+ .type = V4L2_CTRL_TYPE_MENU,\r
+ .name = "Flash Control",\r
+ .minimum = 0,\r
+ .maximum = 3,\r
+ .step = 1,\r
+ .default_value = 0,\r
+ },\r
+ #endif\r
+};\r
+\r
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);\r
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);\r
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);\r
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);\r
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);\r
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);\r
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);\r
+static int sensor_resume(struct soc_camera_device *icd);\r
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);\r
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);\r
+#if CONFIG_SENSOR_Effect\r
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);\r
+#endif\r
+#if CONFIG_SENSOR_WhiteBalance\r
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);\r
+#endif\r
+static int sensor_deactivate(struct i2c_client *client);\r
+\r
+static struct soc_camera_ops sensor_ops =\r
+{\r
+ .suspend = sensor_suspend,\r
+ .resume = sensor_resume,\r
+ .set_bus_param = sensor_set_bus_param,\r
+ .query_bus_param = sensor_query_bus_param,\r
+ .controls = sensor_controls,\r
+ .menus = sensor_menus,\r
+ .num_controls = ARRAY_SIZE(sensor_controls),\r
+ .num_menus = ARRAY_SIZE(sensor_menus),\r
+};\r
+\r
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \\r
+ { .name = _name, .depth = _depth, .fourcc = _fourcc, \\r
+ .colorspace = _colorspace }\r
+\r
+#define JPG_FMT(_name, _depth, _fourcc) \\r
+ COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)\r
+\r
+static const struct soc_camera_data_format sensor_colour_formats[] = {\r
+ JPG_FMT(SENSOR_NAME_STRING(UYVY), 16, V4L2_PIX_FMT_UYVY),\r
+ JPG_FMT(SENSOR_NAME_STRING(YUYV), 16, V4L2_PIX_FMT_YUYV),\r
+};\r
+\r
+typedef struct sensor_info_priv_s\r
+{\r
+ int whiteBalance;\r
+ int brightness;\r
+ int contrast;\r
+ int saturation;\r
+ int effect;\r
+ int scene;\r
+ int digitalzoom;\r
+ int focus;\r
+ int flash;\r
+ int exposure;\r
+ bool snap2preview;\r
+ bool video2preview;\r
+ unsigned char mirror; /* HFLIP */\r
+ unsigned char flip; /* VFLIP */\r
+ unsigned int winseqe_cur_addr;\r
+ unsigned int pixfmt;\r
+\r
+} sensor_info_priv_t;\r
+\r
+struct sensor\r
+{\r
+ struct v4l2_subdev subdev;\r
+ struct i2c_client *client;\r
+ sensor_info_priv_t info_priv;\r
+ int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */\r
+#if CONFIG_SENSOR_I2C_NOSCHED\r
+ atomic_t tasklock_cnt;\r
+#endif\r
+ struct rk29camera_platform_data *sensor_io_request;\r
+ struct rk29camera_gpio_res *sensor_gpio_res;\r
+};\r
+\r
+static struct sensor* to_sensor(const struct i2c_client *client)\r
+{\r
+ return container_of(i2c_get_clientdata(client), struct sensor, subdev);\r
+}\r
+\r
+static int sensor_task_lock(struct i2c_client *client, int lock)\r
+{\r
+#if CONFIG_SENSOR_I2C_NOSCHED\r
+ int cnt = 3;\r
+ struct sensor *sensor = to_sensor(client);\r
+\r
+ if (lock) {\r
+ if (atomic_read(&sensor->tasklock_cnt) == 0) {\r
+ while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {\r
+ SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());\r
+ msleep(35);\r
+ cnt--;\r
+ }\r
+ if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {\r
+ SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());\r
+ goto sensor_task_lock_err;\r
+ }\r
+ preempt_disable();\r
+ }\r
+\r
+ atomic_add(1, &sensor->tasklock_cnt);\r
+ } else {\r
+ if (atomic_read(&sensor->tasklock_cnt) > 0) {\r
+ atomic_sub(1, &sensor->tasklock_cnt);\r
+\r
+ if (atomic_read(&sensor->tasklock_cnt) == 0)\r
+ preempt_enable();\r
+ }\r
+ }\r
+ return 0;\r
+sensor_task_lock_err:\r
+ return -1; \r
+#else\r
+ return 0;\r
+#endif\r
+\r
+}\r
+\r
+/* sensor register write */\r
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)\r
+{\r
+ int err,cnt;\r
+ u8 buf[2];\r
+ struct i2c_msg msg[1];\r
+\r
+ //buf[0] = reg >> 8;\r
+ buf[0] = reg & 0xFF;\r
+ buf[1] = val;\r
+\r
+ msg->addr = client->addr;\r
+ msg->flags = client->flags;\r
+ msg->buf = buf;\r
+ msg->len = sizeof(buf);\r
+ msg->scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */\r
+ msg->read_type = 0; /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */\r
+\r
+ cnt = 3;\r
+ err = -EAGAIN;\r
+\r
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */\r
+ err = i2c_transfer(client->adapter, msg, 1);\r
+\r
+ if (err >= 0) {\r
+ return 0;\r
+ } else {\r
+ SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);\r
+ udelay(10);\r
+ }\r
+ }\r
+\r
+ return err;\r
+}\r
+\r
+/* sensor register read */\r
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)\r
+{\r
+ int err,cnt;\r
+ u8 buf[1];\r
+ struct i2c_msg msg[2];\r
+\r
+ // buf[0] = reg >> 8;\r
+ buf[0] = reg & 0xFF;\r
+\r
+ msg[0].addr = client->addr;\r
+ msg[0].flags = client->flags;\r
+ msg[0].buf = buf;\r
+ msg[0].len = sizeof(buf);\r
+ msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */\r
+ msg[0].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */\r
+\r
+ msg[1].addr = client->addr;\r
+ msg[1].flags = client->flags|I2C_M_RD;\r
+ msg[1].buf = buf;\r
+ msg[1].len = 1;\r
+ msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED; /* ddl@rock-chips.com : 100kHz */\r
+ msg[1].read_type = 2; /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */\r
+\r
+ cnt = 3;\r
+ err = -EAGAIN;\r
+ while ((cnt-- > 0) && (err < 0)) { /* ddl@rock-chips.com : Transfer again if transent is failed */\r
+ err = i2c_transfer(client->adapter, msg, 2);\r
+\r
+ if (err >= 0) {\r
+ *val = buf[0];\r
+ return 0;\r
+ } else {\r
+ SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);\r
+ udelay(10);\r
+ }\r
+ }\r
+\r
+ return err;\r
+}\r
+\r
+/* write a array of registers */\r
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)\r
+{\r
+ int err = 0, cnt;\r
+ int i = 0;\r
+#if CONFIG_SENSOR_I2C_RDWRCHK \r
+ char valchk;\r
+#endif\r
+\r
+ cnt = 0;\r
+ if (sensor_task_lock(client, 1) < 0)\r
+ goto sensor_write_array_end;\r
+ while (regarray[i].reg != 0xff)\r
+ {\r
+ err = sensor_write(client, regarray[i].reg, regarray[i].val);\r
+ if (err < 0)\r
+ {\r
+ if (cnt-- > 0) {\r
+ SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);\r
+ i = 0;\r
+ continue;\r
+ } else {\r
+ SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());\r
+ err = -EPERM;\r
+ goto sensor_write_array_end;\r
+ }\r
+ } else {\r
+ #if CONFIG_SENSOR_I2C_RDWRCHK\r
+ sensor_read(client, regarray[i].reg, &valchk);\r
+ if (valchk != regarray[i].val)\r
+ SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);\r
+ #endif\r
+ }\r
+ i++;\r
+ }\r
+\r
+sensor_write_array_end:\r
+ sensor_task_lock(client,0);\r
+ return err;\r
+}\r
+#if CONFIG_SENSOR_I2C_RDWRCHK\r
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)\r
+{\r
+ int cnt;\r
+ int i = 0;\r
+ char valchk;\r
+\r
+ cnt = 0;\r
+ valchk = 0;\r
+ while (regarray[i].reg != 0xff)\r
+ {\r
+ sensor_read(client, regarray[i].reg, &valchk);\r
+ if (valchk != regarray[i].val)\r
+ SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);\r
+\r
+ i++;\r
+ }\r
+ return 0;\r
+}\r
+#endif\r
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)\r
+{\r
+ struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+ int ret = 0;\r
+\r
+ SENSOR_DG("%s %s cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);\r
+ switch (cmd)\r
+ {\r
+ case Sensor_PowerDown:\r
+ {\r
+ if (icl->powerdown) {\r
+ ret = icl->powerdown(icd->pdev, on);\r
+ if (ret == RK29_CAM_IO_SUCCESS) {\r
+ if (on == 0) {\r
+ mdelay(2);\r
+ if (icl->reset)\r
+ icl->reset(icd->pdev);\r
+ }\r
+ } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {\r
+ ret = -ENODEV;\r
+ goto sensor_power_end;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case Sensor_Flash:\r
+ {\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+ struct sensor *sensor = to_sensor(client);\r
+\r
+ if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {\r
+ sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);\r
+ }\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+ break;\r
+ }\r
+ }\r
+sensor_power_end:\r
+ return ret;\r
+}\r
+static int sensor_init(struct v4l2_subdev *sd, u32 val)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ struct sensor *sensor = to_sensor(client);\r
+ const struct v4l2_queryctrl *qctrl;\r
+ char value;\r
+ int ret,pid = 0;\r
+\r
+ SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);\r
+\r
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+ msleep(100);\r
+#if 0\r
+ /* soft reset */\r
+ if (sensor_task_lock(client,1)<0)\r
+ goto sensor_INIT_ERR;\r
+ ret = sensor_write(client, 0x3012, 0x80);\r
+ if (ret != 0)\r
+ {\r
+ SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+\r
+ mdelay(5); //delay 5 microseconds\r
+ /* check if it is an sensor sensor */\r
+ ret = sensor_read(client, 0x300a, &value);\r
+ if (ret != 0) {\r
+ SENSOR_TR("read chip id high byte failed\n");\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+\r
+ pid |= (value << 8);\r
+\r
+ ret = sensor_read(client, 0x300b, &value);\r
+ if (ret != 0) {\r
+ SENSOR_TR("read chip id low byte failed\n");\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+\r
+ pid |= (value & 0xff);\r
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ if (pid == SENSOR_ID) {\r
+ sensor->model = SENSOR_V4L2_IDENT;\r
+ } else {\r
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+#endif\r
+#if 0\r
+ sensor_read(client,0x01,&value);\r
+ pid = (value & 0xff);\r
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ if (pid == SENSOR_ID) {\r
+ sensor->model = SENSOR_V4L2_IDENT;\r
+ } else {\r
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ ret = -ENODEV;\r
+ goto sensor_INIT_ERR;\r
+ }\r
+#endif\r
+ ret = sensor_write_array(client, sensor_init_data);\r
+ if (ret != 0)\r
+ {\r
+ SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());\r
+ goto sensor_INIT_ERR;\r
+ }\r
+ sensor_task_lock(client,0);\r
+ // icd->user_width = SENSOR_INIT_WIDTH;\r
+ //icd->user_height = SENSOR_INIT_HEIGHT;\r
+ sensor->info_priv.winseqe_cur_addr = (int)SENSOR_INIT_WINSEQADR;\r
+ sensor->info_priv.pixfmt = SENSOR_INIT_PIXFMT;\r
+\r
+ /* sensor sensor information for initialization */\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);\r
+ if (qctrl)\r
+ sensor->info_priv.whiteBalance = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);\r
+ if (qctrl)\r
+ sensor->info_priv.brightness = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);\r
+ if (qctrl)\r
+ sensor->info_priv.effect = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);\r
+ if (qctrl)\r
+ sensor->info_priv.exposure = qctrl->default_value;\r
+\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);\r
+ if (qctrl)\r
+ sensor->info_priv.saturation = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);\r
+ if (qctrl)\r
+ sensor->info_priv.contrast = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);\r
+ if (qctrl)\r
+ sensor->info_priv.mirror = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);\r
+ if (qctrl)\r
+ sensor->info_priv.flip = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);\r
+ if (qctrl)\r
+ sensor->info_priv.scene = qctrl->default_value;\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);\r
+ if (qctrl)\r
+ sensor->info_priv.digitalzoom = qctrl->default_value;\r
+\r
+ /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */\r
+ #if CONFIG_SENSOR_Focus\r
+ sensor_set_focus();\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);\r
+ if (qctrl)\r
+ sensor->info_priv.focus = qctrl->default_value;\r
+ #endif\r
+\r
+ #if CONFIG_SENSOR_Flash\r
+ sensor_set_flash();\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);\r
+ if (qctrl)\r
+ sensor->info_priv.flash = qctrl->default_value;\r
+ #endif\r
+\r
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);\r
+\r
+ return 0;\r
+sensor_INIT_ERR:\r
+ sensor_task_lock(client,0);\r
+ sensor_deactivate(client);\r
+ return ret;\r
+}\r
+\r
+static int sensor_deactivate(struct i2c_client *client)\r
+{\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+\r
+ SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);\r
+\r
+ /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */\r
+ //sensor_task_lock(client, 1);\r
+ //sensor_write(client, 0x30b0, 0x00);\r
+ //sensor_write(client, 0x30b1, 0x00);\r
+ //sensor_task_lock(client, 0);\r
+ sensor_ioctrl(icd, Sensor_PowerDown, 1);\r
+\r
+ /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */\r
+ icd->user_width = SENSOR_INIT_WIDTH;\r
+ icd->user_height = SENSOR_INIT_HEIGHT;\r
+ msleep(100);\r
+ return 0;\r
+}\r
+\r
+static struct reginfo sensor_power_down_sequence[]=\r
+{\r
+ {0xff,0xff}\r
+};\r
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)\r
+{\r
+ int ret;\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if (pm_msg.event == PM_EVENT_SUSPEND) {\r
+ SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());\r
+ ret = sensor_write_array(client, sensor_power_down_sequence) ;\r
+ if (ret != 0) {\r
+ SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);\r
+ return ret;\r
+ } else {\r
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);\r
+ if (ret < 0) {\r
+ SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());\r
+ return -EINVAL;\r
+ }\r
+ }\r
+ } else {\r
+ SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());\r
+ return -EINVAL;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static int sensor_resume(struct soc_camera_device *icd)\r
+{\r
+ int ret;\r
+\r
+ ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);\r
+ if (ret < 0) {\r
+ SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());\r
+ return -EINVAL;\r
+ }\r
+\r
+ SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());\r
+\r
+ return 0;\r
+\r
+}\r
+\r
+static int sensor_set_bus_param(struct soc_camera_device *icd,\r
+ unsigned long flags)\r
+{\r
+\r
+ return 0;\r
+}\r
+\r
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)\r
+{\r
+ struct soc_camera_link *icl = to_soc_camera_link(icd);\r
+ unsigned long flags = SENSOR_BUS_PARAM;\r
+\r
+ return soc_camera_apply_sensor_flags(icl, flags);\r
+}\r
+\r
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ struct sensor *sensor = to_sensor(client);\r
+ struct v4l2_pix_format *pix = &f->fmt.pix;\r
+\r
+ pix->width = icd->user_width;\r
+ pix->height = icd->user_height;\r
+ pix->pixelformat = sensor->info_priv.pixfmt;\r
+ pix->field = V4L2_FIELD_NONE;\r
+ pix->colorspace = V4L2_COLORSPACE_JPEG;\r
+\r
+ return 0;\r
+}\r
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_format *f)\r
+{\r
+ bool ret = false;\r
+\r
+ if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {\r
+ ret = true;\r
+ } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {\r
+ ret = true;\r
+ } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {\r
+ ret = true;\r
+ } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {\r
+ ret = true;\r
+ } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {\r
+ ret = true;\r
+ }\r
+\r
+ if (ret == true)\r
+ SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);\r
+ return ret;\r
+}\r
+\r
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_format *f)\r
+{\r
+ bool ret = false;\r
+\r
+ if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 720)) {\r
+ ret = true;\r
+ } else if ((f->fmt.pix.width == 1920) && (f->fmt.pix.height == 1080)) {\r
+ ret = true;\r
+ }\r
+\r
+ if (ret == true)\r
+ SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);\r
+ return ret;\r
+}\r
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct sensor *sensor = to_sensor(client);\r
+ struct v4l2_pix_format *pix = &f->fmt.pix;\r
+ const struct v4l2_queryctrl *qctrl;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ struct reginfo *winseqe_set_addr=NULL;\r
+ int ret=0, set_w,set_h;\r
+\r
+ if (sensor->info_priv.pixfmt != pix->pixelformat) {\r
+ switch (pix->pixelformat)\r
+ {\r
+ case V4L2_PIX_FMT_YUYV:\r
+ {\r
+ winseqe_set_addr = sensor_ClrFmt_YUYV;\r
+ break;\r
+ }\r
+ case V4L2_PIX_FMT_UYVY:\r
+ {\r
+ winseqe_set_addr = sensor_ClrFmt_UYVY;\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ if (winseqe_set_addr != NULL) {\r
+ sensor_write_array(client, winseqe_set_addr);\r
+ sensor->info_priv.pixfmt = pix->pixelformat;\r
+\r
+ SENSOR_DG("%s Pixelformat(0x%x) set success!\n", SENSOR_NAME_STRING(),pix->pixelformat);\r
+ } else {\r
+ SENSOR_TR("%s Pixelformat(0x%x) is invalidate!\n", SENSOR_NAME_STRING(),pix->pixelformat);\r
+ }\r
+ }\r
+\r
+ set_w = pix->width;\r
+ set_h = pix->height;\r
+\r
+ if (((set_w <= 176) && (set_h <= 144)) &&( sensor_qcif[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_qcif;\r
+ set_w = 176;\r
+ set_h = 144;\r
+ }\r
+ else if (((set_w <= 320) && (set_h <= 240)) && (sensor_qvga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_qvga;\r
+ set_w = 320;\r
+ set_h = 240;\r
+ }\r
+ else if (((set_w <= 352) && (set_h<= 288)) && (sensor_cif[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_cif;\r
+ set_w = 352;\r
+ set_h = 288;\r
+ }\r
+ else if (((set_w <= 640) && (set_h <= 480)) &&( sensor_vga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_vga;\r
+ set_w =640;\r
+ set_h = 480;\r
+ }\r
+ else if (((set_w <= 800) && (set_h <= 600)) && (sensor_svga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_svga;\r
+ set_w = 800;\r
+ set_h = 600;\r
+ }\r
+ else if (((set_w <= 1024) && (set_h <= 768)) &&( sensor_xga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_xga;\r
+ set_w = 1024;\r
+ set_h = 768;\r
+ }\r
+ else if (((set_w <= 1280) && (set_h <= 1024)) && (sensor_sxga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_sxga;\r
+ set_w = 1280;\r
+ set_h = 1024;\r
+ }\r
+ else if (((set_w <= 1600) && (set_h <= 1200)) && (sensor_uxga[0].reg!=0xff))\r
+ {\r
+ winseqe_set_addr = sensor_uxga;\r
+ set_w = 1600;\r
+ set_h = 1200;\r
+ }\r
+ else\r
+ {\r
+ winseqe_set_addr = SENSOR_INIT_WINSEQADR; /* ddl@rock-chips.com : Sensor output smallest size if isn't support app */\r
+ set_w = SENSOR_INIT_WIDTH;\r
+ set_h = SENSOR_INIT_HEIGHT;\r
+ ret = -1;\r
+ SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,pix->width,pix->height);\r
+ }\r
+\r
+ if ((int)winseqe_set_addr != sensor->info_priv.winseqe_cur_addr) {\r
+ #if CONFIG_SENSOR_Flash\r
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */\r
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {\r
+ sensor_ioctrl(icd, Sensor_Flash, Flash_On);\r
+ SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());\r
+ } \r
+ } else { /* ddl@rock-chips.com : Video */\r
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {\r
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);\r
+ SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());\r
+ }\r
+ }\r
+ #endif\r
+ ret |= sensor_write_array(client, winseqe_set_addr);\r
+ if (ret != 0) {\r
+ SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());\r
+ #if CONFIG_SENSOR_Flash\r
+ if (sensor_fmt_capturechk(sd,f) == true) {\r
+ if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {\r
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);\r
+ SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());\r
+ }\r
+ }\r
+ #endif\r
+ goto sensor_s_fmt_end;\r
+ }\r
+\r
+ sensor->info_priv.winseqe_cur_addr = (int)winseqe_set_addr;\r
+\r
+ if (sensor_fmt_capturechk(sd,f) == true) { /* ddl@rock-chips.com : Capture */\r
+ #if CONFIG_SENSOR_Effect\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);\r
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);\r
+ #endif\r
+ #if CONFIG_SENSOR_WhiteBalance\r
+ if (sensor->info_priv.whiteBalance != 0) {\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);\r
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);\r
+ }\r
+ #endif\r
+ sensor->info_priv.snap2preview = true;\r
+ } else if (sensor_fmt_videochk(sd,f) == true) { /* ddl@rock-chips.com : Video */\r
+ #if CONFIG_SENSOR_Effect\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);\r
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);\r
+ #endif\r
+ #if CONFIG_SENSOR_WhiteBalance\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);\r
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);\r
+ #endif\r
+ sensor->info_priv.video2preview = true;\r
+ } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {\r
+ #if CONFIG_SENSOR_Effect\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);\r
+ sensor_set_effect(icd, qctrl,sensor->info_priv.effect);\r
+ #endif\r
+ #if CONFIG_SENSOR_WhiteBalance\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);\r
+ sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);\r
+ #endif\r
+ sensor->info_priv.video2preview = false;\r
+ sensor->info_priv.snap2preview = false;\r
+ }\r
+ SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);\r
+ }\r
+ else\r
+ {\r
+ SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);\r
+ }\r
+\r
+ pix->width = set_w;\r
+ pix->height = set_h;\r
+\r
+sensor_s_fmt_end:\r
+ return ret;\r
+}\r
+\r
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)\r
+{\r
+ struct v4l2_pix_format *pix = &f->fmt.pix;\r
+ bool bayer = pix->pixelformat == V4L2_PIX_FMT_UYVY ||\r
+ pix->pixelformat == V4L2_PIX_FMT_YUYV;\r
+\r
+ /*\r
+ * With Bayer format enforce even side lengths, but let the user play\r
+ * with the starting pixel\r
+ */\r
+ if (pix->height > SENSOR_MAX_HEIGHT)\r
+ pix->height = SENSOR_MAX_HEIGHT;\r
+ else if (pix->height < SENSOR_MIN_HEIGHT)\r
+ pix->height = SENSOR_MIN_HEIGHT;\r
+ else if (bayer)\r
+ pix->height = ALIGN(pix->height, 2);\r
+\r
+ if (pix->width > SENSOR_MAX_WIDTH)\r
+ pix->width = SENSOR_MAX_WIDTH;\r
+ else if (pix->width < SENSOR_MIN_WIDTH)\r
+ pix->width = SENSOR_MIN_WIDTH;\r
+ else if (bayer)\r
+ pix->width = ALIGN(pix->width, 2);\r
+ return 0;\r
+}\r
+\r
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+\r
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)\r
+ return -EINVAL;\r
+\r
+ if (id->match.addr != client->addr)\r
+ return -ENODEV;\r
+\r
+ id->ident = SENSOR_V4L2_IDENT; /* ddl@rock-chips.com : Return OV2655 identifier */\r
+ id->revision = 0;\r
+\r
+ return 0;\r
+}\r
+#if CONFIG_SENSOR_Brightness\r
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Effect\r
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Exposure\r
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Saturation\r
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Contrast\r
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Mirror\r
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Flip\r
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Scene\r
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_WhiteBalance\r
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+\r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum))\r
+ {\r
+ if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ }\r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_DigitalZoom\r
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)\r
+{\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+ struct sensor *sensor = to_sensor(client);\r
+ const struct v4l2_queryctrl *qctrl_info;\r
+ int digitalzoom_cur, digitalzoom_total;\r
+\r
+ qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);\r
+ if (qctrl_info)\r
+ return -EINVAL;\r
+\r
+ digitalzoom_cur = sensor->info_priv.digitalzoom;\r
+ digitalzoom_total = qctrl_info->maximum;\r
+\r
+ if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))\r
+ {\r
+ SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);\r
+ return -EINVAL;\r
+ }\r
+\r
+ if ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))\r
+ {\r
+ SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);\r
+ return -EINVAL;\r
+ }\r
+\r
+ if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))\r
+ {\r
+ *value = digitalzoom_total - digitalzoom_cur;\r
+ }\r
+\r
+ if ((*value < 0) && ((digitalzoom_cur + *value) < 0))\r
+ {\r
+ *value = 0 - digitalzoom_cur;\r
+ }\r
+\r
+ digitalzoom_cur += *value;\r
+\r
+ if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)\r
+ {\r
+ if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)\r
+ {\r
+ SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);\r
+ return -EINVAL;\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);\r
+ return 0;\r
+ }\r
+\r
+ return -EINVAL;\r
+}\r
+#endif\r
+#if CONFIG_SENSOR_Flash\r
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)\r
+{ \r
+ if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {\r
+ if (value == 3) { /* ddl@rock-chips.com: torch */\r
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Torch); /* Flash On */\r
+ } else {\r
+ sensor_ioctrl(icd, Sensor_Flash, Flash_Off);\r
+ }\r
+ SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);\r
+ return 0;\r
+ }\r
+ \r
+ SENSOR_TR("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value);\r
+ return -EINVAL;\r
+}\r
+#endif\r
+\r
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct sensor *sensor = to_sensor(client);\r
+ const struct v4l2_queryctrl *qctrl;\r
+\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);\r
+\r
+ if (!qctrl)\r
+ {\r
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);\r
+ return -EINVAL;\r
+ }\r
+\r
+ switch (ctrl->id)\r
+ {\r
+ case V4L2_CID_BRIGHTNESS:\r
+ {\r
+ ctrl->value = sensor->info_priv.brightness;\r
+ break;\r
+ }\r
+ case V4L2_CID_SATURATION:\r
+ {\r
+ ctrl->value = sensor->info_priv.saturation;\r
+ break;\r
+ }\r
+ case V4L2_CID_CONTRAST:\r
+ {\r
+ ctrl->value = sensor->info_priv.contrast;\r
+ break;\r
+ }\r
+ case V4L2_CID_DO_WHITE_BALANCE:\r
+ {\r
+ ctrl->value = sensor->info_priv.whiteBalance;\r
+ break;\r
+ }\r
+ case V4L2_CID_EXPOSURE:\r
+ {\r
+ ctrl->value = sensor->info_priv.exposure;\r
+ break;\r
+ }\r
+ case V4L2_CID_HFLIP:\r
+ {\r
+ ctrl->value = sensor->info_priv.mirror;\r
+ break;\r
+ }\r
+ case V4L2_CID_VFLIP:\r
+ {\r
+ ctrl->value = sensor->info_priv.flip;\r
+ break;\r
+ }\r
+ default :\r
+ break;\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+\r
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct sensor *sensor = to_sensor(client);\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ const struct v4l2_queryctrl *qctrl;\r
+\r
+\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);\r
+\r
+ if (!qctrl)\r
+ {\r
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);\r
+ return -EINVAL;\r
+ }\r
+\r
+ switch (ctrl->id)\r
+ {\r
+#if CONFIG_SENSOR_Brightness\r
+ case V4L2_CID_BRIGHTNESS:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.brightness)\r
+ {\r
+ if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ sensor->info_priv.brightness = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Exposure\r
+ case V4L2_CID_EXPOSURE:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.exposure)\r
+ {\r
+ if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ sensor->info_priv.exposure = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Saturation\r
+ case V4L2_CID_SATURATION:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.saturation)\r
+ {\r
+ if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ sensor->info_priv.saturation = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Contrast\r
+ case V4L2_CID_CONTRAST:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.contrast)\r
+ {\r
+ if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ sensor->info_priv.contrast = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_WhiteBalance\r
+ case V4L2_CID_DO_WHITE_BALANCE:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.whiteBalance)\r
+ {\r
+ if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ sensor->info_priv.whiteBalance = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Mirror\r
+ case V4L2_CID_HFLIP:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.mirror)\r
+ {\r
+ if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.mirror = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Flip\r
+ case V4L2_CID_VFLIP:\r
+ {\r
+ if (ctrl->value != sensor->info_priv.flip)\r
+ {\r
+ if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.flip = ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return 0;\r
+}\r
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)\r
+{\r
+ const struct v4l2_queryctrl *qctrl;\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+ struct sensor *sensor = to_sensor(client);\r
+\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);\r
+\r
+ if (!qctrl)\r
+ {\r
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);\r
+ return -EINVAL;\r
+ }\r
+\r
+ switch (ext_ctrl->id)\r
+ {\r
+ case V4L2_CID_SCENE:\r
+ {\r
+ ext_ctrl->value = sensor->info_priv.scene;\r
+ break;\r
+ }\r
+ case V4L2_CID_EFFECT:\r
+ {\r
+ ext_ctrl->value = sensor->info_priv.effect;\r
+ break;\r
+ }\r
+ case V4L2_CID_ZOOM_ABSOLUTE:\r
+ {\r
+ ext_ctrl->value = sensor->info_priv.digitalzoom;\r
+ break;\r
+ }\r
+ case V4L2_CID_ZOOM_RELATIVE:\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ case V4L2_CID_FOCUS_ABSOLUTE:\r
+ {\r
+ ext_ctrl->value = sensor->info_priv.focus;\r
+ break;\r
+ }\r
+ case V4L2_CID_FOCUS_RELATIVE:\r
+ {\r
+ return -EINVAL;\r
+ }\r
+ case V4L2_CID_FLASH:\r
+ {\r
+ ext_ctrl->value = sensor->info_priv.flash;\r
+ break;\r
+ }\r
+ default :\r
+ break;\r
+ }\r
+ return 0;\r
+}\r
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)\r
+{\r
+ const struct v4l2_queryctrl *qctrl;\r
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));\r
+ struct sensor *sensor = to_sensor(client);\r
+ int val_offset;\r
+\r
+ qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);\r
+\r
+ if (!qctrl)\r
+ {\r
+ SENSOR_TR("\n %s ioctrl id = %d is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);\r
+ return -EINVAL;\r
+ }\r
+\r
+ val_offset = 0;\r
+ switch (ext_ctrl->id)\r
+ {\r
+#if CONFIG_SENSOR_Scene\r
+ case V4L2_CID_SCENE:\r
+ {\r
+ if (ext_ctrl->value != sensor->info_priv.scene)\r
+ {\r
+ if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.scene = ext_ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Effect\r
+ case V4L2_CID_EFFECT:\r
+ {\r
+ if (ext_ctrl->value != sensor->info_priv.effect)\r
+ {\r
+ if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.effect= ext_ctrl->value;\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_DigitalZoom\r
+ case V4L2_CID_ZOOM_ABSOLUTE:\r
+ {\r
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))\r
+ return -EINVAL;\r
+\r
+ if (ext_ctrl->value != sensor->info_priv.digitalzoom)\r
+ {\r
+ val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;\r
+\r
+ if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.digitalzoom += val_offset;\r
+\r
+ SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);\r
+ }\r
+\r
+ break;\r
+ }\r
+ case V4L2_CID_ZOOM_RELATIVE:\r
+ {\r
+ if (ext_ctrl->value)\r
+ {\r
+ if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.digitalzoom += ext_ctrl->value;\r
+\r
+ SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Focus\r
+ case V4L2_CID_FOCUS_ABSOLUTE:\r
+ {\r
+ if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))\r
+ return -EINVAL;\r
+\r
+ if (ext_ctrl->value != sensor->info_priv.focus)\r
+ {\r
+ val_offset = ext_ctrl->value -sensor->info_priv.focus;\r
+\r
+ sensor->info_priv.focus += val_offset;\r
+ }\r
+\r
+ break;\r
+ }\r
+ case V4L2_CID_FOCUS_RELATIVE:\r
+ {\r
+ if (ext_ctrl->value)\r
+ {\r
+ sensor->info_priv.focus += ext_ctrl->value;\r
+\r
+ SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);\r
+ }\r
+ break;\r
+ }\r
+#endif\r
+#if CONFIG_SENSOR_Flash\r
+ case V4L2_CID_FLASH:\r
+ {\r
+ if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)\r
+ return -EINVAL;\r
+ sensor->info_priv.flash = ext_ctrl->value;\r
+\r
+ SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);\r
+ break;\r
+ }\r
+#endif\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ int i, error_cnt=0, error_idx=-1;\r
+\r
+\r
+ for (i=0; i<ext_ctrl->count; i++) {\r
+ if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {\r
+ error_cnt++;\r
+ error_idx = i;\r
+ }\r
+ }\r
+\r
+ if (error_cnt > 1)\r
+ error_idx = ext_ctrl->count;\r
+\r
+ if (error_idx != -1) {\r
+ ext_ctrl->error_idx = error_idx;\r
+ return -EINVAL;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ int i, error_cnt=0, error_idx=-1;\r
+\r
+\r
+ for (i=0; i<ext_ctrl->count; i++) {\r
+ if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {\r
+ error_cnt++;\r
+ error_idx = i;\r
+ }\r
+ }\r
+\r
+ if (error_cnt > 1)\r
+ error_idx = ext_ctrl->count;\r
+\r
+ if (error_idx != -1) {\r
+ ext_ctrl->error_idx = error_idx;\r
+ return -EINVAL;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+/* Interface active, can use i2c. If it fails, it can indeed mean, that\r
+ * this wasn't our capture interface, so, we wait for the right one */\r
+static int sensor_video_probe(struct soc_camera_device *icd,\r
+ struct i2c_client *client)\r
+{\r
+ char value;\r
+ int ret,pid = 0;\r
+ struct sensor *sensor = to_sensor(client);\r
+\r
+ /* We must have a parent by now. And it cannot be a wrong one.\r
+ * So this entire test is completely redundant. */\r
+ if (!icd->dev.parent ||\r
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)\r
+ return -ENODEV;\r
+\r
+ if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {\r
+ ret = -ENODEV;\r
+ goto sensor_video_probe_err;\r
+ }\r
+#if 0\r
+ /* soft reset */\r
+ ret = sensor_write(client, 0x3012, 0x80);\r
+ if (ret != 0)\r
+ {\r
+ SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());\r
+ return -ENODEV;\r
+ }\r
+ mdelay(5); //delay 5 microseconds\r
+\r
+ /* check if it is an sensor sensor */\r
+ ret = sensor_read(client, 0x300a, &value);\r
+ if (ret != 0) {\r
+ SENSOR_TR("read chip id high byte failed\n");\r
+ ret = -ENODEV;\r
+ goto sensor_video_probe_err;\r
+ }\r
+\r
+ \r
+ ret = sensor_read(client, 0x01, &value);\r
+ if (ret != 0) {\r
+ SENSOR_TR("read chip id low byte failed\n");\r
+ ret = -ENODEV;\r
+ goto sensor_video_probe_err;\r
+ }\r
+\r
+ pid = (value & 0xff);\r
+ SENSOR_DG("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ if (pid == SENSOR_ID) {\r
+ sensor->model = SENSOR_V4L2_IDENT;\r
+ } else {\r
+ SENSOR_TR("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid);\r
+ ret = -ENODEV;\r
+ goto sensor_video_probe_err;\r
+ }\r
+#endif\r
+ icd->formats = sensor_colour_formats;\r
+ icd->num_formats = ARRAY_SIZE(sensor_colour_formats);\r
+\r
+ return 0;\r
+\r
+sensor_video_probe_err:\r
+\r
+ return ret;\r
+}\r
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)\r
+{\r
+ struct i2c_client *client = sd->priv;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ struct sensor *sensor = to_sensor(client);\r
+ int ret = 0;\r
+#if CONFIG_SENSOR_Flash \r
+ int i;\r
+#endif\r
+ \r
+ SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+ switch (cmd)\r
+ {\r
+ case RK29_CAM_SUBDEV_DEACTIVATE:\r
+ {\r
+ sensor_deactivate(client);\r
+ break;\r
+ }\r
+\r
+ case RK29_CAM_SUBDEV_IOREQUEST:\r
+ {\r
+ sensor->sensor_io_request = (struct rk29camera_platform_data*)arg; \r
+ if (sensor->sensor_io_request != NULL) { \r
+ if (sensor->sensor_io_request->gpio_res[0].dev_name && \r
+ (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {\r
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];\r
+ } else if (sensor->sensor_io_request->gpio_res[1].dev_name && \r
+ (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {\r
+ sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];\r
+ }\r
+ } else {\r
+ SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);\r
+ ret = -EINVAL;\r
+ goto sensor_ioctl_end;\r
+ }\r
+ /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control \r
+ for this project */\r
+ #if CONFIG_SENSOR_Flash \r
+ if (sensor->sensor_gpio_res) { \r
+ if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {\r
+ for (i = 0; i < icd->ops->num_controls; i++) {\r
+ if (V4L2_CID_FLASH == icd->ops->controls[i].id) {\r
+ memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl)); \r
+ }\r
+ }\r
+ sensor->info_priv.flash = 0xff;\r
+ SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());\r
+ }\r
+ }\r
+ #endif\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);\r
+ break;\r
+ }\r
+ }\r
+sensor_ioctl_end:\r
+ return ret;\r
+\r
+}\r
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {\r
+ .init = sensor_init,\r
+ .g_ctrl = sensor_g_control,\r
+ .s_ctrl = sensor_s_control,\r
+ .g_ext_ctrls = sensor_g_ext_controls,\r
+ .s_ext_ctrls = sensor_s_ext_controls,\r
+ .g_chip_ident = sensor_g_chip_ident,\r
+ .ioctl = sensor_ioctl,\r
+};\r
+\r
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {\r
+ .s_fmt = sensor_s_fmt,\r
+ .g_fmt = sensor_g_fmt,\r
+ .try_fmt = sensor_try_fmt,\r
+};\r
+\r
+static struct v4l2_subdev_ops sensor_subdev_ops = {\r
+ .core = &sensor_subdev_core_ops,\r
+ .video = &sensor_subdev_video_ops,\r
+};\r
+\r
+static int sensor_probe(struct i2c_client *client,\r
+ const struct i2c_device_id *did)\r
+{\r
+ struct sensor *sensor;\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);\r
+ struct soc_camera_link *icl;\r
+ int ret;\r
+\r
+ SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);\r
+ if (!icd) {\r
+ dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());\r
+ return -EINVAL;\r
+ }\r
+\r
+ icl = to_soc_camera_link(icd);\r
+ if (!icl) {\r
+ dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());\r
+ return -EINVAL;\r
+ }\r
+\r
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {\r
+ dev_warn(&adapter->dev,\r
+ "I2C-Adapter doesn't support I2C_FUNC_I2C\n");\r
+ return -EIO;\r
+ }\r
+\r
+ sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);\r
+ if (!sensor)\r
+ return -ENOMEM;\r
+\r
+ v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);\r
+\r
+ /* Second stage probe - when a capture adapter is there */\r
+ icd->ops = &sensor_ops;\r
+ icd->y_skip_top = 0;\r
+ #if CONFIG_SENSOR_I2C_NOSCHED\r
+ atomic_set(&sensor->tasklock_cnt,0);\r
+ #endif\r
+\r
+ ret = sensor_video_probe(icd, client);\r
+ if (ret < 0) {\r
+ icd->ops = NULL;\r
+ i2c_set_clientdata(client, NULL);\r
+ kfree(sensor);\r
+ sensor = NULL;\r
+ }\r
+ SENSOR_DG("\n%s..%s..%d ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);\r
+ return ret;\r
+}\r
+\r
+static int sensor_remove(struct i2c_client *client)\r
+{\r
+ struct sensor *sensor = to_sensor(client);\r
+ struct soc_camera_device *icd = client->dev.platform_data;\r
+\r
+ icd->ops = NULL;\r
+ i2c_set_clientdata(client, NULL);\r
+ client->driver = NULL;\r
+ kfree(sensor);\r
+ sensor = NULL;\r
+ return 0;\r
+}\r
+\r
+static const struct i2c_device_id sensor_id[] = {\r
+ {SENSOR_NAME_STRING(), 0 },\r
+ { }\r
+};\r
+MODULE_DEVICE_TABLE(i2c, sensor_id);\r
+\r
+static struct i2c_driver sensor_i2c_driver = {\r
+ .driver = {\r
+ .name = SENSOR_NAME_STRING(),\r
+ },\r
+ .probe = sensor_probe,\r
+ .remove = sensor_remove,\r
+ .id_table = sensor_id,\r
+};\r
+\r
+static int __init sensor_mod_init(void)\r
+{\r
+ SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());\r
+ return i2c_add_driver(&sensor_i2c_driver);\r
+}\r
+\r
+static void __exit sensor_mod_exit(void)\r
+{\r
+ i2c_del_driver(&sensor_i2c_driver);\r
+}\r
+\r
+device_initcall_sync(sensor_mod_init);\r
+module_exit(sensor_mod_exit);\r
+\r
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));\r
+MODULE_AUTHOR("ddl <kernel@rock-chips>");\r
+MODULE_LICENSE("GPL");
\ No newline at end of file
#define _GC_OBJ_ZONE gcvZONE_OS
-#define PAGE_ALLOC_LIMIT 1 // ÏÞÖÆPageÉêÇë
+#define PAGE_ALLOC_LIMIT 0 // ÏÞÖÆPageÉêÇë
#define PAGE_ALLOC_LIMIT_SIZE 0 // ÏÞÖÆPageÉêÇëµÄ´óС,µ¥Î»ÎªM
#if PAGE_ALLOC_LIMIT
V4L2_IDENT_GT2005 = 64100, /* ddl@rock-chips.com : GT2005 support */
V4L2_IDENT_GC0308 = 64101, /* ddl@rock-chips.com : GC0308 support */
- V4L2_IDENT_SIV120B = 64102, /* ddl@rock-chips.com : siv120b support */
+ V4L2_IDENT_GC0309 = 64102, /* ddl@rock-chips.com : GC0309 support */
+ V4L2_IDENT_SIV120B = 64103, /* ddl@rock-chips.com : siv120b support */
+
+ V4L2_IDENT_GC2015 = 64105, /* ddl@rock-chips.com : gc2015 support */
+ V4L2_IDENT_HI253 = 64106, /* ddl@rock-chips.com : hi253 support */
+ V4L2_IDENT_HI704 = 64107, /* ddl@rock-chips.com : hi704 support */
+ V4L2_IDENT_NT99250 = 64108, /* ddl@rock-chips.com : nt99250 support */
+ V4L2_IDENT_SID130B = 64109, /* ddl@rock-chips.com : sid130B support */
+
};
#endif
#define WM8900_LRC_MASK 0xfc00
#define SPK_CON RK29_PIN6_PB6
+#define WM8900_IS_SHUTDOWN 0
#define WM8900_IS_STARTUP 1
-#define WM8900_IS_SHUTDOWN 2
static void wm8900_work(struct work_struct *work);
sizeof(codec->reg_cache));
}
-static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static void wm8900_powerdown(void)
{
- struct snd_soc_codec *codec = w->codec;
- u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
-
- WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- /* Clamp headphone outputs */
- hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
- WM8900_REG_HPCTL1_HP_CLAMP_OP;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
- WM8900_DBG("Enter:%s, %d, HPCTL=0x%04X \n", __FUNCTION__, __LINE__, hpctl1);
- break;
-
- case SND_SOC_DAPM_POST_PMU:
- /* Enable the input stage */
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP;
- hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
- WM8900_REG_HPCTL1_HP_SHORT2 |
- WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
- msleep(400);
-
- /* Enable the output stage */
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
- hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
- /* Remove the shorts */
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
- WM8900_DBG("Enter:%s, %d, HPCTL=0x%04X \n", __FUNCTION__, __LINE__, hpctl1);
- break;
+ printk("Power down wm8900\n");
- case SND_SOC_DAPM_PRE_PMD:
- /* Short the output */
- hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
- /* Disable the output stage */
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
- /* Clamp the outputs and power down input */
- hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
- WM8900_REG_HPCTL1_HP_CLAMP_OP;
- hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
- snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
- WM8900_DBG("Enter:%s, %d, HPCTL=0x%04X \n", __FUNCTION__, __LINE__, hpctl1);
- break;
-
- case SND_SOC_DAPM_POST_PMD:
- /* Disable everything */
- snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
- WM8900_DBG("Enter:%s, %d, HPCTL=0x%04X \n", __FUNCTION__, __LINE__, hpctl1);
- break;
-
- default:
- BUG();
+ if (wm8900_current_status != WM8900_IS_SHUTDOWN) {
+#ifdef SPK_CON
+ gpio_set_value(SPK_CON, GPIO_LOW);
+#endif
+ msleep(20);
+ snd_soc_write(wm8900_codec, WM8900_REG_RESET, 0);
+ wm8900_current_status = WM8900_IS_SHUTDOWN;
}
-
- return 0;
-}
-
-static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0);
-
-static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0);
-
-static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0);
-
-static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0);
-
-static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
-
-static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
-
-static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0);
-
-static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
-
-static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
-
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
-
-static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
-
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
-
-static const char *dac_deemphasis_txt[] = {
- "Disabled", "32kHz", "44.1kHz", "48kHz"
-};
-
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
-
-static const char *adc_hpf_cut_txt[] = {
- "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
-};
-
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
-
-static const char *lr_txt[] = {
- "Left", "Right"
-};
-
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
-
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
-
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
-
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
-
-static const char *sidetone_txt[] = {
- "Disabled", "Left ADC", "Right ADC"
-};
-
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
-
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
-
-static const struct snd_kcontrol_new wm8900_snd_controls[] = {
-SOC_ENUM("Mic Bias Level", mic_bias_level),
-
-SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0,
- in_pga_tlv),
-SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1),
-SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0),
-
-SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0,
- in_pga_tlv),
-SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1),
-SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0),
-
-SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
-SOC_ENUM("DAC Mute Rate", dac_mute_rate),
-SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
-SOC_ENUM("DAC Deemphasis", dac_deemphasis),
-SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
- 12, 1, 0),
-
-SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0),
-SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut),
-SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0),
-SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0,
- adc_svol_tlv),
-SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0,
- adc_svol_tlv),
-SOC_ENUM("Left Digital Audio Source", aifl_src),
-SOC_ENUM("Right Digital Audio Source", aifr_src),
-
-SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0,
- dac_boost_tlv),
-SOC_ENUM("Left DAC Source", dacl_src),
-SOC_ENUM("Right DAC Source", dacr_src),
-SOC_ENUM("Left DAC Sidetone", dacl_sidetone),
-SOC_ENUM("Right DAC Sidetone", dacr_sidetone),
-SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0),
-
-SOC_DOUBLE_R_TLV("Digital Playback Volume",
- WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV,
- 1, 96, 0, dac_tlv),
-SOC_DOUBLE_R_TLV("Digital Capture Volume",
- WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv),
-
-SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0,
- out_mix_tlv),
-
-SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0,
- out_mix_tlv),
-SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0,
- out_mix_tlv),
-
-SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0,
- in_boost_tlv),
-SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0,
- in_boost_tlv),
-SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0,
- in_boost_tlv),
-SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0,
- in_boost_tlv),
-SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0,
- in_boost_tlv),
-SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0,
- in_boost_tlv),
-
-SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
- 0, 63, 0, out_pga_tlv),
-SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
- 6, 1, 1),
-SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
- 7, 1, 0),
-
-SOC_DOUBLE_R_TLV("LINEOUT2 Volume",
- WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL,
- 0, 63, 0, out_pga_tlv),
-SOC_DOUBLE_R("LINEOUT2 Switch",
- WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1),
-SOC_DOUBLE_R("LINEOUT2 ZC Switch",
- WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0),
-SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1,
- 0, 1, 1),
-
-};
-
-static const struct snd_kcontrol_new wm8900_dapm_loutput2_control[] = {
-SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0),};
-
-static const struct snd_kcontrol_new wm8900_dapm_routput2_control[] = {
-SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0),};
-
-static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {
-SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),
-SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),
-SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),
-SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),
-SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_routmix_controls[] = {
-SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0),
-SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0),
-SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0),
-SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0),
-SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_linmix_controls[] = {
-SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1),
-SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1),
-SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1),
-SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_rinmix_controls[] = {
-SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1),
-SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1),
-SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1),
-SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_linpga_controls[] = {
-SOC_SINGLE("MIC LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0),
-SOC_SINGLE("MIC LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0),
-SOC_SINGLE("MIC LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_rinpga_controls[] = {
-SOC_SINGLE("MIC RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0),
-SOC_SINGLE("MIC RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0),
-SOC_SINGLE("MIC RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new wm8900_inmix_controls[] = {
-SOC_SINGLE("LINPUT PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0),
-SOC_SINGLE("RINPUT PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0),
-};
-
-static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" };
-
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux);
-
-static const struct snd_kcontrol_new wm8900_lineout2_lp =
-SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
-
-static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
-
-/* Externally visible pins */
-SND_SOC_DAPM_OUTPUT("LINEOUT1L"),
-SND_SOC_DAPM_OUTPUT("LINEOUT1R"),
-SND_SOC_DAPM_OUTPUT("LINEOUT2L"),
-SND_SOC_DAPM_OUTPUT("LINEOUT2R"),
-SND_SOC_DAPM_OUTPUT("HP_L"),
-SND_SOC_DAPM_OUTPUT("HP_R"),
-
-SND_SOC_DAPM_INPUT("RINPUT1"),
-SND_SOC_DAPM_INPUT("LINPUT1"),
-SND_SOC_DAPM_INPUT("RINPUT2"),
-SND_SOC_DAPM_INPUT("LINPUT2"),
-SND_SOC_DAPM_INPUT("RINPUT3"),
-SND_SOC_DAPM_INPUT("LINPUT3"),
-SND_SOC_DAPM_INPUT("AUX"),
-
-SND_SOC_DAPM_VMID("VMID"),
-
-/* Input */
-SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0,
- wm8900_linpga_controls,
- ARRAY_SIZE(wm8900_linpga_controls)),
-SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0,
- wm8900_rinpga_controls,
- ARRAY_SIZE(wm8900_rinpga_controls)),
-
-SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0,
- wm8900_linmix_controls,
- ARRAY_SIZE(wm8900_linmix_controls)),
-SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
- wm8900_rinmix_controls,
- ARRAY_SIZE(wm8900_rinmix_controls)),
-
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
-
-SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
-SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
-
-/* Output */
-SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0),
-SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0),
-
-/*SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0,
- wm8900_hp_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),*/
-
-SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0),
-
-SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp),
-SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0),
-
-SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,
- wm8900_loutmix_controls,
- ARRAY_SIZE(wm8900_loutmix_controls)),
-SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
- wm8900_routmix_controls,
- ARRAY_SIZE(wm8900_routmix_controls)),
-};
-
-/* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
-/* Inputs */
-{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
-{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
-{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"},
-
-{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"},
-{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"},
-{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"},
-
-{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"},
-{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"},
-{"Left Input Mixer", "AUX Switch", "AUX"},
-{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"},
-
-{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"},
-{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"},
-{"Right Input Mixer", "AUX Switch", "AUX"},
-{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"},
-
-{"ADCL", NULL, "Left Input Mixer"},
-{"ADCR", NULL, "Right Input Mixer"},
-
-/* Outputs */
-{"LINEOUT1L", NULL, "LINEOUT1L PGA"},
-{"LINEOUT1L PGA", NULL, "Left Output Mixer"},
-{"LINEOUT1R", NULL, "LINEOUT1R PGA"},
-{"LINEOUT1R PGA", NULL, "Right Output Mixer"},
-
-{"LINEOUT2L PGA", NULL, "Left Output Mixer"},
-{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"},
-{"LINEOUT2 LP", "Enabled", "Left Output Mixer"},
-{"LINEOUT2L", NULL, "LINEOUT2 LP"},
-
-{"LINEOUT2R PGA", NULL, "Right Output Mixer"},
-{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"},
-{"LINEOUT2 LP", "Enabled", "Right Output Mixer"},
-{"LINEOUT2R", NULL, "LINEOUT2 LP"},
-
-{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"},
-{"Left Output Mixer", "AUX Bypass Switch", "AUX"},
-{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
-{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
-{"Left Output Mixer", "DACL Switch", "DACL"},
-
-{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"},
-{"Right Output Mixer", "AUX Bypass Switch", "AUX"},
-{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
-{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
-{"Right Output Mixer", "DACR Switch", "DACR"},
-
-/* Note that the headphone output stage needs to be connected
- * externally to LINEOUT2 via DC blocking capacitors. Other
- * configurations are not supported.
- *
- * Note also that left and right headphone paths are treated as a
- * mono path.
- */
-{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
-{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
-{"HP_L", NULL, "Headphone Amplifier"},
-{"HP_R", NULL, "Headphone Amplifier"},
-};
-
-static int wm8900_add_widgets(struct snd_soc_codec *codec)
-{
- WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
-
- snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets,
- ARRAY_SIZE(wm8900_dapm_widgets));
- snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_new_widgets(codec);
-
- return 0;
}
static void wm8900_work(struct work_struct *work)
{
- WM8900_DBG("Enter::wm8900 work, power down wm8900\n");
+ WM8900_DBG("Enter::wm8900_work\n");
-#ifdef SPK_CON
- gpio_set_value(SPK_CON, GPIO_LOW);
-#endif
- snd_soc_write(wm8900_codec, WM8900_REG_RESET, 0);
-
- wm8900_current_status = WM8900_IS_SHUTDOWN;
+ wm8900_powerdown();
}
static void wm8900_set_hw(struct snd_soc_codec *codec)
{
+ u16 reg;
+
WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+ //snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x140);
+ //snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x140);
+
snd_soc_write(codec, WM8900_REG_HPCTL1, 0x30);
snd_soc_write(codec, WM8900_REG_POWER1, 0x0100);
snd_soc_write(codec, WM8900_REG_POWER3, 0x60);
snd_soc_write(codec, WM8900_REG_ADDCTL, 0x02);
snd_soc_write(codec, WM8900_REG_POWER1, 0x09);
snd_soc_write(codec, WM8900_REG_POWER3, 0xEF);
- snd_soc_write(codec, WM8900_REG_DACCTRL, 0x00);
+ snd_soc_write(codec, WM8900_REG_DACCTRL, WM8900_REG_DACCTRL_MUTE);
snd_soc_write(codec, WM8900_REG_LOUTMIXCTL1, 0x150);
snd_soc_write(codec, WM8900_REG_ROUTMIXCTL1, 0x150);
snd_soc_write(codec, WM8900_REG_INBOOSTMIX2, 0x0042);
snd_soc_write(codec, WM8900_REG_ADCPATH, 0x0055);
+ reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
+
+ reg &= ~WM8900_REG_DACCTRL_MUTE;
+ snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
+
+ snd_soc_write(codec, WM8900_REG_LOUT1CTL, 0x130);
+ snd_soc_write(codec, WM8900_REG_ROUT1CTL, 0x130);
+
+ /* Turn up vol slowly, for HP out pop noise */
+
+ for (reg = 0; reg <= 0x33; reg += 0x10) {
+ snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x100 + reg);
+ snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x100 + reg);
+ msleep(5);
+ }
+ snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x133);
+ snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x133);
+
+ msleep(20);
+
#ifdef SPK_CON
gpio_set_value(SPK_CON, GPIO_HIGH);
#endif
static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- u16 reg;
-
WM8900_DBG("Enter:%s, %d , mute = %d \n", __FUNCTION__, __LINE__, mute);
- if (mute)
- return 0;
-
- reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
-
- reg &= ~WM8900_REG_DACCTRL_MUTE;
- snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
-
- /* Turn up vol slowly, for SPK out pop */
- for (reg = 0; reg <= 0x30; reg += 0x10) {
- if (snd_soc_read(codec, WM8900_REG_LOUT1CTL) < 0x30)
- snd_soc_write(codec, WM8900_REG_LOUT1CTL, 0x100 + reg);
-
- if (snd_soc_read(codec, WM8900_REG_ROUT1CTL) < 0x30)
- snd_soc_write(codec, WM8900_REG_ROUT1CTL, 0x100 + reg);
- }
- snd_soc_write(codec, WM8900_REG_LOUT1CTL, 0x130);
- snd_soc_write(codec, WM8900_REG_ROUT1CTL, 0x130);
-
- /* Turn up vol slowly, for HP out pop */
- for (reg = 0; reg <= 0x33; reg += 0x10) {
- if (snd_soc_read(codec, WM8900_REG_LOUT2CTL) < 0x33)
- snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x100 + reg);
-
- if (snd_soc_read(codec, WM8900_REG_ROUT2CTL) < 0x33)
- snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x100 + reg);
- }
- snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x133);
- snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x133);
-
return 0;
}
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->card->codec;
WM8900_DBG("Enter::%s----%d substream->stream:%s \n",__FUNCTION__,__LINE__,
substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
- if (!(codec_dai->playback.active || codec_dai->capture.active)) {
+ cancel_delayed_work_sync(&delayed_work);
- cancel_delayed_work_sync(&delayed_work);
-
- if (wm8900_current_status & WM8900_IS_STARTUP)
- return 0;
+ if (wm8900_current_status == WM8900_IS_SHUTDOWN) {
- WM8900_DBG("Power up wm8900\n");
+ printk("Power up wm8900\n");
wm8900_set_hw(codec);
wm8900_current_status |= WM8900_IS_STARTUP;
}
static void wm8900_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai_link *machine = rtd->dai;
WM8900_DBG("Is going to power down wm8900\n");
- queue_delayed_work(wm8900_workq, &delayed_work,
- msecs_to_jiffies(3000));
+ /* If codec is useless, queue work to close it */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ queue_delayed_work(wm8900_workq, &delayed_work,
+ msecs_to_jiffies(1000));
+ } else {
+ queue_delayed_work(wm8900_workq, &delayed_work,
+ msecs_to_jiffies(3000));
+ }
}
}
break;
}
-
codec->bias_level = level;
return 0;
}
WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
- snd_soc_write(codec, WM8900_REG_RESET, 0);
+ cancel_delayed_work_sync(&delayed_work);
+
+ wm8900_powerdown();
/* Stop the FLL in an orderly fashion */
ret = wm8900_set_fll(codec, 0, 0, 0);
void wm8900_i2c_shutdown(struct i2c_client *client)
{
WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
- snd_soc_write(wm8900_codec, WM8900_REG_RESET, 0);
+ wm8900_powerdown();
}
#ifdef CONFIG_PM
dev_err(&pdev->dev, "I2C client not yet instantiated\n");
return -ENODEV;
}
+
#if defined(SPK_CON)
gpio_request(SPK_CON,NULL);
gpio_direction_output(SPK_CON, GPIO_LOW);
goto pcm_err;
}
- snd_soc_add_controls(codec, wm8900_snd_controls,
- ARRAY_SIZE(wm8900_snd_controls));
- snd_soc_add_controls(codec, wm8900_linpga_controls,
- ARRAY_SIZE(wm8900_linpga_controls));
- snd_soc_add_controls(codec, wm8900_rinpga_controls,
- ARRAY_SIZE(wm8900_rinpga_controls));
- snd_soc_add_controls(codec, wm8900_inmix_controls,
- ARRAY_SIZE(wm8900_inmix_controls));
-
- wm8900_add_widgets(codec);
-
ret = snd_soc_init_card(socdev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register card\n");