Merge remote-tracking branch 'aosp/android-3.0' into develop-3.0-jb
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / gc0307.c
old mode 100644 (file)
new mode 100755 (executable)
index 7d4c0f2..79c2ec3
@@ -20,8 +20,8 @@ o* Driver for MT9M001 CMOS Image Sensor from Micron
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/soc_camera.h>
-#include <mach/rk_camera.h>
-#include <linux/vmalloc.h>
+#include <plat/rk_camera.h>
+
 static int debug;
 module_param(debug, int, S_IRUGO|S_IWUSR);
 
@@ -44,18 +44,17 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define MAX(x,y)    ((x>y) ? x: y)
 
 /* Sensor Driver Configuration */
-#define SENSOR_NAME RK_CAM_SENSOR_GC0307
+#define SENSOR_NAME RK29_CAM_SENSOR_GC0307
 #define SENSOR_V4L2_IDENT V4L2_IDENT_GC0307
 #define SENSOR_ID 0x99
 #define SENSOR_MIN_WIDTH    640//176
 #define SENSOR_MIN_HEIGHT   480//144
 #define SENSOR_MAX_WIDTH    800//1600
 #define SENSOR_MAX_HEIGHT   600//1200
-#define SENSOR_INIT_WIDTH      sensor_init_width                       /* Sensor pixel size for sensor_init_data array */
-#define SENSOR_INIT_HEIGHT  sensor_init_height
-#define SENSOR_INIT_WINSEQADR  sensor_init_winseq_p
-#define SENSOR_INIT_PIXFMT sensor_init_pixelcode
-#define SENSOR_BUS_PARAM  sensor_init_busparam
+#define SENSOR_INIT_WIDTH      640                     /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT  480
+#define SENSOR_INIT_WINSEQADR sensor_vga
+#define SENSOR_INIT_PIXFMT V4L2_MBUS_FMT_YUYV8_2X8
 
 #define CONFIG_SENSOR_WhiteBalance     1
 #define CONFIG_SENSOR_Brightness       0
@@ -66,7 +65,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define CONFIG_SENSOR_DigitalZoom   0
 #define CONFIG_SENSOR_Focus         0
 #define CONFIG_SENSOR_Exposure      0
-#define CONFIG_SENSOR_Flash         0
+#define CONFIG_SENSOR_Flash         1
 #define CONFIG_SENSOR_Mirror        0
 #define CONFIG_SENSOR_Flip          0
 
@@ -75,6 +74,10 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define CONFIG_SENSOR_I2C_NOSCHED   0
 #define CONFIG_SENSOR_I2C_RDWRCHK   0
 
+#define SENSOR_BUS_PARAM  (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
+                          SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+                          SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8  |SOCAM_MCLK_24MHZ)
+
 #define COLOR_TEMPERATURE_CLOUDY_DN  6500
 #define COLOR_TEMPERATURE_CLOUDY_UP    8000
 #define COLOR_TEMPERATURE_CLEARDAY_DN  5000
@@ -97,14 +100,19 @@ struct reginfo
     u8 val;
 };
 
-static s32 sensor_init_width = 0;
-static s32 sensor_init_height = 0;
-static unsigned long sensor_init_busparam = (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING|SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8  |SOCAM_MCLK_24MHZ);
-static enum v4l2_mbus_pixelcode sensor_init_pixelcode = V4L2_MBUS_FMT_YUYV8_2X8;
-static struct reginfo* sensor_init_data_p = NULL;
-static struct reginfo* sensor_init_winseq_p = NULL;
-static struct reginfo* sensor_init_winseq_board = NULL;
-/* init 800*600 SVGA */
+//flash off in fixed time to prevent from too hot , zyc
+struct  flash_timer{
+    struct soc_camera_device *icd;
+       struct hrtimer timer;
+};
+static enum hrtimer_restart flash_off_func(struct hrtimer *timer);
+
+static struct  flash_timer flash_off_timer;
+//for user defined if user want to customize the series , zyc
+#ifdef CONFIG_GC0307_USER_DEFINED_SERIES
+#include "gc0307_user_series.c"
+#else
+/* init 640X480 VGA */
 static struct reginfo sensor_init_data[] =
 {
 //========= close output
@@ -632,7 +640,7 @@ static struct reginfo sensor_qcif[] =
        {0xff, 0xff},
 
 };
-
+#endif
 static  struct reginfo sensor_ClrFmt_YUYV[]=
 {
        {0xff, 0xff},
@@ -1103,7 +1111,7 @@ static const struct v4l2_querymenu sensor_menus[] =
     #endif
 };
 
-static const struct v4l2_queryctrl sensor_controls[] =
+static  struct v4l2_queryctrl sensor_controls[] =
 {
        #if CONFIG_SENSOR_WhiteBalance
     {
@@ -1349,8 +1357,8 @@ struct sensor
 #if CONFIG_SENSOR_I2C_NOSCHED
        atomic_t tasklock_cnt;
 #endif
-       struct rkcamera_platform_data *sensor_io_request;
-    struct rkcamera_gpio_res *sensor_gpio_res;
+       struct rk29camera_platform_data *sensor_io_request;
+    struct rk29camera_gpio_res *sensor_gpio_res;
 };
 
 static struct sensor* to_sensor(const struct i2c_client *client)
@@ -1573,7 +1581,7 @@ static int sensor_check_array(struct i2c_client *client, struct reginfo *regarra
        
   return 0;
 }
-static int sensor_ioctrl(struct soc_camera_device *icd,enum rksensor_power_cmd cmd, int on)
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
 {
        struct soc_camera_link *icl = to_soc_camera_link(icd);
        int ret = 0;
@@ -1585,13 +1593,13 @@ static int sensor_ioctrl(struct soc_camera_device *icd,enum rksensor_power_cmd c
                {
                        if (icl->powerdown) {
                                ret = icl->powerdown(icd->pdev, on);
-                               if (ret == RK_CAM_IO_SUCCESS) {
+                               if (ret == RK29_CAM_IO_SUCCESS) {
                                        if (on == 0) {
                                                mdelay(2);
                                                if (icl->reset)
                                                        icl->reset(icd->pdev);
                                        }
-                               } else if (ret == RK_CAM_EIO_REQUESTFAIL) {
+                               } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
                                        ret = -ENODEV;
                                        goto sensor_power_end;
                                }
@@ -1605,6 +1613,11 @@ static int sensor_ioctrl(struct soc_camera_device *icd,enum rksensor_power_cmd c
 
                        if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
                                sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+                if(on){
+                    //flash off after 2 secs
+                       hrtimer_cancel(&(flash_off_timer.timer));
+                       hrtimer_start(&(flash_off_timer.timer),ktime_set(0, 800*1000*1000),HRTIMER_MODE_REL);
+                    }
                        }
             break;
                }
@@ -1618,6 +1631,13 @@ sensor_power_end:
        return ret;
 }
 
+static enum hrtimer_restart flash_off_func(struct hrtimer *timer){
+       struct flash_timer *fps_timer = container_of(timer, struct flash_timer, timer);
+    sensor_ioctrl(fps_timer->icd,Sensor_Flash,0);
+       SENSOR_DG("%s %s !!!!!!",SENSOR_NAME_STRING(),__FUNCTION__);
+    return 0;
+    
+}
 static int sensor_init(struct v4l2_subdev *sd, u32 val)
 {
     struct i2c_client *client = v4l2_get_subdevdata(sd);;
@@ -1625,63 +1645,9 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
     struct sensor *sensor = to_sensor(client);
        const struct v4l2_queryctrl *qctrl;
     const struct sensor_datafmt *fmt;
-    char value;
-    int ret,pid = 0,i = 0,j=0;
-    struct rkcamera_platform_data* tmp_plat_data =(struct rkcamera_platform_data*)val;
-    sensor_init_data_p = sensor_init_data;
-       sensor_init_winseq_p = sensor_vga;
-       sensor_init_width = 640;
-       sensor_init_height = 480;
-       if (tmp_plat_data != NULL) { 
-               for(i = 0;i < RK_CAM_NUM_PER_HOST;i++){
-                       if ((tmp_plat_data->sensor_init_data[i])&& tmp_plat_data->info[i].dev_name &&
-                               (strcmp(tmp_plat_data->info[i].dev_name, dev_name(icd->pdev)) == 0))
-                                       break;
-                       }
-               }
-       if(tmp_plat_data  && (i < RK_CAM_NUM_PER_HOST) && tmp_plat_data->sensor_init_data[i]){
-       //user has defined the init data
-               //init reg
-               if(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_data && (sizeof(struct reginfo) != sizeof(struct reginfo_t))){
-                       for(j = 0;j< sizeof(sensor_init_data)/sizeof(struct reginfo);j++){
-                               sensor_init_data[j].reg = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_data[j].reg;
-                               sensor_init_data[j].val = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_data[j].val;
-                               }
-                       sensor_init_data_p = sensor_init_data;
-                       }
-               else if(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_data){
-                       sensor_init_data_p = (struct reginfo*)(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_data);
-                       }
-               //init winseq
-               if(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_winseq && (sizeof(struct reginfo) != sizeof(struct reginfo_t))){
-                       int tmp_winseq_size = tmp_plat_data->sensor_init_data[i]->rk_sensor_winseq_size;
-                       if(sensor_init_winseq_board)
-                               {
-                               vfree(sensor_init_winseq_board);
-                               sensor_init_winseq_board = NULL;
-                               }
-                       sensor_init_winseq_board = (struct reginfo*)vmalloc(tmp_winseq_size);
-                       if(!sensor_init_winseq_board)
-                               SENSOR_TR("%s :vmalloc erro !",__FUNCTION__);
-                       for(j = 0;j< tmp_winseq_size;j++){
-                               sensor_init_winseq_board[j].reg = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_winseq[j].reg;
-                               sensor_init_winseq_board[j].val = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_winseq[j].val;
-                               }
-                       sensor_init_winseq_p = sensor_init_winseq_board;
-                       }
-               else if(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_winseq){
-                       sensor_init_winseq_p = (struct reginfo*)(tmp_plat_data->sensor_init_data[i]->rk_sensor_init_winseq);
-                       }
-               //init width,height,bus,pixelcode
-               if(tmp_plat_data->sensor_init_data[i] && tmp_plat_data->sensor_init_data[i]->rk_sensor_init_width != INVALID_VALUE)
-                       sensor_init_width = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_width;
-               if(tmp_plat_data->sensor_init_data[i] && tmp_plat_data->sensor_init_data[i]->rk_sensor_init_height != INVALID_VALUE)
-                       sensor_init_height = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_height;
-               if(tmp_plat_data->sensor_init_data[i] && tmp_plat_data->sensor_init_data[i]->rk_sensor_init_bus_param != INVALID_VALUE)
-                       sensor_init_busparam = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_bus_param;
-               if(tmp_plat_data->sensor_init_data[i] && tmp_plat_data->sensor_init_data[i]->rk_sensor_init_pixelcode != INVALID_VALUE)
-                       sensor_init_pixelcode = tmp_plat_data->sensor_init_data[i]->rk_sensor_init_pixelcode;
-       }
+    int ret;
+
+
     SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
 
        if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
@@ -1702,7 +1668,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
 
     mdelay(5); */ //delay 5 microseconds
 
-    ret = sensor_write_array(client, sensor_init_data_p);
+    ret = sensor_write_array(client, sensor_init_data);
     if (ret != 0)
     {
         SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
@@ -1713,14 +1679,14 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
        int i;
        u8 val;
        printk("****************** check init data\n");
-       for(i=0; sensor_init_data_p[i].reg!=0xff; i++)
+       for(i=0; sensor_init_data[i].reg!=0xff; i++)
        {
-               sensor_read(client, sensor_init_data_p[i].reg, &val);
+               sensor_read(client, sensor_init_data[i].reg, &val);
                printk("reg 0x%02x: org=0x%02x, val=0x%02x, %s\n", 
-                       sensor_init_data_p[i].reg,
-                       sensor_init_data_p[i].val,
+                       sensor_init_data[i].reg,
+                       sensor_init_data[i].val,
                        val,
-                       sensor_init_data_p[i].val==val?"O":"X");
+                       sensor_init_data[i].val==val?"O":"X");
        }
        printk("**********************************\n");
 
@@ -1783,6 +1749,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
        qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
        if (qctrl)
         sensor->info_priv.flash = qctrl->default_value;
+    flash_off_timer.icd = icd;
+       flash_off_timer.timer.function = flash_off_func;
     #endif
 
     SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
@@ -2094,7 +2062,7 @@ static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
     struct i2c_client *client = v4l2_get_subdevdata(sd);
     struct sensor *sensor = to_sensor(client);
     const struct sensor_datafmt *fmt;
-    int ret = 0;
+    int ret = 0,set_w,set_h;
    
        fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
                                   ARRAY_SIZE(sensor_colour_fmts));
@@ -2113,6 +2081,52 @@ static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
     else if (mf->width < SENSOR_MIN_WIDTH)
         mf->width = SENSOR_MIN_WIDTH;
 
+    set_w = mf->width;
+    set_h = mf->height;
+
+       if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[0].reg!=0xff)
+       {
+        set_w = 176;
+        set_h = 144;
+       }
+       else if (((set_w <= 320) && (set_h <= 240)) && sensor_qvga[0].reg!=0xff)
+    {
+        set_w = 320;
+        set_h = 240;
+    }
+    else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[0].reg!=0xff)
+    {
+        set_w = 352;
+        set_h = 288;
+    }
+    else if (((set_w <= 640) && (set_h <= 480)) && sensor_vga[0].reg!=0xff)
+    {
+        set_w = 640;
+        set_h = 480;
+    }
+    else if (((set_w <= 800) && (set_h <= 600)) && sensor_svga[0].reg!=0xff)
+    {
+        set_w = 800;
+        set_h = 600;
+    }
+    else if (((set_w <= 1280) && (set_h <= 720)) && sensor_720p[0].reg!=0xff)
+    {
+        set_w = 1280;
+        set_h = 720;
+    }
+    else if (((set_w <= 1280) && (set_h <= 1024)) && sensor_sxga[0].reg!=0xff)
+    {
+        set_w = 1280;
+        set_h = 1024;
+    }
+    else
+    {
+        set_w = SENSOR_INIT_WIDTH;
+        set_h = SENSOR_INIT_HEIGHT;
+    }    
+
+    mf->width = set_w;
+    mf->height = set_h;    
     mf->colorspace = fmt->colorspace;
     
     return ret;
@@ -2872,25 +2886,30 @@ static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
        SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
        switch (cmd)
        {
-               case RK_CAM_SUBDEV_DEACTIVATE:
+               case RK29_CAM_SUBDEV_DEACTIVATE:
                {
                        sensor_deactivate(client);
                        break;
                }
 
-               case RK_CAM_SUBDEV_IOREQUEST:
+               case RK29_CAM_SUBDEV_IOREQUEST:
                {
-                       sensor->sensor_io_request = (struct rkcamera_platform_data*)arg;           
+                       sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;           
             if (sensor->sensor_io_request != NULL) { 
-                if (sensor->sensor_io_request->gpio_res[0].dev_name && 
-                    (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
-                    sensor->sensor_gpio_res = (struct rkcamera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
-                } else if (sensor->sensor_io_request->gpio_res[1].dev_name && 
-                    (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
-                    sensor->sensor_gpio_res = (struct rkcamera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+                sensor->sensor_gpio_res = NULL;
+                for (i=0; i<RK29_CAM_SUPPORT_NUMS;i++) {
+                    if (sensor->sensor_io_request->gpio_res[i].dev_name && 
+                        (strcmp(sensor->sensor_io_request->gpio_res[i].dev_name, dev_name(icd->pdev)) == 0)) {
+                        sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[i];
+                    }
+                }
+                if (sensor->sensor_gpio_res == NULL) {
+                    SENSOR_TR("%s %s obtain gpio resource failed when RK29_CAM_SUBDEV_IOREQUEST \n",SENSOR_NAME_STRING(),__FUNCTION__);
+                    ret = -EINVAL;
+                    goto sensor_ioctl_end;
                 }
             } else {
-                SENSOR_TR("%s %s RK_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+                SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
                 ret = -EINVAL;
                 goto sensor_ioctl_end;
             }
@@ -2901,11 +2920,18 @@ static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
                 if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
                     for (i = 0; i < icd->ops->num_controls; i++) {
                                if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
-                                       memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));                                       
+                                       //memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));  
+                              sensor_controls[i].id=0xffff;                            
                                }
                     }
                     sensor->info_priv.flash = 0xff;
                     SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+                }else{ //two cameras are the same,need to deal diffrently ,zyc
+                    for (i = 0; i < icd->ops->num_controls; i++) {
+                           if(0xffff == icd->ops->controls[i].id){
+                              sensor_controls[i].id=V4L2_CID_FLASH;
+                           }               
+                    }
                 }
                }
             #endif
@@ -2999,6 +3025,7 @@ static int sensor_probe(struct i2c_client *client,
         kfree(sensor);
                sensor = NULL;
     }
+       hrtimer_init(&(flash_off_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
     SENSOR_DG("\n%s..%s..%d  ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
     return ret;
 }