From 971e2b441247db5f613975bc1d33f8379c6ce189 Mon Sep 17 00:00:00 2001 From: zyc Date: Wed, 25 Sep 2013 17:13:06 +0800 Subject: [PATCH] camera : add icatch 7002 isp driver --- .../board-rk3188-icatch7002-camera.c | 333 +++ arch/arm/plat-rk/include/plat/rk_camera.h | 26 +- arch/arm/plat-rk/rk_camera.c | 14 +- drivers/media/video/Kconfig | 8 + drivers/media/video/Makefile | 2 +- drivers/media/video/generic_sensor.c | 49 +- drivers/media/video/generic_sensor.h | 47 +- drivers/media/video/icatch7002/Kconfig | 15 + drivers/media/video/icatch7002/Makefile | 10 + .../video/icatch7002/app_i2c_lib_icatch.c | 2298 +++++++++++++++ .../video/icatch7002/app_i2c_lib_icatch.h | 451 +++ .../icatch7002/burn_spi_sample_code_0910.c | 1247 ++++++++ .../video/icatch7002/icatch7002_common.c | 2548 +++++++++++++++++ .../video/icatch7002/icatch7002_common.h | 211 ++ .../video/icatch7002/icatch7002_mi1040.c | 629 ++++ .../video/icatch7002/icatch7002_ov5693.c | 638 +++++ .../media/video/icatch7002/icatch_spi_host.c | 82 + .../media/video/icatch7002/icatch_spi_host.h | 23 + drivers/media/video/rk30_camera_pingpong.c | 1063 ++++--- drivers/media/video/v4l2-ioctl.c | 2 +- include/linux/videodev2.h | 12 + include/media/v4l2-chip-ident.h | 3 +- 22 files changed, 9340 insertions(+), 371 deletions(-) create mode 100755 arch/arm/mach-rk3188/board-rk3188-icatch7002-camera.c create mode 100755 drivers/media/video/icatch7002/Kconfig create mode 100755 drivers/media/video/icatch7002/Makefile create mode 100755 drivers/media/video/icatch7002/app_i2c_lib_icatch.c create mode 100755 drivers/media/video/icatch7002/app_i2c_lib_icatch.h create mode 100755 drivers/media/video/icatch7002/burn_spi_sample_code_0910.c create mode 100755 drivers/media/video/icatch7002/icatch7002_common.c create mode 100755 drivers/media/video/icatch7002/icatch7002_common.h create mode 100755 drivers/media/video/icatch7002/icatch7002_mi1040.c create mode 100755 drivers/media/video/icatch7002/icatch7002_ov5693.c create mode 100755 drivers/media/video/icatch7002/icatch_spi_host.c create mode 100755 drivers/media/video/icatch7002/icatch_spi_host.h diff --git a/arch/arm/mach-rk3188/board-rk3188-icatch7002-camera.c b/arch/arm/mach-rk3188/board-rk3188-icatch7002-camera.c new file mode 100755 index 000000000000..34e382805abd --- /dev/null +++ b/arch/arm/mach-rk3188/board-rk3188-icatch7002-camera.c @@ -0,0 +1,333 @@ +#ifdef CONFIG_VIDEO_RK29 +#include +#include "../../../drivers/spi/rk29_spim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct spi_device* g_icatch_spi_dev = NULL; + + +static struct rk29xx_spi_chip spi_icatch = { + //.poll_mode = 1, + .enable_dma = 0, +}; +//user must define this struct according to hardware config +static struct spi_board_info board_spi_icatch_devices[] = { + { + .modalias = "spi_icatch", + .bus_num = 0, //0 or 1 + .max_speed_hz = 24*1000*1000, + .chip_select = 0, + .mode = SPI_MODE_0, + .controller_data = &spi_icatch, + }, + +}; + + +static int __devinit spi_icatch_probe(struct spi_device *spi) +{ + struct spi_test_data *spi_test_data; + int ret = 0; + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0){ + dev_err(spi, "ERR: fail to setup spi\n"); + return -1; + } + + g_icatch_spi_dev = spi; + + printk("%s:bus_num=%d,ok\n",__func__,spi->master->bus_num); + + return ret; + +} + + +static struct spi_driver spi_icatch_driver = { + .driver = { + .name = "spi_icatch", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = spi_icatch_probe, +}; + +static struct miscdevice spi_test_icatch = { + .minor = MISC_DYNAMIC_MINOR, + .name = "spi_misc_icatch", +}; + +static int __init spi_icatch_init(void) +{ + spi_register_board_info(board_spi_icatch_devices, ARRAY_SIZE(board_spi_icatch_devices)); + + misc_register(&spi_test_icatch); + return spi_register_driver(&spi_icatch_driver); +} + +static void __exit spi_icatch_exit(void) +{ + + misc_deregister(&spi_test_icatch); + return spi_unregister_driver(&spi_icatch_driver); +} + +module_init(spi_icatch_init); +module_exit(spi_icatch_exit); + +/* Notes: + +Simple camera device registration: + + new_camera_device(sensor_name,\ // sensor name, it is equal to CONFIG_SENSOR_X + face,\ // sensor face information, it can be back or front + pwdn_io,\ // power down gpio configuration, it is equal to CONFIG_SENSOR_POWERDN_PIN_XX + flash_attach,\ // sensor is attach flash or not + mir,\ // sensor image mirror and flip control information + i2c_chl,\ // i2c channel which the sensor attached in hardware, it is equal to CONFIG_SENSOR_IIC_ADAPTER_ID_X + cif_chl) \ // cif channel which the sensor attached in hardware, it is equal to CONFIG_SENSOR_CIF_INDEX_X + +Comprehensive camera device registration: + + new_camera_device_ex(sensor_name,\ + face,\ + ori,\ // sensor orientation, it is equal to CONFIG_SENSOR_ORIENTATION_X + pwr_io,\ // sensor power gpio configuration, it is equal to CONFIG_SENSOR_POWER_PIN_XX + pwr_active,\ // sensor power active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + rst_io,\ // sensor reset gpio configuration, it is equal to CONFIG_SENSOR_RESET_PIN_XX + rst_active,\ // sensor reset active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + pwdn_io,\ + pwdn_active,\ // sensor power down active level, is equal to CONFIG_SENSOR_POWERDNACTIVE_LEVEL_X + flash_attach,\ + res,\ // sensor resolution, this is real resolution or resoltuion after interpolate + mir,\ + i2c_chl,\ + i2c_spd,\ // i2c speed , 100000 = 100KHz + i2c_addr,\ // the i2c slave device address for sensor + cif_chl,\ + mclk)\ // sensor input clock rate, 24 or 48 + +*/ +static struct rkcamera_platform_data new_camera[] = { + new_camera_device_ex(RK29_CAM_ISP_ICATCH7002_OV5693, + back, + 180, // sensor orientation, it is equal to CONFIG_SENSOR_ORIENTATION_X + INVALID_VALUE, // sensor power gpio configuration, it is equal to CONFIG_SENSOR_POWER_PIN_XX + INVALID_VALUE, // sensor power active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + RK30_PIN0_PC1, // sensor reset gpio configuration, it is equal to CONFIG_SENSOR_RESET_PIN_XX + 0x0, // sensor reset active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + RK30_PIN0_PC0, + 0x1, // sensor power down active level, is equal to CONFIG_SENSOR_POWERDNACTIVE_LEVEL_X + INVALID_VALUE, + CONS(RK29_CAM_ISP_ICATCH7002_OV5693,_FULL_RESOLUTION), // sensor resolution, this is real resolution or resoltuion after interpolate + 0, + 3, + 300000, // i2c speed , 100000 = 100KHz + CONS(RK29_CAM_ISP_ICATCH7002_OV5693,_I2C_ADDR), // the i2c slave device address for sensor + 0, + 24), // sensor input clock rate, 24 or 48 + new_camera_device_ex(RK29_CAM_ISP_ICATCH7002_MI1040, //RK29_CAM_ISP_ICATCH7002_MI1040, + front, + 360, // sensor orientation, it is equal to CONFIG_SENSOR_ORIENTATION_X + INVALID_VALUE, // sensor power gpio configuration, it is equal to CONFIG_SENSOR_POWER_PIN_XX + INVALID_VALUE, // sensor power active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + RK30_PIN0_PC1, // sensor reset gpio configuration, it is equal to CONFIG_SENSOR_RESET_PIN_XX + 0x0, // sensor reset active level, is equal to CONFIG_SENSOR_RESETACTIVE_LEVEL_X + RK30_PIN0_PC0, + 0x1, // sensor power down active level, is equal to CONFIG_SENSOR_POWERDNACTIVE_LEVEL_X + INVALID_VALUE, + CONS(RK29_CAM_ISP_ICATCH7002_MI1040,_FULL_RESOLUTION), // sensor resolution, this is real resolution or resoltuion after interpolate + 0, + 3, + 300000, // i2c speed , 100000 = 100KHz + CONS(RK29_CAM_ISP_ICATCH7002_MI1040,_I2C_ADDR), // the i2c slave device address for sensor + 0, + 24), // sensor input clock rate, 24 or 48 + new_camera_device_end +}; +#endif //#ifdef CONFIG_VIDEO_RK29 +/*---------------- Camera Sensor Configuration Macro End------------------------*/ +#include "../../../drivers/media/video/rk30_camera.c" +/*---------------- Camera Sensor Macro Define End ---------*/ + +#define PMEM_CAM_SIZE PMEM_CAM_NECESSARY +/***************************************************************************************** + * camera devices + * author: ddl@rock-chips.com + *****************************************************************************************/ +#ifdef CONFIG_VIDEO_RK29 +#define CONFIG_SENSOR_POWER_IOCTL_USR 1 //define this refer to your board layout +#define CONFIG_SENSOR_RESET_IOCTL_USR 1 +#define CONFIG_SENSOR_POWERDOWN_IOCTL_USR 0 +#define CONFIG_SENSOR_FLASH_IOCTL_USR 0 + +static void rk_cif_power(struct rk29camera_gpio_res *res,int on) +{ + struct regulator *ldo_18,*ldo_28; + int camera_reset = res->gpio_reset; + int camera_pwrdn = res->gpio_powerdown; + + + ldo_28 = regulator_get(NULL, "ricoh_ldo8"); // vcc28_cif + ldo_18 = regulator_get(NULL, "ricoh_ldo5"); // vcc18_cif + if (ldo_28 == NULL || IS_ERR(ldo_28) || ldo_18 == NULL || IS_ERR(ldo_18)){ + printk("get cif ldo failed!\n"); + return; + } + if(on == 0){ + while(regulator_is_enabled(ldo_28)>0) + regulator_disable(ldo_28); + regulator_put(ldo_28); + + while(regulator_is_enabled(ldo_18)>0) + regulator_disable(ldo_18); + + iomux_set(GPIO1_A4); + iomux_set(GPIO1_A5) ; + iomux_set(GPIO1_A6); + iomux_set(GPIO1_A7); + iomux_set(GPIO3_B6); + iomux_set(GPIO3_B7); + iomux_set(GPIO0_C0); + gpio_set_value(RK30_PIN1_PA4,0); + gpio_set_value(RK30_PIN1_PA5,0); + gpio_set_value(RK30_PIN1_PA6,0); //Vincent_Liu@asus.com for clk 24M + gpio_set_value(RK30_PIN1_PA7,0); + gpio_set_value(RK30_PIN3_PB6,0); + gpio_set_value(RK30_PIN3_PB7,0); + gpio_set_value(RK30_PIN0_PC0,0); + + printk("%s off ldo5 vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_18)); + regulator_put(ldo_18); + + } + else{ + // reset must be low + if (camera_reset != INVALID_GPIO) + gpio_set_value(camera_reset, 0); + printk("%s ResetPin=%d ..PinLevel = %x\n",res->dev_name,camera_reset,0); + //pwdn musb be low + if (camera_pwrdn != INVALID_GPIO) + gpio_set_value(camera_pwrdn, 0); + printk("%s PwrdnPin=%d ..PinLevel = %x\n",res->dev_name,camera_pwrdn,0); + + gpio_set_value(RK30_PIN1_PA6,1); //Vincent_Liu@asus.com for clk 24M + + + regulator_set_voltage(ldo_18, 1800000, 1800000); + regulator_enable(ldo_18); + printk("%s set ldo5 vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_18)); + regulator_put(ldo_18); + + regulator_set_voltage(ldo_28, 2800000, 2800000); + regulator_enable(ldo_28); + //printk("%s set ldo7 vcc28_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_28)); + regulator_put(ldo_28); + + } +} + +#if CONFIG_SENSOR_RESET_IOCTL_USR +static int sensor_reset_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + //#error "CONFIG_SENSOR_RESET_IOCTL_USR is 1, sensor_reset_usr_cb function must be writed!!"; + + int camera_reset = res->gpio_reset; + int camera_ioflag = res->gpio_flag; + int camera_io_init = res->gpio_init; + int ret = 0; + + if (camera_reset != INVALID_GPIO) { + if (camera_io_init & RK29_CAM_RESETACTIVE_MASK) { + if (on) { + gpio_set_value(camera_reset, ((camera_ioflag&RK29_CAM_RESETACTIVE_MASK)>>RK29_CAM_RESETACTIVE_BITPOS)); + printk("%s ResetPin=%d ..PinLevel = %x\n",res->dev_name,camera_reset, ((camera_ioflag&RK29_CAM_RESETACTIVE_MASK)>>RK29_CAM_RESETACTIVE_BITPOS)); + mdelay(6); + } else { + gpio_set_value(camera_reset,(((~camera_ioflag)&RK29_CAM_RESETACTIVE_MASK)>>RK29_CAM_RESETACTIVE_BITPOS)); + printk("%s ResetPin= %d..PinLevel = %x\n",res->dev_name, camera_reset, (((~camera_ioflag)&RK29_CAM_RESETACTIVE_MASK)>>RK29_CAM_RESETACTIVE_BITPOS)); + mdelay(6); + iomux_set(SPI0_CLK); + iomux_set(SPI0_RXD); + iomux_set(SPI0_TXD); + iomux_set(SPI0_CS0); + iomux_set(I2C3_SDA); + iomux_set(I2C3_SCL); + mdelay(6); + } + } else { + ret = RK29_CAM_EIO_REQUESTFAIL; + printk("%s ResetPin=%d request failed!", res->dev_name,camera_reset); + } + } else { + ret = RK29_CAM_EIO_INVALID; + } + return ret; + +} +#endif + +#if CONFIG_SENSOR_POWER_IOCTL_USR +static int sensor_power_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + //#error "CONFIG_SENSOR_POWER_IOCTL_USR is 1, sensor_power_usr_cb function must be writed!!"; + rk_cif_power(res,on); + return 0; +} +#endif + +#if CONFIG_SENSOR_FLASH_IOCTL_USR +static int sensor_flash_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + #error "CONFIG_SENSOR_FLASH_IOCTL_USR is 1, sensor_flash_usr_cb function must be writed!!"; +} +#endif + +static struct rk29camera_platform_ioctl_cb sensor_ioctl_cb = { + #if CONFIG_SENSOR_POWER_IOCTL_USR + .sensor_power_cb = sensor_power_usr_cb, + #else + .sensor_power_cb = NULL, + #endif + + #if CONFIG_SENSOR_RESET_IOCTL_USR + .sensor_reset_cb = sensor_reset_usr_cb, + #else + .sensor_reset_cb = NULL, + #endif + + #if CONFIG_SENSOR_POWERDOWN_IOCTL_USR + .sensor_powerdown_cb = sensor_powerdown_usr_cb, + #else + .sensor_powerdown_cb = NULL, + #endif + + #if CONFIG_SENSOR_FLASH_IOCTL_USR + .sensor_flash_cb = sensor_flash_usr_cb, + #else + .sensor_flash_cb = NULL, + #endif +}; +static rk_sensor_user_init_data_s rk_init_data_sensor[RK_CAM_NUM] ; +#include "../../../drivers/media/video/rk30_camera.c" + +#endif /* CONFIG_VIDEO_RK29 */ diff --git a/arch/arm/plat-rk/include/plat/rk_camera.h b/arch/arm/plat-rk/include/plat/rk_camera.h index 5db427ae4209..cd349c8a759e 100755 --- a/arch/arm/plat-rk/include/plat/rk_camera.h +++ b/arch/arm/plat-rk/include/plat/rk_camera.h @@ -257,7 +257,8 @@ #define RK29_CAM_SENSOR_NT99240 nt99240 //oyyf@rock-chips.com #define RK29_CAM_SENSOR_NT99252 nt99252 //oyyf@rock-chips.com #define RK29_CAM_SENSOR_NT99340 nt99340 //oyyf@rock-chips.com - +#define RK29_CAM_ISP_ICATCH7002_MI1040 icatchmi1040 +#define RK29_CAM_ISP_ICATCH7002_OV5693 icatchov5693 #define RK29_CAM_SENSOR_NAME_OV7675 "ov7675" #define RK29_CAM_SENSOR_NAME_OV9650 "ov9650" @@ -295,6 +296,8 @@ #define RK29_CAM_ISP_NAME_MTK9335ISP "mtk9335isp" #define RK29_CAM_SENSOR_NAME_HM2057 "hm2057" #define RK29_CAM_SENSOR_NAME_HM5065 "hm5065" +#define RK29_CAM_ISP_NAME_ICATCH7002_MI1040 "icatchmi1040" +#define RK29_CAM_ISP_NAME_ICATCH7002_OV5693 "icatchov5693" //Sensor full resolution define #define ov7675_FULL_RESOLUTION 0x30000 // 0.3 megapixel @@ -357,7 +360,8 @@ #define nt99240_FULL_RESOLUTION 0x200000 // oyyf@rock-chips.com: 2 megapixel 1600*1200 #define nt99252_FULL_RESOLUTION 0x200000 // oyyf@rock-chips.com: 2 megapixel 1600*1200 #define nt99340_FULL_RESOLUTION 0x300000 // oyyf@rock-chips.com: 3 megapixel 2048*1536 - +#define icatchmi1040_FULL_RESOLUTION 0x200000 +#define icatchov5693_FULL_RESOLUTION 0x500000 #define end_FULL_RESOLUTION 0x00 //Sensor i2c addr define @@ -410,6 +414,8 @@ #define mtk9335isp_I2C_ADDR 0x50 #define hm2057_I2C_ADDR 0x48 #define hm5065_I2C_ADDR 0x3e +#define icatchmi1040_I2C_ADDR 0x78 +#define icatchov5693_I2C_ADDR 0x78 #define end_I2C_ADDR INVALID_VALUE @@ -538,6 +544,13 @@ SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWRDN,0)|\ SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,3)) #define mtk9335isp_PWRSEQ sensor_PWRSEQ_DEFAULT +#define icatchov5693_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\ + SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\ + SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1)) +#define icatchmi1040_PWRSEQ (SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_PWR,0)|\ + SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_HWRST,2)|\ + SENSOR_PWRSEQ_SET(SENSOR_PWRSEQ_CLKIN,1)) + #define end_PWRSEQ 0xffffffff @@ -587,6 +600,15 @@ #define Sensor_CropSet(a,b) a->reserved[1] = b; #define Sensor_CropGet(a) a->reserved[1] +#define RK29_CAM_SUBDEV_HDR_EXPOSURE 0x04 + +#define RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1 0x00 +#define RK_VIDEOBUF_HDR_EXPOSURE_NORMAL 0x01 +#define RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1 0x02 +#define RK_VIDEOBUF_HDR_EXPOSURE_FINISH 0x03 +#define RK_VIDEOBUF_CODE_SET(rk_code,type) rk_code = (('R'<<24)|('K'<<16)|type) +#define RK_VIDEOBUF_CODE_CHK(rk_code) ((rk_code&(('R'<<24)|('K'<<16)))==(('R'<<24)|('K'<<16))) + enum rk29camera_ioctrl_cmd { Cam_Power, diff --git a/arch/arm/plat-rk/rk_camera.c b/arch/arm/plat-rk/rk_camera.c index c301bae3e35d..cca0240d13a4 100755 --- a/arch/arm/plat-rk/rk_camera.c +++ b/arch/arm/plat-rk/rk_camera.c @@ -271,8 +271,10 @@ * 2. Reduce delay time after power off or power down camera; *v0.1.5: * 1. if sensor power callback failed, power down sensor; +*v0.1.6: + 1. when power down,HWRST just need to set to powerdown mode. */ -static int camio_version = KERNEL_VERSION(0,1,5); +static int camio_version = KERNEL_VERSION(0,1,6); module_param(camio_version, int, S_IRUGO); @@ -1491,9 +1493,13 @@ static int rk_sensor_pwrseq(struct device *dev,int powerup_sequence, int on, int case SENSOR_PWRSEQ_HWRST: { - ret = rk_sensor_ioctrl(dev,Cam_Reset, 1); - msleep(2); - ret |= rk_sensor_ioctrl(dev,Cam_Reset, 0); + if(!on){ + rk_sensor_ioctrl(dev,Cam_Reset, 1); + }else{ + ret = rk_sensor_ioctrl(dev,Cam_Reset, 1); + msleep(2); + ret |= rk_sensor_ioctrl(dev,Cam_Reset, 0); + } if (ret<0) { eprintk("SENSOR_PWRSEQ_HWRST failed"); } else { diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 0f10c615d09a..3c76616d6d92 100755 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1205,6 +1205,14 @@ config SOC_CAMERA_MV9335 MtekVision camera isp chip source "drivers/media/video/mv9335/Kconfig" +config SOC_CAMERA_ICATCH7002 + tristate "Icatch camera isp chip" + depends on SOC_CAMERA && I2C + default n + help + Icatch camera isp chip + +source "drivers/media/video/icatch7002/Kconfig" config VIDEO_RK29 tristate "RKXX Camera Sensor Interface driver" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index d84dc4db0580..f3b5433da7b4 100755 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -126,7 +126,7 @@ obj-$(CONFIG_SOC_CAMERA_S5K5CA) += s5k5ca.o obj-$(CONFIG_SOC_CAMERA_HM2057) += hm2057.o obj-$(CONFIG_SOC_CAMERA_HM5065) += hm5065.o obj-$(CONFIG_SOC_CAMERA_MV9335) += mv9335/ - +obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += icatch7002/ # And now the v4l2 drivers: obj-$(CONFIG_VIDEO_BT848) += bt8xx/ diff --git a/drivers/media/video/generic_sensor.c b/drivers/media/video/generic_sensor.c index 4928e6d05986..681fd9f2c05f 100755 --- a/drivers/media/video/generic_sensor.c +++ b/drivers/media/video/generic_sensor.c @@ -31,8 +31,10 @@ * 3. support cropcap; *v.0.1.c: * 1. modify generic_sensor_s_fmt, flash will work everytime when capture +*v.0.1.d: + 1. add some callbacks for icatch */ -static int version = KERNEL_VERSION(0,1,0xc); +static int version = KERNEL_VERSION(0,1,0xd); module_param(version, int, S_IRUGO); @@ -951,6 +953,9 @@ int generic_sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl) struct i2c_client *client = v4l2_get_subdevdata(sd); struct generic_sensor *sensor = to_generic_sensor(client); struct sensor_v4l2ctrl_info_s *ctrl_info; + struct v4l2_ext_control ext_ctrl; + struct soc_camera_device *icd = client->dev.platform_data; + int ret = 0; ctrl_info = sensor_find_ctrl(sensor->ctrls,ctrl->id); @@ -958,7 +963,19 @@ int generic_sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl) SENSOR_TR("v4l2_control id(0x%x) is invalidate",ctrl->id); ret = -EINVAL; } else { + ext_ctrl.value = ctrl->value; + ext_ctrl.id = ctrl->id; + ctrl->value = ctrl_info->cur_value; + + if (ctrl_info->cb) { + ret = (ctrl_info->cb)(icd,ctrl_info, &ext_ctrl,false); + if(ret == 0) + ctrl->value = ctrl_info->cur_value; + } else { + SENSOR_TR("v4l2_control id(0x%x) callback isn't exist",ctrl->id); + ret = -EINVAL; + } } return ret; @@ -983,7 +1000,7 @@ int generic_sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ext_ctrl.value = ctrl->value; if (ctrl_info->cb) { - ret = (ctrl_info->cb)(icd,ctrl_info, &ext_ctrl); + ret = (ctrl_info->cb)(icd,ctrl_info, &ext_ctrl,true); } else { SENSOR_TR("v4l2_control id(0x%x) callback isn't exist",ctrl->id); ret = -EINVAL; @@ -1006,6 +1023,13 @@ int generic_sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext ret = -EINVAL; } else { ext_ctrl->value = ctrl_info->cur_value; + if (ctrl_info->cb) { + ret = (ctrl_info->cb)(icd,ctrl_info, ext_ctrl,false); + } else { + SENSOR_TR("v4l2_control id(0x%x) callback isn't exist",ext_ctrl->id); + ret = -EINVAL; + } + } return ret; @@ -1024,7 +1048,7 @@ int generic_sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_ ret = -EINVAL; } else { if (ctrl_info->cb) { - ret = (ctrl_info->cb)(icd,ctrl_info, ext_ctrl); + ret = (ctrl_info->cb)(icd,ctrl_info, ext_ctrl,true); } else { SENSOR_TR("v4l2_ext_control id(0x%x) callback isn't exist",ext_ctrl->id); ret = -EINVAL; @@ -1387,6 +1411,9 @@ int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable) SENSOR_DG("s_stream: %d %d",enable,sensor->sensor_focus.focus_state); if (enable == 1) { + if(sensor->sensor_cb.sensor_s_stream_cb){ + sensor->sensor_cb.sensor_s_stream_cb(sd,enable); + } sensor->info_priv.stream = true; if (sensor->sensor_focus.sensor_wq) { if (sensor->sensor_focus.focus_state == FocusState_Inval) { @@ -1395,6 +1422,10 @@ int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable) } } else if (enable == 0) { sensor->info_priv.stream = false; + if(sensor->sensor_cb.sensor_s_stream_cb){ + sensor->sensor_cb.sensor_s_stream_cb(sd,enable); + } + if (sensor->sensor_focus.sensor_wq) flush_workqueue(sensor->sensor_focus.sensor_wq); @@ -1402,3 +1433,15 @@ int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable) return 0; } +int generic_sensor_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize){ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct generic_sensor *sensor = to_generic_sensor(client); + + if(sensor->sensor_cb.sensor_enum_framesizes){ + return sensor->sensor_cb.sensor_enum_framesizes(sd,fsize); + }else{ + return -1; + } + +} + diff --git a/drivers/media/video/generic_sensor.h b/drivers/media/video/generic_sensor.h index b31814eba3e3..65a4cd55b611 100755 --- a/drivers/media/video/generic_sensor.h +++ b/drivers/media/video/generic_sensor.h @@ -209,7 +209,7 @@ typedef struct rk_sensor_priv_s struct sensor_v4l2ctrl_info_s { struct v4l2_queryctrl *qctrl; int (*cb)(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl); + struct v4l2_ext_control *ext_ctrl,bool is_set); struct rk_sensor_reg **sensor_Seqe; int cur_value; int num_ctrls; @@ -218,7 +218,7 @@ struct sensor_v4l2ctrl_info_s { struct sensor_v4l2ctrl_usr_s { struct v4l2_queryctrl qctrl; int (*cb)(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl); + struct v4l2_ext_control *ext_ctrl,bool is_set); struct rk_sensor_reg **sensor_Seqe; }; @@ -234,6 +234,9 @@ struct sensor_ops_cb_s{ int (*sensor_s_fmt_cb_th)(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture); int (*sensor_s_fmt_cb_bh)(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture); int (*sensor_try_fmt_cb_th)(struct i2c_client *client,struct v4l2_mbus_framefmt *mf); + int (*sensor_s_stream_cb)(struct v4l2_subdev *sd, int enable); + int (*sensor_enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); + }; //flash off in fixed time to prevent from too hot , zyc struct rk_flash_timer{ @@ -300,6 +303,7 @@ extern int generic_sensor_af_workqueue_set(struct soc_camera_device *icd, enum r extern int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable); extern int generic_sensor_writebuf(struct i2c_client *client, char *buf, int buf_size); extern int generic_sensor_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cc); +extern int generic_sensor_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); static inline int sensor_get_full_width_height(int full_resolution, unsigned short *w, unsigned short *h) { @@ -404,7 +408,7 @@ static inline void sensor_v4l2ctrl_info_init (struct sensor_v4l2ctrl_info_s *ptr int step, int default_val, int(*cb)(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl), + struct v4l2_ext_control *ext_ctrl,bool is_set), struct rk_sensor_reg ** sensor_seqe ) { @@ -469,11 +473,15 @@ static inline int sensor_v4l2ctrl_replace_cb(struct generic_sensor *sensor, int } static inline int sensor_v4l2ctrl_default_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) + struct v4l2_ext_control *ext_ctrl,bool is_set) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int value = ext_ctrl->value; int index; + + if(!is_set){ + return 0; + } if ((value < ctrl_info->qctrl->minimum) || (value > ctrl_info->qctrl->maximum)) { printk(KERN_ERR "%s(%d): value(0x%x) isn't between in (0x%x,0x%x)\n",__FUNCTION__,__LINE__,value, @@ -496,7 +504,7 @@ static inline int sensor_v4l2ctrl_default_cb(struct soc_camera_device *icd, stru } } static inline int sensor_v4l2ctrl_flash_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) + struct v4l2_ext_control *ext_ctrl,bool is_set) { //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int value = ext_ctrl->value; @@ -518,7 +526,7 @@ static inline int sensor_v4l2ctrl_flash_cb(struct soc_camera_device *icd, struct return 0; } static inline int sensor_focus_default_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) + struct v4l2_ext_control *ext_ctrl,bool is_set) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int value = ext_ctrl->value; @@ -530,7 +538,7 @@ static inline int sensor_focus_default_cb(struct soc_camera_device *icd, struct ctrl_info->qctrl->minimum,ctrl_info->qctrl->maximum); return -EINVAL; } - + if(sensor->sensor_focus.focus_state == FocusState_Inval){ printk(KERN_ERR "%s(%d): focus have not been init success yet\n",__FUNCTION__,__LINE__); //set focus delay @@ -653,7 +661,7 @@ static inline int sensor_focus_default_cb(struct soc_camera_device *icd, struct } static inline int sensor_face_detect_default_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, - struct v4l2_ext_control *ext_ctrl) + struct v4l2_ext_control *ext_ctrl,bool is_set) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int value = ext_ctrl->value; @@ -672,6 +680,24 @@ static inline int sensor_face_detect_default_cb(struct soc_camera_device *icd, s } return ret; } +static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl); +static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl); + +static inline int sensor_v4l2ctrl_mirror_default_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl,bool is_set){ + return sensor_v4l2ctrl_mirror_cb(icd,ctrl_info, ext_ctrl); + + +} +static inline int sensor_v4l2ctrl_flip_default_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl,bool is_set){ + return sensor_v4l2ctrl_flip_cb(icd,ctrl_info, ext_ctrl); + + +} + #define new_user_v4l2ctrl(ctl_id,ctl_type,ctl_name,ctl_min,ctl_max,ctl_step,default_val,callback,seqe)\ {\ .qctrl = {\ @@ -1026,14 +1052,14 @@ static inline int sensor_face_detect_default_cb(struct soc_camera_device *icd, s } \ if (CFG_FunChk(sensor_config,CFG_Mirror)) { \ sensor_v4l2ctrl_info_init(ctrls,V4L2_CID_HFLIP,V4L2_CTRL_TYPE_BOOLEAN, \ - "Mirror Control",0,1,1,0,sensor_v4l2ctrl_mirror_cb,NULL); \ + "Mirror Control",0,1,1,0,sensor_v4l2ctrl_mirror_default_cb,NULL); \ controls++; \ ctrls++; \ } \ if (CFG_FunChk(sensor_config,CFG_Flip)) { \ ctrls->qctrl = controls; \ sensor_v4l2ctrl_info_init(ctrls,V4L2_CID_VFLIP,V4L2_CTRL_TYPE_BOOLEAN, \ - "Flip Control",0,1,1,0,sensor_v4l2ctrl_flip_cb,NULL); \ + "Flip Control",0,1,1,0,sensor_v4l2ctrl_flip_default_cb,NULL); \ controls++; \ ctrls++; \ } \ @@ -1196,6 +1222,7 @@ static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {\ .enum_mbus_fmt = generic_sensor_enum_fmt,\ .enum_frameintervals = generic_sensor_enum_frameintervals,\ .s_stream = generic_sensor_s_stream,\ + .enum_framesizes = generic_sensor_enum_framesizes,\ };\ static struct v4l2_subdev_ops sensor_subdev_ops = {\ .core = &sensor_subdev_core_ops,\ diff --git a/drivers/media/video/icatch7002/Kconfig b/drivers/media/video/icatch7002/Kconfig new file mode 100755 index 000000000000..4d0fa334a536 --- /dev/null +++ b/drivers/media/video/icatch7002/Kconfig @@ -0,0 +1,15 @@ +# +# Fujitsu camera isp chip: m6moj. +# +config ICATCH7002_OV5693 + depends on SOC_CAMERA_ICATCH7002 + tristate "icatch7002 attached ov5693" + default n + help + Choose Y here if you have this this sensor and it is attach to icatch7002 +config ICATCH7002_MI1040 + depends on SOC_CAMERA_ICATCH7002 + tristate "icatch7002 attached mi1040" + default n + help + Choose Y here if you have this this sensor and it is attach to icatch7002 diff --git a/drivers/media/video/icatch7002/Makefile b/drivers/media/video/icatch7002/Makefile new file mode 100755 index 000000000000..0377415935fb --- /dev/null +++ b/drivers/media/video/icatch7002/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for icatch isp driver +# +obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += icatch7002_common.o +#obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += icatch_spi_host.o +obj-$(CONFIG_ICATCH7002_MI1040) += icatch7002_mi1040.o +obj-$(CONFIG_ICATCH7002_OV5693) += icatch7002_ov5693.o +obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += burn_spi_sample_code_0910.o +obj-$(CONFIG_SOC_CAMERA_ICATCH7002) += app_i2c_lib_icatch.o + diff --git a/drivers/media/video/icatch7002/app_i2c_lib_icatch.c b/drivers/media/video/icatch7002/app_i2c_lib_icatch.c new file mode 100755 index 000000000000..c85a1784662f --- /dev/null +++ b/drivers/media/video/icatch7002/app_i2c_lib_icatch.c @@ -0,0 +1,2298 @@ +/**************************************************************************** + * + * Copyright (c) 2006-2008 by Sunplus mMedia Inc., Ltd. + * + * This software is copyrighted by and is the property of Sunplus + * mMedia Inc., Ltd. All rights are reserved by Sunplus mMedia + * Inc., Ltd. This software may only be used in accordance with the + * corresponding license agreement. Any unauthorized use, duplication, + * distribution, or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of Sunplus mMedia Inc., Ltd. + * + * Sunplus mMedia Inc., Ltd. reserves the right to modify this + * software without notice. + * + * Sunplus mMedia Inc., Ltd. + * 19-1, Innovation First Road, Science-Based Industrial Park, + * Hsin-Chu, Taiwan, R.O.C. + * + ****************************************************************************/ +#include +#include + +#include "app_i2c_lib_icatch.h" +#include +#include "icatch7002_common.h" + +#define I2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) +#define I2CDataRead(reg) icatch_sensor_read((reg)) +extern struct spi_device* g_icatch_spi_dev; + +/**************************************************************************** + * C O N S T A N T S * + ****************************************************************************/ +#define FW_HEADER_SIZE 16 +#define RES_3ACALI_HEADER_SIZE 8 +#define RES_LSC_HEADER_SIZE 24 +#define RES_LSCDQ_HEADER_SIZE 16 + +/**************************************************************************** + * M A C R O S * + ****************************************************************************/ +#ifndef tmrUsDelay +#define tmrUsDelay(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) +#endif +/**************************************************************************** + * D A T A T Y P E S * + ****************************************************************************/ + +/**************************************************************************** + * G L O B A L D A T A * + ****************************************************************************/ + +/**************************************************************************** + * E X T E R N A L R E F E R E N C E S * + ****************************************************************************/ + +/**************************************************************************** + * F U N C T I O N D E C L A R A T I O N S * + ****************************************************************************/ + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_BandSelectionSet + * ucParam: + 0x00 Reserved + 0x01 50 + 0x02 60 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_BandSelectionSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_BANDING_SELECTION, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ColorEffectSet + * ucParam: + 0x00 Normal + 0x01 Aqua + 0x02 Negative + 0x03 Sepia + 0x04 Grayscale + 0x05 Vivid + 0x06 Aura + 0x07 Vintage + 0x08 Vintage2 + 0x09 Lomo + 0x0A Red + 0x0B Blue + 0x0C Green + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_ColorEffectSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_COLOR_EFFECT, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_EvSet + * ucParam: + 0x00 +2.0 + 0x01 +1.7 + 0x02 +1.3 + 0x03 +1.0 + 0x04 +0.7 + 0x05 +0.3 + 0x06 0 + 0x07 -0.3 + 0x08 -0.7 + 0x09 -1.0 + 0x0A -1.3 + 0x0B -1.7 + 0x0C -2.0 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_EvSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_EV_COMPENSATION, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_FlashModeSet + * ucParam: + 0x00 Auto + 0x01 Off + 0x02 On + 0x03 Reserved + 0x04 Torch + 0xFF Main Flash(100%, once) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_FlashModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_FLASH_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_FocusModeSet + * ucParam: + 0x00 Auto + 0x01 Macro + 0x02 Infinity Fixed + 0x03 Continuous AF + 0x04 Full Search + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_FocusModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_FOCUS_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvSizeSet + * ucParam: + 0x00 1280x960 + 0x01 3264x2448 + 0x02 1920x1080 + 0x03 320x240(reserved) + 0x04 1280x720 + 0x05 1040x780 + 0x06 2080x1560 + 0x07 3648x2736 + 0x08 4160x3120 + 0x09 3360x1890 + 0x0A 2592x1944 + 0x0B 640x480 + 0x0C 1408x1408 + 0x0D 1920x1088 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvSizeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_PV_SIZE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_SceneModeSet + * ucParam: + 0x00 Normal + 0x01 Action + 0x02 Text + 0x03 Beach + 0x04 Candle light + 0x05 Firework + 0x06 Landscape + 0x07 Night + 0x08 Night Portrait + 0x09 Party + 0x0A Portrait + 0x0B Snow + 0x0C Sport + 0x0D Anti-shake + 0x0E Sunset + 0x0F High Sensitivity + 0x10 Landscape Portrait + 0x11 Kids + 0x12 Pet + 0x13 Flower + 0x14 Soft Flowing Water + 0x15 Food + 0x16 Backlight + 0x17 Indoor + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_SceneModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_SCENE_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_WhiteBalanceSet + * ucParam: + 0x00 Auto + 0x01 Daylight + 0x02 Cloudy + 0x03 Shade + 0x04 Fluorescent_L + 0x05 Fluorescent_H + 0x06 Tungsten + 0x07 Reserved + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_WhiteBalanceSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_WHITE_BALANCE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AEModeSet + * ucParam: + 0x00 Multi + 0x01 Center + 0x02 Spot + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AEModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_AE_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CapModeSet + * ucParam: + 0x00 Single + 0x01 HDR + 0x02 Reserved + 0x03 Burst capture(Unlimited)(ZSL) + 0x04 Burst capture(Unlimited)(mode switch) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CapModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CAP_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ISOSet + * ucParam: + 0x00 Auto + 0x01 ISO 50 + 0x02 ISO 100 + 0x03 ISO 200 + 0x04 ISO 400 + 0x05 ISO 800 + 0x06 ISO 1600 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_ISOSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CAP_ISO, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AuraColorIndexSet + * ucParam : Color index (bit control) + Effect bit : bit 0~5 + 1 : Color enable + 0 : Color disable + bit 0 : Red + bit 1 : Orange + bit 2 : Yellow + bit 3 : Green + bit 4 : Blue + bit 5 : Violet + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AuraColorIndexSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_AURA_COLOR_INDEX, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_OpticalZoomSet + * ucParam: + 0x00 Zoom in + 0x01 Zoom out + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_OpticalZoomSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_OPTICAL_ZOOM, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_IspFuncSet + * ucParam: Function control (bit control) + Effect bit : bit 0~1 + 1 : function enable + 0 : function disable + bit 0 : DWDR + bit 1 : Edge information + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_IspFuncSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_ISP_FUNCTION, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvCapModeSet + * ucParam: + 0x00 Preview mode + 0x01 Capture mode(mode switch) + 0x02 Capture mode(ZSL) + 0x03 Capture mode(Non-ZSL) + 0x04 Idle mode + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvCapModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_PV_CAP_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvStreamSet + * ucParam: + 0x00 Stream off + 0x01 Stream on + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvStreamSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_PV_STREAM, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_BurstAbortSet + * ucParam: + 0x00 Burst abort(mode switch) + 0x01 Burst abort(ZSL) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_BurstAbortSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_BURST_ABORT, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CapEdgeQuantitySet + * ucValue: + Max = 100 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CapEdgeQuantitySet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_CAP_EDGE_QUANTITY, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvFixFrameRateSet + * ucValue : + 0x00 Disable Fix Frame Rate function + 0x01~0xFF : Frame Rate + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvFixFrameRateSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_PV_FIX_FRAME_RATE, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvMaxExposureTimeSet + * ucValue : 1/N + N=0 : Disable Max. Exposure Time function + N=0x01~0xFF : Max. Exposure time + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvMaxExposureTimeSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_PV_MAX_EXPTIME, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_HdrPositiveEvSet + * ucValue: 2.4bits + eg. +1.5EV : 0x15 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_HdrPositiveEvSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_HDR_POSITIVE_EV, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_HdrNegativeEvSet + * ucValue: 2.4bits + eg. -0.4EV : 0x04 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_HdrNegativeEvSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_HDR_NEGATIVE_EV, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvMinISOSet + * ucParam: + 0x00 Disable + 0x01 ISO 50 + 0x02 ISO 100 + 0x03 ISO 200 + 0x04 ISO 400 + 0x05 ISO 800 + 0x06 ISO 1600 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_PvMinISOSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_PV_MIN_ISO, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_GSensorInfoSet + * ucX: G sensor information X axis + ucY: G sensor information Y axis + ucZ: G sensor information Z axis + Value: ((-32.768~32.767)*1000)>>8 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_GSensorInfoSet(SINT8 ucX, SINT8 ucY, SINT8 ucZ) +{ + I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_X, ucX); + I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_Y, ucY); + I2CDataWrite(SP7K_MSG_G_SENSOR_INFO_Z, ucZ); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_GyroInfoSet + * ucX: Gyro information X axis + ucY: Gyro information Y axis + ucZ: Gyro information Z axis + Value: ((Radian : 0~2£k)*1000)>>8 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_GyroInfoSet(UINT8 ucX, UINT8 ucY, UINT8 ucZ) +{ + I2CDataWrite(SP7K_MSG_GYRO_INFO_X, ucX); + I2CDataWrite(SP7K_MSG_GYRO_INFO_Y, ucY); + I2CDataWrite(SP7K_MSG_GYRO_INFO_Z, ucZ); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFROISet + * usSize: AF ROI size + usX: AF ROI x + usY: AF ROI y + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AFROISet(UINT16 usSize, UINT16 usX, UINT16 usY) +{ + I2CDataWrite(SP7K_MSG_AF_ROI_SIZE_H, (usSize>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AF_ROI_SIZE_L, usSize&0x00FF); + I2CDataWrite(SP7K_MSG_AF_ROI_X_H, (usX>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AF_ROI_X_L, usX&0x00FF); + I2CDataWrite(SP7K_MSG_AF_ROI_Y_H, (usY>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AF_ROI_Y_L, usY&0x00FF); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFROITriggerSet + * Input : None + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AFROITriggerSet(void) +{ + I2CDataWrite(SP7K_MSG_AF_ROI_TRIGGER, 0x01); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AEROISet + * usSize: AE ROI size + usX: AE ROI x + usY: AE ROI y + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AEROISet(UINT16 usSize, UINT16 usX, UINT16 usY) +{ + I2CDataWrite(SP7K_MSG_AE_ROI_SIZE_H, (usSize>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AE_ROI_SIZE_L, usSize&0x00FF); + I2CDataWrite(SP7K_MSG_AE_ROI_X_H, (usX>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AE_ROI_X_L, usX&0x00FF); + I2CDataWrite(SP7K_MSG_AE_ROI_Y_H, (usY>>8)&0x00FF); + I2CDataWrite(SP7K_MSG_AE_ROI_Y_L, usY&0x00FF); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AEROITriggerSet + * ucParam: + 0x00 TAE off + 0x01 TAE on (Use TAE ROI : 0x48~0x4D) + 0x02 TAE on (Use TAF ROI : 0x40~0x45) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AEROITriggerSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_AE_ROI_TRIGGER, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFAbortSet + * ucParam: + 0x00 AF abort and go to infinity + 0x01 AF abort and stop in the current position + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AFAbortSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_AF_ABORT, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VcmStepSet + * usValue : VCM step value (0~1023) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VcmStepSet(UINT16 usValue) +{ + I2CDataWrite(SP7K_MSG_VCM_STEP_L, usValue&0x00FF); + I2CDataWrite(SP7K_MSG_VCM_STEP_H, (usValue>>8)&0x00FF); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CapEdgeInfoSet + * ucParam: + 0x00 None + 0x01 Ask for capture edge + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CapEdgeInfoSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CAP_EDGE_INFO, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_RawPathSet + * ucParam: + 0x00 After Front + 0x01 After WB + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_RawPathSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_RAW_PATH, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_RawFormatSet + * ucParam: + 0x00 RAW8 + 0x01 RAW10 + 0x02 RAW12 + 0x03 YUV8 + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_RawFormatSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_RAW_FORMAT, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawLinearSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawLinearSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_LINEAR, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawObSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawObSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_OB, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawBpSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawBpSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_BP, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawLscSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawLscSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_LSC, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawCaSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawCaSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_CA, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawArdSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawArdSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_ARD, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawDepeakSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawDepeakSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_DEPEAK, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationRawWbSet + * ucParam: + 0x00 Off + 0x01 On + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationRawWbSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_RAW_WB, ucParam); +} + +/*------------------------------------------------------------------------- + * File Name : EXISP_I2C_CalibrationAwbCriteriaSet + * ucVaule: 1~100, default 10% + * return none + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationAwbCriteriaSet(UINT8 ucVaule) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_AWB_CRITERIA, ucVaule); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AEAWBThreadModeSet + * ucParam: + 0x00 AE/AWB thread off + 0x01 AE/AWB thread on + 0x02 AWB thread off + 0x03 AWB thread on + 0x04 AE thread off + 0x05 AE thread on + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_AEAWBThreadModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_AEAWBTHREAD_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_DqModeSet + * ucParam: + 0x00 Pause on + 0x01 Pause off + 0x02 Interpolation Off + 0x03 Interpolation On + 0x04 Fix Color Temperature On + 0x05 Fix Color Temperature Off + 0x06 Fix ISO On(Reserved) + 0x07 Fix ISO Off(Reserved) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_DqModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_DQ_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CdspOnOffModeSet + * ucParam: + 0x00 CDSP all block off + 0x01 CDSP all block recovery + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CdspOnOffModeSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CDSP_MODE, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationCmd1Set + * ucParam: + bit 0 : Reserved + bit 1 : OB calibration(Reserved) + bit 2 : WB calibration + bit 3 : AF calibration(Reserved) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationCmd1Set(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_CMD1, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationCmd2Set + * ucParam: + bit 0 : LSC_D50 calibration + bit 1 : LSC_A calibration + bit 2 : LSC_CW calibration + bit 3 : LSC_TL84 calibration + bit 4 : LSC_D65 calibration + bit 5 : LSC_H calibration + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationCmd2Set(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_CMD2, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationInitCmdSet + * ucParam: + bit 0, 1: Calibration data target + 0x01 HOST + 0x02 EEPROM + 0x03 SPI + bit 2, 3: Band selection + 0x00 50Hz + 0x04 60Hz + bit 4, 5: LSC compression method + 0x00 Differential + 0x10 Non-compression + bit 6, 7: LSC table number + 0x00 4 table + 0x40 5 table + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationInitCmdSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_INIT_CMD, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationLscMaxGainSet + * ucVaule : 6.2bits + Range : 0x00~0xFF + 0x01 0.25% + 0x02 0.50% + 0x03 0.75% + 0xFF 63.75% + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationLscMaxGainSet(UINT8 ucVaule) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_LENS_MAX_LUM_DECAY, ucVaule); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationDqIndexFixSet + * ucParam: + bit 0~3: Color Temperature Index + 0x00 LSC off + 0x01 SPI flash is 1MB to load golden LSC & LSC_DQ table, auto + 0x02 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix A light table + 0x03 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix TL84 table + 0x04 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix CW table + 0x05 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix D50 table + 0x06 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix D65 table + 0x07 SPI flash is 1MB to load golden LSC & LSC_DQ table, fix H table + bit 4~7: ISO index(0~5) (Reserved) + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CalibrationDqIndexFixSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_DQ_INDEX_FIX, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CaliUtilizationOptionSet + * ucParam: + bit 0: Rear Camera(3ACALI) + 0 : Use Calubration data(default) + 1 : Use Golden data + bit 1: Rear Camera(LSC) + 0 : Use Calubration data(default) + 1 : Use Golden data + bit 2: Front Camera(3ACALI) + 0 : Use Calubration data(default) + 1 : Use Golden data + bit 3: Front Camera(LSC) + 0 : Use Calubration data(default) + 1 : Use Golden data + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_CaliUtilizationOptionSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_CALIBRATION_UTILIZATION_OPTION, ucParam); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ROISwitchSet + * ucParam: + 0x00 ROI off + 0x01 ROI on + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_ROISwitchSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_ROI_SWITCH, ucParam); +} + + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqIdSet + * ucValue: vendor command ID + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqIdSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_ID, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqParamSet + * ucValue: vendor command parameter + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqParamSet(UINT8 ucValue) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_PARAM, ucValue); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqValuesSet_L + * ucVaule: vendor command the low byte of value + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqValuesSet_L(UINT8 ucVaule) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_VALUES_L, ucVaule); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqProcessSet + * Input : None + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqProcessSet(void) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_PROCESS, 0x00); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqValuesSet_H + * ucVaule: vendor command the high byte of value + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqValuesSet_H(UINT8 ucVaule) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_VALUES_H, ucVaule); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendreqCmdSet + * ucParam: + 0x00 Reserved + 0x01 Reserved + 0x02 Reserved + 0x03 AE lock + 0x04 AWB lock + 0x05 AE unlock + 0x06 AWB unlock + * Return : None + *------------------------------------------------------------------------*/ +void EXISP_I2C_VendreqCmdSet(UINT8 ucParam) +{ + I2CDataWrite(SP7K_MSG_VENDREQ_CMD, ucParam); +} + + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFStatusGet + * Input : None + * Return : AF status + 0x00 Idle + 0x01 Busy + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_AFStatusGet(void) +{ + return I2CDataRead(SP7K_RDREG_AF_STATUS); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFResultGet + * Input : None + * Return : AF result + 0x00 Focus success + 0x01 Focus fail + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_AFResultGet(void) +{ + return I2CDataRead(SP7K_RDREG_AF_RESULT); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_AFConsumeTimeGet + * Input : None + * Return : AF consuming time (ms) + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_AFConsumeTimeGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_AF_CONSUME_TIME_H)<<8) | + I2CDataRead(SP7K_RDREG_AF_CONSUME_TIME_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VcmCurrentPosGet + * Input : None + * Return : VCM current position (Range 0~1023) + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_VcmCurrentPosGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_VCM_CURRENT_POS_H)<<8) | + I2CDataRead(SP7K_RDREG_VCM_CURRENT_POS_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ExposureTimeNumeratorGet + * Input : None + * Return : exposure time numerator + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_ExposureTimeNumeratorGet(void) +{ + return I2CDataRead(SP7K_RDREG_EXPTIME_NUMERATOR); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ExposureTimeDenominatorGet + * Input : None + * Return : exposure time denominator + *------------------------------------------------------------------------*/ +UINT32 EXISP_I2C_ExposureTimeDenominatorGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_H)<<16) | + (I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_M)<<8) | + I2CDataRead(SP7K_RDREG_EXPTIME_DENOMINATOR_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ExposureTimeCompensationGet + * Input : None + * Return : exposure time compensation + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_ExposureTimeCompensationGet(void) +{ + return I2CDataRead(SP7K_RDREG_EXPTIME_COMPENSATION); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_LensFocalLengthGet + * Input : None + * Return : lens focal length + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_LensFocalLengthGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_LENS_FOCAL_LENGTH_H)<<8) | + I2CDataRead(SP7K_RDREG_LENS_FOCAL_LENGTH_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_ISOValueGet + * Input : None + * Return : ISO value + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_ISOValueGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_ISO_H)<<8) | + I2CDataRead(SP7K_RDREG_ISO_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_FlashModeGet + * Input : None + * Return : flash mode + 0x00 Flash off + 0x01 Flash on + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_FlashModeGet(void) +{ + return I2CDataRead(SP7K_RDREG_FLASH_MODE); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CapEdgeInfoGet + * Input : None + * Return : capture edge information + *------------------------------------------------------------------------*/ +UINT32 EXISP_I2C_CapEdgeInfoGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B3)<<24) | + (I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B2)<<16) | + (I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B1)<<8) | + I2CDataRead(SP7K_RDREG_CAP_EDGE_INFO_B0)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_3AStatusGet + * Input : None + * Return : 3A status + bit 0: AE ready bit + 0 : AE not ready + 1 : AE ready + bit 1: AWB ready bit + 0 : AWB not ready + 1 : AWB ready + bit 2: flash info + 0 : Do not flash fire + 1 : Do flash fire + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_3AStatusGet(void) +{ + return I2CDataRead(SP7K_RDREG_3A_STATUS); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_EdgeInfoCountGet + * Input : None + * Return : edge information count + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_EdgeInfoCountGet(void) +{ + return I2CDataRead(SP7K_RDREG_EDGE_INFO_COUNT); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_RearSensorIdGet + * Input : None + * Return : rear sensor id + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_RearSensorIdGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_REAR_SENSORID_H)<<8) | + I2CDataRead(SP7K_RDREG_REAR_SENSORID_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_FrontSensorIdGet + * Input : None + * Return : front sensor id + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_FrontSensorIdGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_FRONT_SENSORID_H)<<8) | + I2CDataRead(SP7K_RDREG_FRONT_SENSORID_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_FWVersionGet + * Input : None + * Return : FW version + *------------------------------------------------------------------------*/ +UINT32 EXISP_I2C_FWVersionGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_FW_VER_H)<<16) | + (I2CDataRead(SP7K_RDREG_FW_VER_M)<<8) | + I2CDataRead(SP7K_RDREG_FW_VER_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_VendorIdGet + * Input : None + * Return : vendor ID (0x7002) + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_VendorIdGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_VENDOR_ID_H)<<8) | + I2CDataRead(SP7K_RDREG_VENDOR_ID_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationLscMaxRGainGet + * Input : None + * Return : the max R gain after LSC calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationLscMaxRGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationLscMaxGGainGet + * Input : None + * Return : the max G gain after LSC calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationLscMaxGGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationLscMaxBGainGet + * Input : None + * Return : the max B gain after LSC calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationLscMaxBGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationAWBRGainGet + * Input : None + * Return : the R gain after AWB calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationAWBRGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_RGain_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_RGain_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationAWBGGainGet + * Input : None + * Return : the G gain after AWB calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationAWBGGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_GGain_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_GGain_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationAWBBGainGet + * Input : None + * Return : the B gain after AWB calibration + *------------------------------------------------------------------------*/ +UINT16 EXISP_I2C_CalibrationAWBBGainGet(void) +{ + return ((I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_BGain_H)<<8) | + I2CDataRead(SP7K_RDREG_CALIBRATION_AWB_BGain_L)); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationExecStatus1Get + * Input : None + * Return : OB/WB/AF calibration execution status + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationExecStatus1Get(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_EXEC_STATUS1); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationExecStatus2Get + * Input : None + * Return : LSC_D50/LSC_A/LSC_CW/LSC_TL84/LSC_D65/LSC_H calibration execution status + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationExecStatus2Get(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_EXEC_STATUS2); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationErrorStatus1Get + * Input : None + * Return : OB/WB/AF calibration error status + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationErrorStatus1Get(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_STATUS1); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationErrorStatus2Get + * Input : None + * Return : LSC_D50/LSC_A/LSC_CW/LSC_TL84/LSC_D65/LSC_H calibration error status + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationErrorStatus2Get(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_STATUS2); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationErrorCodeGet + * Input : None + * Return : calibration error code + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationErrorCodeGet(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_ERROR_CODE); +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_CalibrationLoadTableStatusGet + * Input : None + * Return : load table status + *------------------------------------------------------------------------*/ +UINT8 EXISP_I2C_CalibrationLoadTableStatusGet(void) +{ + return I2CDataRead(SP7K_RDREG_CALIBRATION_LOAD_TABLE_STATUS); +} + + +/*------------------------------------------------------------------------- + * Function Name : EXISP_SuspendGpioCfgSet + * Description : Suspend GPIO configuration + * ucCtl: + 0x00 GPIO_CTL_LOW(GPIO pull low) + 0x01 GPIO_CTL_HIGH(GPIO pull high) + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_SuspendGpioCfgSet(UINT8 ucCtl) +{ + UINT8 ucRet = SUCCESS; + + if (ucCtl >= GPIO_CTL_MAX) { + ucRet = FAIL; + return ucRet; + } + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_DigitalPowerCfgSet + * Description : Provide digital power to external ISP + On: + 0x00 Close + 0x01 Open + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_DigitalPowerCfgSet(UINT8 On) +{ + UINT8 ucRet = SUCCESS; + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_AnalogPowerCfgSet + * Description : Provide analog power to external ISP + On: + 0x00 Close + 0x01 Open + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_AnalogPowerCfgSet(UINT8 On) +{ + UINT8 ucRet = SUCCESS; + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ClockCfgSet + * Description : Provide clock or not to external ISP + ucEnable: + 0x00 Don't provide clock + 0x01 Provide clock + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ClockCfgSet(UINT8 ucEnable) +{ + UINT8 ucRet = SUCCESS; + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ResetGpioCfgSet + * Description : Reset GPIO configuration + * ucCtl: + 0x00 GPIO_CTL_LOW(GPIO pull low) + 0x01 GPIO_CTL_HIGH(GPIO pull high) + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ResetGpioCfgSet(UINT8 ucCtl) +{ + UINT8 ucRet = SUCCESS; + + if (ucCtl >= GPIO_CTL_MAX) { + ucRet = FAIL; + return ucRet; + } + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_PowerOn + * Description : Power on external ISP + * ucBoot: + 0x00 BOOT_FROM_SPI(Boot from SPI) + 0x01 BOOT_FROM_HOST(Boot from host) + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_PowerOn(UINT8 ucBoot) +{ + UINT8 ucRet = SUCCESS; + + /* 1. Open digital power, 1.2V */ + ucRet = EXISP_DigitalPowerCfgSet(0x01); /* 2. Open analog power, 1.8V and 2.8V */ + ucRet = EXISP_AnalogPowerCfgSet(0x01); + /* 3. Open clock */ + ucRet = EXISP_ClockCfgSet(0x01); + /* 4. Suspend GPIO configuration */ + if (ucBoot == BOOT_FROM_SPI) { + ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_HIGH); + } + else if (ucBoot == BOOT_FROM_HOST) { + ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_LOW); + } + else { + ucRet = FAIL; + return ucRet; + } + /* 5. Reset GPIO configuration */ + ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_LOW); + /* Delay 10ms */ + tmrUsDelay(10000); + /* 6. Reset GPIO configuration */ + ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_HIGH); + /* Delay 16ms */ + tmrUsDelay(16000); + /* 7. Suspend GPIO configuration for boot from SPI */ + if (ucBoot == BOOT_FROM_SPI) { + ucRet = EXISP_SuspendGpioCfgSet(GPIO_CTL_LOW); + } + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_PowerOff + * Description : Power off external ISP + * Input : None + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_PowerOff(void) +{ + UINT8 ucRet = SUCCESS; + + /* 1. Reset GPIO configuration */ + ucRet = EXISP_ResetGpioCfgSet(GPIO_CTL_LOW); + /* 2. Close clock */ + ucRet = EXISP_ClockCfgSet(0x00); + /* 3. Close analog power, 2.8V and 1.8V */ + ucRet = EXISP_AnalogPowerCfgSet(0x00); + /* 4. Close digital power, 1.2V */ + ucRet = EXISP_DigitalPowerCfgSet(0x00); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_LoadCodeStart + * Description : Load code start + * ucBoot: + 0x00 BOOT_FROM_SPI(Boot from SPI) + 0x01 BOOT_FROM_HOST(Boot from host) + ucFwIdx: Set which FW will be loaded + is_calibration: calibration flag, calibration:1 normal:0 + *pIspFw: external ISP FW pointer + *pCalibOpt: read from calibration_option.BIN + *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN + *pLsc: read from LSC.BIN or LSC_F.BIN + *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_LoadCodeStart( + UINT8 ucBoot, + UINT8 ucFwIdx, + UINT8 is_calibration, + UINT8 *pIspFw, + UINT8 *pCalibOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq) +{ + UINT8 ucRet = SUCCESS; + + if (ucBoot >= BOOT_FROM_MAX || ucFwIdx > 2) { + ucRet = FAIL; return ucRet; + } + + DEBUG_TRACE("@@@ISP FW: Load Code Start\n"); + if (ucBoot == BOOT_FROM_SPI) { + I2CDataWrite(0x1011, 1); /* CPU reset */ + /* Reset flash module */ + I2CDataWrite(0x001C, 0x08); /* reset FM */ + I2CDataWrite(0x001C, 0x00); + I2CDataWrite(0x1010, 0x02); + I2CDataWrite(0x1010, 0x00); + + I2CDataWrite(0x1306, ucFwIdx); /* Set which FW will be loaded */ + I2CDataWrite(0x1011, 0); + } + else if (ucBoot == BOOT_FROM_HOST) { + ucRet = EXISP_LoadCode(ucFwIdx, is_calibration, pIspFw, pCalibOpt, p3acali, pLsc, pLscdq); + I2CDataWrite(0x1306, ucFwIdx); /* Set which FW to be loaded */ + } + DEBUG_TRACE("@@@ISP FW: Load Code End, sts=%d\n", ucRet); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_LoadCode + * Description : Load code from host, support boot from host only + * ucFwIdx: Set which FW will be loaded + is_calibration: calibration flag, calibration:1 normal:0 + *pIspFw: external ISP FW pointer + *pCaliOpt: read from calibration_option.BIN + *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN + *pLsc: read from LSC.BIN or LSC_F.BIN + *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_LoadCode( + UINT8 ucFwIdx, + UINT8 is_calibration, + UINT8 *pIspFw, + UINT8 *pCalibOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq) +{ + UINT8 ucRet = SUCCESS; + UINT32 t1=0, t2=0, t3=0, tmrCnt=0, i=0; + UINT32 checksumWrite=0, checksumRead=0; + ispFwHeaderInfo_t *pFwInfo; + ispLoadCodeRet_t loadCodeRet; + + if (pIspFw == NULL) { + return LOADCODE_BOOT_FILE_ERR; + } + + pFwInfo = (ispFwHeaderInfo_t *)pIspFw; + for (i = 0; i < ucFwIdx; i++) { + pIspFw += FW_HEADER_SIZE+pFwInfo->DmemFicdmemSize+pFwInfo->ImemSize; + pFwInfo = (ispFwHeaderInfo_t *)pIspFw; + } + + /* Modify length to 16-alignment */ + pFwInfo->DmemFicdmemSize = (pFwInfo->DmemFicdmemSize+15)&0xFFFFFFF0; + pFwInfo->ImemSize = (pFwInfo->ImemSize+15)&0xFFFFFFF0; + //DEBUG_TRACE(" %s, %d, DmemFicdmemSize=%d\n", __FUNCTION__, __LINE__, pFwInfo->DmemFicdmemSize); + //DEBUG_TRACE(" %s, %d, ImemSize=%d\n", __FUNCTION__, __LINE__, pFwInfo->ImemSize); + //DEBUG_TRACE("0.pIspFw =%x\n", pIspFw); + DEBUG_TRACE("@@@ISP FW: Get BOOT.BIN Bin File End\n"); + +#if 1 //update golden or calibration resource + DEBUG_TRACE("@@@ISP FW: Update Resource Start\n"); + if (is_calibration == 1) { //calibration + //Nothing to do + } + else { //normal + memset(&loadCodeRet, 0, sizeof(ispLoadCodeRet_t)); + + /* pCalibOpt check */ + if (pCalibOpt == NULL) { + loadCodeRet.retCalibOpt= LOADCODE_CALIB_OPT_FILE_ERR; + goto _EXIT_; + } + /* p3acali check */ + if (p3acali == NULL) { + loadCodeRet.ret3acli= LOADCODE_3ACALI_FILE_ERR; + } + /* pLsc check */ + if (pLsc == NULL) { + loadCodeRet.retLsc= LOADCODE_LSC_FILE_ERR; + } + /* pLscdq check */ + if (pLscdq == NULL) { + loadCodeRet.retLscdq = LOADCODE_LSC_DQ_FILE_ERR; + } + + EXISP_UpdateCalibResStart(ucFwIdx, pIspFw, pFwInfo, &loadCodeRet, *pCalibOpt, p3acali, pLsc, pLscdq); + } + DEBUG_TRACE("@@@ISP FW: Update Resource End\n"); +#endif + +_EXIT_: + if (is_calibration == 1) { //calibration + DEBUG_TRACE("********** Load Golden Res **********\n"); + } + else { //normal + if (loadCodeRet.retCalibOpt == SUCCESS && + loadCodeRet.ret3acli == SUCCESS && + loadCodeRet.retLsc == SUCCESS && + loadCodeRet.retLscdq == SUCCESS) { + DEBUG_TRACE("********** Load Calibration Res **********\n"); + } + else { + if (loadCodeRet.retCalibOpt != SUCCESS) { + DEBUG_TRACE("********** Load Golden Res, retCalibOpt=%d **********\n", loadCodeRet.retCalibOpt); + } + else if (loadCodeRet.ret3acli != SUCCESS) { + DEBUG_TRACE("********** Load Golden 3ACALI Res, ret3acli=%d **********\n", loadCodeRet.ret3acli); + } + else if (loadCodeRet.retLsc != SUCCESS || loadCodeRet.retLscdq == SUCCESS) { + DEBUG_TRACE("********** Load Golden LSC Res, retLsc=%d, retLscdq=%d **********\n", loadCodeRet.retLsc, loadCodeRet.retLscdq); + } + } + } + + /* CPU reset */ + I2CDataWrite(0x1011, 1); + + /* Set imemmode*/ + t1 = pFwInfo->ImemSize/8192; + t2 = t1-32; + t3 = 1; + if ((int)t2 < 0) { + t1 = t3 << t1; + --t1; + } + else { + t3 <<= t2; + t1 = -1U; + } + --t3; + I2CDataWrite(0x1070, t1); + I2CDataWrite(0x1071, t1>>8); + I2CDataWrite(0x1072, t1>>16); + I2CDataWrite(0x1073, t1>>24); + I2CDataWrite(0x1074, t3); + + /* @@@ Start load code to SPCA7002 */ + + /* Enable checksum mechanism */ + I2CDataWrite(0x4280, 1); + + /* Wait Ready For Load Code interrupt */ + while (!(I2CDataRead(SP7K_RDREG_INT_STS_REG_0)&0x02)) { + tmrCnt++; + if (tmrCnt >= 10) { + DEBUG_TRACE("@@@ISP FW: polling RFLC bit timeout\n"); + ucRet = FAIL; return ucRet; + } + tmrUsDelay(10000); + } + I2CDataWrite(SP7K_RDREG_INT_STS_REG_0, 0x02); + + /* Load DMEM/FICDMEM bin file Start */ + DEBUG_TRACE("@@@ISP FW: Load DMEM/FICDMEM Bin File Start\n"); + pIspFw += FW_HEADER_SIZE; + /* Reset checksum value */ + I2CDataWrite(0x4284, 0x00); + checksumWrite = 0; + for (i = 0; i < pFwInfo->DmemFicdmemSize; i++) { + checksumWrite += pIspFw[i]; + } + checksumWrite &= 0xFF; + + /* Transmit DMEM/FICDMEM data */ + if(pFwInfo->DmemFicdmemSize <= 6*1024) { /* Data size <6K, load all bin file */ + ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, pFwInfo->DmemFicdmemSize, 0x0800); + I2CDataWrite(0x1011, 0); /* Set CPU to normal operation */ + } + else { + ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, 6*1024, 0x0800); + I2CDataWrite(0x1011, 0); /* Set CPU to normal operation */ + ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw+(6*1024), pFwInfo->DmemFicdmemSize-(6*1024), 0x0800+(6*1024)); + } + + /* Checksum value check */ + checksumRead = I2CDataRead(0x4284); + if (checksumWrite == checksumRead) { + DEBUG_TRACE("@@@ISP FW: Checksum DMEM/FICDMEM test: OK, %x, %x\n", checksumRead, checksumWrite); + } + else { + DEBUG_TRACE("@@@ISP FW: Checksum DMEM/FICDMEM test: FAIL, %x, %x\n", checksumRead, checksumWrite); + ucRet = FAIL; return ucRet; + } + DEBUG_TRACE("@@@ISP FW: Load DMEM/FICDMEM Bin File End\n"); + /* Load DMEM/FICDMEM bin file End */ + + /* Load IMEM bin file Start */ + DEBUG_TRACE("@@@ISP FW: Load IMEM Bin File Start\n"); + pIspFw += pFwInfo->DmemFicdmemSize; + /* Reset checksum value */ + I2CDataWrite(0x4284, 0x00); + checksumWrite = 0; + for (i = 0; i < pFwInfo->ImemSize; i++) { + checksumWrite += pIspFw[i]; + } + checksumWrite &= 0xFF; + + /* Transmit IMEM data */ + ucRet = EXISP_SPIDataWrite(0/*SPI mode0*/, pIspFw, pFwInfo->ImemSize, (320*1024)-pFwInfo->ImemSize); + + /* Checksum value check */ + checksumRead = I2CDataRead(0x4284); + if (checksumWrite == checksumRead) { + DEBUG_TRACE("@@@ISP FW: Checksum IMEM test: OK, %x, %x\n", checksumRead, checksumWrite); + } + else { + DEBUG_TRACE("@@@ISP FW: Checksum IMEM test: FAIL, %x, %x\n", checksumRead, checksumWrite); + ucRet = FAIL; return ucRet; + } + DEBUG_TRACE("@@@ISP FW: Load IMEM Bin File End\n"); + /* Load IMEM bin file End */ + + /* @@@ End load code to SPCA7002 */ + + /* Disable checksum mechanism */ + I2CDataWrite(0x4280, 0); + + /* Write load code end register */ + I2CDataWrite(0x1307, 0xA5); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_UpdateCalibResStart + * Description : Update calibration data start + * ucFwIdx: Set which FW will be loaded + *pIspFw: external ISP FW pointer + *pFwInfo: external ISP FW header information + *pLoadCodeRet: load code status result + ucCaliOpt: read from calibration_option.BIN + *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN + *pLsc: read from LSC.BIN or LSC_F.BIN + *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN + * Return : none + *------------------------------------------------------------------------*/ +void EXISP_UpdateCalibResStart( + UINT8 ucFwIdx, + UINT8 *pIspFw, + ispFwHeaderInfo_t *pFwInfo, + ispLoadCodeRet_t *pLoadCodeRet, + UINT8 ucCaliOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq) +{ + //DEBUG_TRACE("1.pIspFw =%x\n", pIspFw); + + if ((ucFwIdx == 0) && (ucCaliOpt != 0xFF)) { //rear sensor + ucCaliOpt = ucCaliOpt & 0x03; + } + else if ((ucFwIdx == 1) && (ucCaliOpt != 0xFF)){ //front sensor + ucCaliOpt = ucCaliOpt >> 2; + } + + switch (ucCaliOpt) { + case 1: /* load golden 3ACALI.BIN and calibrated LSC.BIN & LSC_DQ.BIN */ + if (pLsc == NULL || pLscdq == NULL) { + pLoadCodeRet->retLsc = LOADCODE_LSC_FILE_ERR; + pLoadCodeRet->retLscdq = LOADCODE_LSC_DQ_FILE_ERR; + break; + } + pLoadCodeRet->retLsc = EXISP_UpdateCalibRes(1, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); + pLoadCodeRet->retLscdq = pLoadCodeRet->retLsc; + break; + case 2: /* load calibrated 3ACALI.BIN and golden LSC.BIN & LSC_DQ.BIN */ + if (p3acali == NULL) { + pLoadCodeRet->ret3acli = LOADCODE_3ACALI_FILE_ERR; + break; + } + pLoadCodeRet->ret3acli = EXISP_UpdateCalibRes(0, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); + break; + case 3: /* load golden 3ACALI.BIN and golden LSC.BIN & LSC_DQ.BIN */ + //Nothing to do + break; + default: /* load calibrated 3ACALI.BIN and calibrated LSC.BIN & LSC_DQ.BIN */ + if (p3acali == NULL) { + pLoadCodeRet->ret3acli = LOADCODE_3ACALI_FILE_ERR; + } + if (pLoadCodeRet->ret3acli == SUCCESS) { + pLoadCodeRet->ret3acli = EXISP_UpdateCalibRes(0, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); + } + + if (pLoadCodeRet->ret3acli == LOADCODE_GET_RES_NUM_ERR) { + break; + } + else if (pLsc == NULL || pLscdq == NULL) { + pLoadCodeRet->retLsc = LOADCODE_LSC_FILE_ERR; + pLoadCodeRet->retLscdq = LOADCODE_LSC_DQ_FILE_ERR; + break; + } + pLoadCodeRet->retLsc = EXISP_UpdateCalibRes(1, pIspFw, pFwInfo, p3acali, pLsc, pLscdq); + pLoadCodeRet->retLscdq = pLoadCodeRet->retLsc; + break; + } +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_UpdateCalibRes + * Description : Update calibration data from host, support boot from host only + * idx: Set which resource will be loaded + *pIspFw: external ISP FW pointer + *pFwInfo: external ISP FW header information + *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN + *pLsc: read from LSC.BIN or LSC_F.BIN + *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_UpdateCalibRes( + UINT8 idx, + UINT8 *pIspFw, + ispFwHeaderInfo_t *pFwInfo, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq) +{ + UINT32 iqOffset = 0, resNumCnt = 0, iqSize = 0, caliSize = 0, tempSize = 0, i; + UINT32 start3acali = 0, startLsc = 0, startLscdq = 0, size3acali = 0, sizeLsc = 0, sizeLscdq = 0; + UINT8 ucRet = SUCCESS; + + /* resource header and checksum check */ + ucRet = EXISP_ResCheck(idx, p3acali, pLsc, pLscdq); + if (ucRet != SUCCESS) { + goto _EXIT_; + } + + /* find out where IQ.BIN is */ + pIspFw += FW_HEADER_SIZE + pFwInfo->DmemSize; + //DEBUG_TRACE("2.pIspFw =%x\n", pIspFw); + if (*(pIspFw+0x38) == 0x43 && + *(pIspFw+0x39) == 0x41 && + *(pIspFw+0x3A) == 0x4C && + *(pIspFw+0x3B) == 0x49) { + iqOffset = ((*(pIspFw+0x51)<<8)&0x0000FF00) + (*(pIspFw+0x50)&0x000000FF); + } + else { + iqOffset = ((*(pIspFw+0x31)<<8)&0x0000FF00) + (*(pIspFw+0x30)&0x000000FF); + } + //DEBUG_TRACE("iqOffset=%x\n", iqOffset); + + /* point to IQ.BIN start position */ + pIspFw += iqOffset; + //DEBUG_TRACE("3.pIspFw =%x\n", pIspFw); + + /* parsing out the file size to get the start position of calibration data, + FICDMEM file size should be 16 alignment */ + ucRet = EXISP_ResNumGet(&resNumCnt, pIspFw+0x10); + if (ucRet != SUCCESS) { + goto _EXIT_; + } + //DEBUG_TRACE("resNumCnt=%d\n", resNumCnt); + //DEBUG_TRACE("5.pIspFw =%x\n", pIspFw); + + for (i = 0; i < resNumCnt; i++) { + tempSize = *(pIspFw+14+(1+i)*0x10); + tempSize += ((*(pIspFw+15+((1+i)*0x10)))<<8); + //DEBUG_TRACE("tempSize=0x%02x\n", tempSize); + if ((tempSize%0x10) != 0) { + tempSize = ((tempSize+0xF)>>4)<<4; + } + //DEBUG_TRACE("size of IQ BIN files %d: 0x%02x\n", i, tempSize); + iqSize += tempSize; + } + //DEBUG_TRACE("iqSize=%d\n", iqSize); + //DEBUG_TRACE("6.pIspFw =%x\n", pIspFw); + + /* find out 3ACALI.BIN & LSC.BIN & LSC_DQ.BIN start position */ + start3acali = iqSize+(1+resNumCnt+3)*0x10; + for (i = 0; i < 3; i++) { + tempSize = *(pIspFw+14+(1+resNumCnt+i)*0x10); + tempSize += ((*(pIspFw+15+(1+resNumCnt+i)*0x10))<<8); + if (i == 0) { + size3acali = tempSize; + } + else if (i == 1){ + sizeLsc = tempSize; + } + else { + sizeLscdq = tempSize; + } + + if ((tempSize%0x10) != 0) { + tempSize = ((tempSize+0xF)>>4)<<4; + } + //DEBUG_TRACE("0.size of IQ BIN files %d: 0x%02x\n", i, tempSize); + caliSize += tempSize; + if (i == 0) { + startLsc = start3acali + caliSize; + } + else if (i == 1) { + startLscdq = start3acali + caliSize; + } + } + //DEBUG_TRACE("start3acali=%x, size3acali=%d\n", start3acali, size3acali); + //DEBUG_TRACE("startLsc=%x, sizeLsc=%d\n", startLsc, sizeLsc); + //DEBUG_TRACE("startLscdq=%x, size=%d\n", startLscdq, sizeLscdq); + + /* update calibration data into FW buffer */ + if (idx == 0) { + memcpy(pIspFw+start3acali, p3acali, size3acali); + } + else if (idx == 1) { + memcpy(pIspFw+startLsc, pLsc, sizeLsc); + memcpy(pIspFw+startLscdq, pLscdq, sizeLscdq); + } + +_EXIT_: + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ResCheck + * Description : check resource header and checksum + * idx: Set which resource will be loaded + *p3acali: read from 3ACALI.BIN or 3ACALI_F.BIN + *pLsc: read from LSC.BIN or LSC_F.BIN + *pLscdq: read from LSC_DQ.BIN or LSC_DQ_F.BIN + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ResCheck(UINT8 idx, UINT8 *p3acali, UINT8 *pLsc, UINT8 *Lscdq) +{ + UINT8 ucRet = SUCCESS; + UINT32 header_3ACALI = 0, header_LSC = 0, header_LSCDQ = 0; + UINT32 chksuum_3ACALI = 0, chksuum_LSC = 0, chksuum_LSCDQ = 0, checksum = 0, dataSize = 0, i; + + /* Header check */ + if (idx == 0) { //3ACALI + header_3ACALI = *(p3acali); + header_3ACALI += (*(p3acali+1)<<8); + header_3ACALI += (*(p3acali+2)<<16); + header_3ACALI += (*(p3acali+3)<<24); + if (header_3ACALI == 0xFFFFFFFF || header_3ACALI == 0x00000000) { + DEBUG_TRACE("header_3ACALI=0x%04x\n", header_3ACALI); + ucRet = LOADCODE_3ACALI_HEADER_ERR; + goto _EXIT_; + } + } + else if (idx == 1) { //LSC & LSC_DQ + header_LSC = *(pLsc); + header_LSC += (*(pLsc+1)<<8); + header_LSC += (*(pLsc+2)<<16); + header_LSC += (*(pLsc+3)<<24); + if (header_LSC == 0xFFFFFFFF || header_LSC == 0x00000000) { + DEBUG_TRACE("header_LSC=0x%04x\n", header_LSC); + ucRet = LOADCODE_LSC_HEADER_ERR; + goto _EXIT_; + } + + header_LSCDQ = *(Lscdq); + header_LSCDQ += (*(Lscdq+1)<<8); + header_LSCDQ += (*(Lscdq+2)<<16); + header_LSCDQ += (*(Lscdq+3)<<24); + if (header_LSCDQ == 0xFFFFFFFF || header_LSCDQ == 0x00000000) { + DEBUG_TRACE("header_LSCDQ=0x%04x\n", header_LSCDQ); + ucRet = LOADCODE_LSC_DQ_HEADER_ERR; + goto _EXIT_; + } + } + + /* Checksum check */ + if (idx == 0) { //3ACALI + dataSize = *(p3acali+6); + dataSize += (*(p3acali+7)<<8); + checksum = *(p3acali+RES_3ACALI_HEADER_SIZE); + checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+1)<<8); + checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+2)<<16); + checksum += (*(p3acali+RES_3ACALI_HEADER_SIZE+3)<<24); + + for (i = 0; i < dataSize-sizeof(UINT32); i++) { + chksuum_3ACALI = chksuum_3ACALI + (*(p3acali+RES_3ACALI_HEADER_SIZE+sizeof(UINT32)+i)); + } + if (chksuum_3ACALI != checksum) { + DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_3ACALI=0x%04x\n", dataSize, checksum, chksuum_3ACALI); + ucRet = LOADCODE_3ACALI_CHKSUM_ERR; + goto _EXIT_; + } + } + else if (idx == 1) { //LSC & LSC_DQ + dataSize = *(pLsc+6); + dataSize += (*(pLsc+7)<<8); + checksum = *(pLsc+RES_LSC_HEADER_SIZE-4); + checksum += (*(pLsc+RES_LSC_HEADER_SIZE-3)<<8); + checksum += (*(pLsc+RES_LSC_HEADER_SIZE-2)<<16); + checksum += (*(pLsc+RES_LSC_HEADER_SIZE-1)<<24); + for (i = 0; i < dataSize; i++) { + chksuum_LSC = chksuum_LSC + (*(pLsc+RES_LSC_HEADER_SIZE+i)); + } + if (chksuum_LSC != checksum) { + DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_LSC=0x%04x\n", dataSize, checksum, chksuum_LSC); + ucRet = LOADCODE_LSC_CHKSUM_ERR; + goto _EXIT_; + } + + dataSize = *(Lscdq+6); + dataSize += (*(Lscdq+7)<<8); + checksum = *(Lscdq+RES_LSCDQ_HEADER_SIZE-4); + checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-3)<<8); + checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-2)<<16); + checksum += (*(Lscdq+RES_LSCDQ_HEADER_SIZE-1)<<24); + for (i = 0; i < dataSize; i++) { + chksuum_LSCDQ = chksuum_LSCDQ + (*(Lscdq+RES_LSCDQ_HEADER_SIZE+i)); + } + if (chksuum_LSCDQ != checksum) { + DEBUG_TRACE("dataSize=%d, checksum=0x%04x, chksuum_LSCDQ=0x%04x\n", dataSize, checksum, chksuum_LSCDQ); + ucRet = LOADCODE_LSC_DQ_CHKSUN_ERR; + goto _EXIT_; + } + } + +_EXIT_: + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ResNumGet + * Description : get the resource number in the IQ.BIN + * *resNum: resource number + *pIspFw: external ISP FW pointer + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ResNumGet(UINT32 *resNum, UINT8 *pIspFw) +{ + UINT8 i = 0, ucRet = SUCCESS; + + //DEBUG_TRACE("4.pIspFw =%x\n", pIspFw); + while (1) { + //DEBUG_TRACE("[%s] %d 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__, __LINE__, + // *(pIspFw),*(pIspFw+1),*(pIspFw+2), *(pIspFw+3),*(pIspFw+4),*(pIspFw+5)); + if ((*(pIspFw) == 0x33) && (*(pIspFw+1) == 0x41) && (*(pIspFw+2) == 0x43) && + (*(pIspFw+3)==0x41) && (*(pIspFw+4)==0x4C) && (*(pIspFw+5)==0x49)) { + break; + } + i++; + pIspFw += 0x10; + if (i > 30) { + ucRet = LOADCODE_GET_RES_NUM_ERR; + goto _EXIT_; + } + } + +_EXIT_: + *resNum = i; + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_SPIDataWrite + * Description : write data to external ISP through SPI interface + * ucSPIMode: SPI mode + *ucStartAddr: buffer to be wrote + ulTransByteCnt: buffer size to be wrote + ulDmaAddr: SPCA7002 DMA start address + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_SPIDataWrite(UINT8 ucSPIMode, UINT8 *ucStartAddr, UINT32 ulTransByteCnt, UINT32 ulDmaAddr) +{ + UINT8 ucRet = SUCCESS; + UINT16 tmrCnt = 0; + + EXISP_7002SPICfg(ucSPIMode, ulDmaAddr, ulTransByteCnt); + + /*Trigger the 7002 SPI DMA0*/ + I2CDataWrite(0x4160, 0x01); + /* Enable data transaction */ + if(g_icatch_spi_dev) + spi_write(g_icatch_spi_dev, (void*)ucStartAddr, ulTransByteCnt); + else{ + DEBUG_TRACE("%s:g_icatch_spi_dev is null\n",__func__); + return FAIL; + } + /* Wait SPCA7002 DAM done */ + while ((I2CDataRead(0x4003)&0x02) != 0x02) { + tmrUsDelay(5000); + tmrCnt++; + if (1000 < tmrCnt) { + DEBUG_TRACE("Wait 7002 DMA0 INT Timeout.\n"); + return FAIL; + } + } + + /* Restore SPCA7002 DMA setting */ + I2CDataWrite(0x1084, 0); + I2CDataWrite(0x1085, 0); + I2CDataWrite(0x1086, 0); + I2CDataWrite(0x1087, 0); + I2CDataWrite(0x1088, 0); + I2CDataWrite(0x108c, 0); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_7002SPICfg + * Description : external SPI configuration + * ucSPIMode: SPI mode + ulDmaAddr: SPCA7002 DMA start address + ulTransByteCnt: buffer size to be wrote + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_7002SPICfg(UINT8 ucSPIMode, UINT32 ulDmaAddr, UINT32 ulTransByteCnt) +{ + UINT8 ucRet = SUCCESS; + UINT8 startBank, endBank, realEndBank, readData, i; + UINT32 bankEndValue=0; + const UINT16 bankSize = 8192; + const UINT32 maxTransByteCnt = 0x50000; + + static UINT8 regdata1[][3] = { + {0x40, 0x10, 0x10}, /*SPI reset*/ + {0x40, 0xe1, 0x00}, /*SPI mode*/ + {0x40, 0x51, 0x01}, /*SPI enable*/ + {0x40, 0x11, 0x10}, /*DMA0 reset*/ + {0x41, 0x64, 0x01}, /*Read data from host*/ + {0x41, 0x70, 0x0f}, /*Byte Cnt Low*/ + {0x41, 0x71, 0x0f}, /*Byte Cnt Mid*/ + {0x41, 0x72, 0x0f}, /*Byte Cnt High*/ + {0x10, 0x8c, 0x00}, /*DMA master select FM*/ + {0x10, 0x80, 0x00}, /*DMA start addr Low*/ + {0x10, 0x81, 0x00}, /*DMA start addr Mid*/ + {0x10, 0x82, 0x00}, /*DMA start addr High*/ + {0x10, 0x84, 0x00}, /*DMA bank enable*/ + {0x10, 0x85, 0x00}, + {0x10, 0x86, 0x00}, + {0x10, 0x87, 0x00}, + {0x10, 0x88, 0x00}, + {0x00, 0x26, 0x00}, + {0x40, 0x03, 0x02}, /*Clear DMA0 INT status*/ + }; + + regdata1[1][2] = (((UINT8)ucSPIMode) & 0xf); + regdata1[4][2] = (1&0x1); + + if (maxTransByteCnt < ulTransByteCnt) + ulTransByteCnt = (maxTransByteCnt-1); + else + ulTransByteCnt--; + + regdata1[5][2] = (ulTransByteCnt & 0xff); + regdata1[6][2] = ((ulTransByteCnt >> 8) & 0xff); + regdata1[7][2] = ((ulTransByteCnt >> 16) & 0xff); + regdata1[8][2] = 0<<4; + regdata1[9][2] = (ulDmaAddr & 0xff); + regdata1[10][2] = ((ulDmaAddr >> 8) & 0xff); + regdata1[11][2] = ((ulDmaAddr >> 16) & 0xff); + + startBank = (ulDmaAddr&0xffffff)/bankSize; + endBank = ((ulDmaAddr&0xffffff)+ulTransByteCnt)/bankSize; + realEndBank = endBank; + + if (endBank > 31) { + + for (i = 32; i <= endBank; i++) + bankEndValue |= (1 << (i-32)); + + regdata1[16][2] = (bankEndValue & 0xff); + realEndBank = 32; + bankEndValue = 0; + } + + for (i = startBank; i <= realEndBank; i++) + bankEndValue |= (1 << i); + + regdata1[12][2] = (bankEndValue & 0xff); + regdata1[13][2] = ((bankEndValue >> 8) & 0xff); + regdata1[14][2] = ((bankEndValue >>16) & 0xff); + regdata1[15][2] = ((bankEndValue >>24) & 0xff); + + readData = I2CDataRead(0x0026); /*Config the SPI pin GPIO/Function mode.*/ + readData &= (~0xf); + regdata1[17][2] = readData; + + for (i = 0; i < sizeof(regdata1)/sizeof(regdata1[0]); i++) + I2CDataWrite(((regdata1[i][0]<<8)&0xFF00)+(regdata1[i][1]&0x00FF), regdata1[i][2]); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_PvSizeSet + * Description : Set preview size + * ucResolutionIdx: resolution index + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_PvSizeSet(UINT8 ucResolutionIdx) +{ + UINT8 ucRet = SUCCESS; + + EXISP_I2C_PvSizeSet(ucResolutionIdx); + EXISP_I2C_PvCapModeSet(0x00); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ImageCapSet + * Description : Image capture + * ucImageCapIdx: image capture index + 0x00 IMAGE_CAP_SINGLE + 0x01 IMAGE_CAP_HDR + 0x02 IMAGE_CAP_ZSL_SINGLE_FLASH + 0x03 IMAGE_CAP_ZSL_BURST_FLASH + 0x04 IMAGE_CAP_NONZSL_SINGLE + 0x05 IMAGE_CAP_NONZSL_BURST + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ImageCapSet(UINT8 ucImageCapIdx) +{ + UINT8 ucRet = SUCCESS; + + if (ucImageCapIdx >= IMAGE_CAP_MAX) { + ucRet = FAIL; + return ucRet; + } + + switch (ucImageCapIdx) { + case IMAGE_CAP_SINGLE: + EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP); + break; + case IMAGE_CAP_HDR: + EXISP_I2C_CapModeSet(CAP_MODE_HDR); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP); + break; + case IMAGE_CAP_ZSL_SINGLE_FLASH: + EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_ZSL); + break; + case IMAGE_CAP_ZSL_BURST_FLASH: + EXISP_I2C_CapModeSet(CAP_MODE_BURST); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_ZSL); + break; + case IMAGE_CAP_NONZSL_SINGLE: + EXISP_I2C_CapModeSet(CAP_MODE_SINGLE); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_NONZSL); + break; + case IMAGE_CAP_NONZSL_BURST: + EXISP_I2C_CapModeSet(CAP_MODE_BURST); + EXISP_I2C_PvCapModeSet(PVCAP_MODE_CAP_NONZSL); + break; + } + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_TAFTAEROISet + * Description : Set TAF or TAE ROI and trigger + * ucTrg: + 0x00 TAFTAE_TAF_ONLY + 0x01 TAFTAE_TAE_OFF + 0x02 TAFTAE_TAE_USE_TAE_ROI + 0x03 TAFTAE_TAE_USE_TAF_ROI + 0x04 TAFTAE_TAE_ONLY + usTAFSize: AF ROI size + usTAFX: AF ROI x + usTAFY: AF ROI y + usTAESize: AE ROI size + usTAEX: AE ROI x + usTAEY: AE ROI y + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_TAFTAEROISet( + UINT8 ucTrg, + UINT16 usTAFSize, + UINT16 usTAFX, + UINT16 usTAFY, + UINT16 usTAESize, + UINT16 usTAEX, + UINT16 usTAEY) +{ + UINT8 ucRet = SUCCESS; + + if (ucTrg >= TAFTAE_MAX) { + ucRet = FAIL; + return ucRet; + } + + switch (ucTrg) { + case TAFTAE_TAF_ONLY: + EXISP_I2C_ROISwitchSet(0x01); + EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); + EXISP_I2C_AFROITriggerSet(); + break; + case TAFTAE_TAE_OFF: + EXISP_I2C_AEROITriggerSet(0x00); + break; + + case TAFTAE_TAE_USE_TAE_ROI: + EXISP_I2C_ROISwitchSet(0x01); + EXISP_I2C_AEROISet(usTAESize, usTAEX, usTAEY); + EXISP_I2C_AEROITriggerSet(0x01); + EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); + EXISP_I2C_AFROITriggerSet(); + break; + case TAFTAE_TAE_USE_TAF_ROI: + EXISP_I2C_ROISwitchSet(0x01); + EXISP_I2C_AFROISet(usTAFSize, usTAFX, usTAFY); + EXISP_I2C_AEROITriggerSet(0x02); + EXISP_I2C_AFROITriggerSet(); + break; + case TAFTAE_TAE_ONLY: + EXISP_I2C_ROISwitchSet(0x01); + EXISP_I2C_AEROISet(usTAESize, usTAEX, usTAEY); + EXISP_I2C_AEROITriggerSet(0x01); + } + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_SwitchRAWFormatSet + * Description : Switch to RAW format from YUV format + * Input : None + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_SwitchRAWFormatSet(void) +{ + UINT8 ucRet = SUCCESS; + + EXISP_I2C_RawPathSet(0x00); + EXISP_I2C_RawFormatSet(0x01); + + return ucRet; +} + +/*------------------------------------------------------------------------- + * Function Name : EXISP_ExifInfoGet + * Description : Get EXIF information from external ISP + * Input : None + * Return : status result + *------------------------------------------------------------------------*/ +UINT8 EXISP_ExifInfoGet( + UINT8 *ucExpTimeNumerator, + UINT32 *ulExpTimeDenominator, + UINT8 *ucExpTimeCompensation, + UINT16 *usLensFocalLength, + UINT16 *usIsoInfo, + UINT8 *ucFlashInfo) +{ + UINT8 ucRet = SUCCESS; + + /* Get exposure time numerator */ + *ucExpTimeNumerator = EXISP_I2C_ExposureTimeNumeratorGet(); + /* Get exposure time denominator */ + *ulExpTimeDenominator = EXISP_I2C_ExposureTimeDenominatorGet(); + /* Get exposure time compensation */ + *ucExpTimeCompensation = EXISP_I2C_ExposureTimeCompensationGet(); + /* Get lens focal length */ + *usLensFocalLength = EXISP_I2C_LensFocalLengthGet(); + /* Get ISO information */ + *usIsoInfo = EXISP_I2C_ISOValueGet(); + /* Get flash mode information */ + *ucFlashInfo = EXISP_I2C_FlashModeGet(); + + return ucRet; +} + diff --git a/drivers/media/video/icatch7002/app_i2c_lib_icatch.h b/drivers/media/video/icatch7002/app_i2c_lib_icatch.h new file mode 100755 index 000000000000..5a0a79572f1d --- /dev/null +++ b/drivers/media/video/icatch7002/app_i2c_lib_icatch.h @@ -0,0 +1,451 @@ +/**************************************************************************** + * + * Copyright (c) 2006-2008 by Sunplus mMedia Inc., Ltd. + * + * This software is copyrighted by and is the property of Sunplus + * mMedia Inc., Ltd. All rights are reserved by Sunplus mMedia + * Inc., Ltd. This software may only be used in accordance with the + * corresponding license agreement. Any unauthorized use, duplication, + * distribution, or disclosure of this software is expressly forbidden. + * + * This Copyright notice MUST not be removed or modified without prior + * written consent of Sunplus mMedia Inc., Ltd. + * + * Sunplus mMedia Inc., Ltd. reserves the right to modify this + * software without notice. + * + * Sunplus mMedia Inc., Ltd. + * 19-1, Innovation First Road, Science-Based Industrial Park, + * Hsin-Chu, Taiwan, R.O.C. + * + ****************************************************************************/ +#ifndef APP_I2C_LIB_ICATCH_H +#define APP_I2C_LIB_ICATCH_H + + +/**************************************************************************** + * C O N S T A N T S * + ****************************************************************************/ +#ifndef NULL +#define NULL ((void *)0) +#endif +#ifndef SUCCESS +#define SUCCESS 0 +#endif +#ifndef FAIL +#define FAIL 1 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define UINT64 unsigned long long +#define UINT32 unsigned int +#define UINT16 unsigned short +#define UINT8 unsigned char +#define SINT64 signed long long +#define SINT32 signed int +#define SINT16 signed short +#define SINT8 signed char +#define BOOL unsigned char + +#define SP7K_MSG_BASE 0x7100 +#define SP7K_REG_BASE 0x7280 + +/**************************************************************************** + * D A T A T Y P E S * + ****************************************************************************/ +typedef enum { + SP7K_MSG_BANDING_SELECTION = (SP7K_MSG_BASE | 0x01), + SP7K_MSG_COLOR_EFFECT = (SP7K_MSG_BASE | 0x02), + SP7K_MSG_EV_COMPENSATION = (SP7K_MSG_BASE | 0x03), + SP7K_MSG_FLASH_MODE = (SP7K_MSG_BASE | 0x04), + SP7K_MSG_FOCUS_MODE = (SP7K_MSG_BASE | 0x05), + SP7K_MSG_PV_SIZE = (SP7K_MSG_BASE | 0x06), + SP7K_MSG_SCENE_MODE = (SP7K_MSG_BASE | 0x09), + SP7K_MSG_WHITE_BALANCE = (SP7K_MSG_BASE | 0x0A), + SP7K_MSG_AE_MODE = (SP7K_MSG_BASE | 0x0E), + SP7K_MSG_CAP_MODE = (SP7K_MSG_BASE | 0x0F), + SP7K_MSG_CAP_ISO = (SP7K_MSG_BASE | 0x10), + SP7K_MSG_AURA_COLOR_INDEX = (SP7K_MSG_BASE | 0x19), + SP7K_MSG_OPTICAL_ZOOM = (SP7K_MSG_BASE | 0x1A), + SP7K_MSG_ISP_FUNCTION = (SP7K_MSG_BASE | 0x1B), + SP7K_MSG_PV_CAP_MODE = (SP7K_MSG_BASE | 0x20), + SP7K_MSG_PV_STREAM = (SP7K_MSG_BASE | 0x21), + SP7K_MSG_BURST_ABORT = (SP7K_MSG_BASE | 0x22), + SP7K_MSG_CAP_EDGE_QUANTITY = (SP7K_MSG_BASE | 0x23), + SP7K_MSG_PV_FIX_FRAME_RATE = (SP7K_MSG_BASE | 0x24), + SP7K_MSG_PV_MAX_EXPTIME = (SP7K_MSG_BASE | 0x25), + SP7K_MSG_HDR_POSITIVE_EV = (SP7K_MSG_BASE | 0x27), + SP7K_MSG_HDR_NEGATIVE_EV = (SP7K_MSG_BASE | 0x28), + SP7K_MSG_PV_MIN_ISO = (SP7K_MSG_BASE | 0x29), + SP7K_MSG_G_SENSOR_INFO_X = (SP7K_MSG_BASE | 0x2A), + SP7K_MSG_G_SENSOR_INFO_Y = (SP7K_MSG_BASE | 0x2B), + SP7K_MSG_G_SENSOR_INFO_Z = (SP7K_MSG_BASE | 0x2C), + SP7K_MSG_GYRO_INFO_X = (SP7K_MSG_BASE | 0x2D), + SP7K_MSG_GYRO_INFO_Y = (SP7K_MSG_BASE | 0x2E), + SP7K_MSG_GYRO_INFO_Z = (SP7K_MSG_BASE | 0x2F), + SP7K_MSG_AF_ROI_SIZE_H = (SP7K_MSG_BASE | 0x40), + SP7K_MSG_AF_ROI_SIZE_L = (SP7K_MSG_BASE | 0x41), + SP7K_MSG_AF_ROI_X_H = (SP7K_MSG_BASE | 0x42), + SP7K_MSG_AF_ROI_X_L = (SP7K_MSG_BASE | 0x43), + SP7K_MSG_AF_ROI_Y_H = (SP7K_MSG_BASE | 0x44), + SP7K_MSG_AF_ROI_Y_L = (SP7K_MSG_BASE | 0x45), + SP7K_MSG_AF_ROI_TRIGGER = (SP7K_MSG_BASE | 0x46), + SP7K_MSG_AE_ROI_SIZE_H = (SP7K_MSG_BASE | 0x48), + SP7K_MSG_AE_ROI_SIZE_L = (SP7K_MSG_BASE | 0x49), + SP7K_MSG_AE_ROI_X_H = (SP7K_MSG_BASE | 0x4A), + SP7K_MSG_AE_ROI_X_L = (SP7K_MSG_BASE | 0x4B), + SP7K_MSG_AE_ROI_Y_H = (SP7K_MSG_BASE | 0x4C), + SP7K_MSG_AE_ROI_Y_L = (SP7K_MSG_BASE | 0x4D), + SP7K_MSG_AE_ROI_TRIGGER = (SP7K_MSG_BASE | 0x4E), + SP7K_MSG_AF_ABORT = (SP7K_MSG_BASE | 0x4F), + SP7K_MSG_VCM_STEP_L = (SP7K_MSG_BASE | 0x5C), + SP7K_MSG_VCM_STEP_H = (SP7K_MSG_BASE | 0x5D), + SP7K_MSG_CAP_EDGE_INFO = (SP7K_MSG_BASE | 0x5F), + SP7K_MSG_RAW_PATH = (SP7K_MSG_BASE | 0x60), + SP7K_MSG_RAW_FORMAT = (SP7K_MSG_BASE | 0x61), + SP7K_MSG_CALIBRATION_RAW_LINEAR = (SP7K_MSG_BASE | 0x62), + SP7K_MSG_CALIBRATION_RAW_OB = (SP7K_MSG_BASE | 0x63), + SP7K_MSG_CALIBRATION_RAW_BP = (SP7K_MSG_BASE | 0x64), + SP7K_MSG_CALIBRATION_RAW_LSC = (SP7K_MSG_BASE | 0x65), + SP7K_MSG_CALIBRATION_RAW_CA = (SP7K_MSG_BASE | 0x66), + SP7K_MSG_CALIBRATION_RAW_ARD = (SP7K_MSG_BASE | 0x67), + SP7K_MSG_CALIBRATION_RAW_DEPEAK = (SP7K_MSG_BASE | 0x68), + SP7K_MSG_CALIBRATION_RAW_WB = (SP7K_MSG_BASE | 0x69), + SP7K_MSG_CALIBRATION_AWB_CRITERIA = (SP7K_MSG_BASE | 0x6D), + SP7K_MSG_AEAWBTHREAD_MODE = (SP7K_MSG_BASE | 0x70), + SP7K_MSG_DQ_MODE = (SP7K_MSG_BASE | 0x71), + SP7K_MSG_CDSP_MODE = (SP7K_MSG_BASE | 0x72), + SP7K_MSG_CALIBRATION_CMD1 = (SP7K_MSG_BASE | 0x74), + SP7K_MSG_CALIBRATION_CMD2 = (SP7K_MSG_BASE | 0x75), + SP7K_MSG_CALIBRATION_INIT_CMD = (SP7K_MSG_BASE | 0x76), + SP7K_MSG_CALIBRATION_LENS_MAX_LUM_DECAY = (SP7K_MSG_BASE | 0x77), + SP7K_MSG_CALIBRATION_DQ_INDEX_FIX = (SP7K_MSG_BASE | 0x78), + SP7K_MSG_CALIBRATION_UTILIZATION_OPTION = (SP7K_MSG_BASE | 0x7F), + SP7K_MSG_ROI_SWITCH = (SP7K_MSG_BASE | 0x88), + + SP7K_MSG_VENDREQ_ID = (SP7K_MSG_BASE | 0xE4), + SP7K_MSG_VENDREQ_PARAM = (SP7K_MSG_BASE | 0xE5), + SP7K_MSG_VENDREQ_VALUES_L = (SP7K_MSG_BASE | 0xE6), + SP7K_MSG_VENDREQ_PROCESS = (SP7K_MSG_BASE | 0xE8), + SP7K_MSG_VENDREQ_VALUES_H = (SP7K_MSG_BASE | 0xEA), + SP7K_MSG_VENDREQ_CMD = (SP7K_MSG_BASE | 0xEB), +} sp7kHostMsgList_e; + +typedef enum { + SP7K_RDREG_AF_STATUS = (SP7K_REG_BASE | 0xA0), + SP7K_RDREG_AF_RESULT = (SP7K_REG_BASE | 0xA1), + SP7K_RDREG_AF_CONSUME_TIME_L = (SP7K_REG_BASE | 0xA2), + SP7K_RDREG_AF_CONSUME_TIME_H = (SP7K_REG_BASE | 0xA3), + SP7K_RDREG_VCM_CURRENT_POS_L = (SP7K_REG_BASE | 0xA4), + SP7K_RDREG_VCM_CURRENT_POS_H = (SP7K_REG_BASE | 0xA5), + SP7K_RDREG_EXPTIME_NUMERATOR = (SP7K_REG_BASE | 0xB0), + SP7K_RDREG_EXPTIME_DENOMINATOR_L = (SP7K_REG_BASE | 0xB1), + SP7K_RDREG_EXPTIME_DENOMINATOR_M = (SP7K_REG_BASE | 0xB2), + SP7K_RDREG_EXPTIME_DENOMINATOR_H = (SP7K_REG_BASE | 0xB3), + SP7K_RDREG_EXPTIME_COMPENSATION = (SP7K_REG_BASE | 0xB4), + SP7K_RDREG_LENS_FOCAL_LENGTH_L = (SP7K_REG_BASE | 0xB5), + SP7K_RDREG_LENS_FOCAL_LENGTH_H = (SP7K_REG_BASE | 0xB6), + SP7K_RDREG_ISO_L = (SP7K_REG_BASE | 0xB7), + SP7K_RDREG_ISO_H = (SP7K_REG_BASE | 0xB8), + SP7K_RDREG_FLASH_MODE = (SP7K_REG_BASE | 0xB9), + SP7K_RDREG_CAP_EDGE_INFO_B0 = (SP7K_REG_BASE | 0xBA), + SP7K_RDREG_CAP_EDGE_INFO_B1 = (SP7K_REG_BASE | 0xBB), + SP7K_RDREG_CAP_EDGE_INFO_B2 = (SP7K_REG_BASE | 0xBC), + SP7K_RDREG_CAP_EDGE_INFO_B3 = (SP7K_REG_BASE | 0xBD), + SP7K_RDREG_3A_STATUS = (SP7K_REG_BASE | 0xC3), + SP7K_RDREG_EDGE_INFO_COUNT = (SP7K_REG_BASE | 0xC4), + SP7K_RDREG_REAR_SENSORID_L = (SP7K_REG_BASE | 0xC6), + SP7K_RDREG_REAR_SENSORID_H = (SP7K_REG_BASE | 0xC7), + SP7K_RDREG_FRONT_SENSORID_L = (SP7K_REG_BASE | 0xC8), + SP7K_RDREG_FRONT_SENSORID_H = (SP7K_REG_BASE | 0xC9), + SP7K_RDREG_FW_VER_L = (SP7K_REG_BASE | 0xCA), + SP7K_RDREG_FW_VER_M = (SP7K_REG_BASE | 0xCB), + SP7K_RDREG_FW_VER_H = (SP7K_REG_BASE | 0xCC), + SP7K_RDREG_VENDOR_ID_L = (SP7K_REG_BASE | 0xCE), + SP7K_RDREG_VENDOR_ID_H = (SP7K_REG_BASE | 0xCF), + SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_L = (SP7K_REG_BASE | 0xD8), + SP7K_RDREG_CALIBRATION_LSC_MAX_RGAIN_H = (SP7K_REG_BASE | 0xD9), + SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_L = (SP7K_REG_BASE | 0xDA), + SP7K_RDREG_CALIBRATION_LSC_MAX_GGAIN_H = (SP7K_REG_BASE | 0xDB), + SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_L = (SP7K_REG_BASE | 0xDC), + SP7K_RDREG_CALIBRATION_LSC_MAX_BGAIN_H = (SP7K_REG_BASE | 0xDD), + SP7K_RDREG_CALIBRATION_AWB_RGain_L = (SP7K_REG_BASE | 0xE1), + SP7K_RDREG_CALIBRATION_AWB_RGain_H = (SP7K_REG_BASE | 0xE2), + SP7K_RDREG_CALIBRATION_AWB_GGain_L = (SP7K_REG_BASE | 0xE3), + SP7K_RDREG_CALIBRATION_AWB_GGain_H = (SP7K_REG_BASE | 0xE4), + SP7K_RDREG_CALIBRATION_AWB_BGain_L = (SP7K_REG_BASE | 0xE5), + SP7K_RDREG_CALIBRATION_AWB_BGain_H = (SP7K_REG_BASE | 0xE6), + SP7K_RDREG_CALIBRATION_EXEC_STATUS1 = (SP7K_REG_BASE | 0xF0), + SP7K_RDREG_CALIBRATION_EXEC_STATUS2 = (SP7K_REG_BASE | 0xF1), + SP7K_RDREG_CALIBRATION_ERROR_STATUS1 = (SP7K_REG_BASE | 0xF2), + SP7K_RDREG_CALIBRATION_ERROR_STATUS2 = (SP7K_REG_BASE | 0xF3), + SP7K_RDREG_CALIBRATION_ERROR_CODE = (SP7K_REG_BASE | 0xF4), + SP7K_RDREG_CALIBRATION_LOAD_TABLE_STATUS= (SP7K_REG_BASE | 0xF5), + SP7K_RDREG_INT_STS_REG_0 = (SP7K_REG_BASE | 0xF8), + SP7K_RDREG_INT_MASK_REG_0 = (SP7K_REG_BASE | 0xFC), +} sp7kReadRegList_e; + +typedef enum { + GPIO_CTL_LOW, + GPIO_CTL_HIGH, + GPIO_CTL_MAX, +} sp7kGpioCtlList_e; + +typedef enum { + BOOT_FROM_SPI, + BOOT_FROM_HOST, + BOOT_FROM_MAX, +} sp7kPowerOnList_e; + +typedef enum { + SENSOR_ID_REAR, + SENSOR_ID_FRONT, + SENSOR_ID_REAR_CALIBRATION, + SENSOR_ID_MAX, +} sp7kSensorIdList_e; + +typedef enum { + IMAGE_CAP_SINGLE, + IMAGE_CAP_HDR, + IMAGE_CAP_ZSL_SINGLE_FLASH, + IMAGE_CAP_ZSL_BURST_FLASH, + IMAGE_CAP_NONZSL_SINGLE, + IMAGE_CAP_NONZSL_BURST, + IMAGE_CAP_MAX, +} sp7kImageCapList_e; + +typedef enum { + CAP_MODE_SINGLE, + CAP_MODE_HDR, + CAP_MODE_RSV, + CAP_MODE_BURST, + CAP_MODE_MAX, +} sp7kCapModeList_e; + +typedef enum { + PVCAP_MODE_PV, + PVCAP_MODE_CAP, + PVCAP_MODE_CAP_ZSL, + PVCAP_MODE_CAP_NONZSL, + PVCAP_MODE_MAX, +} sp7kPvCapModeList_e; + +typedef enum { + TAFTAE_TAF_ONLY, + TAFTAE_TAE_OFF, + TAFTAE_TAE_USE_TAE_ROI, + TAFTAE_TAE_USE_TAF_ROI, + TAFTAE_TAE_ONLY, + TAFTAE_MAX, +} sp7kTAFTAEList_e; + +typedef enum { + NONE, + LOADCODE_BOOT_FILE_ERR, + + LOADCODE_CALIB_OPT_FILE_ERR, + LOADCODE_CALIB_OPT_MAX_ERR, + + LOADCODE_3ACALI_FILE_ERR, + LOADCODE_3ACALI_HEADER_ERR, + LOADCODE_3ACALI_CHKSUM_ERR, + + LOADCODE_LSC_FILE_ERR, + LOADCODE_LSC_HEADER_ERR, + LOADCODE_LSC_CHKSUM_ERR, + + LOADCODE_LSC_DQ_FILE_ERR, + LOADCODE_LSC_DQ_HEADER_ERR, + LOADCODE_LSC_DQ_CHKSUN_ERR, + + LOADCODE_GET_RES_NUM_ERR, +} LoadCodeErrList_e; + +typedef struct { + UINT32 DmemFicdmemSize; /*DMEM+FICDMEM size*/ + UINT32 ImemSize; /*IMEM size*/ + UINT16 FmClk; /*FM clock*/ + UINT16 Checksum; /*checksum*/ + UINT32 DmemSize; /*DMEM size*/ +} ispFwHeaderInfo_t; + +typedef struct { + UINT32 retCalibOpt; + UINT32 ret3acli; + UINT32 retLsc; + UINT32 retLscdq; +} ispLoadCodeRet_t; + +/**************************************************************************** + * M A C R O S * + ****************************************************************************/ + +/**************************************************************************** + * E X T E R N V A R I A B L E S D E C L A R A T I O N S * + ****************************************************************************/ + +/**************************************************************************** + * F U N C T I O N D E C L A R A T I O N S * + ****************************************************************************/ +void EXISP_I2C_BandSelectionSet(UINT8 ucParam); +void EXISP_I2C_ColorEffectSet(UINT8 ucParam); +void EXISP_I2C_EvSet(UINT8 ucParam); +void EXISP_I2C_FlashModeSet(UINT8 ucParam); +void EXISP_I2C_FocusModeSet(UINT8 ucParam); +void EXISP_I2C_PvSizeSet(UINT8 ucParam); +void EXISP_I2C_SceneModeSet(UINT8 ucParam); +void EXISP_I2C_WhiteBalanceSet(UINT8 ucParam); +void EXISP_I2C_AEModeSet(UINT8 ucParam); +void EXISP_I2C_CapModeSet(UINT8 ucParam); +void EXISP_I2C_ISOSet(UINT8 ucParam); +void EXISP_I2C_AuraColorIndexSet(UINT8 ucParam); +void EXISP_I2C_OpticalZoomSet(UINT8 ucParam); +void EXISP_I2C_IspFuncSet(UINT8 ucParam); +void EXISP_I2C_PvCapModeSet(UINT8 ucParam); +void EXISP_I2C_PvStreamSet(UINT8 ucParam); +void EXISP_I2C_BurstAbortSet(UINT8 ucParam); +void EXISP_I2C_CapEdgeQuantitySet(UINT8 ucValue); +void EXISP_I2C_PvFixFrameRateSet(UINT8 ucValue); +void EXISP_I2C_PvMaxExposureTimeSet(UINT8 ucValue); +void EXISP_I2C_HdrPositiveEvSet(UINT8 ucValue); +void EXISP_I2C_HdrNegativeEvSet(UINT8 ucValue); +void EXISP_I2C_PvMinISOSet(UINT8 ucParam); +void EXISP_I2C_GSensorInfoSet(SINT8 ucX, SINT8 ucY, SINT8 ucZ); +void EXISP_I2C_GyroInfoSet(UINT8 ucX, UINT8 ucY, UINT8 ucZ); +void EXISP_I2C_AFROISet(UINT16 usSize, UINT16 usX, UINT16 usY); +void EXISP_I2C_AFROITriggerSet(void); +void EXISP_I2C_AEROISet(UINT16 usSize, UINT16 usX, UINT16 usY); +void EXISP_I2C_AEROITriggerSet(UINT8 ucParam); +void EXISP_I2C_AFAbortSet(UINT8 ucParam); +void EXISP_I2C_VcmStepSet(UINT16 usValue); +void EXISP_I2C_CapEdgeInfoSet(UINT8 ucParam); +void EXISP_I2C_RawPathSet(UINT8 ucParam); +void EXISP_I2C_RawFormatSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawLinearSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawObSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawBpSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawLscSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawCaSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawArdSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawDepeakSet(UINT8 ucParam); +void EXISP_I2C_CalibrationRawWbSet(UINT8 ucParam); +void EXISP_I2C_CalibrationAwbCriteriaSet(UINT8 ucVaule); +void EXISP_I2C_AEAWBThreadModeSet(UINT8 ucParam); +void EXISP_I2C_DqModeSet(UINT8 ucParam); +void EXISP_I2C_CdspOnOffModeSet(UINT8 ucParam); +void EXISP_I2C_CalibrationCmd1Set(UINT8 ucParam); +void EXISP_I2C_CalibrationCmd2Set(UINT8 ucParam); +void EXISP_I2C_CalibrationInitCmdSet(UINT8 ucParam); +void EXISP_I2C_CalibrationLscMaxGainSet(UINT8 ucVaule); +void EXISP_I2C_CalibrationDqIndexFixSet(UINT8 ucParam); +void EXISP_I2C_CaliUtilizationOptionSet(UINT8 ucParam); +void EXISP_I2C_ROISwitchSet(UINT8 ucParam); +void EXISP_I2C_VendreqIdSet(UINT8 ucValue); +void EXISP_I2C_VendreqParamSet(UINT8 ucValue); +void EXISP_I2C_VendreqValuesSet_L(UINT8 ucVaule); +void EXISP_I2C_VendreqProcessSet(void); +void EXISP_I2C_VendreqValuesSet_H(UINT8 ucVaule); +void EXISP_I2C_VendreqCmdSet(UINT8 ucParam); + + +UINT8 EXISP_I2C_AFStatusGet(void); +UINT8 EXISP_I2C_AFResultGet(void); +UINT16 EXISP_I2C_AFConsumeTimeGet(void); +UINT16 EXISP_I2C_VcmCurrentPosGet(void); +UINT8 EXISP_I2C_ExposureTimeNumeratorGet(void); +UINT32 EXISP_I2C_ExposureTimeDenominatorGet(void); +UINT8 EXISP_I2C_ExposureTimeCompensationGet(void); +UINT16 EXISP_I2C_LensFocalLengthGet(void); +UINT16 EXISP_I2C_ISOValueGet(void); +UINT8 EXISP_I2C_FlashModeGet(void); +UINT32 EXISP_I2C_CapEdgeInfoGet(void); +UINT8 EXISP_I2C_3AStatusGet(void); +UINT8 EXISP_I2C_EdgeInfoCountGet(void); +UINT16 EXISP_I2C_RearSensorIdGet(void); +UINT16 EXISP_I2C_FrontSensorIdGet(void); +UINT32 EXISP_I2C_FWVersionGet(void); +UINT16 EXISP_I2C_VendorIdGet(void); +UINT16 EXISP_I2C_CalibrationLscMaxRGainGet(void); +UINT16 EXISP_I2C_CalibrationLscMaxGGainGet(void); +UINT16 EXISP_I2C_CalibrationLscMaxBGainGet(void); +UINT16 EXISP_I2C_CalibrationAWBRGainGet(void); +UINT16 EXISP_I2C_CalibrationAWBGGainGet(void); +UINT16 EXISP_I2C_CalibrationAWBBGainGet(void); +UINT8 EXISP_I2C_CalibrationExecStatus1Get(void); +UINT8 EXISP_I2C_CalibrationExecStatus2Get(void); +UINT8 EXISP_I2C_CalibrationErrorStatus1Get(void); +UINT8 EXISP_I2C_CalibrationErrorStatus2Get(void); +UINT8 EXISP_I2C_CalibrationErrorCodeGet(void); +UINT8 EXISP_I2C_CalibrationLoadTableStatusGet(void); + + +UINT8 EXISP_SuspendGpioCfgSet(UINT8 ucCtl); +UINT8 EXISP_DigitalPowerCfgSet(UINT8 On); +UINT8 EXISP_AnalogPowerCfgSet(UINT8 On); +UINT8 EXISP_ClockCfgSet(UINT8 ucEnable); +UINT8 EXISP_ResetGpioCfgSet(UINT8 ucCtl); +UINT8 EXISP_PowerOn(UINT8 ucBoot); +UINT8 EXISP_PowerOff(void); +UINT8 EXISP_LoadCodeStart( + UINT8 ucBoot, + UINT8 ucFwIdx, + UINT8 is_calibration, + UINT8 *pIspFw, + UINT8 *pCalibOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq); +UINT8 EXISP_LoadCode( + UINT8 ucFwIdx, + UINT8 is_calibration, + UINT8 *pIspFw, + UINT8 *pCalibOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq); +void EXISP_UpdateCalibResStart( + UINT8 ucFwIdx, + UINT8 *pIspFw, + ispFwHeaderInfo_t *pFwInfo, + ispLoadCodeRet_t *pLoadCodeRet, + UINT8 ucCaliOpt, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq); +UINT8 EXISP_UpdateCalibRes( + UINT8 idx, + UINT8 *pIspFw, + ispFwHeaderInfo_t *pFwInfo, + UINT8 *p3acali, + UINT8 *pLsc, + UINT8 *pLscdq); +UINT8 EXISP_ResCheck(UINT8 idx, UINT8 *p3acali, UINT8 *pLsc, UINT8 *Lscdq); +UINT8 EXISP_ResNumGet(UINT32 *resNum, UINT8 *pIspFw); +UINT8 EXISP_SPIDataWrite(UINT8 ucSPIMode, UINT8 *ucStartAddr, UINT32 ulTransByteCnt, UINT32 ulDmaAddr); +UINT8 EXISP_7002SPICfg(UINT8 ucSPIMode, UINT32 ulDmaAddr, UINT32 ulTransByteCnt); +UINT8 EXISP_PvSizeSet(UINT8 ucResolutionIdx); +UINT8 EXISP_ImageCapSet(UINT8 ucImageCapIdx); +UINT8 EXISP_TAFTAEROISet( + UINT8 ucTrg, + UINT16 usTAFSize, + UINT16 usTAFX, + UINT16 usTAFY, + UINT16 usTAESize, + UINT16 usTAEX, + UINT16 usTAEY); +UINT8 EXISP_SwitchRAWFormatSet(void); +UINT8 EXISP_ExifInfoGet( + UINT8 *ucExpTimeNumerator, + UINT32 *ulExpTimeDenominator, + UINT8 *ucExpTimeCompensation, + UINT16 *usLensFocalLength, + UINT16 *usIsoInfo, + UINT8 *ucFlashInfo); + +#endif /* APP_I2C_LIB_ICATCH_H */ + diff --git a/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c b/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c new file mode 100755 index 000000000000..0053acd99719 --- /dev/null +++ b/drivers/media/video/icatch7002/burn_spi_sample_code_0910.c @@ -0,0 +1,1247 @@ +#include "app_i2c_lib_icatch.h" +#include +#include +#include +#include "icatch7002_common.h" + +#define SPI_CMD_BYTE_READ 0x03 +#define SPI_CMD_RD_ID 0x9F +#define SPI_CMD_WRT_EN 0x06 +#define SPI_CMD_BYTE_PROG 0x02 +#define SPI_CMD_RD_STS 0x05 +#define SPI_CMD_BYTE_PROG_AAI 0xAD +#define SPI_CMD_WRT_STS_EN 0x50 +#define SPI_CMD_WRT_STS 0x01 +#define SPI_CMD_WRT_DIS 0x04 +#define SPI_CMD_ERASE_ALL 0xC7 +#define SPI_CMD_SECTOR_ERASE 0x20 +#define SPI_CMD_32KB_BLOCK_ERASE 0x52 +#define SPI_CMD_64KB_BLOCK_ERASE 0xD8 +#define WAIT_COUNT 100 + +#define I2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) +#define I2CDataRead(reg) icatch_sensor_read((reg)) +#define osMemAlloc(len) kzalloc((len), GFP_KERNEL); +#define osMemFree(pbuf) kfree(pbuf) +#define seqI2CDataRead(reg,buf) *((u8*)(buf))= icatch_sensor_read(reg) +#define seqI2CDataWrite(reg,buf) icatch_sensor_write((reg),(*(u8*)(buf))) + +#define hsI2CDataRead(reg) icatch_sensor_read((reg)) +#define hsI2CDataWrite(reg,val) icatch_sensor_write((reg),(val)) + +#ifndef tmrUsDelay +#define tmrUsWait(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) +#endif +#define ros_thread_sleep(ulTime) (((ulTime)>1000)?(msleep((ulTime)/1000)):udelay((ulTime))) + + +//local declare +void I2C_SPIInit(void); +UINT32 I2C_SPIFlashReadId(void); +UINT32 BB_SerialFlashTypeCheck(UINT32 id,UINT32 *spiSize); +void BB_EraseSPIFlash(UINT32 type,UINT32 spiSize); +UINT32 I2C_SPISstFlashWrite(UINT32 addr,UINT32 pages,UINT8 *pbuf); +UINT32 I2C_SPIFlashWrite_DMA(UINT32 addr,UINT32 pages,UINT32 usage,UINT8 *pbuf); +UINT32 I2C_SPI64KBBlockErase(UINT32 address,UINT32 stFlag); +UINT32 I2C_SPI32KBBlockErase(UINT32 address,UINT32 stFlag); +UINT32 I2C_SPISectorErase(UINT32 address,UINT32 stFlag); + +static const UINT32 stSpiIdInfo[7][3] = +{ + /*Winbond*/ + {0x00EF3017,4096, 2048}, + {0x00EF3016,4096, 1024}, + {0x00EF3015,4096, 512}, + {0x00EF3014,4096, 256}, + {0x00EF5014,4096, 256}, + {0x00EF3013,4096, 128}, + {0x00EF5013,4096, 128}, + /*Fail*/ + {0x00000000,0,0}, +}; + +static const UINT32 sstSpiIdInfo[6][3] = +{ + /*ESMT*/ + {0x008C4016,4096,512}, + /*SST*/ + {0x00BF254A,4096,1024}, + {0x00BF2541,4096,512}, + {0x00BF258E,4096,256}, + {0x00BF258D,4096,128}, + /*Fail*/ + {0x00000000,0,0}, +}; + +/* BB_WrSPIFlash ¬° main function for burning SPI */ +UINT32 I2C_SPIStChipErase( + void +); + +void +BB_WrSPIFlash( + UINT32 size +) +{ + UINT32 id, type; + UINT32 pages, spiSize; + + UINT32 fd, fileSize; + UINT8* pbootBuf = NULL; + const struct firmware *fw = NULL; + + printk("loadcode from file\n"); + /*#define FILE_PATH_BOOTCODE "D:\\FPGA.IME"*/ + //#define FILE_PATH_BOOTCODE "D:\\DCIM\\BOOT.BIN" + + //fd = sp5kFsFileOpen( FILE_PATH_BOOTCODE, SP5K_FS_OPEN_RDONLY ); + #if 0 + if( icatch_request_firmware(&fw) !=0){ + printk("%s:%d,requst firmware failed!!\n",__func__,__LINE__); + goto out; + } + #endif + I2CDataWrite(0x70c4,0x00); + I2CDataWrite(0x70c5,0x00); + + I2CDataWrite(0x1011,0x01); /* CPU Reset */ + I2CDataWrite(0x001C,0x08);/* FM reset */ + I2CDataWrite(0x001C,0x00); + I2CDataWrite(0x108C,0x00);/* DMA select */ + I2CDataWrite(0x009a,0x00);/*CPU normal operation */ +#if 0 + if(fd != 0) + { + fileSize = sp5kFsFileSizeGet(fd); + printk("fileSize:0x%x\n",fileSize); + pbootBuf= (UINT8*)sp5kMalloc(fileSize); + sp5kFsFileRead(fd, pbootBuf, fileSize); + printk("pbootBuf:0x%x\n",pbootBuf); + fsFileClose(fd); + } + else + { + printk("file open error\n"); + return; + } +#endif + fileSize = fw->data; + pbootBuf = fw->size; + if(pbootBuf == NULL) + { + printk("buffer allocate failed\n"); + goto out; + } + + I2C_SPIInit(); + + id = I2C_SPIFlashReadId(); + if(id==0) + { + printk("read id failed\n"); + goto out; + } + /*printk("spiSize:0x%x\n",&spiSize);*/ + type = BB_SerialFlashTypeCheck(id, &spiSize); + if( type == 0 ) + { + printk("read id failed\n"); + goto out; + } + + if( size > 0 && size < fileSize ) + { + pages = size/0x100; + if((size%0x100)!=0) + pages += 1; + } + else + { + pages = fileSize/0x100; + } + /*printk("pages:0x%x\n",pages);*/ + + //BB_EraseSPIFlash(type,spiSize); + I2C_SPIStChipErase(); + msleep(4*1000); + if( type == 2 ) + { + printk("SST operation\n"); + I2C_SPISstFlashWrite(0,pages,pbootBuf); + } + else if( type == 1 || type == 3 ) + { + printk("ST operation\n"); + I2C_SPIFlashWrite_DMA(0,pages,1,pbootBuf); + } +out: + if(fw) + icatch_release_firmware(fw); + return; + +// osMemFree(pbootBuf); +} + +UINT32 +BB_SerialFlashTypeCheck( + UINT32 id, + UINT32 *spiSize +) +{ + UINT32 i=0; + UINT32 fullID = 1; + UINT32 shift = 0, tblId, type = 0; + /*printk("id:0x%x spiSize:0x%x\n",id,spiSize);*/ + /* check whether SST type serial flash */ + while( 1 ){ + tblId = sstSpiIdInfo[i][0] >> shift; + if( id == tblId ) { + printk("SST type serial flash:%x %x %x\n",i,id,sstSpiIdInfo[i][0]); + type = 2; + *spiSize = sstSpiIdInfo[i][1]*sstSpiIdInfo[i][2]; + break; + } + if( id == 0x00FFFFFF || id == 0x00000000) { + return 0; + } + if( sstSpiIdInfo[i][0] == 0x00000000 ) { + #if 0 + if( fullID ){ + fullID = 0;/* sarch partial ID */ + i = 0; + shift = 16; + id = id >> shift; + continue; + } + #endif + type = 3; + break; + } + i ++; + } + if( type == 2 ) + return type; + + i = 0; + /* check whether ST type serial flash */ + while( 1 ){ + tblId = stSpiIdInfo[i][0] >> shift; + if( id == tblId ) { + printk("ST Type serial flash:%x %x %x\n",i,id,stSpiIdInfo[i][0]); + type = 1; + *spiSize = stSpiIdInfo[i][1]*stSpiIdInfo[i][2]; + /*printk("spiSize:0x%x\n",*spiSize);*/ + break; + } + if( id == 0x00FFFFFF || id == 0x00000000) { + return 0; + } + if( stSpiIdInfo[i][0] == 0x00000000 ) { + if( fullID ){ + fullID = 0;/* sarch partial ID */ + i = 0; + shift = 16; + id = id >> shift; + continue; + } + type = 3; + break; + } + i ++; + } + + return type; +} + +void +BB_EraseSPIFlash( + UINT32 type, + UINT32 spiSize +) +{ + UINT8 typeFlag; + UINT32 i, temp1; + if( type == 2 )/* SST */ + { + typeFlag = 0; + } + else if( type == 1 || type == 3 )/* ST */ + { + typeFlag = 1; + } + /*printk("spiSize:0x%x\n",spiSize);*/ + if(spiSize == (512*1024)) + { + /* skip 0x7B000 ~ 0x7EFF, to keep calibration data */ + temp1 = (spiSize / 0x10000)-1; + for(i=0;i 4.8us */ { + break; + } + time ++; + if( *ptimeOut < time ) { + printk("TimeOut %d, sts=0x%x, poll=0x%x\n",time,sts,poll); + break; + } + } +} + +UINT32 I2C_SPIStChipErase( + void +) +{ + UINT32 timeout; + printk("ST Chip Erasing...\n"); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); + I2C_SPIFlashPortWrite(0x02); + hsI2CDataWrite(0x40e7,0x01); + + I2C_SPIFlashWrEnable(); + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_ERASE_ALL); + hsI2CDataWrite(0x40e7,0x01); + + timeout = 0xffffffff; + I2C_SPITimeOutWait(0x01, &timeout); + ros_thread_sleep(1); + hsI2CDataWrite(0x40e7,0x01); + return SUCCESS; +} + + +UINT32 I2C_SPISstChipErase( + void +) +{ + UINT32 timeout; + printk("SST Chip Erasing...\n"); + + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ + hsI2CDataWrite(0x40e7,0x01); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); + I2C_SPIFlashPortWrite(0x02); + hsI2CDataWrite(0x40e7,0x01); + + I2C_SPIFlashWrEnable(); + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_ERASE_ALL); + hsI2CDataWrite(0x40e7,0x01); + + timeout = 0xffffffff; + I2C_SPITimeOutWait(0x01, &timeout); + + return SUCCESS; +} + +UINT32 I2C_SPISectorErase( + UINT32 address, + UINT32 stFlag +) +{ + UINT32 timeout; + printk("addr:0x%x\n",address); + if(!stFlag) + { + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ + hsI2CDataWrite(0x40e7,0x01); + } + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ + I2C_SPIFlashPortWrite(0x02); + hsI2CDataWrite(0x40e7,0x01); + + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_SECTOR_ERASE); + I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ + I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ + I2C_SPIFlashPortWrite(address); /* A07~A00 */ + hsI2CDataWrite(0x40e7,0x01); + + timeout = 5000000; + I2C_SPITimeOutWait(0x01, &timeout); + + return SUCCESS; +} + +UINT32 I2C_SPI32KBBlockErase( + UINT32 address, + UINT32 stFlag +) +{ + UINT32 timeout; + printk("addr:0x%x\n",address); + if(!stFlag) + { + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ + hsI2CDataWrite(0x40e7,0x01); + } + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ + I2C_SPIFlashPortWrite(0x02); + hsI2CDataWrite(0x40e7,0x01); + + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_32KB_BLOCK_ERASE); + I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ + I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ + I2C_SPIFlashPortWrite(address); /* A07~A00 */ + hsI2CDataWrite(0x40e7,0x01); + + timeout = 5000000; + I2C_SPITimeOutWait(0x01, &timeout); + + return SUCCESS; +} + +UINT32 I2C_SPI64KBBlockErase( + UINT32 address, + UINT32 stFlag +) +{ + UINT32 timeout; + printk("addr:0x%x\n",address); + if(!stFlag) + { + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); /*Write Status register command*/ + hsI2CDataWrite(0x40e7,0x01); + } + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ + I2C_SPIFlashPortWrite(0x02); + hsI2CDataWrite(0x40e7,0x01); + + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_64KB_BLOCK_ERASE); + I2C_SPIFlashPortWrite(address >> 16); /* A23~A16 */ + I2C_SPIFlashPortWrite(address >> 8); /* A15~A08 */ + I2C_SPIFlashPortWrite(address); /* A07~A00 */ + hsI2CDataWrite(0x40e7,0x01); + + timeout = 5000000; + I2C_SPITimeOutWait(0x01, &timeout); + + return SUCCESS; +} + + +/*------------------------------------------------------------------------- + * File Name : I2C_SPIFlashWrite + * addr: SPI flash starting address + pages: pages size for data -> datasize = pages * pagesize(0x100) + pbuf: data buffer + * return SUCCESS: normal finish + FAIL: write failed + *------------------------------------------------------------------------*/ +UINT32 I2C_SPIFlashWrite( + UINT32 addr, + UINT32 pages, + UINT8 *pbuf +) +{ + UINT32 i, err = SUCCESS; + UINT32 pageSize = 0x100; + UINT32 timeout = 100000; + UINT32 rsvSec1, rsvSec2; + + rsvSec1 = pages*pageSize - 0x5000; + rsvSec2 = pages*pageSize - 0x1000; + addr = addr * pageSize; + + printk("ST type writing...\n"); + while( pages ) { + if((pages%0x40)==0)printk("page:0x%x\n",pages); + if((addr>=rsvSec1) && (addr > 16)); /* Send 3 bytes address*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); + I2C_SPIFlashPortWrite((UINT8)(addr)); + + for (i = 0; i < pageSize ; i++) { + I2C_SPIFlashPortWrite(*pbuf); + pbuf++; + } + hsI2CDataWrite(0x40e7,0x01); + addr += pageSize; + pages --; + tmrUsWait(400); + } + + return err; +} + +void I2C_SPISstStatusWrite(UINT8 dat) +{ + UINT32 timeout, poll; + + I2C_SPIFlashWrEnable(); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS_EN); + hsI2CDataWrite(0x40e7,0x01); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_STS); + I2C_SPIFlashPortWrite(dat); + hsI2CDataWrite(0x40e7,0x01); + + poll = 0x01; + + timeout = 100000; + I2C_SPITimeOutWait(poll, &timeout); + return; +} + +void I2C_SPIStStatusWrite( + UINT8 value, + UINT8 value2 +) +{ + I2C_SPIFlashWrEnable(); + + #if 1 + hsI2CDataWrite(0x40e7,0x00); + //has not implement spi related interface,zyc +// halSpiPortWrite(SPI_CMD_WRT_STS); /*Write Status register command*/ +// halSpiPortWrite(value); +// halSpiPortWrite(value2); + hsI2CDataWrite(0x40e7,0x01); + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(0x04); + hsI2CDataWrite(0x40e7,0x01); + #endif +} + +UINT32 I2C_SPISstFlashWrite( + UINT32 addr, + UINT32 pages, + UINT8 *pbuf +) +{ + UINT32 i, err = SUCCESS; + UINT32 pageSize = 0x100; + UINT32 timeout = 100000; + + addr = addr * pageSize; + + printk("SST type writing...\n"); + I2C_SPISstStatusWrite(0x40); + while( pages ) { + printk("page:0x%x\n",pages); + if((addr>=0x7C000) && (addr <0x7F000)) + { + addr += 0x1000; + pages -= 0x10; + continue; + } + I2C_SPIFlashWrEnable(); + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_BYTE_PROG_AAI); /* Write one byte command*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); + I2C_SPIFlashPortWrite((UINT8)(addr)); + I2C_SPIFlashPortWrite(*pbuf); + pbuf++; + I2C_SPIFlashPortWrite(*pbuf); + pbuf++; + hsI2CDataWrite(0x40e7,0x01); + timeout = 100000; + I2C_SPITimeOutWait(0x01,&timeout); + + for (i = 2; i < pageSize ; i = i+2) { + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_BYTE_PROG_AAI); + I2C_SPIFlashPortWrite(*pbuf); + pbuf++; + I2C_SPIFlashPortWrite(*pbuf); + pbuf++; + hsI2CDataWrite(0x40e7,0x01); + timeout = 100000; + I2C_SPITimeOutWait(0x01,&timeout); + } + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_DIS); + hsI2CDataWrite(0x40e7,0x01); + + addr += pageSize; + pages --; + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_WRT_DIS); + hsI2CDataWrite(0x40e7,0x01); + } + + return err; +} + + +/*------------------------------------------------------------------------- + * File Name : I2C_SPIFlashRead + * addr: SPI flash starting address + pages: pages size for data -> datasize = pages * pagesize(0x100) + pbuf: data buffer + * return SUCCESS: normal finish + FAIL: read failed + *------------------------------------------------------------------------*/ +UINT32 I2C_SPIFlashRead( + UINT32 addr, + UINT32 pages, + UINT8 *pbuf +) +{ + UINT8* pbufR; + UINT32 ch, err = SUCCESS; + UINT32 i, ret, count=0, size=0, bytes, offset; + UINT32 pageSize = 0x100; + + + addr = addr * pageSize; + size = pages*pageSize; + + I2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_BYTE_READ); /* Write one byte command*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); + I2C_SPIFlashPortWrite((UINT8)(addr)); + + for (i = 0; i < size ; i++) { + *pbuf = I2C_SPIFlashPortRead(); + if((i%256)==0) + printk("page:0x%x\n",(i/256)); + pbuf ++; + } + + I2CDataWrite(0x40e7,0x01); + + return err; +} + +UINT32 I2C_7002DmemWr( + UINT32 bankNum, + UINT32 byteNum, + UINT8* pbuf +) +{ + UINT32 i, bank; + + bank = 0x40+bankNum; + I2CDataWrite(0x10A6,bank); + + //for(i=0;i=rsvSec2) || (i =0x10000) + { + chk1 -= 0x10000; + } + } + + while( pages ) { + if((pages%0x40)==0) + { + printk("page:0x%x",pages); + } + if((addr>=rsvSec1) && (addr > 16)); /* Send 3 bytes address*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); + I2C_SPIFlashPortWrite((UINT8)(addr)); + + I2CDataWrite(0x4160,0x01); + count = 30; + pbuf += pageSize; + addr += pageSize; + pages --; + while( hsI2CDataRead(0x4003) == 0 ) + { + count--; + tmrUsWait(200);/* wait for DMA done */ + if( count == 0 ) + { + printk("DMA time out: %2x, 0x%2x%2x, %2x\n",pages, + hsI2CDataRead(0x4179),hsI2CDataRead(0x4178),hsI2CDataRead(0x40E6)); + hsI2CDataWrite(0x4011,0x10); + hsI2CDataWrite(0x1010,0x02); + pbuf -= pageSize; + addr -= pageSize; + pages ++; + hsI2CDataWrite(0x1010,0x00); + break; + } + } + hsI2CDataWrite(0x4003, 0x02); + I2CDataWrite(0x40e7,0x01); + } + + tmrUsWait(500);/* wait for DMA done */ + + temp = hsI2CDataRead(0x4285); + chk2 = hsI2CDataRead(0x4284); + chk2 = chk2 | (temp<<8); + printk("checksum: 0x%x 0x%x\n",chk1,chk2); + + return err; +} + +UINT32 I2C_7002DmemRd( + UINT32 bankNum, + UINT32 byteNum, + UINT8* pbuf +) +{ + UINT32 i, bank; + + bank = 0x40+bankNum; + hsI2CDataWrite(0x10A6,bank); + + //for(i=0;i pageSize ) + { + tempSize = 0x100; + size -= tempSize; + } + else + { + tempSize = size; + size = 0; + } + + hsI2CDataWrite(0x40e7,0x00); + I2C_SPIFlashPortWrite(SPI_CMD_BYTE_READ); /* Write one byte command*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 16)); /* Send 3 bytes address*/ + I2C_SPIFlashPortWrite((UINT8)(addr >> 8)); + I2C_SPIFlashPortWrite((UINT8)(addr)); + + if( ((size/0x100)%0x40)==0x00 ) + { + printk("RE:0x%x\n",((size/0x100)%0x40)); + } + dmemBank = count % 2; + hsI2CDataWrite(0x1081,dmemBank*0x20); + hsI2CDataWrite(0x1084,(1<>4)<<4; + UINT32 resLscDqSize = ((13276+15)>>4)<<4; +#else /* for 8M sensor IMX175 */ + UINT32 resOffset = 0x5000; + UINT32 res3acaliSize = 528; + UINT32 resLscSize = ((2292+15)>>4)<<4; + UINT32 resLscDqSize = ((8521+15)>>4)<<4; +#endif + + UINT32 startSector, finalSector, sectorCount; + + UINT8* pBuf; + + if( resId > 0x02 ) + { + printk(" ID ERROR \n"); + return FAIL; + } + + I2C_SPIInit(); + + spiId = I2C_SPIFlashReadId(); + if( spiId == 0 ) + { + printk("read id failed\n"); + return FAIL; + } + /*printk("spiSize:0x%x\n",&spiSize);*/ + spiType = BB_SerialFlashTypeCheck(spiId, &spiSize); + + if( resId == 0x00 )/* 3ACALI.BIN */ + { + resStartAddr = spiSize - resOffset; + resEndAddr = resStartAddr + res3acaliSize; + resSize = res3acaliSize; + } + else if( resId == 0x01 )/* LSC.BIN */ + { + resStartAddr = spiSize - resOffset + res3acaliSize; + resEndAddr = resStartAddr + resLscSize; + resSize = resLscSize; + } + else /* LSC_DQ.BIN */ + { + resStartAddr = spiSize -resOffset + res3acaliSize + resLscSize; + resEndAddr = resStartAddr + resLscDqSize; + resSize = resLscDqSize; + } + printk("%x %x %x\n", resStartAddr, resEndAddr, resSize); + + startSector = (resStartAddr/sectorSize)*sectorSize; + finalSector = (resEndAddr/sectorSize)*sectorSize; + sectorCount = ((finalSector - startSector)/sectorSize) + 1; + residue = resStartAddr - startSector; + + pBuf = osMemAlloc( sectorCount * sectorSize ); + printk("%x %x %x %x\n", startSector, finalSector, sectorCount, residue); + + I2C_SPIFlashRead_DMA(startSector,(sectorCount*sectorSize),pBuf); + + memcpy((pBuf+residue), resBuf, resSize); + + if( spiType == 2 ) + { + for( i=0; i 0x02 ) + { + printk(" ID ERROR \n"); + return FAIL; + } + + I2C_SPIInit(); + + spiId = I2C_SPIFlashReadId(); + if( spiId == 0 ) + { + printk("read id failed\n"); + return FAIL; + } + /*printk("spiSize:0x%x\n",&spiSize);*/ + spiType = BB_SerialFlashTypeCheck(spiId, &spiSize); + + if( resId == 0x00 )/* 3ACALI.BIN */ + { + resStartAddr = spiSize - resOffset; + resSize = res3acaliSize; + } + else if( resId == 0x01 )/* LSC.BIN */ + { + resStartAddr = spiSize - resOffset + (((res3acaliSize+0x0f)>>4)<<4); + resSize = resLscSize; + } + else /* LSC_DQ.BIN */ + { + resStartAddr = spiSize -resOffset + (((res3acaliSize+0x0f)>>4)<<4) + + (((resLscSize+0x0f)>>4)<<4); + resSize = resLscDqSize; + } + /*printk("%x %x\n", resStartAddr, resSize);*/ + + /* buffer used to stored calibration data */ + pBuf = osMemAlloc( resSize ); + printk("pBuf resSize:%x %x\n", pBuf, resSize); + + I2C_SPIFlashRead_DMA(resStartAddr,resSize,pBuf); + *bufAddr = pBuf; + printk("pBuf resSize:%x %x\n", (*bufAddr), resSize); + + *size = resSize; + + return SUCCESS; +} diff --git a/drivers/media/video/icatch7002/icatch7002_common.c b/drivers/media/video/icatch7002/icatch7002_common.c new file mode 100755 index 000000000000..0639212b12c2 --- /dev/null +++ b/drivers/media/video/icatch7002/icatch7002_common.c @@ -0,0 +1,2548 @@ +#define __ICATCH7002_COMMON_CFILE__ +#include "icatch7002_common.h" +#include +#include + +#define CONFIG_SENSOR_I2C_SPEED 300000 /* 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_NAME_STRING() sensor->dev_name + + +#define ICATCHFWNAME "icatch7002boot.bin" + +u8 g_Calibration_Option_Def = 0xff; +bool IsZSL = FALSE; + +#ifdef CALIBRATION_MODE_FUN +struct icatch_cali_fw_data { + const char * const fname_option; + struct firmware const*fw_option; + const char * const fname_3acali; + struct firmware const*fw_3acali; + const char * const fname_lsc; + struct firmware const*fw_lsc; + const char * const fname_lscdq; + struct firmware const*fw_lscdq; +}; + +struct icatch_cali_fw_data g_cali_fw_data_front = { + .fname_option = "icatch7002/calibration_option.BIN", + .fname_3acali = "icatch7002/3ACALI_F.BIN", + .fname_lsc = "icatch7002/LSC_F.BIN", + .fname_lscdq = "icatch7002/LSC_DQ_F.BIN", +}; + +struct icatch_cali_fw_data g_cali_fw_data_back = { + .fname_option = "icatch7002/calibration_option.BIN", + .fname_3acali = "icatch7002/3ACALI.BIN", + .fname_lsc = "icatch7002/LSC.BIN", + .fname_lscdq = "icatch7002/LSC_DQ.BIN", +}; +#endif + +#define ICATCH_BOOT_FROM_SPI 0 +#define ICATCH_BOOT_FROM_HOST 1 +#define ICATCH_BOOT ICATCH_BOOT_FROM_HOST +#define ASUS_CAMERA_SUPPORT 1 + +#ifndef FAIL +#define FAIL 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#if 1 + +static struct rk_sensor_reg rs_reset_data[]={ + {0x1011,0x01}, + {0x001c,0x08}, + {0x001c,0x00}, + {0x1010,0x02}, + {0x1010,0x00}, + {0x1306,0x00},//0 rear,1 front + {0x1011,0x00}, + SensorEnd +}; + +static struct rk_sensor_reg fs_reset_data[]={ + {0x1011,0x01}, + {0x001c,0x08}, + {0x001c,0x00}, + {0x1010,0x02}, + {0x1010,0x00}, + {0x1306,0x01},//0 rear,1 front + {0x1011,0x00}, + SensorEnd +}; + +static struct rk_sensor_reg init_data[]={ + {SP7K_MSG_COLOR_EFFECT, 0x0}, // normal + {SP7K_MSG_EV_COMPENSATION, 0x6}, // 0 + {SP7K_MSG_FLASH_MODE, 0x1}, // off + {SP7K_MSG_FOCUS_MODE, 0x0}, // auto + {SP7K_MSG_PV_SIZE, 0x0}, // 1280*960 + {SP7K_MSG_SCENE_MODE, 0x0}, // normal + {SP7K_MSG_WHITE_BALANCE, 0x0}, // auto + {SP7K_MSG_CAP_ISO, 0x0}, //auto + {SP7K_MSG_AURA_COLOR_INDEX, 0x0}, // disable + {SP7K_MSG_PV_CAP_MODE, 0x4}, // idle + SensorEnd +}; +#endif + +struct i2c_client *g_icatch_i2c_client = NULL; +#if CONFIG_SENSOR_WhiteBalance +static int icatch_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)); + u8 set_val = 0; + struct generic_sensor*sensor = to_generic_sensor(client); + + DEBUG_TRACE("%s: value = %d\n", __FUNCTION__, value); + + if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) + { + switch(value){ + case 0: //enable auto + set_val = 0x0; + break; + case 1: //incandescent Tungsten + set_val = 0x6; + break; + case 2: //fluorescent + set_val = 0x5; + break; + case 3: //daylight + set_val = 0x1; + break; + case 4: //cloudy-daylight + set_val = 0x2; + break; + default: + break; + } + //awb + EXISP_I2C_WhiteBalanceSet(set_val); + return 0; + } + DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); + return -1; +} +#endif + +#if CONFIG_SENSOR_Effect +static int icatch_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value, int auravalue) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + u8 set_val = 0; + struct generic_sensor*sensor = to_generic_sensor(client); + DEBUG_TRACE("set effect,value = %d ......\n",value); + if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) + { + switch(value){ + case 0: //normal + case 5: //none + set_val = 0x00; + break; + case 1: //aqua + set_val = 0x01; + break; + case 2: //negative + set_val = 0x02; + break; + case 3: //sepia + set_val = 0x03; + break; + case 4: //mono Grayscale + set_val = 0x04; + break; + case 6: //aura + set_val = 0x06; + break; + case 7: //vintage + set_val = 0x07; + break; + case 8: //vintage2 + set_val = 0x08; + break; + case 9: //lomo + set_val = 0x09; + break; + case 10: //red + set_val = 0x0A; + break; + case 11: //blue + set_val = 0x0B; + break; + case 12: //green + set_val = 0x0C; + break; + default: + set_val = value; + break; + } + EXISP_I2C_ColorEffectSet(set_val); + if(set_val == 6){ + EXISP_I2C_AuraColorIndexSet(auravalue); + } + return 0; + } + DEBUG_TRACE("\n%s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); + return -1; +} +#endif + +#if CONFIG_SENSOR_Scene +static int icatch_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)); + u8 set_val = 0; + struct generic_sensor*sensor = to_generic_sensor(client); +//when scene mod is working , face deteciton and awb and iso are not recomemnded. + if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) + { + switch(value){ + case 0: //normal + set_val = 0x00; + break; + case 1: //auto + set_val = 0x00; + break; + case 2: //landscape + set_val = 0x10; + break; + case 3: //night + set_val = 0x07; + break; + case 4: //night_portrait + set_val = 0x08; + break; + case 5: //snow + set_val = 0x0B; + break; + case 6: //sports + set_val = 0x0C; + break; + case 7: //candlelight + set_val = 0x04; + break; + + default: + break; + } + + EXISP_I2C_SceneModeSet(set_val); + DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); + return 0; + } + DEBUG_TRACE("\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)); + u8 set_val = 0x0; + struct generic_sensor*sensor = to_generic_sensor(client); + if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) + { + set_val = 6 - value; + EXISP_I2C_EvSet(set_val); + DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); + return 0; + } + DEBUG_TRACE("\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)); + return 0; +} +#endif + +#if CONFIG_SENSOR_Flip +//off 0x00;mirror 0x01,flip 0x10; +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)); + return 0; + +} +#endif + +#if CONFIG_SENSOR_ISO +static int sensor_set_iso(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + u8 set_val = 0x0; + struct generic_sensor*sensor = to_generic_sensor(client); + if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) + { + set_val = value; + EXISP_I2C_ISOSet(set_val); + DEBUG_TRACE("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value); + return 0; + } + DEBUG_TRACE("\n %s..%s valure = %d is invalidate.. \n",SENSOR_NAME_STRING(),__FUNCTION__,value); + return -EINVAL; +} +#endif +void __dump_i2c(UINT16 addr_s, UINT16 addr_e); +static void sensor_interrupt_wait_clear() +{ + int loop_cnt = 0; + + printk("sensor_interrupt_wait_clear() Entry\n"); + while((icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0) & 0x04) == 0){ + msleep(10); + if(loop_cnt++ == 100){ + __dump_i2c(0x7200,0x727F); + __dump_i2c(0x7072,0x7075); + __dump_i2c(0x72F8,0x72F8); + __dump_i2c(0x7005,0x7006); + } + } + icatch_sensor_write(SP7K_RDREG_INT_STS_REG_0,(icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0)|0x04)); + printk("sensor_interrupt_wait_clear() Exit\n"); +} + +#if CONFIG_SENSOR_Wdr +// EXISP_I2C_IspFuncSet(), bit 0 : DWDR +static void sensor_set_wdr(bool Enable) +{ + if(Enable){ + EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) | 0x01); + }else{ + EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) &~0x01); + } +} +#endif + +#if CONFIG_SENSOR_EDGE +static void sensor_set_edge(bool Enable) +{ + if(Enable){ + EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) | 0x02); + }else{ + EXISP_I2C_IspFuncSet( icatch_sensor_read(SP7K_REG_BASE|(SP7K_MSG_ISP_FUNCTION&0x7F)) &~0x02); + } +} +#endif + + +static int icatch_sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) +{ + return 0; +} +static int icatch_sensor_resume(struct soc_camera_device *icd) +{ + return 0; + +} +static int icatch_sensor_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + + return 0; +} + + +#if CALIBRATION_MODE_FUN +struct proc_dir_entry *g_icatch7002_proc_entry = NULL; +#define PROC_ENTRY_NAME SENSOR_NAME_STRING() +int g_is_calibrationMode = 0; +char g_procbuff[1024]; +union icatch_fw_version { + __u32 fw; + struct { + __u8 b1; + __u8 b2; + __u8 b3; + __u8 b4; + }; +} g_fw_version; +int icatch_proc_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + if (off > 0) { + *eof = 1; + return 0; + } + + len = sprintf(page, "fw %02x.%02x.%02x\nis_calibration %d\n", + g_fw_version.b3, g_fw_version.b2, g_fw_version.b1, + g_is_calibrationMode); + return len; +} + +int icatch_proc_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char *ptr = NULL; + if (count >= sizeof(g_procbuff)) { + DEBUG_TRACE("%s no space\n", __FUNCTION__); + return -ENOSPC; + } + + if (copy_from_user(g_procbuff, buffer, count)) { + DEBUG_TRACE("%s copy from user fail %d\n", __FUNCTION__, count); + return -EFAULT; + } + g_procbuff[count] = 0; + + if ( (ptr = strstr(g_procbuff, "is_calibration")) == NULL) { + goto l_ret; + } + + ptr += strlen("is_calibration"); + while(*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r') { + ptr++; + } + + switch (*ptr) { + case '0': + g_is_calibrationMode = 0; + DEBUG_TRACE("%s disable calibration mode\n", __FUNCTION__); + break; + case '1': + g_is_calibrationMode = 1; + DEBUG_TRACE("%s enable calibration mode\n", __FUNCTION__); + break; + } + +l_ret: + return count; +} + +void icatch_create_proc_entry() +{ + struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); + + if (g_icatch7002_proc_entry == NULL) { + DEBUG_TRACE("%s need create_proc_entry\n", __FUNCTION__); + g_fw_version.fw = 0; + g_icatch7002_proc_entry = create_proc_entry(PROC_ENTRY_NAME, O_RDWR, NULL); + if (g_icatch7002_proc_entry) { + memset(g_procbuff, 0, sizeof(g_procbuff)); + g_icatch7002_proc_entry->read_proc = icatch_proc_read; + g_icatch7002_proc_entry->write_proc = icatch_proc_write; + } else { + DEBUG_TRACE("%s create_proc_entry fail\n", __FUNCTION__); + } + } +} + +void icatch_remove_proc_entry() +{ + struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); + if (g_icatch7002_proc_entry != NULL) { + remove_proc_entry(PROC_ENTRY_NAME, NULL); + g_icatch7002_proc_entry = NULL; + } +} +#endif + +#if 1//CONFIG_SENSOR_Focus + +void __dump_i2c(UINT16 addr_s, UINT16 addr_e) { + int size = (addr_e - addr_s + 1); + int i = 0; + int soffset = addr_s%16; + char buf[100] = {0}; + char lbuf[12]; + + for (i = 0; i < soffset; i++) { + if (i == 0) { + sprintf(lbuf, "%08X:", addr_s / 16 * 16); + strcat(buf, lbuf); + } + sprintf(lbuf, " "); + strcat(buf, lbuf); + } + + size += soffset; + i = soffset; + while( i < size) { + if ((i%16 == 0) && (i != 0)) { + printk("%s\n", buf); + } + if (i%16 == 0) { + buf[0] = 0; + sprintf(lbuf, "%08X:", (addr_s + i - soffset) / 16 * 16); + strcat(buf, lbuf); + } + sprintf(lbuf, " %02X", icatch_sensor_read(addr_s + i - soffset)); + strcat(buf, lbuf); + i++; + } + + printk("%s\n", buf); +} + +static void icatch_mapping_zone(const char * tag, struct rk_sensor_focus_zone *dst, const int *rect) +{ + DEBUG_TRACE("%s: %s set from (%d, %d), (%d, %d)\n", + __FUNCTION__, tag, + dst->lx, dst->ty, + dst->rx, dst->dy); + + dst->lx = ((rect[0] + 1000) * 1024)/2001; + dst->ty = ((rect[1] + 1000) * 1024)/2001; + dst->rx = ((rect[2] + 1000) * 1024)/2001; + dst->dy = ((rect[3] + 1000) * 1024)/2001; + + DEBUG_TRACE("%s: %s to (%d, %d), (%d, %d)\n", + __FUNCTION__, tag, + dst->lx, dst->ty, + dst->rx, dst->dy); +} + +//value: disable metering area +//force_set: if not set, it will not drive the sensor +// to set metering area really if focus is +// supported. +//rect: set to NULL if don't want to change. +static int icatch_set_metering_zone( + struct specific_sensor *sensor, + __s32 value, + rk_sensor_tae_zone zone, + int force_set) +{ + int ret = 0, w = 0, iret = 0; + + if ( sensor->isp_priv_info.MeteringAreas != value) { + DEBUG_TRACE("%s set metering areas to %d\n", + __FUNCTION__, + value); + } + + if (value == 0) { + if (sensor->isp_priv_info.MeteringAreas > 0) { + if ( EXISP_TAFTAEROISet( + TAFTAE_TAE_OFF, + 0,0,0,0,0,0 ) != SUCCESS) + { + ret = -EINVAL; + } + } + sensor->isp_priv_info.MeteringAreas = value; + return ret; + } + + sensor->isp_priv_info.MeteringAreas = value; + + if (force_set) { + goto f_set; + } + + if (sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_AUTO) || + sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_CONTINUOUS) || + sensor_find_ctrl(sensor->common_sensor.ctrls, V4L2_CID_FOCUS_ABSOLUTE) ) { + return ret; + } + +f_set: + //set TAE if focus is not supported + + w = sensor->isp_priv_info.tae_zone.rx - sensor->isp_priv_info.tae_zone.lx; + if (w < 0) { + w = -w; + } + + DEBUG_TRACE("%s: set TAE zone to (%d, %d), (%d, %d)\n", + __FUNCTION__, + sensor->isp_priv_info.tae_zone.lx, + sensor->isp_priv_info.tae_zone.ty, + sensor->isp_priv_info.tae_zone.rx, + sensor->isp_priv_info.tae_zone.dy); + + if (w == 0) { + iret = EXISP_TAFTAEROISet(TAFTAE_TAE_ONLY, 0, 0, 0, 0x80, 0x1bf, 0x1bf); + } else { + iret = EXISP_TAFTAEROISet( + TAFTAE_TAE_ONLY, + 0, 0, 0, + w, + sensor->isp_priv_info.tae_zone.lx, + sensor->isp_priv_info.tae_zone.ty); + } + + if (iret != SUCCESS) { + ret = -EINVAL; + } + + return ret; +} + +int icatch_sensor_set_auto_focus(struct i2c_client *client, int value,int *tmp_zone) +{ + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + + //u8 zone_x = 0x0,zone_y = 0x0; // 0->0x0f + UINT16 w = 0; + int ret = 0; + int cnt = 100; + int set_val; + + ret = icatch_set_metering_zone( + sensor, + sensor->isp_priv_info.MeteringAreas, + sensor->isp_priv_info.tae_zone, + 1); + if (ret) { + return ret; + } + + if(value == WqCmd_af_single) + set_val = 0; + else if(value == WqCmd_af_update_zone){ + icatch_mapping_zone( + "focus zone", + &sensor->isp_priv_info.focus_zone, + tmp_zone); + return 0; + + }else if(value == WqCmd_af_continues) + set_val = 3; + else{ + + } + + EXISP_I2C_FocusModeSet(set_val); + + //EXISP_I2C_AFROITriggerSet(); + if (value != WqCmd_af_far_pos) { + //EXISP_I2C_ROISwitchSet(01); + //set the zone + DEBUG_TRACE("%s: lx = %d,rx = %d,ty = %d,dy = %d\n", __FUNCTION__, sensor->isp_priv_info.focus_zone.lx,sensor->isp_priv_info.focus_zone.rx,sensor->isp_priv_info.focus_zone.ty,sensor->isp_priv_info.focus_zone.dy); + w = sensor->isp_priv_info.focus_zone.rx - sensor->isp_priv_info.focus_zone.lx; + //zone_x = (sensor->isp_priv_info.focus_zone.lx << 4) | (sensor->isp_priv_info.focus_zone.rx & 0x0f); + //zone_y = (sensor->isp_priv_info.focus_zone.ty << 4) | (sensor->isp_priv_info.focus_zone.dy & 0x0f); + //auto focus + //sendI2cCmd(client, 0x0E, 0x00); + if( w != 0) { + EXISP_TAFTAEROISet( + TAFTAE_TAF_ONLY, + w, + sensor->isp_priv_info.focus_zone.lx, + sensor->isp_priv_info.focus_zone.ty, + 0, 0, 0); + DEBUG_TRACE("%s:auto focus, val = %d, w = 0x%x, x = 0x%x y = 0x%x\n",__func__,value, w, sensor->isp_priv_info.focus_zone.lx, sensor->isp_priv_info.focus_zone.ty); + }else{ + EXISP_TAFTAEROISet(TAFTAE_TAF_ONLY, 0x80, 0x1bf, 0x1bf, 0, 0, 0); + DEBUG_TRACE("%s:auto focus, all zero, val = %d, size=0x80, x=0x1bf, y=0x1bf\n",__func__,value); + } + } + + while (cnt--) { + if (EXISP_I2C_AFStatusGet() == 0) { + break; + } + msleep(30); + } + + //__dump_i2c(0x7200, 0x727f); + + if (cnt <= 0) { + DEBUG_TRACE("%s: focus timeout %d\n",__func__, value); + //__dump_i2c(0x7005, 0x7005); + return 1; + } + + if (EXISP_I2C_AFResultGet() != 0) { + DEBUG_TRACE("%s: focus fail %d\n",__func__, value); + return 1; + } + + DEBUG_TRACE("%s: focus success %d\n\n",__func__, value); + return 0; +} + + +#endif + +int icatch_sensor_init(struct i2c_client *client) +{ + struct soc_camera_device *icd = client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + // struct isp_data * sensor = spnsor->isp_priv_info; + struct v4l2_queryctrl* qctrl; + int pid = 0; + u8 sensorid = 0; + char* sensorid_str = NULL; + struct sensor_v4l2ctrl_info_s* qctrl_info; + + sensorid_str = strstr(dev_name(icd->pdev),"front"); + if(sensorid_str) + sensorid = 1; + else + sensorid = 0; + +#if CALIBRATION_MODE_FUN + if (g_is_calibrationMode == 1 ) { + if (sensorid == SENSOR_ID_REAR) + sensorid = SENSOR_ID_REAR_CALIBRATION; + + DEBUG_TRACE("%s CALIBRATION MODE is enable, SENSOR_ID:%d\n", __FUNCTION__, sensorid); + } + sensor->isp_priv_info.sensor_id = sensorid; +#endif + + DEBUG_TRACE("@@NY@@%s: %d\n", __FUNCTION__, sensorid); + sensor->isp_priv_info.curRes = -1; + sensor->isp_priv_info.curPreviewCapMode = IDLE_MODE; + sensor->isp_priv_info.had_setprvsize = 0; + sensor->isp_priv_info.hdr = false; + +#if CALIBRATION_MODE_FUN + sensor->isp_priv_info.rk_query_PreviewCapMode = IDLE_MODE; +#endif + g_icatch_i2c_client = client; + + +#if 0 + //get id check +{ + int count = 200; + while(count--){ + pid = icatch_sensor_read(0x0004); + DEBUG_TRACE("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid); + mdelay(1000); + } +} +#endif + + if(icatch_load_fw(icd,sensorid)<0){ + DEBUG_TRACE("icatch7002 load sensor %d firmware failed!!-->%s:%d\n",sensorid, __FUNCTION__, __LINE__); + return -ENODEV; + } +#if 0 + if(sensorid == SENSOR_ID_FRONT){ + // front camera + icatch_sensor_write_array((void*)fs_reset_data); + } + else{ + // rear camera + icatch_sensor_write_array((void*)rs_reset_data); + } + + //50Hz + EXISP_I2C_BandSelectionSet(0x01); + //DEBUG_TRACE("%s Set BandSelection to 50Hz\n", __FUNCTION__); + + //get id check + mdelay(100); + pid = EXISP_I2C_RearSensorIdGet(); + DEBUG_TRACE("\n %s pid = 0x%x\n", SENSOR_NAME_STRING(), pid); + if (pid != SENSOR_ID) { + DEBUG_TRACE("error: %s mismatched pid = 0x%x\n", SENSOR_NAME_STRING(), pid); + return -ENODEV; + } +#endif + + //50Hz + EXISP_I2C_BandSelectionSet(0x01); + /* sensor sensor information for initialization */ + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_DO_WHITE_BALANCE); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.whiteBalance = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_BRIGHTNESS); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.brightness = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EFFECT); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.effect = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EXPOSURE); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl){ + sensor->isp_priv_info.exposure = qctrl->default_value; + } + + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_SATURATION); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.saturation = qctrl->default_value; + + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_CONTRAST); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.contrast = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_HFLIP); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.mirror = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_VFLIP); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.flip = qctrl->default_value; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_SCENE); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl){ + sensor->isp_priv_info.scene = qctrl->default_value; + } +#if CONFIG_SENSOR_AntiBanding + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ANTIBANDING); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.antibanding = qctrl->default_value; +#endif +#if CONFIG_SENSOR_WhiteBalanceLock + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_WHITEBALANCE_LOCK); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.WhiteBalanceLock = qctrl->default_value; +#endif +#if CONFIG_SENSOR_ExposureLock + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_EXPOSURE_LOCK); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.ExposureLock = qctrl->default_value; +#endif +#if CONFIG_SENSOR_MeteringAreas + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_METERING_AREAS); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.MeteringAreas = qctrl->default_value; +#endif +#if CONFIG_SENSOR_Wdr + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_WDR); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.Wdr = qctrl->default_value; +#endif +#if CONFIG_SENSOR_EDGE + sensor_set_edge(1); +#endif + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ZOOM_ABSOLUTE); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.digitalzoom = qctrl->default_value; + /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code */ + //qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_AUTO); +#if 0 + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_FOCUS_AUTO); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.auto_focus = SENSOR_AF_AUTO; + + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_FACEDETECT); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.face = qctrl->default_value; +#endif +#if CONFIG_SENSOR_ISO + qctrl_info =sensor_find_ctrl(sgensor->ctrls, V4L2_CID_ISO); + if(qctrl_info) + qctrl = qctrl_info->qctrl; + if (qctrl) + sensor->isp_priv_info.iso = qctrl->default_value; +#endif + return 0; +} + + + +/* sensor register read */ +static int icatch_sensor_burst_read( u16 reg, u16 len, __u8 *buffer) +{ + struct generic_sensor*sensor = to_generic_sensor(g_icatch_i2c_client); + + int err,cnt; + u8 buf[2]; + struct i2c_msg msg[2]; + struct i2c_client* client =g_icatch_i2c_client; + + 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 = buffer; + msg[1].len = len; + 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[0], 1); + + if (err >= 0) { + break; + } else { + DEBUG_TRACE("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, buf[0]); + udelay(10); + } + } + + if(err <0) + return -FAIL; + + 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], 1); + + if (err >= 0) { + break; + } else { + DEBUG_TRACE("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, buf[0]); + udelay(10); + } + } + if(err >=0) + return 0; + else + return -FAIL; +} + +struct icatch_dumpreg_dsc { + __u16 addr; + __u16 len; + unsigned long user_ptr; +}; + +static int icatch_dump_regs(void __user * arg) +{ + int err, ret = 0; + struct icatch_dumpreg_dsc dsc; + __u8 *buf = NULL; + + err = !access_ok(VERIFY_READ, + (void __user *)arg, sizeof(struct icatch_dumpreg_dsc)); + + if (err) { + DEBUG_TRACE("%s(%d) error to access argument\n", + __FUNCTION__, __LINE__); + return -EACCES; + } + + if (copy_from_user( + &dsc, arg, + sizeof(struct icatch_dumpreg_dsc))) { + return -EFAULT; + } + + if (dsc.len == 0) { + DEBUG_TRACE("%s length is 0\n", __FUNCTION__); + return -EINVAL; + } + + DEBUG_TRACE("%s add=0x%04x len=%d\n", + __FUNCTION__, + dsc.addr, dsc.len); + + if ( !access_ok(VERIFY_WRITE, + (void __user *)dsc.user_ptr, dsc.len)) { + DEBUG_TRACE("%s(%d) error to access user_ptr\n", + __FUNCTION__, __LINE__); + return -EACCES; + } + + buf = kmalloc( dsc.len, GFP_KERNEL); + if (buf == NULL) { + return -ENOMEM; + } + + //dump + ret = icatch_sensor_burst_read(dsc.addr, dsc.len, buf); + if (ret < 0) { + DEBUG_TRACE("%s(%d) error read these regs\n", + __FUNCTION__, __LINE__); + goto l_exit; + } + + + if (copy_to_user(dsc.user_ptr, buf, dsc.len)) { + DEBUG_TRACE("%s(%d) fail to copy to user_ptr\n", + __FUNCTION__, __LINE__); + ret = -EFAULT; + goto l_exit; + } + +l_exit: + if (buf != NULL) + kfree(buf); + DEBUG_TRACE("%s(%d) return value %d\n", + __FUNCTION__, __LINE__, + ret); + return ret; +} + +static int icatch_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl,struct v4l2_queryctrl *qctrl) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + int ret = 0; + + switch (ext_ctrl->id) + { + case V4L2_CID_SCENE: + { + ext_ctrl->value = sensor->isp_priv_info.scene; + break; + } +#if CONFIG_SENSOR_AntiBanding + case V4L2_CID_ANTIBANDING: + { + ext_ctrl->value = sensor->isp_priv_info.antibanding; + break; + } +#endif +#if CONFIG_SENSOR_WhiteBalanceLock + case V4L2_CID_WHITEBALANCE_LOCK: + { + ext_ctrl->value = sensor->isp_priv_info.WhiteBalanceLock; + break; + } +#endif +#if CONFIG_SENSOR_ExposureLock + case V4L2_CID_EXPOSURE_LOCK: + { + ext_ctrl->value = sensor->isp_priv_info.ExposureLock; + break; + } +#endif +#if CONFIG_SENSOR_MeteringAreas + case V4L2_CID_METERING_AREAS: + { + ext_ctrl->value = sensor->isp_priv_info.MeteringAreas; + break; + } +#endif +#if CONFIG_SENSOR_Wdr + case V4L2_CID_WDR: + { + ext_ctrl->value = sensor->isp_priv_info.Wdr; + break; + } +#endif +#if CONFIG_SENSOR_EDGE + case V4L2_CID_EDGE: + { + ext_ctrl->value = EXISP_I2C_CapEdgeInfoGet(); + break; + } +#endif + case V4L2_CID_EFFECT: + { + ext_ctrl->value = sensor->isp_priv_info.effect; + break; + } + case V4L2_CID_ZOOM_ABSOLUTE: + { + ext_ctrl->value = sensor->isp_priv_info.digitalzoom; + break; + } + case V4L2_CID_ZOOM_RELATIVE: + { + return -EINVAL; + } + case V4L2_CID_FOCUS_ABSOLUTE: + { + return -EINVAL; + } + case V4L2_CID_FOCUS_RELATIVE: + { + return -EINVAL; + } + case V4L2_CID_FLASH: + { + ext_ctrl->value = sensor->isp_priv_info.flash; + break; + } + case V4L2_CID_FACEDETECT: + { + ext_ctrl->value =sensor->isp_priv_info.face ; + break; + } +#if CONFIG_SENSOR_ISO + case V4L2_CID_ISO: + { + ext_ctrl->value = sensor->isp_priv_info.iso; + if(ext_ctrl->value == 0){ + ext_ctrl->value = icatch_sensor_read(SP7K_RDREG_ISO_H); + ext_ctrl->value <<= 8; + ext_ctrl->value |= icatch_sensor_read(SP7K_RDREG_ISO_L); + } + break; + } +#endif +#if CONFIG_SENSOR_JPEG_EXIF + case V4L2_CID_JPEG_EXIF: + { + RkExifInfo *pExitInfo = (RkExifInfo *)ext_ctrl->value; + + UINT8 ucExpTimeNumerator; + UINT32 ulExpTimeDenominator; + UINT8 ucExpTimeCompensation; + UINT16 usLensFocalLength; + UINT16 usIsoInfo; + UINT8 ucFlashInfo; + + EXISP_ExifInfoGet( + &ucExpTimeNumerator, + &ulExpTimeDenominator, + &ucExpTimeCompensation, + &usLensFocalLength, + &usIsoInfo, + &ucFlashInfo); + + pExitInfo->ExposureTime.num = ucExpTimeNumerator; + pExitInfo->ExposureTime.denom = ulExpTimeDenominator; + //pExitInfo->Flash = ucFlashInfo; + pExitInfo->ISOSpeedRatings = usIsoInfo; + pExitInfo->FocalPlaneYResolution.num = EXISP_I2C_CapEdgeInfoGet(); + pExitInfo->ExposureBiasValue.num = sensor->isp_priv_info.exposure ; + pExitInfo->ExposureBiasValue.denom = 3; + + break; + } +#endif + +#if CONFIG_SENSOR_DUMPREGS + case V4L2_CID_DUMPREGS: + { + //static long icatch_dump_regs(void __user * arg); + return icatch_dump_regs(ext_ctrl->string); + } +#endif + default : + ret = -1; + break; + } + return ret; +} + + +static int icatch_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl,struct v4l2_queryctrl *qctrl) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + int val_offset; + int ret = 0; + + val_offset = 0; + switch (ext_ctrl->id) + { +#if CONFIG_SENSOR_Scene + case V4L2_CID_SCENE: + { + if (ext_ctrl->value != sensor->isp_priv_info.scene) + { + if (icatch_set_scene(icd, qctrl,ext_ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.scene = ext_ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_AntiBanding + case V4L2_CID_ANTIBANDING: + { + if (ext_ctrl->value != sensor->isp_priv_info.antibanding) + { + if(ext_ctrl->value){ + EXISP_I2C_BandSelectionSet(2); //60Hz + }else{ + EXISP_I2C_BandSelectionSet(1); //50Hz + } + sensor->isp_priv_info.antibanding = ext_ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_WhiteBalanceLock + case V4L2_CID_WHITEBALANCE_LOCK: + { + if (ext_ctrl->value != sensor->isp_priv_info.WhiteBalanceLock) + { + if(ext_ctrl->value){ + EXISP_I2C_VendreqCmdSet(4); + }else{ + EXISP_I2C_VendreqCmdSet(6); + } + sensor->isp_priv_info.WhiteBalanceLock = ext_ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_ExposureLock + case V4L2_CID_EXPOSURE_LOCK: + { + if (ext_ctrl->value != sensor->isp_priv_info.ExposureLock) + { + if(ext_ctrl->value){ + EXISP_I2C_VendreqCmdSet(3); + }else{ + EXISP_I2C_VendreqCmdSet(5); + } + sensor->isp_priv_info.ExposureLock = ext_ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_MeteringAreas + case V4L2_CID_METERING_AREAS: + { + if (ext_ctrl->value) { + icatch_mapping_zone( + "metering zone", + &sensor->isp_priv_info.tae_zone, + ext_ctrl->rect); + } + ret = icatch_set_metering_zone( + sensor, + ext_ctrl->value, + sensor->isp_priv_info.tae_zone, + 0); + sensor->isp_priv_info.MeteringAreas = ext_ctrl->value; + break; + } +#endif +#if CONFIG_SENSOR_Wdr + case V4L2_CID_WDR: + { + if (ext_ctrl->value != sensor->isp_priv_info.Wdr) + { + sensor_set_wdr(ext_ctrl->value); + sensor->isp_priv_info.Wdr = ext_ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Effect + case V4L2_CID_EFFECT: + { + if (ext_ctrl->value != sensor->isp_priv_info.effect) + { + if (icatch_set_effect(icd, qctrl,ext_ctrl->value,ext_ctrl->rect[0]) != 0) + return -EINVAL; + sensor->isp_priv_info.effect= ext_ctrl->value; + } + if(sensor->isp_priv_info.effect == 6) + { + EXISP_I2C_AuraColorIndexSet(ext_ctrl->rect[0]); + } + break; + } +#endif +#if CONFIG_SENSOR_DigitalZoom + case V4L2_CID_ZOOM_ABSOLUTE: + { + DEBUG_TRACE("V4L2_CID_ZOOM_ABSOLUTE ...... ext_ctrl->value = %d\n",ext_ctrl->value); + if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum)){ + return -EINVAL; + } + + if (ext_ctrl->value != sensor->isp_priv_info.digitalzoom) + { + val_offset = ext_ctrl->value -sensor->isp_priv_info.digitalzoom; + + if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0) + return -EINVAL; + sensor->isp_priv_info.digitalzoom += val_offset; + + DEBUG_TRACE("%s digitalzoom is %x\n",sgensor->dev_name, sensor->isp_priv_info.digitalzoom); + } + + break; + } + case V4L2_CID_ZOOM_RELATIVE: + { + if (ext_ctrl->value) + { + if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.digitalzoom += ext_ctrl->value; + + DEBUG_TRACE("%s digitalzoom is %x\n", sgensor->dev_name, sensor->isp_priv_info.digitalzoom); + } + 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; + + DEBUG_TRACE("%s flash is %x\n",sgensor->dev_name, sensor->isp_priv_info.flash); + break; + } +#endif +#if CONFIG_SENSOR_FACE_DETECT + case V4L2_CID_FACEDETECT: + { + if(sensor->isp_priv_info.face != ext_ctrl->value){ + if (sensor_set_face_detect(client, ext_ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.face = ext_ctrl->value; + DEBUG_TRACE("%s face value is %x\n",sgensor->dev_name, sensor->isp_priv_info.face); + } + break; + } +#endif +#if CONFIG_SENSOR_ISO + case V4L2_CID_ISO: + { + if (sensor->isp_priv_info.iso != ext_ctrl->value) { + if (sensor_set_iso(icd, qctrl, ext_ctrl->value) != 0) { + return -EINVAL; + } + sensor->isp_priv_info.iso = ext_ctrl->value; + DEBUG_TRACE("%s set ISO to %d\n", sgensor->dev_name, sensor->isp_priv_info.iso); + } + break; + } +#endif + default: + ret = -1; + break; + } + + return ret; +} + +static int icatch_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl,struct v4l2_queryctrl *qctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + int ret = 0; + + + switch (ctrl->id) + { + case V4L2_CID_BRIGHTNESS: + { + ctrl->value = sensor->isp_priv_info.brightness; + break; + } + case V4L2_CID_SATURATION: + { + ctrl->value = sensor->isp_priv_info.saturation; + break; + } + case V4L2_CID_CONTRAST: + { + ctrl->value = sensor->isp_priv_info.contrast; + break; + } + case V4L2_CID_DO_WHITE_BALANCE: + { + ctrl->value = sensor->isp_priv_info.whiteBalance; + break; + } + case V4L2_CID_EXPOSURE: + { + ctrl->value = sensor->isp_priv_info.exposure; + break; + } + case V4L2_CID_HFLIP: + { + ctrl->value = sensor->isp_priv_info.mirror; + break; + } + case V4L2_CID_VFLIP: + { + ctrl->value = sensor->isp_priv_info.flip; + break; + } + case V4L2_CID_ZOOM_ABSOLUTE: + { + ctrl->value = sensor->isp_priv_info.digitalzoom; + break; + } + default : + ret = -1; + break; + } + return ret; +} + +static int icatch_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl,struct v4l2_queryctrl *qctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + struct soc_camera_device *icd = client->dev.platform_data; + int ret = 0; + + switch (ctrl->id) + { +#if CONFIG_SENSOR_Brightness + case V4L2_CID_BRIGHTNESS: + { + if (ctrl->value != sensor->isp_priv_info.brightness) + { + if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0) + { + return -EINVAL; + } + sensor->isp_priv_info.brightness = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Exposure + case V4L2_CID_EXPOSURE: + { + if (ctrl->value != sensor->isp_priv_info.exposure) + { + if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0) + { + return -EINVAL; + } + sensor->isp_priv_info.exposure = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Saturation + case V4L2_CID_SATURATION: + { + if (ctrl->value != sensor->isp_priv_info.saturation) + { + if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0) + { + return -EINVAL; + } + sensor->isp_priv_info.saturation = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Contrast + case V4L2_CID_CONTRAST: + { + if (ctrl->value != sensor->isp_priv_info.contrast) + { + if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0) + { + return -EINVAL; + } + sensor->isp_priv_info.contrast = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_WhiteBalance + case V4L2_CID_DO_WHITE_BALANCE: + { + if (ctrl->value != sensor->isp_priv_info.whiteBalance) + { + if (icatch_set_whiteBalance(icd, qctrl,ctrl->value) != 0) + { + return -EINVAL; + } + sensor->isp_priv_info.whiteBalance = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Mirror + case V4L2_CID_HFLIP: + { + if (ctrl->value != sensor->isp_priv_info.mirror) + { + if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.mirror = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_Flip + case V4L2_CID_VFLIP: + { + if (ctrl->value != sensor->isp_priv_info.flip) + { + if (sensor_set_flip(icd, qctrl,ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.flip = ctrl->value; + } + break; + } +#endif +#if CONFIG_SENSOR_DigitalZoom + case V4L2_CID_ZOOM_ABSOLUTE: + { + int val_offset = 0; + DEBUG_TRACE("V4L2_CID_ZOOM_ABSOLUTE ...... ctrl->value = %d\n",ctrl->value); + if ((ctrl->value < qctrl->minimum) || (ctrl->value > qctrl->maximum)){ + return -EINVAL; + } + + if (ctrl->value != sensor->isp_priv_info.digitalzoom) + { + val_offset = ctrl->value -sensor->isp_priv_info.digitalzoom; + + if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0) + return -EINVAL; + sensor->isp_priv_info.digitalzoom += val_offset; + + DEBUG_TRACE("%s digitalzoom is %x\n",sgensor->dev_name, sensor->isp_priv_info.digitalzoom); + } + + break; + } + case V4L2_CID_ZOOM_RELATIVE: + { + if (ctrl->value) + { + if (sensor_set_digitalzoom(icd, qctrl,&ctrl->value) != 0) + return -EINVAL; + sensor->isp_priv_info.digitalzoom += ctrl->value; + + DEBUG_TRACE("%s digitalzoom is %x\n", sgensor->dev_name, sensor->isp_priv_info.digitalzoom); + } + break; + } +#endif + default: + ret = -1; + break; + } + + return ret; +} + +int sensor_set_get_control_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl,bool is_set) +{ + int ret = 0; + struct v4l2_control ctrl; + + if(is_set){ + // belong to ext_control ? + ret = icatch_s_ext_control(icd, ext_ctrl,ctrl_info->qctrl); + if(ret == 0){ + ctrl_info->cur_value = ext_ctrl->value; + goto sensor_set_get_control_cb_end; + } + // belong to control? + ctrl.id = ext_ctrl->id; + ctrl.value = ext_ctrl->value; + ret = icatch_s_control(soc_camera_to_subdev(icd), &ctrl,ctrl_info->qctrl); + if(ret == 0){ + ctrl_info->cur_value = ctrl.value; + goto sensor_set_get_control_cb_end; + } + + }else{ + // belong to ext_control ? + ret = icatch_g_ext_control(icd, ext_ctrl,ctrl_info->qctrl); + + if(ret == 0){ + ctrl_info->cur_value = ext_ctrl->value; + goto sensor_set_get_control_cb_end; + } + // belong to control? + ctrl.id = ext_ctrl->id; + ret = icatch_g_control(soc_camera_to_subdev(icd), &ctrl,ctrl_info->qctrl); + if(ret == 0){ + ctrl_info->cur_value = ctrl.value; + goto sensor_set_get_control_cb_end; + } + + } + +sensor_set_get_control_cb_end: + return ret; + + +} +static int sensor_hdr_exposure(struct i2c_client *client, unsigned int code) +{ + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + //printk("sensor_hdr_exposure_cb: %d %d\n",code,sensor->isp_priv_info.exposure); + switch (code) + { + case RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1: + { + //if( (sensor->isp_priv_info.exposure - 1 >= -6) && (sensor->isp_priv_info.exposure - 1 <= 6) ){ + // EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure - 1); + //} + printk("RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1\n"); + if(IsZSL){ + printk("EXISP_ImageCapSet(IMAGE_CAP_HDR)\n"); + EXISP_ImageCapSet(IMAGE_CAP_HDR); + sensor_interrupt_wait_clear(); + } + break; + } + + case RK_VIDEOBUF_HDR_EXPOSURE_NORMAL: + { + //EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure); + sensor->isp_priv_info.hdr = true; + break; + } + + case RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1: + { + //if( (sensor->isp_priv_info.exposure + 1 >= -6) && (sensor->isp_priv_info.exposure + 1 <= 6) ){ + // EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure + 1); + //} + break; + } + + case RK_VIDEOBUF_HDR_EXPOSURE_FINISH: + { + printk("HDR_EXPOSURE_FINISH\n"); + sensor->isp_priv_info.hdr = FALSE; + //EXISP_I2C_EvSet(6 - sensor->isp_priv_info.exposure); + if(IsZSL){ + u8 res_sel = 0; + if(sensor->isp_priv_info.curRes == OUTPUT_QSXGA){ + res_sel = 0xA; + }else if(sensor->isp_priv_info.curRes == OUTPUT_QUADVGA){ + res_sel = 0; + } + printk("HDR_EXPOSURE_FINISH Switch resolution\n"); + EXISP_PvSizeSet(res_sel); + sensor_interrupt_wait_clear(); + } + break; + } + default: + break; + } + + return 0; +} + + long icatch_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + switch (cmd){ + case RK29_CAM_SUBDEV_HDR_EXPOSURE: + { + sensor_hdr_exposure(client,(unsigned int)arg); + break; + } + + default: + { + //SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd); + break; + } + } + + return 0; +} + + + + int icatch_s_fmt(struct i2c_client *client, struct v4l2_mbus_framefmt *mf) +{ + const struct sensor_datafmt *fmt; + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + //const struct v4l2_queryctrl *qctrl; + //struct soc_camera_device *icd = client->dev.platform_data; + int ret=0; + int set_w,set_h; + int supported_size = sensor->isp_priv_info.outputSize; + int res_set = 0; + u8 preview_cap_mode = 0;//0 is preview mode + set_w = mf->width; + set_h = mf->height; + if (((set_w <= 176) && (set_h <= 144)) && (supported_size & OUTPUT_QCIF)) + { + set_w = 176; + set_h = 144; + res_set = OUTPUT_QCIF; + } + else if (((set_w <= 320) && (set_h <= 240)) && (supported_size & OUTPUT_QVGA)) + { + set_w = 320; + set_h = 240; + res_set = OUTPUT_QVGA; + + } + else if (((set_w <= 352) && (set_h<= 288)) && (supported_size & OUTPUT_CIF)) + { + set_w = 352; + set_h = 288; + res_set = OUTPUT_CIF; + + } + else if (((set_w <= 640) && (set_h <= 480)) && (supported_size & OUTPUT_VGA)) + { + set_w = 640; + set_h = 480; + res_set = OUTPUT_VGA; + + } + else if (((set_w <= 800) && (set_h <= 600)) && (supported_size & OUTPUT_SVGA)) + { + set_w = 800; + set_h = 600; + res_set = OUTPUT_SVGA; + + } + else if (((set_w <= 1024) && (set_h <= 768)) && (supported_size & OUTPUT_XGA)) + { + set_w = 1024; + set_h = 768; + res_set = OUTPUT_XGA; + + } + else if (((set_w <= 1280) && (set_h <= 720)) && (supported_size & OUTPUT_720P)) + { + set_w = 1280; + set_h = 720; + res_set = OUTPUT_720P; + } + + else if (((set_w <= 1280) && (set_h <= 960)) && (supported_size & OUTPUT_QUADVGA)) + { + set_w = 1280; + set_h = 960; + res_set = OUTPUT_QUADVGA; + } + else if (((set_w <= 1280) && (set_h <= 1024)) && (supported_size & OUTPUT_XGA)) + { + set_w = 1280; + set_h = 1024; + res_set = OUTPUT_XGA; + } + else if (((set_w <= 1600) && (set_h <= 1200)) && (supported_size & OUTPUT_UXGA)) + { + set_w = 1600; + set_h = 1200; + res_set = OUTPUT_UXGA; + } + else if (((set_w <= 1920) && (set_h <= 1080)) && (supported_size & OUTPUT_1080P)) + { + set_w = 1920; + set_h = 1080; + res_set = OUTPUT_1080P; + } + else if (((set_w <= 2048) && (set_h <= 1536)) && (supported_size & OUTPUT_QXGA)) + { + set_w = 2048; + set_h = 1536; + res_set = OUTPUT_QXGA; + } + else if (((set_w <= 2592) && (set_h <= 1944)) && (supported_size & OUTPUT_QSXGA)) + { + set_w = 2592; + set_h = 1944; + res_set = OUTPUT_QSXGA; + } + else + { + set_w = 1280; + set_h = 960; + res_set = OUTPUT_QUADVGA; + } + + //if(res_set != sensor->isp_priv_info.curRes) + // sensor_set_isp_output_res(client,res_set); + //res will be setted + sensor->isp_priv_info.curRes = res_set; + mf->width = set_w; + mf->height = set_h; + //enter capture or preview mode + //EXISP_I2C_PvCapModeSet(preview_cap_mode); + DEBUG_TRACE("%s:setw = %d,seth = %d\n",__func__,set_w,set_h); + + sensor_s_fmt_end: + return ret; + } + +int icatch_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize) +{ + int err = 0,i=0,num = 0; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + + printk("icatch_enum_framesizes fsize->reserved[0](%x) fsize->reserved[1](%x)\n",fsize->reserved[0],fsize->reserved[1]); + if( (fsize->reserved[1] & 0xff) == 0x01){ + IsZSL = TRUE; + }else{ + IsZSL = FALSE; + } + + //get supported framesize num + + if (fsize->index >= sensor->isp_priv_info.supportedSizeNum) { + err = -1; + goto end; + } + + if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QCIF)) + { + + fsize->discrete.width = 176; + fsize->discrete.height = 144; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QVGA)) + { + fsize->discrete.width = 320; + fsize->discrete.height = 240; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_CIF) ) + { + + fsize->discrete.width = 352; + fsize->discrete.height = 288; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_VGA)) + { + + fsize->discrete.width = 640; + fsize->discrete.height = 480; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_SVGA)) + { + + fsize->discrete.width = 800; + fsize->discrete.height = 600; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_XGA)) + { + + fsize->discrete.width = 1024; + fsize->discrete.height = 768; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_720P)) + { + + fsize->discrete.width = 1280; + fsize->discrete.height = 720; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QUADVGA)) + { + fsize->discrete.width = 1280; + fsize->discrete.height = 960; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_XGA)) + { + fsize->discrete.width = 1280; + fsize->discrete.height = 1024; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_UXGA) ) + { + fsize->discrete.width = 1600; + fsize->discrete.height = 1200; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_1080P)) + { + fsize->discrete.width = 1920; + fsize->discrete.height = 1080; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QXGA)) + { + fsize->discrete.width = 2048; + fsize->discrete.height = 1536; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } + else if ((sensor->isp_priv_info.supportedSize[fsize->index] & OUTPUT_QSXGA)) + { + + fsize->discrete.width = 2592; + fsize->discrete.height = 1944; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + } else { + err = -1; + } + + + +end: + return err; +} + + +/*------------------------------------------------------------------------- + * Function Name : EXISP_I2C_PvSizeSet + * ucParam: + 0x00 1280x960 + 0x01 3264x2448 + 0x02 1920x1080 + 0x03 320x240(reserved) + 0x04 1280x720 + 0x05 1040x780 + 0x06 2080x1560 + 0x07 3648x2736 + 0x08 4160x3120 + 0x09 3360x1890 + 0x0A 2592x1944 + 0x0B 640x480 + 0x0C 1408x1408 + 0x0D 1920x1088 + * Return : None + *------------------------------------------------------------------------*/ + +static int icatch_set_isp_output_res(struct i2c_client *client,enum ISP_OUTPUT_RES outputSize){ + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); +#if 0 + u8 res_sel = 0; + switch(outputSize) { + case OUTPUT_QCIF: + case OUTPUT_HQVGA: + case OUTPUT_QVGA: + case OUTPUT_CIF: + case OUTPUT_VGA: + case OUTPUT_SVGA: + case OUTPUT_720P: + case OUTPUT_QUADVGA: + res_sel = 0; + break; + case OUTPUT_XGA: + case OUTPUT_SXGA: + case OUTPUT_UXGA: + case OUTPUT_1080P: + case OUTPUT_QXGA: + case OUTPUT_QSXGA: + res_sel = IMAGE_CAP_NONZSL_SINGLE;// non-zsl single + break; + default: + DEBUG_TRACE("%s %s isp not support this resolution!\n",sgensor->dev_name,__FUNCTION__); + break; + } +#endif + int cnt = 16; + //preview mode set + if(outputSize == OUTPUT_QSXGA){ + if(sensor->isp_priv_info.hdr == FALSE){ + if(IsZSL){ + printk("IsZSL EXISP_PvSizeSet(0x0A)\n"); + EXISP_PvSizeSet(0x0A); + //polling until AE ready + while (((EXISP_I2C_3AStatusGet() & 0x1) == 0) && (cnt -- > 0)) { + DEBUG_TRACE("%s %s polling AE ready\n",sgensor->dev_name,__FUNCTION__); + mdelay(50); + } + sensor_interrupt_wait_clear(); + }else{ + printk("Is not ZSL HdrEn FALSE EXISP_ImageCapSet(IMAGE_CAP_NONZSL_SINGLE)\n"); + icatch_sensor_write(SP7K_RDREG_INT_STS_REG_0,icatch_sensor_read(SP7K_RDREG_INT_STS_REG_0)); + EXISP_ImageCapSet(IMAGE_CAP_NONZSL_SINGLE); + sensor_interrupt_wait_clear(); + } + }else{ + printk("HdrEn EXISP_ImageCapSet(IMAGE_CAP_HDR)\n"); + EXISP_ImageCapSet(IMAGE_CAP_HDR); + sensor_interrupt_wait_clear(); + } + sensor->isp_priv_info.curPreviewCapMode = CAPTURE_NONE_ZSL_MODE; + } + else{ + EXISP_PvSizeSet(IMAGE_CAP_SINGLE); + //polling until AE ready + while (((EXISP_I2C_3AStatusGet() & 0x1) == 0) && (cnt -- > 0)) { + DEBUG_TRACE("%s %s polling AE ready\n",sgensor->dev_name,__FUNCTION__); + mdelay(50); + } + sensor_interrupt_wait_clear(); + sensor->isp_priv_info.curPreviewCapMode = PREVIEW_MODE; +#if 1 + DEBUG_TRACE("\n %s pid = 0x%x\n", sgensor->dev_name, EXISP_I2C_VendorIdGet); + DEBUG_TRACE("fw version is 0x%x\n ",EXISP_I2C_FWVersionGet()); + + DEBUG_TRACE("front id= 0x%x,rear id = 0x%x\n ",EXISP_I2C_FrontSensorIdGet(),EXISP_I2C_RearSensorIdGet()); +#endif + } + return 0; +} + + int icatch_s_stream(struct v4l2_subdev *sd, int enable){ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_device *icd = client->dev.platform_data; + struct generic_sensor*sgensor = to_generic_sensor(client); + struct specific_sensor*sensor = to_specific_sensor(sgensor); + DEBUG_TRACE("%s:enable = %d\n",__func__,enable); + DEBUG_TRACE("@@NY@@%s: client %0x\n", __FUNCTION__, client); + if(enable == 0){ + // sensor_set_face_detect(client,0); + // sensor_af_workqueue_set(icd,0,0,true); +#if CALIBRATION_MODE_FUN + if (g_is_calibrationMode) + EXISP_I2C_PvStreamSet(0); // stream off +#endif + sensor->isp_priv_info.curPreviewCapMode = IDLE_MODE; + }else{ +#if CALIBRATION_MODE_FUN + if (g_is_calibrationMode && + sensor->isp_priv_info.sensor_id == SENSOR_ID_REAR_CALIBRATION && + sensor->isp_priv_info.rk_query_PreviewCapMode == PREVIEW_MODE) { + EXISP_PvSizeSet(0x0A); + sensor->isp_priv_info.curPreviewCapMode = PREVIEW_MODE; + EXISP_I2C_PvStreamSet(1); // stream on + return 0; + } +#endif + printk(KERN_ERR"icatch_set_isp_output_res: curRes(%x)\n",sensor->isp_priv_info.curRes); + //sensor_set_face_detect(client,1); + icatch_set_isp_output_res(client, sensor->isp_priv_info.curRes); + + +#if CALIBRATION_MODE_FUN + if (g_is_calibrationMode) + EXISP_I2C_PvStreamSet(1); // stream on +#endif + } + + return 0; +} + + +int icatch_request_firmware(const struct firmware ** fw){ + int ret = 0; + if( request_firmware(fw, ICATCHFWNAME, &g_icatch_i2c_client->dev) !=0){ + DEBUG_TRACE("%s:%d, request firmware erro,please check firmware!\n"); + ret = -1; + }else{ + ret = 0; + } + return ret; +} + +void icatch_release_firmware(const struct firmware * fw){ + if(fw) + release_firmware(fw); +} + +void icatch_sensor_power_ctr(struct soc_camera_device *icd ,int on,int power_mode){ +#if 0 + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct rk29camera_platform_data* pdata = (struct rk29camera_platform_data*)(to_soc_camera_host(icd->dev.parent)->v4l2_dev.dev->platform_data); + if(!on){ + //power down + if(icl->power) + icl->power(icd->pdev,0); + if(pdata && pdata->sensor_mclk) + pdata->sensor_mclk(RK29_CAM_PLATFORM_DEV_ID,0,24*1000*1000); + if(icl->powerdown) + icl->powerdown(icd->pdev,0); + iomux_set(GPIO1_A4); + iomux_set(GPIO1_A5) ; + iomux_set(GPIO1_A6); + iomux_set(GPIO1_A7); + iomux_set(GPIO3_B6); + iomux_set(GPIO3_B7); + iomux_set(GPIO0_C0); + gpio_set_value(RK30_PIN1_PA4,0); + gpio_set_value(RK30_PIN1_PA5,0); + gpio_set_value(RK30_PIN1_PA6,0); //Vincent_Liu@asus.com for clk 24M + gpio_set_value(RK30_PIN1_PA7,0); + gpio_set_value(RK30_PIN3_PB6,0); + gpio_set_value(RK30_PIN3_PB7,0); + gpio_set_value(RK30_PIN0_PC0,0); + //msleep(500); + }else{ + //power ON + gpio_set_value(RK30_PIN1_PA6,1); //Vincent_Liu@asus.com for clk 24M + + if(icl->power) + icl->power(icd->pdev,1); + if(icl->powerdown){ + if(power_mode == 0)//from spi + icl->powerdown(icd->pdev,1); + else + icl->powerdown(icd->pdev,0); + } + if(pdata && pdata->sensor_mclk) + pdata->sensor_mclk(RK29_CAM_PLATFORM_DEV_ID,1,24*1000*1000); + //reset , reset pin low ,then high + if (icl->reset) + icl->reset(icd->pdev); + if(power_mode == 0)//from spi + icl->powerdown(icd->pdev,0); + iomux_set(SPI0_CLK); + iomux_set(SPI0_RXD); + iomux_set(SPI0_TXD); + iomux_set(SPI0_CS0); + iomux_set(I2C3_SDA); + iomux_set(I2C3_SCL); + msleep(100); + } + #endif +} + +#if CALIBRATION_MODE_FUN +#if 0 +void __dump(const u8 *data, size_t size) { + size_t i = 0; + char buf[100] = {0}; + char lbuf[12]; + + while( i < size) { + if ((i%16 == 0) && (i != 0)) { + DEBUG_TRACE("%s\n", buf); + } + if (i%16 == 0) { + buf[0] = 0; + sprintf(lbuf, "%08X:", i); + strcat(buf, lbuf); + } + sprintf(lbuf, " %02X", *(data + i)); + strcat(buf, lbuf); + i++; + } + + DEBUG_TRACE("%s\n", buf); +} +#endif + +struct icatch_cali_fw_data * icatch_load_cali_fw_data(u8 sensorid) { + + if (g_is_calibrationMode) { + return NULL; + } + + struct icatch_cali_fw_data * fw = NULL; + switch (sensorid) { + case SENSOR_ID_FRONT: + fw = &g_cali_fw_data_front; + break; + case SENSOR_ID_REAR: + fw = &g_cali_fw_data_back; + break; + default: + break; + } + if (fw == NULL) + return NULL; + + if (request_firmware( + &(fw->fw_option), + fw->fname_option, + &g_icatch_i2c_client->dev) != 0) { + DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_option); + fw->fw_option = NULL; + } + + if (request_firmware( + &(fw->fw_3acali), + fw->fname_3acali, + &g_icatch_i2c_client->dev) != 0) { + DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_3acali); + fw->fw_3acali = NULL; + } +#if 0 + else { + DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_3acali, fw->fw_3acali->size); + __dump(fw->fw_3acali->data, fw->fw_3acali->size); + } +#endif + + if (request_firmware( + &(fw->fw_lsc), + fw->fname_lsc, + &g_icatch_i2c_client->dev) != 0) { + DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_lsc); + fw->fw_lsc = NULL; + } +#if 0 + else { + DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_lsc, fw->fw_lsc->size); + __dump(fw->fw_lsc->data, fw->fw_lsc->size); + } +#endif + + if (request_firmware( + &(fw->fw_lscdq), + fw->fname_lscdq, + &g_icatch_i2c_client->dev) != 0) { + DEBUG_TRACE("%s: load calibration fw data: %s fail", __FUNCTION__, fw->fname_lscdq); + fw->fw_lscdq = NULL; + } +#if 0 + else { + DEBUG_TRACE("%s: dump %s (size: %d)\n", __FUNCTION__, fw->fname_lscdq, fw->fw_lscdq->size); + __dump(fw->fw_lscdq->data, fw->fw_lscdq->size); + } +#endif + + return fw; +} + +void icatch_free_cali_fw_data(struct icatch_cali_fw_data * data) { + if (data == NULL) + return ; + + if (data->fw_option != NULL) { + release_firmware(data->fw_option); + } + + if (data->fw_3acali != NULL) { + release_firmware(data->fw_3acali); + } + + if (data->fw_lsc != NULL) { + release_firmware(data->fw_lsc); + } + + if (data->fw_lscdq != NULL) { + release_firmware(data->fw_lscdq); + } +} +#endif + +//#include "BOOT_OV5693_126MHz(075529).c" + int icatch_load_fw(struct soc_camera_device *icd,u8 sensorid){ + struct firmware *fw =NULL; +#if CALIBRATION_MODE_FUN + struct icatch_cali_fw_data * cali_data = NULL; +#endif + int ret = 0; + icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); + icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); + if(ICATCH_BOOT == ICATCH_BOOT_FROM_HOST){ + DEBUG_TRACE("@@NY@@%s: %d\n", __FUNCTION__, sensorid); + if(icatch_request_firmware(&fw)!= 0){ + ret = -1; + goto icatch_load_fw_out; + } + +#if CALIBRATION_MODE_FUN + g_fw_version.fw = *((__u32*)(fw->data + fw->size - 4)); + + cali_data = icatch_load_cali_fw_data(sensorid); + if (cali_data != NULL) { + DEBUG_TRACE("%s:%d,load calibration fw data success !!!!\n",__func__,__LINE__); + ret = EXISP_LoadCodeStart( + ICATCH_BOOT, + sensorid, + g_is_calibrationMode, + (u8*)(fw->data), + cali_data->fw_option ? (u8*)(cali_data->fw_option->data) : &g_Calibration_Option_Def, + cali_data->fw_3acali ? (u8*)(cali_data->fw_3acali->data) : NULL, + cali_data->fw_lsc ? (u8*)(cali_data->fw_lsc->data) : NULL, + cali_data->fw_lscdq ? (u8*)(cali_data->fw_lscdq->data) : NULL); + } else { + DEBUG_TRACE("%s:%d,load calibration fw data fail !!!!\n",__func__,__LINE__); + ret = EXISP_LoadCodeStart( + ICATCH_BOOT, + sensorid, + g_is_calibrationMode, + (u8*)(fw->data), + &g_Calibration_Option_Def, + NULL, + NULL, + NULL); + } +#else + ret = EXISP_LoadCodeStart( + ICATCH_BOOT, + sensorid, + 0, + (u8*)(fw->data), + &g_Calibration_Option_Def, + NULL, + NULL, + NULL); +#endif + + if (ret != SUCCESS) { + DEBUG_TRACE("%s:%d,load firmware failed !!!!\n",__func__,__LINE__); + ret = -1; + } else { + ret = 0; + } + + icatch_release_firmware(fw); + icatch_free_cali_fw_data(cali_data); + + if(ret < 0) + goto icatch_load_fw_out; + + }else{ + #if 1 + BB_WrSPIFlash(0xffffff); + + icatch_sensor_power_ctr(icd,0,0); + icatch_sensor_power_ctr(icd,1,0); + gpio_set_value(RK30_PIN1_PA6,0); //Vincent_Liu@asus.com for clk 24M + #endif + } + // msleep(100); + return 0; +icatch_load_fw_out: + return ret; +} + + +int icatch_get_rearid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *rear_id) +{ + static int ret = 0; + static int done = 0; + static UINT16 _rear_id = 0; + + static const struct rk_sensor_reg reset_1[]={ + {0x1011, 0x01}, /* CPU suspend */ + {0x0084, 0x14}, /* To sensor clock divider */ + {0x0034, 0xFF}, /* Turn on all clock */ + {0x9032, 0x00}, + {0x9033, 0x10}, + {0x9030, 0x3f}, + {0x9031, 0x04}, + {0x9034, 0xf2}, + {0x9035, 0x04}, + {0x9032, 0x10}, + {0x00, 0x00}, + }; + + //tmrUsWait(10000); /*10ms*/ + + static const struct rk_sensor_reg reset_2[] = { + {0x9032, 0x30}, + {0x00, 0x00}, + }; + + //tmrUsWait(10000); /*10ms*/ + + + static const struct rk_sensor_reg reset_3[] = { + /*End - Power on sensor & enable clock */ + {0x9008, 0x00}, + {0x9009, 0x00}, + {0x900A, 0x00}, + {0x900B, 0x00}, + + /*Start - I2C Read*/ + {0x923C, 0x01}, /* Sub address enable */ + {0x9238, 0x30}, /* Sub address enable */ + {0x9240, 0x6C}, /* Slave address */ + {0x9200, 0x03}, /* Read mode */ + {0x9210, 0x00}, /* Register addr MSB */ + {0x9212, 0x00}, /* Register addr LSB */ + {0x9204, 0x01}, /* Trigger I2C read */ + {0x00, 0x00}, + }; + + // tmrUsWait(2000);/*2ms*/ + + DEBUG_TRACE("%s: entry!\n", __FUNCTION__); + + if (done == 1) { + if (rear_id != NULL) + *rear_id = _rear_id; + return ret; + } + + icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); + icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); + + if (icatch_sensor_write_array(reset_1) != 0) { + ret = -ENXIO; + goto l_ret; + } + msleep(10); + + if (icatch_sensor_write_array(reset_2) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(10); + if (icatch_sensor_write_array(reset_3) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(2); + _rear_id = (UINT16)icatch_sensor_read(0x9211) << 8; + _rear_id += icatch_sensor_read(0x9213); + DEBUG_TRACE("%s: rear_id = 0x%04X\n", __FUNCTION__, _rear_id); + *rear_id = _rear_id; + + +l_ret: + icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); + done = 1; + return ret; +} + + +int icatch_get_frontid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *front_id) +{ + static int ret = 0; + static int done = 0; + static UINT16 _front_id = 0; + + static const struct rk_sensor_reg reset_1[]={ + { 0x1011, 0x01,0x0,0x0}, /* CPU Suspend */ + + { 0x0084, 0x14}, /* To sensor clock divider */ + { 0x0034, 0xFF}, /* Turn on all clock */ + { 0x9030, 0x3f}, + { 0x9031, 0x04}, + { 0x9034, 0xf2}, + { 0x9035, 0x04}, + { 0x9033, 0x04}, + { 0x9032, 0x3c}, + SensorEnd + }; + + //tmrUsWait(10000); /* 10ms */ + + static const struct rk_sensor_reg reset_2[] = { + {0x9033, 0x00}, + SensorEnd + }; + + //tmrUsWait(10000); /*10ms*/ + + + static const struct rk_sensor_reg reset_3[] = { + { 0x9033, 0x04}, + { 0x9032, 0x3e}, + SensorEnd + }; + + //tmrUsWait(10000); /* 10ms */ + + static const struct rk_sensor_reg reset_4[] = { + { 0x9032, 0x3c}, + /*End - Power on sensor & enable clock */ + + /*Start - I2C Read ID*/ + { 0x9138, 0x30}, /* Sub address enable */ + { 0x9140, 0x90}, /* Slave address */ + { 0x9100, 0x03}, /* Read mode */ + { 0x9110, 0x00}, /* Register addr MSB */ + { 0x9112, 0x00}, /* Register addr LSB */ + { 0x9104, 0x01 }, /* Trigger I2C read */ + SensorEnd + }; + + //tmrUsWait(100); /* 0.1ms */ + + static const struct rk_sensor_reg reset_5[] = { + { 0x9110, 0x00}, /* Register addr MSB */ + { 0x9112, 0x01}, /* Register addr LSB */ + { 0x9104, 0x01}, /* Trigger I2C read */ + SensorEnd + }; + + DEBUG_TRACE("%s: entry!\n", __FUNCTION__); + + if (done == 1) { + if (front_id != NULL) + *front_id = _front_id; + return ret; + } + + icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); + icatch_sensor_power_ctr(icd,1,ICATCH_BOOT); + + if (icatch_sensor_write_array(reset_1) != 0) { + ret = -ENXIO; + goto l_ret; + } + msleep(10); + + if (icatch_sensor_write_array(reset_2) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(10); + if (icatch_sensor_write_array(reset_3) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(10); + + + if (icatch_sensor_write_array(reset_4) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(1); + _front_id = (UINT16)icatch_sensor_read(0x9111) << 8; + + if (icatch_sensor_write_array(reset_5) != 0) { + ret = -ENXIO; + goto l_ret; + } + + msleep(1); + _front_id += icatch_sensor_read(0x9111); + DEBUG_TRACE("%s: front_id = 0x%04X\n", __FUNCTION__, _front_id); + *front_id = _front_id; + +l_ret: + icatch_sensor_power_ctr(icd,0,ICATCH_BOOT); + done = 1; + return ret; +} + diff --git a/drivers/media/video/icatch7002/icatch7002_common.h b/drivers/media/video/icatch7002/icatch7002_common.h new file mode 100755 index 000000000000..cf90ccd00ed8 --- /dev/null +++ b/drivers/media/video/icatch7002/icatch7002_common.h @@ -0,0 +1,211 @@ +#ifndef ICATCH7002_COMMON_H +#include "../generic_sensor.h" +#include "app_i2c_lib_icatch.h" +#include + +/* CAMERA_REAR_SENSOR_SETTING:V17.00.18 */ +/* CAMERA_FRONT_SENSOR_SETTING:V17.00.18 */ +#if defined(CONFIG_TRACE_LOG_PRINTK) + #define DEBUG_TRACE(format, ...) printk(KERN_WARNING format, ## __VA_ARGS__) +#else + #define DEBUG_TRACE(format, ...) +#endif +#define LOG_TRACE(format, ...) printk(KERN_WARNING format, ## __VA_ARGS__) + + +#define CALIBRATION_MODE_FUN 1 + +#define SENSOR_REGISTER_LEN 2 // sensor register address bytes +#define SENSOR_VALUE_LEN 1 // sensor register value bytes + +extern struct i2c_client *g_icatch_i2c_client; +#define icatch_sensor_write(reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)((g_icatch_i2c_client),(reg),(v)) +#define icatch_sensor_write_array(regarry) generic_sensor_write_array(g_icatch_i2c_client,regarry) + + +static inline u8 icatch_sensor_read(u16 reg) +{ + u8 val; + sensor_read_reg2val1(g_icatch_i2c_client,reg,&val); + return val; +} + + +enum sensor_work_state { + sensor_work_ready = 0, + sensor_working, +}; + +#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 1 +#define CONFIG_SENSOR_Exposure 1 +#define CONFIG_SENSOR_Flash 0 +#define CONFIG_SENSOR_Mirror 0 +#define CONFIG_SENSOR_Flip 0 +#define CONFIG_SENSOR_FOCUS_ZONE 0 +#define CONFIG_SENSOR_FACE_DETECT 0 +#define CONFIG_SENSOR_ISO 1 +#define CONFIG_SENSOR_AntiBanding 1 +#define CONFIG_SENSOR_WhiteBalanceLock 1 +#define CONFIG_SENSOR_ExposureLock 1 +#define CONFIG_SENSOR_MeteringAreas 1 +#define CONFIG_SENSOR_Wdr 1 +#define CONFIG_SENSOR_EDGE 1 +#define CONFIG_SENSOR_JPEG_EXIF 1 +#define CONFIG_SENSOR_DUMPREGS 0 + +#if CONFIG_SENSOR_Focus +extern int icatch_sensor_set_auto_focus(struct i2c_client *client, int value,int *tmp_zone); +#endif + +#if CALIBRATION_MODE_FUN +void icatch_create_proc_entry(void); +void icatch_remove_proc_entry(void); +#endif +extern void BB_WrSPIFlash(u32 size); +extern int icatch_request_firmware(const struct firmware ** fw); +extern void icatch_release_firmware(const struct firmware * fw); +extern void icatch_sensor_power_ctr(struct soc_camera_device *icd ,int on,int power_mode); +extern int icatch_load_fw(struct soc_camera_device *icd,u8 sensorid); +int icatch_get_rearid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *rear_id); +int icatch_get_frontid_by_lowlevelmode(struct soc_camera_device *icd,UINT16 *front_id); +extern int icatch_sensor_init(struct i2c_client *client); +extern int icatch_s_fmt(struct i2c_client *client, struct v4l2_mbus_framefmt *mf); +extern int icatch_s_stream(struct v4l2_subdev *sd, int enable); +extern int sensor_set_get_control_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl,bool is_set); +extern int icatch_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); + +enum ISP_OUTPUT_RES{ + OUTPUT_QCIF =0x0001, // 176*144 + OUTPUT_HQVGA =0x0002,// 240*160 + OUTPUT_QVGA =0x0004, // 320*240 + OUTPUT_CIF =0x0008, // 352*288 + OUTPUT_VGA =0x0010, // 640*480 + OUTPUT_SVGA =0x0020, // 800*600 + OUTPUT_720P =0x0040, // 1280*720 + OUTPUT_XGA =0x0080, // 1024*768 + OUTPUT_QUADVGA =0x0100, // 1280*960 + OUTPUT_SXGA =0x0200, // 1280*1024 + OUTPUT_UXGA =0x0400, // 1600*1200 + OUTPUT_1080P =0x0800, //1920*1080 + OUTPUT_QXGA =0x1000, // 2048*1536 + OUTPUT_QSXGA =0x2000, // 2592*1944 +}; + + + +enum sensor_preview_cap_mode{ + PREVIEW_MODE, + CAPTURE_MODE, + CAPTURE_ZSL_MODE, + CAPTURE_NONE_ZSL_MODE, + IDLE_MODE, +}; + + +typedef struct rk_sensor_focus_zone rk_sensor_tae_zone; +typedef struct{ + uint32_t num; + uint32_t denom; +}rat_t; + + +typedef struct{ + /*IFD0*/ + char *maker;//manufacturer of digicam, just to adjust to make inPhybusAddr to align to 64 + int makerchars;//length of maker, contain the end '\0', so equal strlen(maker)+1 + char *modelstr;//model number of digicam + int modelchars;//length of modelstr, contain the end '\0' + int Orientation;//usually 1 + //XResolution, YResolution; if need be not 72, TODO... + char DateTime[20];//must be 20 chars-> yyyy:MM:dd0x20hh:mm:ss'\0' + /*Exif SubIFD*/ + rat_t ExposureTime;//such as 1/400=0.0025s + rat_t ApertureFNumber;//actual f-number + int ISOSpeedRatings;//CCD sensitivity equivalent to Ag-Hr film speedrate + rat_t CompressedBitsPerPixel; + rat_t ShutterSpeedValue; + rat_t ApertureValue; + rat_t ExposureBiasValue; + rat_t MaxApertureValue; + int MeteringMode; + int Flash; + rat_t FocalLength; + rat_t FocalPlaneXResolution; + rat_t FocalPlaneYResolution; + int SensingMethod;//2 means 1 chip color area sensor + int FileSource;//3 means the image source is digital still camera + int CustomRendered;//0 + int ExposureMode;//0 + int WhiteBalance;//0 + rat_t DigitalZoomRatio;// inputw/inputw + //int FocalLengthIn35mmFilm; + int SceneCaptureType;//0 + +}RkExifInfo; + +//flash and focus must be considered. + +//soft isp or external isp used +//if soft isp is defined , the value in this sturct is used in cif driver . cif driver use this value to do isp func. +//value of this sturct MUST be defined(initialized) correctly. +struct isp_data{ + int focus; + int auto_focus; + int flash; + int whiteBalance; + int brightness; + int contrast; + int saturation; + int effect; + int scene; + int digitalzoom; + int exposure; + int iso; + int face; + int antibanding; + int WhiteBalanceLock; + int ExposureLock; + int MeteringAreas; + int Wdr; + int hdr; + //mirror or flip + unsigned char mirror; /* HFLIP */ + unsigned char flip; /* VFLIP */ + //preview or capture + int outputSize; // supported resolution + int curRes; + int curPreviewCapMode; + int supportedSize[10]; + int supportedSizeNum; + int had_setprvsize; + RkExifInfo exifInfo; +#if CALIBRATION_MODE_FUN + int rk_query_PreviewCapMode; + int sensor_id; +#endif + struct rk_sensor_focus_zone focus_zone; + rk_sensor_tae_zone tae_zone; + +}; + + + + +struct specific_sensor{ + struct generic_sensor common_sensor; + //define user data below + struct isp_data isp_priv_info; + +}; + +#endif + + diff --git a/drivers/media/video/icatch7002/icatch7002_mi1040.c b/drivers/media/video/icatch7002/icatch7002_mi1040.c new file mode 100755 index 000000000000..7291b847c24a --- /dev/null +++ b/drivers/media/video/icatch7002/icatch7002_mi1040.c @@ -0,0 +1,629 @@ + +#include "icatch7002_common.h" +/* +* Driver Version Note +*v0.0.1: this driver is compatible with generic_sensor +*v0.0.3: +* add sensor_focus_af_const_pause_usr_cb; +*/ +static int version = KERNEL_VERSION(0,0,3); +module_param(version, int, S_IRUGO); + + + +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) + +/* Sensor Driver Configuration Begin */ +#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_MI1040 +#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_MI1040 +#define SENSOR_ID 0x2481 +#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ + SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ + SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) +#define SENSOR_PREVIEW_W 1280 +#define SENSOR_PREVIEW_H 960 +#define SENSOR_PREVIEW_FPS 30000 // 15fps +#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps +#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps +#define SENSOR_720P_FPS 0 +#define SENSOR_1080P_FPS 0 + + +static unsigned int SensorConfiguration = 0; +static unsigned int SensorChipID[] = {SENSOR_ID}; +/* Sensor Driver Configuration End */ + + +#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) +//#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) + +//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) +//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) +//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) +//#define sensor_write_array generic_sensor_write_array + + + +/* +* The follow setting need been filled. +* +* Must Filled: +* sensor_init_data : Sensor initial setting; +* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; +* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; +* sensor_softreset_data : Sensor software reset register; +* sensor_check_id_data : Sensir chip id register; +* +* Optional filled: +* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; +* sensor_720p: Sensor 720p setting, it is for video; +* sensor_1080p: Sensor 1080p setting, it is for video; +* +* :::::WARNING::::: +* The SensorEnd which is the setting end flag must be filled int the last of each setting; +*/ + +/* Sensor initial setting */ +static struct rk_sensor_reg sensor_init_data[] ={ + SensorStreamChk, + SensorEnd +}; +/* Senor full resolution setting: recommand for capture */ +static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ + SensorEnd + +}; + +/* Senor full resolution setting: recommand for video */ +static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ + SensorEnd +}; +/* Preview resolution setting*/ +static struct rk_sensor_reg sensor_preview_data[] = +{ + SensorStreamChk, + SensorEnd +}; +/* 1280x720 */ +static struct rk_sensor_reg sensor_720p[]={ + SensorEnd +}; + +/* 1920x1080 */ +static struct rk_sensor_reg sensor_1080p[]={ + SensorEnd +}; + + +static struct rk_sensor_reg sensor_softreset_data[]={ + SensorEnd +}; + +static struct rk_sensor_reg sensor_check_id_data[]={ + SensorEnd +}; +/* +* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx +*/ +static struct rk_sensor_reg sensor_WhiteB_Auto[]= +{ + SensorEnd +}; +/* Cloudy Colour Temperature : 6500K - 8000K */ +static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= +{ + SensorEnd +}; +/* ClearDay Colour Temperature : 5000K - 6500K */ +static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= +{ + //Sunny + SensorEnd +}; +/* Office Colour Temperature : 3500K - 5000K */ +static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= +{ + //Office + SensorEnd + +}; +/* Home Colour Temperature : 2500K - 3500K */ +static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= +{ + //Home + SensorEnd +}; +static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, + sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, +}; + +static struct rk_sensor_reg sensor_Brightness0[]= +{ + // Brightness -2 + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness1[]= +{ + // Brightness -1 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness2[]= +{ + // Brightness 0 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness3[]= +{ + // Brightness +1 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness4[]= +{ + // Brightness +2 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness5[]= +{ + // Brightness +3 + + SensorEnd +}; +static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, + sensor_Brightness4, sensor_Brightness5,NULL, +}; + +static struct rk_sensor_reg sensor_Effect_Normal[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_WandB[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Sepia[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Negative[] = +{ + //Negative + SensorEnd +}; +static struct rk_sensor_reg sensor_Effect_Bluish[] = +{ + // Bluish + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Green[] = +{ + // Greenish + SensorEnd +}; +static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, + sensor_Effect_Bluish, sensor_Effect_Green,NULL, +}; + +static struct rk_sensor_reg sensor_Exposure0[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure1[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure2[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure3[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure4[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure5[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure6[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, + sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, +}; + +static struct rk_sensor_reg sensor_Saturation0[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Saturation1[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Saturation2[]= +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; + +static struct rk_sensor_reg sensor_Contrast0[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast1[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast2[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast3[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast4[]= +{ + + SensorEnd +}; + + +static struct rk_sensor_reg sensor_Contrast5[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast6[]= +{ + + SensorEnd +}; +static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, + sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, +}; +static struct rk_sensor_reg sensor_SceneAuto[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_SceneNight[] = +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; + +static struct rk_sensor_reg sensor_Zoom0[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Zoom1[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Zoom2[] = +{ + SensorEnd +}; + + +static struct rk_sensor_reg sensor_Zoom3[] = +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; + +/* +* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu +*/ +static struct v4l2_querymenu sensor_menus[] = +{ + //white balance + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), + + //speical effect + new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), + + //scence + new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), + new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), + new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), + new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), + new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), + new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), + new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), + new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), + + //antibanding + new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), + new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), + + //ISO + new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), + new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), + new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), + new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), + new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), + new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), + new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), +}; +/* +* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl +*/ +static struct sensor_v4l2ctrl_usr_s sensor_controls[] = +{ + new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), +}; + +//MUST define the current used format as the first item +static struct rk_sensor_datafmt sensor_colour_fmts[] = { + {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} +}; + + +/* +********************************************************** +* Following is local code: +* +* Please codeing your program here +********************************************************** +*/ +/* +********************************************************** +* Following is callback +* If necessary, you could coding these callback +********************************************************** +*/ +/* +* the function is called in open sensor +*/ +static int sensor_activate_cb(struct i2c_client *client) +{ + return icatch_sensor_init(client); +} +/* +* the function is called in close sensor +*/ +static int sensor_deactivate_cb(struct i2c_client *client) +{ + + return 0; +} +/* +* the function is called before sensor register setting in VIDIOC_S_FMT +*/ +static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) +{ + return icatch_s_fmt(client, mf); +} +/* +* the function is called after sensor register setting finished in VIDIOC_S_FMT +*/ +static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) +{ + return 0; +} +static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) +{ + return 0; +} + +static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) +{ + + return 0; +} +static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) +{ + struct generic_sensor *sensor = to_generic_sensor(client); + return sensor->info_priv.chip_id[0]; +} +static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) +{ + //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + + if (pm_msg.event == PM_EVENT_SUSPEND) { + SENSOR_DG("Suspend"); + + } else { + SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); + return -EINVAL; + } + return 0; +} + +static int sensor_resume(struct soc_camera_device *icd) +{ + + SENSOR_DG("Resume"); + + return 0; + +} +/* +* the function is v4l2 control V4L2_CID_HFLIP callback +*/ +static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl) +{ + return 0; +} + +/* +* the function is v4l2 control V4L2_CID_VFLIP callback +*/ +static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl) +{ + return 0; +} +/* +* the function is v4l2 control V4L2_CID_HFLIP callback +*/ + +static int sensor_flip_cb(struct i2c_client *client, int flip) +{ + int err = 0; + + return err; +} +static int sensor_mirror_cb(struct i2c_client *client, int flip) +{ + int err = 0; + + return err; +} + +/* +* the functions are focus callbacks +*/ +static int sensor_focus_init_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ + return 0; +} + +static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ + + return 0; +} +static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) +{ + return 0; +} +static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) +{ + return 0; +} + +/* +face defect call back +*/ +static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ + return 0; +} + +/* +* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some +* initialization in the function. +*/ +static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) +{ + spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; + spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; + + spsensor->isp_priv_info.outputSize =OUTPUT_QUADVGA; + spsensor->isp_priv_info.supportedSizeNum = 1; + spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; + + + return; +} + +/* +* :::::WARNING::::: +* It is not allowed to modify the following code +*/ + +sensor_init_parameters_default_code(); + +sensor_v4l2_struct_initialization(); + +sensor_probe_default_code(); + +sensor_remove_default_code(); + +sensor_driver_default_module_code(); + + + + diff --git a/drivers/media/video/icatch7002/icatch7002_ov5693.c b/drivers/media/video/icatch7002/icatch7002_ov5693.c new file mode 100755 index 000000000000..755d21b69283 --- /dev/null +++ b/drivers/media/video/icatch7002/icatch7002_ov5693.c @@ -0,0 +1,638 @@ + +#include "icatch7002_common.h" +/* +* Driver Version Note +*v0.0.1: this driver is compatible with generic_sensor +*v0.0.3: +* add sensor_focus_af_const_pause_usr_cb; +*/ +static int version = KERNEL_VERSION(0,0,3); +module_param(version, int, S_IRUGO); + + + +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) + +/* Sensor Driver Configuration Begin */ +#define SENSOR_NAME RK29_CAM_ISP_ICATCH7002_OV5693 +#define SENSOR_V4L2_IDENT V4L2_IDENT_ICATCH7002_OV5693 +#define SENSOR_ID 0x5690 +#define SENSOR_BUS_PARAM (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|\ + SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ + SOCAM_DATA_ACTIVE_HIGH|SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) +#define SENSOR_PREVIEW_W 1280 +#define SENSOR_PREVIEW_H 960 +#define SENSOR_PREVIEW_FPS 30000 // 15fps +#define SENSOR_FULLRES_L_FPS 15000 // 7.5fps +#define SENSOR_FULLRES_H_FPS 15000 // 7.5fps +#define SENSOR_720P_FPS 0 +#define SENSOR_1080P_FPS 0 + + +static unsigned int SensorConfiguration = CFG_Focus |CFG_FocusContinues|CFG_FocusZone; +static unsigned int SensorChipID[] = {SENSOR_ID}; +/* Sensor Driver Configuration End */ + + +#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a)) +#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a) + +//#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b) +//#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) +//#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v)) +//#define sensor_write_array generic_sensor_write_array + + + +/* +* The follow setting need been filled. +* +* Must Filled: +* sensor_init_data : Sensor initial setting; +* sensor_fullres_lowfps_data : Sensor full resolution setting with best auality, recommand for video; +* sensor_preview_data : Sensor preview resolution setting, recommand it is vga or svga; +* sensor_softreset_data : Sensor software reset register; +* sensor_check_id_data : Sensir chip id register; +* +* Optional filled: +* sensor_fullres_highfps_data: Sensor full resolution setting with high framerate, recommand for video; +* sensor_720p: Sensor 720p setting, it is for video; +* sensor_1080p: Sensor 1080p setting, it is for video; +* +* :::::WARNING::::: +* The SensorEnd which is the setting end flag must be filled int the last of each setting; +*/ + +/* Sensor initial setting */ +static struct rk_sensor_reg sensor_init_data[] ={ + SensorStreamChk, + SensorEnd +}; +/* Senor full resolution setting: recommand for capture */ +static struct rk_sensor_reg sensor_fullres_lowfps_data[] ={ + SensorStreamChk, + SensorEnd + +}; + +/* Senor full resolution setting: recommand for video */ +static struct rk_sensor_reg sensor_fullres_highfps_data[] ={ + SensorEnd +}; +/* Preview resolution setting*/ +static struct rk_sensor_reg sensor_preview_data[] = +{ + SensorStreamChk, + SensorEnd +}; +/* 1280x720 */ +static struct rk_sensor_reg sensor_720p[]={ + SensorEnd +}; + +/* 1920x1080 */ +static struct rk_sensor_reg sensor_1080p[]={ + SensorEnd +}; + + +static struct rk_sensor_reg sensor_softreset_data[]={ + SensorEnd +}; + +static struct rk_sensor_reg sensor_check_id_data[]={ + SensorEnd +}; +/* +* The following setting must been filled, if the function is turn on by CONFIG_SENSOR_xxxx +*/ +static struct rk_sensor_reg sensor_WhiteB_Auto[]= +{ + SensorEnd +}; +/* Cloudy Colour Temperature : 6500K - 8000K */ +static struct rk_sensor_reg sensor_WhiteB_Cloudy[]= +{ + SensorEnd +}; +/* ClearDay Colour Temperature : 5000K - 6500K */ +static struct rk_sensor_reg sensor_WhiteB_ClearDay[]= +{ + //Sunny + SensorEnd +}; +/* Office Colour Temperature : 3500K - 5000K */ +static struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[]= +{ + //Office + SensorEnd + +}; +/* Home Colour Temperature : 2500K - 3500K */ +static struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[]= +{ + //Home + SensorEnd +}; +static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2, + sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL, +}; + +static struct rk_sensor_reg sensor_Brightness0[]= +{ + // Brightness -2 + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness1[]= +{ + // Brightness -1 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness2[]= +{ + // Brightness 0 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness3[]= +{ + // Brightness +1 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness4[]= +{ + // Brightness +2 + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Brightness5[]= +{ + // Brightness +3 + + SensorEnd +}; +static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3, + sensor_Brightness4, sensor_Brightness5,NULL, +}; + +static struct rk_sensor_reg sensor_Effect_Normal[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_WandB[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Sepia[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Negative[] = +{ + //Negative + SensorEnd +}; +static struct rk_sensor_reg sensor_Effect_Bluish[] = +{ + // Bluish + SensorEnd +}; + +static struct rk_sensor_reg sensor_Effect_Green[] = +{ + // Greenish + SensorEnd +}; +static struct rk_sensor_reg *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia, + sensor_Effect_Bluish, sensor_Effect_Green,NULL, +}; + +static struct rk_sensor_reg sensor_Exposure0[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure1[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure2[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure3[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure4[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure5[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Exposure6[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3, + sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL, +}; + +static struct rk_sensor_reg sensor_Saturation0[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Saturation1[]= +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Saturation2[]= +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,}; + +static struct rk_sensor_reg sensor_Contrast0[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast1[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast2[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast3[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast4[]= +{ + + SensorEnd +}; + + +static struct rk_sensor_reg sensor_Contrast5[]= +{ + + SensorEnd +}; + +static struct rk_sensor_reg sensor_Contrast6[]= +{ + + SensorEnd +}; +static struct rk_sensor_reg *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3, + sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL, +}; +static struct rk_sensor_reg sensor_SceneAuto[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_SceneNight[] = +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,}; + +static struct rk_sensor_reg sensor_Zoom0[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Zoom1[] = +{ + SensorEnd +}; + +static struct rk_sensor_reg sensor_Zoom2[] = +{ + SensorEnd +}; + + +static struct rk_sensor_reg sensor_Zoom3[] = +{ + SensorEnd +}; +static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,}; + +/* +* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu +*/ +static struct v4l2_querymenu sensor_menus[] = +{ + //white balance + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,0,"auto",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,1,"incandescent",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,2,"fluorescent",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,3,"daylight",0), + new_usr_v4l2menu(V4L2_CID_DO_WHITE_BALANCE,4,"cloudy-daylight",0), + + //speical effect + new_usr_v4l2menu(V4L2_CID_EFFECT,0,"normal",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,1,"aqua",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,2,"negative",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,3,"sepia",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,4,"mono",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,5,"none",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,6,"aura",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,7,"vintage",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,8,"vintage2",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,9,"lomo",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,10,"red",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,11,"blue",0), + new_usr_v4l2menu(V4L2_CID_EFFECT,12,"green",0), + + //scence + new_usr_v4l2menu(V4L2_CID_SCENE,0,"normal",0), + new_usr_v4l2menu(V4L2_CID_SCENE,1,"auto",0), + new_usr_v4l2menu(V4L2_CID_SCENE,2,"landscape",0), + new_usr_v4l2menu(V4L2_CID_SCENE,3,"night",0), + new_usr_v4l2menu(V4L2_CID_SCENE,4,"night_portrait",0), + new_usr_v4l2menu(V4L2_CID_SCENE,5,"snow",0), + new_usr_v4l2menu(V4L2_CID_SCENE,6,"sports",0), + new_usr_v4l2menu(V4L2_CID_SCENE,7,"candlelight",0), + + //antibanding + new_usr_v4l2menu(V4L2_CID_ANTIBANDING,0,"50hz",0), + new_usr_v4l2menu(V4L2_CID_ANTIBANDING,1,"60hz",0), + + //ISO + new_usr_v4l2menu(V4L2_CID_ISO,0,"auto",0), + new_usr_v4l2menu(V4L2_CID_ISO,1,"50",0), + new_usr_v4l2menu(V4L2_CID_ISO,2,"100",0), + new_usr_v4l2menu(V4L2_CID_ISO,3,"200",0), + new_usr_v4l2menu(V4L2_CID_ISO,4,"400",0), + new_usr_v4l2menu(V4L2_CID_ISO,5,"800",0), + new_usr_v4l2menu(V4L2_CID_ISO,6,"1600",0), +}; +/* +* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl +*/ +static struct sensor_v4l2ctrl_usr_s sensor_controls[] = +{ + new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 4, 1, 0,sensor_set_get_control_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_BRIGHTNESS,V4L2_CTRL_TYPE_INTEGER,"Brightness Control", -3, 2, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 12, 1, 5,sensor_set_get_control_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_SCENE,V4L2_CTRL_TYPE_MENU,"Scene Control", 0, 7, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_ANTIBANDING,V4L2_CTRL_TYPE_MENU,"Antibanding Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_WHITEBALANCE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"WhiteBalanceLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE_LOCK,V4L2_CTRL_TYPE_BOOLEAN,"ExposureLock Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_METERING_AREAS,V4L2_CTRL_TYPE_INTEGER,"MeteringAreas Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_WDR,V4L2_CTRL_TYPE_BOOLEAN,"WDR Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_EDGE,V4L2_CTRL_TYPE_BOOLEAN,"EDGE Control", 0, 1, 1, 1,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_JPEG_EXIF,V4L2_CTRL_TYPE_BOOLEAN,"Exif Control", 0, 1, 1, 0,sensor_set_get_control_cb, NULL), + new_user_v4l2ctrl(V4L2_CID_ISO,V4L2_CTRL_TYPE_MENU,"Exif Control", 0, 6, 1, 0,sensor_set_get_control_cb, NULL), + +// new_user_v4l2ctrl(V4L2_CID_FOCUSZONE,V4L2_CTRL_TYPE_BOOLEAN,"FocusZone Control", 0, 1, 1, 1,sensor_focus_default_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_FOCUS_ABSOLUTE,V4L2_CTRL_TYPE_INTEGER,"Focus Control", 0, 0xff, 1, 0,sensor_focus_default_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_FOCUS_AUTO,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), +// new_user_v4l2ctrl(V4L2_CID_FOCUS_CONTINUOUS,V4L2_CTRL_TYPE_BOOLEAN,"Focus Control", 0, 1, 1, 0,sensor_focus_default_cb, NULL), +}; + +//MUST define the current used format as the first item +static struct rk_sensor_datafmt sensor_colour_fmts[] = { + {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG} +}; + + +/* +********************************************************** +* Following is local code: +* +* Please codeing your program here +********************************************************** +*/ +/* +********************************************************** +* Following is callback +* If necessary, you could coding these callback +********************************************************** +*/ +/* +* the function is called in open sensor +*/ +static int sensor_activate_cb(struct i2c_client *client) +{ + return icatch_sensor_init(client); +} +/* +* the function is called in close sensor +*/ +static int sensor_deactivate_cb(struct i2c_client *client) +{ + + return 0; +} +/* +* the function is called before sensor register setting in VIDIOC_S_FMT +*/ +static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) +{ + return icatch_s_fmt(client, mf); +} +/* +* the function is called after sensor register setting finished in VIDIOC_S_FMT +*/ +static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture) +{ + return 0; +} +static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf) +{ + return 0; +} + +static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) +{ + + return 0; +} +static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series) +{ + struct generic_sensor *sensor = to_generic_sensor(client); + return sensor->info_priv.chip_id[0]; +} +static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg) +{ + //struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + + if (pm_msg.event == PM_EVENT_SUSPEND) { + SENSOR_DG("Suspend"); + + } else { + SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event); + return -EINVAL; + } + return 0; +} + +static int sensor_resume(struct soc_camera_device *icd) +{ + + SENSOR_DG("Resume"); + + return 0; + +} +/* +* the function is v4l2 control V4L2_CID_HFLIP callback +*/ +static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl) +{ + return 0; +} + +/* +* the function is v4l2 control V4L2_CID_VFLIP callback +*/ +static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info, + struct v4l2_ext_control *ext_ctrl) +{ + return 0; +} +/* +* the function is v4l2 control V4L2_CID_HFLIP callback +*/ + +static int sensor_flip_cb(struct i2c_client *client, int flip) +{ + int err = 0; + + return err; +} +static int sensor_mirror_cb(struct i2c_client *client, int flip) +{ + int err = 0; + + return err; +} + +/* +* the functions are focus callbacks +*/ +static int sensor_focus_init_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_single_usr_cb(struct i2c_client *client){ + return icatch_sensor_set_auto_focus(client, WqCmd_af_single,NULL); +} + +static int sensor_focus_af_near_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_far_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ + return 0; +} + +static int sensor_focus_af_const_usr_cb(struct i2c_client *client){ + + return icatch_sensor_set_auto_focus(client, WqCmd_af_continues,NULL); +} +static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client) +{ + return 0; +} +static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ + return 0; +} + +static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos) +{ + return icatch_sensor_set_auto_focus(client, WqCmd_af_update_zone,zone_tm_pos); +} + +/* +face defect call back +*/ +static int sensor_face_detect_usr_cb(struct i2c_client *client,int on){ + return 0; +} + +/* +* The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some +* initialization in the function. +*/ +static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd) +{ + spsensor->common_sensor.sensor_cb.sensor_s_stream_cb = icatch_s_stream; + spsensor->isp_priv_info.focus_zone.lx = 256; + spsensor->isp_priv_info.focus_zone.rx = 768; + spsensor->isp_priv_info.focus_zone.ty = 256; + spsensor->isp_priv_info.focus_zone.dy = 768; + spsensor->common_sensor.sensor_cb.sensor_enum_framesizes = icatch_enum_framesizes; + + spsensor->isp_priv_info.outputSize = OUTPUT_QSXGA|OUTPUT_QUADVGA; + spsensor->isp_priv_info.supportedSizeNum = 2; + spsensor->isp_priv_info.supportedSize[0] = OUTPUT_QUADVGA; + spsensor->isp_priv_info.supportedSize[1] = OUTPUT_QSXGA; + return; +} + +/* +* :::::WARNING::::: +* It is not allowed to modify the following code +*/ + +sensor_init_parameters_default_code(); + +sensor_v4l2_struct_initialization(); + +sensor_probe_default_code(); + +sensor_remove_default_code(); + +sensor_driver_default_module_code(); + + + + diff --git a/drivers/media/video/icatch7002/icatch_spi_host.c b/drivers/media/video/icatch7002/icatch_spi_host.c new file mode 100755 index 000000000000..4d220a0b4b23 --- /dev/null +++ b/drivers/media/video/icatch7002/icatch_spi_host.c @@ -0,0 +1,82 @@ +/*icatch host mode ,spi device + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "icatch_spi_host.h" +#include +struct spi_device* g_icatch_spi_dev = NULL; + +static int __devinit spi_icatch_probe(struct spi_device *spi) +{ + struct spi_test_data *spi_test_data; + int ret = 0; + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0){ + dev_err(spi, "ERR: fail to setup spi\n"); + return -1; + } + + g_icatch_spi_dev = spi; + + printk("%s:bus_num=%d,ok\n",__func__,spi->master->bus_num); + + return ret; + +} + + +static struct spi_driver spi_icatch_driver = { + .driver = { + .name = "spi_icatch", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = spi_icatch_probe, +}; + +static struct miscdevice spi_test_icatch = { + .minor = MISC_DYNAMIC_MINOR, + .name = "spi_misc_icatch", +}; + +static int __init spi_icatch_init(void) +{ + spi_register_board_info(board_spi_icatch_devices, ARRAY_SIZE(board_spi_icatch_devices)); + + misc_register(&spi_test_icatch); + return spi_register_driver(&spi_icatch_driver); +} + +static void __exit spi_icatch_exit(void) +{ + + misc_deregister(&spi_test_icatch); + return spi_unregister_driver(&spi_icatch_driver); +} +module_init(spi_icatch_init); +module_exit(spi_icatch_exit); + + diff --git a/drivers/media/video/icatch7002/icatch_spi_host.h b/drivers/media/video/icatch7002/icatch_spi_host.h new file mode 100755 index 000000000000..70a73c618f46 --- /dev/null +++ b/drivers/media/video/icatch7002/icatch_spi_host.h @@ -0,0 +1,23 @@ +#ifndef ICATCH_SPI_HOST_H +#define ICATCH_SPI_HOST_H +#include "../../../spi/rk29_spim.h" +#include + +static struct rk29xx_spi_chip spi_icatch = { + //.poll_mode = 1, + .enable_dma = 0, +}; +//user must define this struct according to hardware config +static struct spi_board_info board_spi_icatch_devices[] = { + { + .modalias = "spi_icatch", + .bus_num = 0, //0 or 1 + .max_speed_hz = 24*1000*1000, + .chip_select = 0, + .mode = SPI_MODE_0, + .controller_data = &spi_icatch, + }, + +}; +#endif + diff --git a/drivers/media/video/rk30_camera_pingpong.c b/drivers/media/video/rk30_camera_pingpong.c index 005d8afc4ea4..04eef257d075 100755 --- a/drivers/media/video/rk30_camera_pingpong.c +++ b/drivers/media/video/rk30_camera_pingpong.c @@ -53,9 +53,16 @@ #define SOFT_RST_CIF1 (SOFT_RST_MAX+1) #endif #include -static int debug; +static int debug = 0; module_param(debug, int, S_IRUGO|S_IWUSR); +#if defined(CONFIG_TRACE_LOG_PRINTK) + #define RK30_CAM_DEBUG_TRACE(format, ...) printk(KERN_ERR"rk30_camera: " format, ## __VA_ARGS__) +#else + #define RK30_CAM_DEBUG_TRACE(format, ...) +#endif +#define RK30_CAM_LOG_TRACE(format, ...) printk(KERN_WARNING"rk30_camera: " format, ## __VA_ARGS__) + #define dprintk(level, fmt, arg...) do { \ if (debug >= level) \ printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0) @@ -156,8 +163,9 @@ module_param(debug, int, S_IRUGO|S_IWUSR); #define MIN(x,y) ((xy) ? x: y) +#define RK_SENSOR_12MHZ 12*1000*1000 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */ -#define RK_SENSOR_48MHZ 48 +#define RK_SENSOR_48MHZ 48*1000*1000 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base)) #define read_cif_reg(base,addr) __raw_readl(addr+(base)) @@ -293,8 +301,10 @@ module_param(debug, int, S_IRUGO|S_IWUSR); * 2. fix 2928 digitzoom erro(arm crop scale) of selected zone; *v0.x.1f: * 1. support rk3188 +*v0.x.21: + 1. cif change mode to free run.support icatch 7002. */ -#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0x1f) +#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0x21) /* limit to rk29 hardware capabilities */ #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\ @@ -313,8 +323,8 @@ module_param(debug, int, S_IRUGO|S_IWUSR); #define RK_CAM_H_MIN 32 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */ #define RK_CAM_H_MAX 2764 -#define RK_CAM_FRAME_INVAL_INIT 3 -#define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */ +#define RK_CAM_FRAME_INVAL_INIT 0 +#define RK_CAM_FRAME_INVAL_DC 0 /* ddl@rock-chips.com : */ #define RK30_CAM_FRAME_MEASURE 5 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf); extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); @@ -327,6 +337,7 @@ struct rk_camera_buffer enum v4l2_mbus_pixelcode code; int inwork; }; + enum rk_camera_reg_state { Reg_Invalidate, @@ -351,18 +362,22 @@ struct rk_camera_work struct rk_camera_dev *pcdev; struct work_struct work; struct list_head queue; - unsigned int index; + unsigned int index; + unsigned int ts; }; + struct rk_camera_frmivalenum { struct v4l2_frmivalenum fival; struct rk_camera_frmivalenum *nxt; }; + struct rk_camera_frmivalinfo { struct soc_camera_device *icd; struct rk_camera_frmivalenum *fival_list; }; + struct rk_camera_zoominfo { struct semaphore sem; @@ -371,6 +386,7 @@ struct rk_camera_zoominfo int vir_height; int zoom_rate; }; + #if CAMERA_VIDEOBUF_ARM_ACCESS struct rk29_camera_vbinfo { @@ -379,11 +395,39 @@ struct rk29_camera_vbinfo unsigned int size; }; #endif + struct rk_camera_timer{ struct rk_camera_dev *pcdev; struct hrtimer timer; bool istarted; - }; +}; +struct rk_cif_clk +{ + //************must modify start************/ + struct clk *pd_cif; + struct clk *aclk_cif; + struct clk *hclk_cif; + struct clk *cif_clk_in; + struct clk *cif_clk_out; + //************must modify end************/ + + spinlock_t lock; + bool on; +}; +static struct rk_cif_clk cif_clk[2]; +struct hdr_exposure +{ + unsigned int set_ts; + unsigned int get_ts; + unsigned int code; +}; +struct rk_hdr_info_s +{ + bool en; + struct hdr_exposure frame[3]; +}; +#define CONFIG_CIF_STOP_SYNC 1 + struct rk_camera_dev { struct soc_camera_host soc_host; @@ -414,8 +458,9 @@ struct rk_camera_dev unsigned int vipmem_bsize; #if CAMERA_VIDEOBUF_ARM_ACCESS struct rk29_camera_vbinfo *vbinfo; - unsigned int vbinfo_count; -#endif +#endif + unsigned int vbinfo_count; + int host_width; int host_height; int host_left; //sensor output size ? @@ -447,8 +492,15 @@ struct rk_camera_dev bool timer_get_fps; unsigned int reinit_times; struct videobuf_queue *video_vq; - bool stop_cif; + volatile bool stop_cif; +#if CONFIG_CIF_STOP_SYNC + wait_queue_head_t cif_stop_done; + volatile bool cif_stopped; +#endif struct timeval first_tv; + + struct rk_hdr_info_s hdr_info; +// spinlock_t irq_lock; }; static const struct v4l2_queryctrl rk_camera_controls[] = @@ -464,6 +516,18 @@ static const struct v4l2_queryctrl rk_camera_controls[] = .default_value = 100, }, #endif + + { + .id = V4L2_CID_HDR, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "HDR", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + } + + }; static DEFINE_MUTEX(camera_lock); @@ -472,6 +536,7 @@ static const char *rk_cam_driver_description = "RK_Camera"; static int rk_camera_s_stream(struct soc_camera_device *icd, int enable); static void rk_camera_capture_process(struct work_struct *work); +#define OPTIMIZE_MEMORY_USE /* * Videobuf operations @@ -514,9 +579,11 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, #endif { BUG_ON(pcdev->vipmem_sizevipmem_bsize); + #ifndef OPTIMIZE_MEMORY_USE if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */ *count = pcdev->vipmem_size/pcdev->vipmem_bsize; } + #endif } if ((pcdev->camera_work_count != *count) && pcdev->camera_work) { kfree(pcdev->camera_work); @@ -527,7 +594,7 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (pcdev->camera_work == NULL) { pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL); if (pcdev->camera_work == NULL) { - RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__); + RK30_CAM_DEBUG_TRACE("\n %s kmalloc fail\n", __FUNCTION__); BUG(); } INIT_LIST_HEAD(&pcdev->camera_work_queue); @@ -549,7 +616,7 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (pcdev->vbinfo == NULL) { pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL); if (pcdev->vbinfo == NULL) { - RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__); + RK30_CAM_DEBUG_TRACE("\n %s vbinfo kmalloc fail\n", __FUNCTION__); BUG(); } memset(pcdev->vbinfo,0,sizeof(struct rk29_camera_vbinfo)*(*count)); @@ -557,8 +624,10 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, } #endif } + + pcdev->vbinfo_count = *count; pcdev->video_vq = vq; - RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count); + RK30_CAM_DEBUG_TRACE("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count); return 0; } @@ -606,9 +675,9 @@ static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer BUG_ON(NULL == icd->current_fmt); if (buf->code != icd->current_fmt->code || - vb->width != icd->user_width || - vb->height != icd->user_height || - vb->field != field) { + vb->width != icd->user_width || + vb->height != icd->user_height || + vb->field != field) { buf->code = icd->current_fmt->code; vb->width = icd->user_width; vb->height = icd->user_height; @@ -637,6 +706,38 @@ out: return ret; } +#if 0 +static void rk_camera_store_register(struct rk_camera_dev *pcdev) +{ +#if defined(CONFIG_ARCH_RK3188) + pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL); + pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP); + pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE); + pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN); + pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR); + pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH); + pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL); + + cru_set_soft_reset(SOFT_RST_CIF0, true); + udelay(3); + cru_set_soft_reset(SOFT_RST_CIF0, false); + +#endif +} +static void rk_camera_restore_register(struct rk_camera_dev *pcdev) +{ +#if defined(CONFIG_ARCH_RK3188) + write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE); + write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn); + write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop); + write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs); + write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt); + write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth); + write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale); +#endif +} +#endif + static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev, int fmt_ready) { unsigned int y_addr,uv_addr; @@ -644,13 +745,18 @@ static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_came if (vb) { if (CAM_WORKQUEUE_IS_EN()) { + #ifdef OPTIMIZE_MEMORY_USE + y_addr = vb->boff; + uv_addr = y_addr + vb->width * vb->height; + #else y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) { - RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height, + RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height, pcdev->icd->user_width,pcdev->icd->user_height, vb->i); BUG(); } + #endif } else { y_addr = vb->boff; uv_addr = y_addr + vb->width * vb->height; @@ -667,7 +773,7 @@ static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_came write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr); break; default: - RKCAMERA_TR("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready); + RK30_CAM_DEBUG_TRACE("%s(%d): fmt_ready(%d) is wrong!\n", __FUNCTION__, __LINE__,fmt_ready); break; } @@ -686,6 +792,7 @@ static void rk_videobuf_queue(struct videobuf_queue *vq, dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); + // spin_lock_irqsave(&pcdev->irq_lock, flags); vb->state = VIDEOBUF_QUEUED; if (list_empty(&pcdev->capture)) { @@ -716,20 +823,23 @@ static void rk_videobuf_queue(struct videobuf_queue *vq, vb_info->size = vb->bsize; vb_info->phy_addr = vb->boff; } else { - RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i); + RK30_CAM_DEBUG_TRACE("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i); } } } -#endif - if (!pcdev->active0) { - pcdev->active0 = vb; - rk_videobuf_capture(vb,pcdev,0); - list_del_init(&(vb->queue)); - } else if (!pcdev->active1) { - pcdev->active1 = vb; - rk_videobuf_capture(vb,pcdev,1); - list_del_init(&(vb->queue)); +#endif + if((((read_cif_reg(pcdev->base,CIF_CIF_CTRL)) & ENABLE_CAPTURE) == 0)){ + if (!pcdev->active0) { + pcdev->active0 = vb; + rk_videobuf_capture(vb,pcdev,0); + list_del_init(&(vb->queue)); + } else if (!pcdev->active1) { + pcdev->active1 = vb; + rk_videobuf_capture(vb,pcdev,1); + list_del_init(&(vb->queue)); + } } + //spin_unlock_irqrestore(&pcdev->irq_lock, flags); } static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt) { @@ -756,6 +866,7 @@ rk_pixfmt2ippfmt_err: return -1; } +#if 0 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt) { switch (pixfmt) @@ -792,6 +903,8 @@ static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt) rk_pixfmt2rgafmt_err: return -1; } +#endif + #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP) static int rk_camera_scale_crop_pp(struct work_struct *work){ struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); @@ -852,7 +965,7 @@ static int rk_camera_scale_crop_rga(struct work_struct *work){ vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565) && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){ - RKCAMERA_TR("RGA not support this format !\n"); + RK30_CAM_DEBUG_TRACE("RGA not support this format !\n"); goto do_ipp_err; } if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) { @@ -917,13 +1030,13 @@ static int rk_camera_scale_crop_rga(struct work_struct *work){ req.dst.x_offset = pcdev->icd->user_width*w/scale_times; req.dst.y_offset = pcdev->icd->user_height*h/scale_times; req.dst.yrgb_addr = vb->boff ; - // RKCAMERA_TR("src.act_w = %d , src.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset); - // RKCAMERA_TR("dst.act_w = %d , dst.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset); - // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr); + // RK30_CAM_DEBUG_TRACE("src.act_w = %d , src.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset); + // RK30_CAM_DEBUG_TRACE("dst.act_w = %d , dst.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset); + // RK30_CAM_DEBUG_TRACE("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr); while(rga_times-- > 0) { if (rga_blit_sync(&session, &req)){ - RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times); + RK30_CAM_DEBUG_TRACE("rga do erro,do again,rga_times = %d!\n",rga_times); } else { break; } @@ -967,7 +1080,7 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work) struct rk29_ipp_req ipp_req; int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size; int scale_times,w,h; - int ret = 0; + int ret = 0; /* *ddl@rock-chips.com: * IPP Dest image resolution is 2047x1088, so scale operation break up some times @@ -979,7 +1092,49 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work) scale_times = 1; } memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); - +#ifdef OPTIMIZE_MEMORY_USE + //need copy to ipp buffer? + if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width) + ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){ + if((pcdev->zoominfo.vir_width != pcdev->icd->user_width) || (pcdev->zoominfo.vir_height != pcdev->icd->user_height)){ + printk("OPTIMIZE_MEMORY_USE erro: src size not equal to dst size\n"); + goto do_ipp_err; + } + ipp_req.timeout = 3000; + ipp_req.flag = IPP_ROT_0; + ipp_req.store_clip_mode =1; + ipp_req.src0.w = pcdev->zoominfo.vir_width/scale_times; + ipp_req.src0.h = pcdev->zoominfo.vir_height/scale_times; + ipp_req.dst0.w = pcdev->icd->user_width/scale_times; + ipp_req.dst0.h = pcdev->icd->user_height/scale_times; + ipp_req.src_vir_w = pcdev->zoominfo.vir_width; + ipp_req.dst_vir_w = pcdev->icd->user_width; + rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt); + rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt); + vipdata_base = pcdev->vipmem_phybase; + src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem + dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height; + for (h=0; hzoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width + + w*pcdev->zoominfo.vir_width/scale_times; + src_uv_offset = (h*pcdev->zoominfo.vir_height/scale_times)* pcdev->zoominfo.vir_width/2 + + w*pcdev->zoominfo.vir_width/scale_times; + + dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times; + dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times; + ipp_req.src0.YrgbMst = vb->boff + src_y_offset; + ipp_req.src0.CbrMst = vb->boff + src_y_size + src_uv_offset; + ipp_req.dst0.YrgbMst = vipdata_base + dst_y_offset; + ipp_req.dst0.CbrMst = vipdata_base + dst_y_size + dst_uv_offset; + if (ipp_blit_sync(&ipp_req)){ + RK30_CAM_DEBUG_TRACE("ipp do erro\n"); + } + } + } + memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); + } +#endif ipp_req.timeout = 3000; ipp_req.flag = IPP_ROT_0; @@ -992,7 +1147,16 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work) ipp_req.dst0.h = pcdev->icd->user_height/scale_times; ipp_req.dst_vir_w = pcdev->icd->user_width; rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt); +#ifdef OPTIMIZE_MEMORY_USE + if((pcdev->zoominfo.a.c.width != pcdev->zoominfo.vir_width) + ||(pcdev->zoominfo.a.c.height != pcdev->zoominfo.vir_height)){ + vipdata_base = pcdev->vipmem_phybase; + }else + vipdata_base = vb->boff; + +#else vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; +#endif src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height; for (h=0; hboff + dst_y_size + dst_uv_offset; while(ipp_times-- > 0) { if (ipp_blit_sync(&ipp_req)){ - RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times); + RK30_CAM_DEBUG_TRACE("ipp do erro,do again,ipp_times = %d!\n",ipp_times); } else { break; } @@ -1022,17 +1186,17 @@ static int rk_camera_scale_crop_ipp(struct work_struct *work) spin_lock_irqsave(&pcdev->lock, flags); vb->state = VIDEOBUF_NEEDS_INIT; spin_unlock_irqrestore(&pcdev->lock, flags); - RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i); - RKCAMERA_TR("widx:%d hidx:%d ",w,h); - RKCAMERA_TR("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height); - RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst); - RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h); - RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt); - RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst); - RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h); - RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt); - RKCAMERA_TR("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); - RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag); + RK30_CAM_DEBUG_TRACE("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i); + RK30_CAM_DEBUG_TRACE("widx:%d hidx:%d ",w,h); + RK30_CAM_DEBUG_TRACE("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height); + RK30_CAM_DEBUG_TRACE("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst); + RK30_CAM_DEBUG_TRACE("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h); + RK30_CAM_DEBUG_TRACE("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt); + RK30_CAM_DEBUG_TRACE("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst); + RK30_CAM_DEBUG_TRACE("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h); + RK30_CAM_DEBUG_TRACE("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt); + RK30_CAM_DEBUG_TRACE("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); + RK30_CAM_DEBUG_TRACE("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag); goto do_ipp_err; } @@ -1070,8 +1234,8 @@ static int rk_camera_scale_crop_arm(struct work_struct *work) cropW = pcdev->zoominfo.a.c.width; cropH = pcdev->zoominfo.a.c.height; - psY = psY + (srcW-cropW)/2; - psUV = psUV + (srcW-cropW)/2; + psY = psY + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width+pcdev->zoominfo.a.c.left; + psUV = psUV + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width/2+pcdev->zoominfo.a.c.left; vb_info = pcdev->vbinfo+vb->i; dst_phy = vb_info->phy_addr; @@ -1080,9 +1244,8 @@ static int rk_camera_scale_crop_arm(struct work_struct *work) dstW = pcdev->icd->user_width; dstH = pcdev->icd->user_height; - zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1; - zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1; - + zoomindstxIntInv = ((unsigned long)(cropW)<<16)/dstW + 1; + zoomindstyIntInv = ((unsigned long)(cropH)<<16)/dstH + 1; //y //for(y = 0; yvb; struct rk_camera_dev *pcdev = camera_work->pcdev; //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code; + struct device *control = to_soc_camera_control(pcdev->icd); + struct v4l2_subdev *sd=dev_get_drvdata(control); unsigned long flags = 0; - int err = 0; + int err = 0,i; if (!CAM_WORKQUEUE_IS_EN()) goto rk_camera_capture_process_end; + + camera_work->vb->rk_code = 0x00; + if (pcdev->hdr_info.en) { + printk("rk_camera_capture_process hdr %d fps\n",camera_work->ts); + if (pcdev->hdr_info.frame[0].set_ts == 0) { + v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)pcdev->hdr_info.frame[0].code); + pcdev->hdr_info.frame[0].set_ts = pcdev->fps; + printk("set hdr %d @ %d fps\n",0,pcdev->fps); + } else { + if ((camera_work->ts - pcdev->hdr_info.frame[0].set_ts) > 1) { + for (i=0; i<3; i++) { + if (pcdev->hdr_info.frame[i].get_ts == 0) { + printk("get hdr %d @ %d fps %dx%d\n",i,camera_work->ts,camera_work->vb->width,camera_work->vb->height); + pcdev->hdr_info.frame[i].get_ts = camera_work->ts; + RK_VIDEOBUF_CODE_SET(camera_work->vb->rk_code,pcdev->hdr_info.frame[i].code); + break; + } + } + + if (i==2) { + v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,(void*)RK_VIDEOBUF_HDR_EXPOSURE_FINISH); + pcdev->hdr_info.en = false; + printk("hdr off\n"); + } + } + } + } + down(&pcdev->zoominfo.sem); if (pcdev->icd_cb.scale_crop_cb){ @@ -1193,13 +1387,41 @@ rk_camera_capture_process_end: vb->state = VIDEOBUF_DONE; vb->field_count++; } - } - wake_up(&(camera_work->vb->done)); + } spin_lock_irqsave(&pcdev->camera_work_lock, flags); - list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); - spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); + list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); + spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); + wake_up(&(camera_work->vb->done)); return; } +#if defined(CONFIG_ARCH_RK3188) +static void rk_camera_store_resore_register(struct rk_camera_dev *pcdev) +{ + + pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL); + pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP); + pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE); + pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN); + pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR); + pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH); + pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL); + + cru_set_soft_reset(SOFT_RST_CIF0, true); + udelay(5); + cru_set_soft_reset(SOFT_RST_CIF0, false); + + if (pcdev->reginfo_suspend.cifCtrl&ENABLE_CAPTURE) + write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE); + write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn); + write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop); + write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs); + write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt); + write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth); + write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale); + +} +#endif + static irqreturn_t rk_camera_irq(int irq, void *data) { struct rk_camera_dev *pcdev = data; @@ -1209,33 +1431,88 @@ static irqreturn_t rk_camera_irq(int irq, void *data) unsigned long tmp_intstat; unsigned long tmp_cifctrl; unsigned long tmp_cif_frmst; - struct videobuf_buffer **active; + struct videobuf_buffer **active = 0; int flag = 0; - + unsigned int invalid_y_addr ,invalid_uv_addr; +#ifdef OPTIMIZE_MEMORY_USE + invalid_y_addr = 0/*pcdev->vipmem_phybase + pcdev->vipmem_bsize*/; + invalid_uv_addr = 0/*invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height*/; +#else + invalid_y_addr = pcdev->vipmem_phybase + pcdev->vbinfo_count *pcdev->vipmem_bsize; + invalid_uv_addr = invalid_y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; +#endif tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL); tmp_cif_frmst = read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS); - +#if (CONFIG_CIF_STOP_SYNC == 0) if(pcdev->stop_cif == true) { - //RKCAMERA_TR("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__); - write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */ - return IRQ_HANDLED; - } - + //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__); + write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */ + return IRQ_HANDLED; + } +#endif + if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/) {//bit9 =1 ,bit0 = 0 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */ - if(tmp_cifctrl & ENABLE_CAPTURE) - write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE)); + // if(tmp_cifctrl & ENABLE_CAPTURE) + // write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE)); return IRQ_HANDLED; } /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */ if (tmp_cif_frmst & (CIF_F0_READY | CIF_F1_READY)) { write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */ +#if CONFIG_CIF_STOP_SYNC + if(pcdev->stop_cif == true) { + //RK30_CAM_DEBUG_TRACE("%s(%d): cif has stopped by app,needn't to deal this irq\n",__FUNCTION__,__LINE__); + write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */ + +#if 1 + // write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0); //capture complete interrupt enable + { +#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928)) + mdelay(100); + if(IS_CIF0()){ + cru_set_soft_reset(SOFT_RST_CIF0, true); + udelay(5); + cru_set_soft_reset(SOFT_RST_CIF0, false); + + }else{ + cru_set_soft_reset(SOFT_RST_CIF1, true); + udelay(5); + cru_set_soft_reset(SOFT_RST_CIF1, false); + } +#elif defined(CONFIG_ARCH_RK3188) + cru_set_soft_reset(SOFT_RST_CIF0, true); + udelay(5); + cru_set_soft_reset(SOFT_RST_CIF0, false); +#endif + } +#endif + spin_lock(&pcdev->lock); + pcdev->cif_stopped = true; + wake_up(&pcdev->cif_stop_done); + spin_unlock(&pcdev->lock); + return IRQ_HANDLED; + } +#endif if (!pcdev->fps) { do_gettimeofday(&pcdev->first_tv); } +process_another_frame: + if((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){ + printk(KERN_DEBUG"%s:f0 && f1 ready ,need to resart cif!!!!!\n",__func__); + spin_lock(&pcdev->lock); + + rk_camera_store_resore_register(pcdev); + rk_videobuf_capture(pcdev->active0,pcdev,0); + rk_videobuf_capture(pcdev->active1,pcdev,1); + tmp_cifctrl &=~ENABLE_CAPTURE; + spin_unlock(&pcdev->lock); + + goto RK_CAMERA_IRQ_END; + } pcdev->fps++; if (tmp_cif_frmst & CIF_F0_READY){ @@ -1244,70 +1521,103 @@ static irqreturn_t rk_camera_irq(int irq, void *data) } else if (tmp_cif_frmst & CIF_F1_READY){ active = &pcdev->active1; flag = 1; + } else { + printk("irq frame status erro \n"); + goto RK_CAMERA_IRQ_END; } - +#if 0 if (!(*active)){ goto RK_CAMERA_IRQ_END; } +#endif + if (pcdev->frame_inval>0) { + pcdev->frame_inval--; + rk_videobuf_capture(*active,pcdev,flag); + goto first_frame_done; + } else if (pcdev->frame_inval) { + RK30_CAM_DEBUG_TRACE("frame_inval : %0x",pcdev->frame_inval); + pcdev->frame_inval = 0; + } - if (pcdev->frame_inval>0) { - pcdev->frame_inval--; - rk_videobuf_capture(*active,pcdev,flag); - goto RK_CAMERA_IRQ_END; - } else if (pcdev->frame_inval) { - RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval); - pcdev->frame_inval = 0; - } - - if(pcdev->fps == RK30_CAM_FRAME_MEASURE) { - do_gettimeofday(&tv); - pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec)) - /(RK30_CAM_FRAME_MEASURE-1); + if(pcdev->fps == RK30_CAM_FRAME_MEASURE) { + do_gettimeofday(&tv); + pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec)) + /(RK30_CAM_FRAME_MEASURE-1); } - vb = *active; - if(!vb){ - RKCAMERA_TR("no acticve buffer!!!\n"); - goto RK_CAMERA_IRQ_END; - } + vb = *active; + +#if 0 + if(!vb){ + RK30_CAM_DEBUG_TRACE("no acticve buffer!!!\n"); + goto RK_CAMERA_IRQ_END; + } if (vb->stream.prev != &(pcdev->video_vq->stream)) { - RKCAMERA_DG("vb(%d) isn't first node in stream list\n", vb->i); + RK30_CAM_DEBUG_TRACE("vb(%d) isn't first node in stream list\n", vb->i); goto RK_CAMERA_IRQ_END; } - +#endif *active = NULL; - if (!list_empty(&pcdev->capture)) { - *active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue); + spin_lock(&pcdev->lock); + if (!list_empty(&pcdev->capture)) { + *active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue); if (*active) { - WARN_ON((*active)->state != VIDEOBUF_QUEUED); + WARN_ON((*active)->state != VIDEOBUF_QUEUED); + if (tmp_cif_frmst & CIF_F0_READY){ + pcdev->active0 = *active; + } else if (tmp_cif_frmst & CIF_F1_READY){ + pcdev->active1 = *active; + }else{ + printk("irq frame status erro !\n"); + } rk_videobuf_capture((*active),pcdev,flag); list_del_init(&((*active)->queue)); } - } - if ((*active) == NULL) { - RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__); } - - do_gettimeofday(&vb->ts); + spin_unlock(&pcdev->lock); + if ((*active) == NULL) { + // RK30_CAM_DEBUG_TRACE("%s video_buf queue is empty!\n",__FUNCTION__); + if(flag == 0){ + pcdev->active0 = NULL; + write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, invalid_y_addr); + write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, invalid_uv_addr); + }else{ + pcdev->active1 = NULL; + write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, invalid_y_addr); + write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, invalid_uv_addr); + } + } + if(vb) + do_gettimeofday(&vb->ts); if (CAM_WORKQUEUE_IS_EN()) { - if (!list_empty(&pcdev->camera_work_queue)) { - wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue); - list_del_init(&wk->queue); - INIT_WORK(&(wk->work), rk_camera_capture_process); - wk->vb = vb; - wk->pcdev = pcdev; - queue_work(pcdev->camera_wq, &(wk->work)); - } + if(vb){ + if (!list_empty(&pcdev->camera_work_queue)) { + wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue); + list_del_init(&wk->queue); + INIT_WORK(&(wk->work), rk_camera_capture_process); + wk->vb = vb; + wk->pcdev = pcdev; + wk->ts = pcdev->fps; + queue_work(pcdev->camera_wq, &(wk->work)); + }else{ + printk("work queue is empty \n!!!!!!!!"); + } + } } else { - if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { - vb->state = VIDEOBUF_DONE; - vb->field_count++; - } + if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { + vb->state = VIDEOBUF_DONE; + vb->field_count++; + } wake_up(&vb->done); } - } +first_frame_done: + if ((tmp_cif_frmst & CIF_F0_READY) && (tmp_cif_frmst & CIF_F1_READY)){ + printk(KERN_DEBUG"%s:f0 && f1 ready ,need to process f1 too!!!!!\n",__func__); + tmp_cif_frmst &=~CIF_F0_READY; + goto process_another_frame; + } RK_CAMERA_IRQ_END: if((tmp_cifctrl & ENABLE_CAPTURE) == 0) @@ -1348,27 +1658,26 @@ static void rk_videobuf_release(struct videobuf_queue *vq, } #endif - #if 0 /* ddl@rock-chips.com: this wait operation is not nessary, invalidate in v0.x.1f */ + #if 0 /* ddl@rock-chips.com: this wait operation is not nessary, invalidate in v0.x.1f */ if (vb == pcdev->active0 || vb == pcdev->active1) { - RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb); + RK30_CAM_DEBUG_TRACE("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb); interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500)); - RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb); + RK30_CAM_DEBUG_TRACE("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb); } - #endif - flush_workqueue(pcdev->camera_wq); + #endif + flush_workqueue(pcdev->camera_wq); #if CAMERA_VIDEOBUF_ARM_ACCESS - if (pcdev->vbinfo) { - vb_info = pcdev->vbinfo + vb->i; + if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) { + vb_info = pcdev->vbinfo + vb->i; - if (vb_info->vir_addr) { - iounmap(vb_info->vir_addr); - release_mem_region(vb_info->phy_addr, vb_info->size); - memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); - } - + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); + } } #endif - rk_videobuf_free(vq, buf); + rk_videobuf_free(vq, buf); } static struct videobuf_queue_ops rk_videobuf_ops = @@ -1395,67 +1704,74 @@ static void rk_camera_init_videobuf(struct videobuf_queue *q, sizeof(struct rk_camera_buffer), icd,&icd->video_lock); } -static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd) -{ - int err = 0; - - if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){ - RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n"); - err = -ENOENT; - goto RK_CAMERA_ACTIVE_ERR; - } - clk_enable(pcdev->pd_cif); - clk_enable(pcdev->aclk_cif); +static int rk_camera_mclk_ctrl(int cif_idx, int on, int clk_rate){ + int err = 0,cif; + struct rk_cif_clk *clk; + struct clk *cif_clk_out_div; - clk_enable(pcdev->hclk_cif); - clk_enable(pcdev->cif_clk_in); + cif = cif_idx - RK29_CAM_PLATFORM_DEV_ID; + if ((cif<0)||(cif>1)) { + RKCAMERA_TR(KERN_ERR "cif index(%d) is invalidate\n",cif_idx); + err = -1; + goto rk_camera_clk_ctrl_end; + } - //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */ - //sensor_bus_flags = icd->ops->query_bus_param(icd); - clk_enable(pcdev->cif_clk_out); - clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ); + clk = &cif_clk[cif]; - ndelay(10); - //soft reset the registers - #if 0 //has somthing wrong when suspend and resume now - if(IS_CIF0()){ - printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30)); - //dump regs - { - printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL)); - printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN)); - printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT)); - printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR)); - printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP)); - printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE)); - printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL)); - printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30)); - printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE)); - - printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX)); - printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH)); - printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR)); - printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y)); - printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV)); - printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS)); - } + if(!clk->aclk_cif || !clk->hclk_cif || !clk->cif_clk_in || !clk->cif_clk_out) { + RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n"); + err = -ENOENT; + goto rk_camera_clk_ctrl_end; + } + spin_lock(&clk->lock); + if (on && !clk->on) { + clk_enable(clk->pd_cif); + clk_enable(clk->aclk_cif); + clk_enable(clk->hclk_cif); + clk_enable(clk->cif_clk_in); + clk_enable(clk->cif_clk_out); + clk_set_rate(clk->cif_clk_out,clk_rate); + mdelay(10); + clk->on = true; + + } else if (!on && clk->on) { + clk_disable(clk->aclk_cif); + clk_disable(clk->hclk_cif); + clk_disable(clk->cif_clk_in); + + clk_disable(clk->cif_clk_out); + clk_disable(clk->pd_cif); + clk->on = false; + if(cif){ + cif_clk_out_div = clk_get(NULL, "cif1_out_div"); + }else{ + cif_clk_out_div = clk_get(NULL, "cif0_out_div"); + if(IS_ERR_OR_NULL(cif_clk_out_div)) { + cif_clk_out_div = clk_get(NULL, "cif_out_div"); + } + } - mdelay(100); - write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 )); - printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30)); - write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0); - mdelay(1000); - printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30)); - }else{ - write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30))); - write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1); + if(IS_ERR_OR_NULL(cif_clk_out_div)) { + err = clk_set_parent(clk->cif_clk_out, cif_clk_out_div); + clk_put(cif_clk_out_div); + } else { + err = -1; + } + + if(err) + RKCAMERA_TR("WARNING %s_%s_%d: camera sensor mclk maybe not close, please check!!!\n", __FILE__, __FUNCTION__, __LINE__); } - #endif + spin_unlock(&clk->lock); +rk_camera_clk_ctrl_end: + return err; +} +static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd) +{ write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_PINGPONG|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */ write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable - RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL)); + RK30_CAM_DEBUG_TRACE("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL)); return 0; RK_CAMERA_ACTIVE_ERR: return -ENODEV; @@ -1463,18 +1779,6 @@ RK_CAMERA_ACTIVE_ERR: static void rk_camera_deactivate(struct rk_camera_dev *pcdev) { - clk_disable(pcdev->aclk_cif); - - clk_disable(pcdev->hclk_cif); - clk_disable(pcdev->cif_clk_in); - - clk_disable(pcdev->cif_clk_out); - clk_enable(pcdev->cif_clk_out); - clk_set_rate(pcdev->cif_clk_out,48*1000*1000); - clk_disable(pcdev->cif_clk_out); - - clk_disable(pcdev->pd_cif); - return; } @@ -1496,7 +1800,7 @@ static int rk_camera_add_device(struct soc_camera_device *icd) goto ebusy; } - RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev)); + RK30_CAM_DEBUG_TRACE("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev)); pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT; pcdev->active0 = NULL; @@ -1566,7 +1870,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) mutex_lock(&camera_lock); BUG_ON(icd != pcdev->icd); - RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev)); + RK30_CAM_DEBUG_TRACE("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev)); /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but stream may be turn on again before close device, if suspend and resume happened. */ @@ -1627,7 +1931,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) INIT_LIST_HEAD(&pcdev->capture); mutex_unlock(&camera_lock); - RKCAMERA_DG("%s exit\n",__FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s exit\n",__FUNCTION__); return; } @@ -1639,7 +1943,7 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) int ret = 0; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk_camera_dev *pcdev = ici->priv; - RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s..%d..\n",__FUNCTION__,__LINE__); fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); if (!fmt) @@ -1680,22 +1984,22 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) goto RK_CAMERA_SET_BUS_PARAM_END; cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR); - RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val); + RK30_CAM_DEBUG_TRACE("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val); if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) { if(IS_CIF0()) { write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0); - RKCAMERA_DG("enable cif0 pclk invert\n"); + RK30_CAM_DEBUG_TRACE("enable cif0 pclk invert\n"); } else { write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1); - RKCAMERA_DG("enable cif1 pclk invert\n"); + RK30_CAM_DEBUG_TRACE("enable cif1 pclk invert\n"); } } else { if(IS_CIF0()){ write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0); - RKCAMERA_DG("diable cif0 pclk invert\n"); + RK30_CAM_DEBUG_TRACE("diable cif0 pclk invert\n"); } else { write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1); - RKCAMERA_DG("diable cif1 pclk invert\n"); + RK30_CAM_DEBUG_TRACE("diable cif1 pclk invert\n"); } } if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) { @@ -1712,11 +2016,11 @@ static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */ //vip_ctrl_val |= ENABLE_CAPTURE; write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val); - RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR)); + RK30_CAM_DEBUG_TRACE("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR)); RK_CAMERA_SET_BUS_PARAM_END: if (ret) - RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); + RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); return ret; } @@ -1733,10 +2037,21 @@ static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) } ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ; - if (ret < 0) - dev_warn(icd->dev.parent, - "Flags incompatible: camera %lx, host %lx\n", - camera_flags, bus_flags); + /*nelson_yang@asus.com fix: rock-chip coding bug*/ + /* rockchip BUGBUG + if (ret < 0) + dev_warn(icd->dev.parent, + "Flags incompatible: camera %lx, host %lx\n", + camera_flags, bus_flags); + */ + if(!ret){ + dev_warn(icd->dev.parent, "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags); + ret = -EINVAL; + } + else{ + ret = 0; + } + /*nelson_yang@asus.com fix: rock-chip coding bug end*/ return ret; } @@ -1864,7 +2179,7 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix cru_set_soft_reset(SOFT_RST_CIF1, false); // pmu_set_idle_request(IDLE_REQ_VIO, false); } -#else defined(CONFIG_ARCH_RK3188) +#elif defined(CONFIG_ARCH_RK3188) // pmu_set_idle_request(IDLE_REQ_VIO, true); cru_set_soft_reset(SOFT_RST_CIF0, true); udelay(5); @@ -1879,11 +2194,15 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix write_cif_reg(pcdev->base,CIF_CIF_FOR,cif_fmt_val); /* ddl@rock-chips.com: VIP capture mode and capture format must be set before FS register set */ // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */ - write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); - - cif_crop = (rect->left+ (rect->top<<16)); - cif_fs = ((rect->width ) + (rect->height<<16)); - + write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); + /* + if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG) + ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) { + BUG(); + } else*/{ // this is one frame mode + cif_crop = (rect->left+ (rect->top<<16)); + cif_fs = ((rect->width ) + (rect->height<<16)); + } write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop); write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs); @@ -1892,7 +2211,7 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix //MUST bypass scale write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10); - RKCAMERA_DG("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR)); + RK30_CAM_DEBUG_TRACE("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR)); return; } @@ -2043,7 +2362,7 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd, usr_w = pix->width; usr_h = pix->height; - RKCAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h); xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { dev_err(dev, "Format %x not found\n", pix->pixelformat); @@ -2073,43 +2392,43 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd, if ((mf.width != usr_w) || (mf.height != usr_h)) { int ratio; if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) { - RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height); + RK30_CAM_DEBUG_TRACE("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } if (unlikely((usr_w <16)||(usr_h < 16))) { - RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } //need crop ? - if((mf.width*10/mf.height) != (usr_w*10/usr_h)){ + if((mf.width*10/mf.height) != (usr_w*10/usr_h)) { ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w); pcdev->host_width = ratio*usr_w/10; pcdev->host_height = ratio*usr_h/10; //for ipp ,need 4 bit alligned. pcdev->host_width &= ~CROP_ALIGN_BYTES; pcdev->host_height &= ~CROP_ALIGN_BYTES; - RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height); - } - else{ // needn't crop ,just scaled by ipp + RK30_CAM_DEBUG_TRACE("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height); + } + else { // needn't crop ,just scaled by ipp pcdev->host_width = mf.width; pcdev->host_height = mf.height; - } + } } - else{ + else { pcdev->host_width = usr_w; pcdev->host_height = usr_h; - } + } #else //according to crop and scale capability to change , here just cropt to user needed if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) { - RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height); + RK30_CAM_DEBUG_TRACE("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } if (unlikely((usr_w <16)||(usr_h < 16))) { - RKCAMERA_TR("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } @@ -2118,7 +2437,7 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd, #endif icd->sense = NULL; if (!ret) { - RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__, + RK30_CAM_DEBUG_TRACE("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__, pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h); rect.width = pcdev->host_width; rect.height = pcdev->host_height; @@ -2148,14 +2467,14 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd, pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate; pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES; //now digital zoom use ipp to do crop and scale - if(pcdev->zoominfo.zoom_rate != 100){ + if(pcdev->zoominfo.zoom_rate != 100) { pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01); pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01); - } - else{ + } + else { pcdev->zoominfo.a.c.left = 0; pcdev->zoominfo.a.c.top = 0; - } + } pcdev->zoominfo.vir_width = pcdev->host_width; pcdev->zoominfo.vir_height = pcdev->host_height; #endif @@ -2165,19 +2484,19 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd, if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) { if (usr_w > 0x7f0) { if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) { - RKCAMERA_TR("IPP Destination resolution(%dx%d, ((%d div 1) mod 64)=%d is <= 8)",usr_w,usr_h, usr_w, (int)((usr_w>>1)&0x3f)); + RK30_CAM_DEBUG_TRACE("IPP Destination resolution(%dx%d, ((%d div 1) mod 64)=%d is <= 8)",usr_w,usr_h, usr_w, (int)((usr_w>>1)&0x3f)); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } } else { if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) { - RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f)); + RK30_CAM_DEBUG_TRACE("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f)); ret = -EINVAL; goto RK_CAMERA_SET_FMT_END; } } } - RKCAMERA_DG("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name, + RK30_CAM_DEBUG_TRACE("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name, rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top, pix->width, pix->height); rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect); @@ -2198,7 +2517,7 @@ RK_CAMERA_SET_FMT_END: if (stream_on & ENABLE_CAPTURE) write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE)); if (ret) - RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); + RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); return ret; } static bool rk_camera_fmt_capturechk(struct v4l2_format *f) @@ -2220,7 +2539,7 @@ static bool rk_camera_fmt_capturechk(struct v4l2_format *f) } if (ret == true) - RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height); + RK30_CAM_DEBUG_TRACE("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height); return ret; } static int rk_camera_try_fmt(struct soc_camera_device *icd, @@ -2246,10 +2565,10 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd, dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF, (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF); ret = -EINVAL; - RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16, + RK30_CAM_DEBUG_TRACE("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16, (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff)); for (i = 0; i < icd->num_user_formats; i++) - RKCAMERA_TR("(%c%c%c%c)-%s\n", + RK30_CAM_DEBUG_TRACE("(%c%c%c%c)-%s\n", icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF, icd->user_formats[i].host_fmt->name); @@ -2285,26 +2604,30 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd, if((usr_w == 10000) && (usr_h == 10000)) { pix->width = mf.width; pix->height = mf.height; - RKCAMERA_DG("%s: Sensor resolution : %dx%d\n",__FUNCTION__,mf.width,mf.height); + RK30_CAM_DEBUG_TRACE("%s: Sensor resolution : %dx%d\n",__FUNCTION__,mf.width,mf.height); goto RK_CAMERA_TRY_FMT_END; } else { - RKCAMERA_DG("%s: user demand: %dx%d sensor output: %dx%d \n",__FUNCTION__,usr_w,usr_h,mf.width,mf.height); + RK30_CAM_DEBUG_TRACE("%s: user demand: %dx%d sensor output: %dx%d \n",__FUNCTION__,usr_w,usr_h,mf.width,mf.height); } #ifdef CONFIG_VIDEO_RK29_WORK_IPP if ((mf.width != usr_w) || (mf.height != usr_h)) { bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt); + #ifndef OPTIMIZE_MEMORY_USE if (is_capture) { vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size); } else { /* Assume preview buffer minimum is 4 */ vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size); - } + } + #else + vipmem_is_overflow =false; + #endif if (vipmem_is_overflow == false) { pix->width = usr_w; pix->height = usr_h; } else { - RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h); pix->width = mf.width; pix->height = mf.height; } @@ -2312,7 +2635,7 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd, #if 0 if ((mf.width < usr_w) || (mf.height < usr_h)) { if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) { - RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h); pix->width = mf.width; pix->height = mf.height; } @@ -2325,7 +2648,7 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd, pix->width = usr_w; pix->height = usr_h; } else if ((mf.width < usr_w) && (mf.height < usr_h)) { - RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h); + RK30_CAM_DEBUG_TRACE("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h); pix->width = mf.width; pix->height = mf.height; } @@ -2346,7 +2669,7 @@ static int rk_camera_try_fmt(struct soc_camera_device *icd, RK_CAMERA_TRY_FMT_END: if (ret) - RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); + RK30_CAM_DEBUG_TRACE("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret); return ret; } @@ -2390,51 +2713,46 @@ static int rk_camera_querycap(struct soc_camera_host *ici, struct v4l2_capability *cap) { struct rk_camera_dev *pcdev = ici->priv; + struct rkcamera_platform_data *new_camera; char orientation[5]; + char fov[9]; int i; - strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card)); + strlcpy(cap->card, dev_name(pcdev->icd->pdev), 18); memset(orientation,0x00,sizeof(orientation)); for (i=0; ipdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) { sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation); + sprintf(fov,"_50_50"); } } - + + i=0; + new_camera = pcdev->pdata->register_dev_new; + while (strstr(new_camera->dev_name,"end")==NULL) { + if (strcmp(dev_name(pcdev->icd->pdev), new_camera->dev_name) == 0) { + sprintf(orientation,"-%d",new_camera->orientation); + sprintf(fov,"_%d_%d",new_camera->fov_h,new_camera->fov_v); + } + new_camera++; + } + if (orientation[0] != '-') { RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev)); - if (strstr(dev_name(pcdev->icd->pdev),"front")) + if (strstr(dev_name(pcdev->icd->pdev),"front")) strcat(cap->card,"-270"); - else + else strcat(cap->card,"-90"); } else { - strcat(cap->card,orientation); + strcat(cap->card,orientation); } + + strcat(cap->card,fov); /* ddl@rock-chips.com: v0.3.f */ cap->version = RK_CAM_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; return 0; } -static void rk_camera_store_register(struct rk_camera_dev *pcdev) -{ - pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL); - pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP); - pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE); - pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN); - pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR); - pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH); - pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL); -} -static void rk_camera_restore_register(struct rk_camera_dev *pcdev) -{ - write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE); - write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn); - write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop); - write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs); - write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt); - write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth); - write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale); -} static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state) { struct soc_camera_host *ici = @@ -2461,9 +2779,9 @@ static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state) pcdev->reginfo_suspend.Inval = Reg_Validate; rk_camera_deactivate(pcdev); - RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s Enter Success...\n", __FUNCTION__); } else { - RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__); } mutex_unlock(&camera_lock); return ret; @@ -2493,7 +2811,7 @@ static int rk_camera_resume(struct soc_camera_device *icd) rk_camera_s_stream(icd, 1); pcdev->reginfo_suspend.Inval = Reg_Invalidate; } else { - RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n"); + RK30_CAM_DEBUG_TRACE("Resume fail, vip register recored is invalidate!!\n"); goto rk_camera_resume_end; } @@ -2501,9 +2819,9 @@ static int rk_camera_resume(struct soc_camera_device *icd) sd = soc_camera_to_subdev(icd); v4l2_subdev_call(sd, video, s_stream, 1); - RKCAMERA_DG("%s Enter success\n",__FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s Enter success\n",__FUNCTION__); } else { - RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s icd has been deattach, don't need enter resume\n", __FUNCTION__); } rk_camera_resume_end: @@ -2525,27 +2843,27 @@ static void rk_camera_reinit_work(struct work_struct *work) tmp_soc_cam_link = to_soc_camera_link(pcdev->icd); //dump regs { - RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL)); - RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN)); - RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT)); - RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR)); - RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP)); - RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE)); - RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL)); - RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30)); - RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL)); + RK30_CAM_DEBUG_TRACE("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE)); - RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX)); - RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH)); - RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR)); - RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y)); - RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV)); - RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV)); + RK30_CAM_DEBUG_TRACE("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS)); } - + return; pcdev->stop_cif = true; write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE))); - RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times); + RK30_CAM_DEBUG_TRACE("the reinit times = %d\n",pcdev->reinit_times); if(pcdev->video_vq && pcdev->video_vq->irqlock){ spin_lock_irqsave(pcdev->video_vq->irqlock, flags); for (index = 0; index < VIDEO_MAX_FRAME; index++) { @@ -2562,10 +2880,10 @@ static void rk_camera_reinit_work(struct work_struct *work) } spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags); }else{ - RKCAMERA_TR("video queue has somthing wrong !!\n"); + RK30_CAM_DEBUG_TRACE("video queue has somthing wrong !!\n"); } - RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times); + RK30_CAM_DEBUG_TRACE("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times); } static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) { @@ -2577,9 +2895,9 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) struct soc_camera_link *tmp_soc_cam_link; tmp_soc_cam_link = to_soc_camera_link(pcdev->icd); - RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps); + RK30_CAM_DEBUG_TRACE("rk_camera_fps_func fps:%d\n",(pcdev->fps - pcdev->last_fps)/3); if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) { - RKCAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps); + RK30_CAM_DEBUG_TRACE("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps); pcdev->camera_reinit_work.pcdev = pcdev; //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work); pcdev->reinit_times++; @@ -2596,7 +2914,7 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) fival_pre = fival_nxt; while (fival_nxt != NULL) { - RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev), + RK30_CAM_DEBUG_TRACE("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev), fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF, (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24), fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator, @@ -2655,8 +2973,8 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) static int rk_camera_s_stream(struct soc_camera_device *icd, int enable) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct rk_camera_dev *pcdev = ici->priv; - int cif_ctrl_val; + struct rk_camera_dev *pcdev = ici->priv; + int cif_ctrl_val; int ret; unsigned long flags; @@ -2665,39 +2983,45 @@ static int rk_camera_s_stream(struct soc_camera_device *icd, int enable) cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL); if (enable) { pcdev->fps = 0; - pcdev->last_fps = 0; - pcdev->frame_interval = 0; + pcdev->last_fps = 0; + pcdev->frame_interval = 0; hrtimer_cancel(&(pcdev->fps_timer.timer)); pcdev->fps_timer.pcdev = pcdev; - pcdev->timer_get_fps = false; - pcdev->reinit_times = 0; - pcdev->stop_cif = false; -// hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL); + pcdev->timer_get_fps = false; + pcdev->reinit_times = 0; + pcdev->stop_cif = false; + pcdev->cif_stopped = false; + // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL); cif_ctrl_val |= ENABLE_CAPTURE; - write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val); + write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val); hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL); - pcdev->fps_timer.istarted = true; + pcdev->fps_timer.istarted = true; } else { //cancel timer before stop cif ret = hrtimer_cancel(&pcdev->fps_timer.timer); pcdev->fps_timer.istarted = false; flush_work(&(pcdev->camera_reinit_work.work)); - cif_ctrl_val &= ~ENABLE_CAPTURE; spin_lock_irqsave(&pcdev->lock, flags); - write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val); + // write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val); pcdev->stop_cif = true; spin_unlock_irqrestore(&pcdev->lock, flags); +#if CONFIG_CIF_STOP_SYNC + init_waitqueue_head(&pcdev->cif_stop_done); + if (wait_event_timeout(pcdev->cif_stop_done, pcdev->cif_stopped, msecs_to_jiffies(1000)) == 0) { + RKCAMERA_DG("%s:%d, wait cif stop timeout!",__func__,__LINE__); + } +#endif + //mdelay(35); flush_workqueue((pcdev->camera_wq)); - RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret); + RK30_CAM_DEBUG_TRACE("STREAM_OFF cancel timer and flush work:0x%x \n", ret); } //must be reinit,or will be somthing wrong in irq process. - if(enable == false){ + if(enable == false) { pcdev->active0 = NULL; pcdev->active1 = NULL; INIT_LIST_HEAD(&pcdev->capture); - } - RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL)); + } return 0; } int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival) @@ -2735,7 +3059,7 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm ret = -EINVAL; } } else { - RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__); + RK30_CAM_DEBUG_TRACE("%s: fival_list is NULL\n",__FUNCTION__); ret = -EINVAL; } } else { @@ -2747,7 +3071,7 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm } if (fival_head == NULL) { - RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev)); + RK30_CAM_DEBUG_TRACE("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev)); ret = -EINVAL; goto rk_camera_enum_frameintervals_end; } @@ -2767,20 +3091,20 @@ int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frm if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) { memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum)); - RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev), + RK30_CAM_DEBUG_TRACE("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev), fival->width, fival->height, fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF, (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24), fival->discrete.denominator,fival->discrete.numerator); } else { if (index == 0) - RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev), + RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev), fival->width,fival->height, fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF, (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24), index); else - RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev), + RK30_CAM_DEBUG_TRACE("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev), fival->width,fival->height, fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF, (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24), @@ -2840,7 +3164,7 @@ static int rk_camera_set_digit_zoom(struct soc_camera_device *icd, up(&pcdev->zoominfo.sem); pcdev->stop_cif = false; hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL); - RKCAMERA_DG("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height ); + RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height ); #else a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a.c.width = pcdev->host_width*100/zoom_rate; @@ -2857,7 +3181,7 @@ static int rk_camera_set_digit_zoom(struct soc_camera_device *icd, pcdev->zoominfo.vir_width = pcdev->host_width; pcdev->zoominfo.vir_height= pcdev->host_height; up(&pcdev->zoominfo.sem); - RKCAMERA_DG("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height ); + RK30_CAM_DEBUG_TRACE("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height ); #endif return 0; @@ -2892,16 +3216,18 @@ static int rk_camera_set_ctrl(struct soc_camera_device *icd, ret = -ENOIOCTLCMD; goto rk_camera_set_ctrl_end; } - + + if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){ + ret = -EINVAL; + goto rk_camera_set_ctrl_end; + } + switch (sctrl->id) { #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON case V4L2_CID_ZOOM_ABSOLUTE: { - if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){ - ret = -EINVAL; - goto rk_camera_set_ctrl_end; - } + ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value); if (ret == 0) { pcdev->zoominfo.zoom_rate = sctrl->value; @@ -2911,6 +3237,31 @@ static int rk_camera_set_ctrl(struct soc_camera_device *icd, break; } #endif + + case V4L2_CID_HDR: + { + if (pcdev->hdr_info.en != sctrl->value) { + pcdev->hdr_info.en = sctrl->value; + if (sctrl->value) { + struct device *control = to_soc_camera_control(pcdev->icd); + struct v4l2_subdev *sd=dev_get_drvdata(control); + + printk("hdr on\n"); + pcdev->hdr_info.frame[0].code = RK_VIDEOBUF_HDR_EXPOSURE_MINUS_1; + pcdev->hdr_info.frame[0].set_ts = 0; + pcdev->hdr_info.frame[0].get_ts = 0; + pcdev->hdr_info.frame[1].code = RK_VIDEOBUF_HDR_EXPOSURE_NORMAL; + pcdev->hdr_info.frame[1].set_ts = 0; + pcdev->hdr_info.frame[1].get_ts = 0; + pcdev->hdr_info.frame[2].code = RK_VIDEOBUF_HDR_EXPOSURE_PLUS_1; + pcdev->hdr_info.frame[2].set_ts = 0; + pcdev->hdr_info.frame[2].get_ts = 0; + v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_HDR_EXPOSURE,RK_VIDEOBUF_HDR_EXPOSURE_NORMAL); + } + } + break; + } + default: ret = -ENOIOCTLCMD; break; @@ -2919,6 +3270,16 @@ rk_camera_set_ctrl_end: return ret; } +int rk_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum *fsize) +{ + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd; + + sd = dev_get_drvdata(control); + return v4l2_subdev_call(sd, video, enum_framesizes, fsize); + +} + static struct soc_camera_host_ops rk_soc_camera_host_ops = { .owner = THIS_MODULE, @@ -2927,6 +3288,7 @@ static struct soc_camera_host_ops rk_soc_camera_host_ops = .suspend = rk_camera_suspend, .resume = rk_camera_resume, .enum_frameinervals = rk_camera_enum_frameintervals, + .enum_fsizes = rk_camera_enum_fsizes, .set_crop = rk_camera_set_crop, .get_formats = rk_camera_get_formats, .put_formats = rk_camera_put_formats, @@ -2941,15 +3303,15 @@ static struct soc_camera_host_ops rk_soc_camera_host_ops = .set_ctrl = rk_camera_set_ctrl, .controls = rk_camera_controls, .num_controls = ARRAY_SIZE(rk_camera_controls) - }; + static void rk_camera_cif_iomux(int cif_index) { #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) switch(cif_index){ case 0: - iomux_set(CIF0_CLKOUT); - write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA)); + iomux_set(CIF0_CLKOUT); + write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_4MA)); write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8)); #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12)) iomux_set(CIF0_D0); @@ -2958,12 +3320,12 @@ static void rk_camera_cif_iomux(int cif_index) #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12) iomux_set(CIF0_D10); iomux_set(CIF0_D11); - RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__); #endif break; default: - RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index); + RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index); break; } #elif defined(CONFIG_ARCH_RK30) @@ -2999,7 +3361,7 @@ static void rk_camera_cif_iomux(int cif_index) rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT); break; default: - RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index); + RK30_CAM_DEBUG_TRACE("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index); break; } #endif @@ -3014,17 +3376,18 @@ static int rk_camera_probe(struct platform_device *pdev) struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr; int irq,i; int err = 0; + struct rk_cif_clk *clk=NULL; printk("%s version: v%d.%d.%d Zoom by %s\n",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16, (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE); if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) { - RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__); BUG(); } if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) { - RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__); BUG(); } @@ -3045,32 +3408,33 @@ static int rk_camera_probe(struct platform_device *pdev) pcdev->hostid = pdev->id; /*config output clk*/ // must modify start if(IS_CIF0()){ - pcdev->pd_cif = clk_get(NULL, "pd_cif0"); - pcdev->aclk_cif = clk_get(NULL, "aclk_cif0"); - pcdev->hclk_cif = clk_get(NULL, "hclk_cif0"); - pcdev->cif_clk_in = clk_get(NULL, "cif0_in"); - pcdev->cif_clk_out = clk_get(NULL, "cif0_out"); + clk = &cif_clk[0]; + cif_clk[0].pd_cif = clk_get(NULL, "pd_cif0"); + cif_clk[0].aclk_cif = clk_get(NULL, "aclk_cif0"); + cif_clk[0].hclk_cif = clk_get(NULL, "hclk_cif0"); + cif_clk[0].cif_clk_in = clk_get(NULL, "cif0_in"); + cif_clk[0].cif_clk_out = clk_get(NULL, "cif0_out"); + spin_lock_init(&cif_clk[0].lock); + cif_clk[0].on = false; rk_camera_cif_iomux(0); } else { - pcdev->pd_cif = clk_get(NULL, "pd_cif1"); - pcdev->aclk_cif = clk_get(NULL, "aclk_cif1"); - pcdev->hclk_cif = clk_get(NULL, "hclk_cif1"); - pcdev->cif_clk_in = clk_get(NULL, "cif1_in"); - pcdev->cif_clk_out = clk_get(NULL, "cif1_out"); + clk = &cif_clk[1]; + cif_clk[1].pd_cif = clk_get(NULL, "pd_cif1"); + cif_clk[1].aclk_cif = clk_get(NULL, "aclk_cif1"); + cif_clk[1].hclk_cif = clk_get(NULL, "hclk_cif1"); + cif_clk[1].cif_clk_in = clk_get(NULL, "cif1_in"); + cif_clk[1].cif_clk_out = clk_get(NULL, "cif1_out"); + spin_lock_init(&cif_clk[1].lock); + cif_clk[1].on = false; rk_camera_cif_iomux(1); } - if(IS_ERR(pcdev->pd_cif) || IS_ERR(pcdev->aclk_cif) || IS_ERR(pcdev->hclk_cif) || IS_ERR(pcdev->cif_clk_in) || IS_ERR(pcdev->cif_clk_out)){ - RKCAMERA_TR(KERN_ERR "%s(%d): failed to get cif clock source\n",__FUNCTION__,__LINE__); - err = -ENOENT; - goto exit_reqmem_vip; - } dev_set_drvdata(&pdev->dev, pcdev); pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */ - + pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl; if (pcdev->pdata && pcdev->pdata->io_init) { pcdev->pdata->io_init(); } @@ -3088,12 +3452,12 @@ static int rk_camera_probe(struct platform_device *pdev) if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) { err = -EBUSY; - RKCAMERA_TR("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); + RK30_CAM_DEBUG_TRACE("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); goto exit_ioremap_vipmem; } meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size); if (pcdev->vipmem_virbase == NULL) { - RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__); err = -ENXIO; goto exit_ioremap_vipmem; } @@ -3108,6 +3472,7 @@ static int rk_camera_probe(struct platform_device *pdev) INIT_LIST_HEAD(&pcdev->camera_work_queue); spin_lock_init(&pcdev->lock); spin_lock_init(&pcdev->camera_work_lock); + // spin_lock_init(&pcdev->irq_lock); sema_init(&pcdev->zoominfo.sem,1); /* @@ -3181,7 +3546,7 @@ static int rk_camera_probe(struct platform_device *pdev) #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP) pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp; #endif - RKCAMERA_DG("%s(%d) Exit \n",__FUNCTION__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s(%d) Exit \n",__FUNCTION__,__LINE__); return 0; exit_free_irq: @@ -3259,7 +3624,7 @@ static int __devexit rk_camera_remove(struct platform_device *pdev) if (meminfo_ptr->vbase == meminfo_ptrr->vbase) { meminfo_ptr->vbase = NULL; } else { - iounmap((void __iomem*)pcdev->vipmem_phybase); + iounmap((void __iomem*)pcdev->vipmem_virbase); release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size); meminfo_ptr->vbase = NULL; } @@ -3297,7 +3662,7 @@ static int rk_camera_init_async(void *unused) static int __devinit rk_camera_init(void) { - RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__); + RK30_CAM_DEBUG_TRACE("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__); kthread_run(rk_camera_init_async, NULL, "rk_camera_init"); return 0; } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index d27e88b33ea4..0348a5b6bbbf 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -2252,7 +2252,7 @@ static unsigned long cmd_input_size(unsigned int cmd) CMDINSIZE(ENCODER_CMD, encoder_cmd, flags); CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags); CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type); - CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format); + CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, reserved[1]); CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height); default: return _IOC_SIZE(cmd); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index f1ba530824d2..7f001c4e68eb 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1404,6 +1404,18 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_FOCUS_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE_ROCK+4) #define V4L2_CID_FOCUSZONE (V4L2_CID_CAMERA_CLASS_BASE_ROCK+5) #define V4L2_CID_FACEDETECT (V4L2_CID_CAMERA_CLASS_BASE_ROCK+6) +#define V4L2_CID_HDR (V4L2_CID_CAMERA_CLASS_BASE_ROCK+7) + +/* nelson_yang@asus.com : Add ioctrl - V4L2_CID_ISO for camera ISO control */ +#define V4L2_CID_CAMERA_CLASS_BASE_ASUS (V4L2_CID_CAMERA_CLASS_BASE + 50) +#define V4L2_CID_ISO (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 1) +#define V4L2_CID_ANTIBANDING (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 2) +#define V4L2_CID_WHITEBALANCE_LOCK (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 3) +#define V4L2_CID_EXPOSURE_LOCK (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 4) +#define V4L2_CID_METERING_AREAS (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 5) +#define V4L2_CID_WDR (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 6) +#define V4L2_CID_EDGE (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 7) +#define V4L2_CID_JPEG_EXIF (V4L2_CID_CAMERA_CLASS_BASE_ASUS + 8) /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 4bddbb54b68d..96d18ce42224 100755 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -93,7 +93,8 @@ enum { V4L2_IDENT_S5K5CA = 311, /* ddl@rock-chips.com : s5k5ca support */ V4L2_IDENT_MTK9335ISP = 320, /* ddl@rock-chips.com : MTK9335ISP support */ - + V4L2_IDENT_ICATCH7002_MI1040 = 321, + V4L2_IDENT_ICATCH7002_OV5693 =322, /* Conexant MPEG encoder/decoders: reserved range 400-420 */ V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ V4L2_IDENT_CX23415 = 415, -- 2.34.1