\r
#include "generic_sensor.h"\r
-/*
+/*\r
* Driver Version Note\r
*v0.0.1: this driver is compatible with generic_sensor\r
*v0.1.1:\r
* add sensor_focus_af_const_pause_usr_cb;\r
+*v0.1.2:\r
+ crop for rk3188m\r
*/\r
-static int version = KERNEL_VERSION(0,1,1);\r
+static int version = KERNEL_VERSION(0,1,2);\r
module_param(version, int, S_IRUGO);\r
\r
static int debug =1;\r
#define SENSOR_BUS_PARAM (SOCAM_MASTER |\\r
SOCAM_PCLK_SAMPLE_RISING|SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\\r
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)\r
-#define SENSOR_PREVIEW_W 800\r
-#define SENSOR_PREVIEW_H 600\r
+#if defined(CONFIG_SOC_RK3188M)\r
+#define SENSOR_PREVIEW_W (800 - 20)\r
+#define SENSOR_PREVIEW_H (600 - 20)\r
+#else\r
+#define SENSOR_PREVIEW_W (800)\r
+#define SENSOR_PREVIEW_H (600)\r
+#endif\r
#define SENSOR_PREVIEW_FPS 15000 // 15fps \r
#define SENSOR_FULLRES_L_FPS 5000 // 7.5fps\r
#define SENSOR_FULLRES_H_FPS 10000 // 7.5fps\r
SensorEnd\r
};\r
\r
-static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure04,sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00,\r
- sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,sensor_Exposure14,NULL,\r
+static struct rk_sensor_reg *sensor_ExposureSeqe[] = {/*sensor_Exposure04,*/sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00,\r
+ sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,/*sensor_Exposure14,*/NULL,\r
};\r
\r
\r
static struct sensor_v4l2ctrl_usr_s sensor_controls[] =\r
{\r
new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 5, 1, 0,sensor_v4l2ctrl_default_cb, sensor_WhiteBalanceSeqe),\r
- new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe),\r
+ new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe),\r
new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 6, 1, 0,sensor_v4l2ctrl_default_cb, sensor_EffectSeqe),\r
new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ContrastSeqe),\r
};\r
if (capture) {\r
//sensor_ae_transfer(client);\r
}\r
+#if defined(CONFIG_SOC_RK3188M)\r
+ mf->width-=20;\r
+ mf->height-=20;\r
+ msleep(300);\r
+#endif\r
return 0;\r
}\r
\r
static int sensor_focus_af_const_usr_cb(struct i2c_client *client){\r
return 0;\r
}\r
-static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client)
-{
- return 0;
+static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client)\r
+{\r
+ return 0;\r
}\r
static int sensor_focus_af_close_usr_cb(struct i2c_client *client){\r
return 0;\r
\r
#include "generic_sensor.h"\r
-/*
+/*\r
* Driver Version Note\r
*v0.0.1: this driver is compatible with generic_sensor\r
*v0.1.1:\r
* add sensor_focus_af_const_pause_usr_cb;\r
+*v0.1.2:\r
+ crop for rk3188m\r
*/\r
-static int version = KERNEL_VERSION(0,1,1);\r
+static int version = KERNEL_VERSION(0,1,2);\r
module_param(version, int, S_IRUGO);\r
\r
static int debug =1;\r
SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\\r
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ)\r
\r
-#define SENSOR_PREVIEW_W 800\r
-#define SENSOR_PREVIEW_H 600\r
+#if defined(CONFIG_SOC_RK3188M)\r
+#define SENSOR_PREVIEW_W (800 - 20)\r
+#define SENSOR_PREVIEW_H (600 - 20)\r
+#else\r
+#define SENSOR_PREVIEW_W (800)\r
+#define SENSOR_PREVIEW_H (600)\r
+#endif\r
#define SENSOR_PREVIEW_FPS 15000 // 15fps \r
#define SENSOR_FULLRES_L_FPS 5000 // 7.5fps\r
#define SENSOR_FULLRES_H_FPS 10000 // 7.5fps\r
SensorEnd\r
};\r
\r
-static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure04,sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00,\r
- sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,sensor_Exposure14,NULL,\r
+static struct rk_sensor_reg *sensor_ExposureSeqe[] = {/*sensor_Exposure04,*/sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00,\r
+ sensor_Exposure11, sensor_Exposure12,sensor_Exposure13/*,sensor_Exposure14*/,NULL,\r
};\r
\r
static struct rk_sensor_reg sensor_Saturation0[]=\r
static struct sensor_v4l2ctrl_usr_s sensor_controls[] =\r
{\r
new_user_v4l2ctrl(V4L2_CID_DO_WHITE_BALANCE,V4L2_CTRL_TYPE_MENU,"White Balance Control", 0, 5, 1, 0,sensor_v4l2ctrl_default_cb, sensor_WhiteBalanceSeqe),\r
- new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe),\r
+ new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe),\r
new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 6, 1, 0,sensor_v4l2ctrl_default_cb, sensor_EffectSeqe),\r
new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ContrastSeqe),\r
};\r
if (capture) {\r
// sensor_ae_transfer(client);\r
}\r
+#if defined(CONFIG_SOC_RK3188M)\r
+ mf->width-=20;\r
+ mf->height-=20;\r
+ msleep(300);\r
+#endif\r
return 0;\r
}\r
\r
static int sensor_focus_af_const_usr_cb(struct i2c_client *client){\r
return 0;\r
}\r
-static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client)
-{
- return 0;
+static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client)\r
+{\r
+ return 0;\r
}\r
static int sensor_focus_af_close_usr_cb(struct i2c_client *client){\r
return 0;\r
*v0.3.9:
* 1. return real sensor output size in rk_camera_enum_frameintervals;
* 2. wake up vb after add camera work to list in rk_camera_capture_process;
+*v0.3.b:
+ 1. support rk3188m, delay 300ms todo softrest for first frame to avoid chip abnormal running
+ 2. sync stream off with irq thread for 3188m
+
*/
-#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 3, 0x09)
+#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 3, 0x0b)
static int version = RK_CAM_VERSION_CODE;
module_param(version, int, S_IRUGO);
struct hrtimer timer;
bool istarted;
};
+#if defined(CONFIG_SOC_RK3188M)
+#define CONFIG_CIF_STOP_SYNC 1
+#else
+#define CONFIG_CIF_STOP_SYNC 0
+#endif
struct rk_cif_clk
{
//************must modify start************/
unsigned int reinit_times;
struct videobuf_queue *video_vq;
bool stop_cif;
+ #if CONFIG_CIF_STOP_SYNC
+ wait_queue_head_t cif_stop_done;
+ volatile bool cif_stopped;
+ #endif
struct timeval first_tv;
int chip_id;
static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
static void rk_camera_capture_process(struct work_struct *work);
static int rk_camera_scale_crop_arm(struct work_struct *work);
-
+static void rk_camera_soft_reset(struct rk_camera_dev *rk_pcdev);
/*
* Videobuf operations
*/
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);
+ rk_camera_soft_reset(pcdev);
}
static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
{
wake_up(&(camera_work->vb->done)); /* ddl@rock-chips.com : v0.3.9 */
return;
}
+#if defined(CONFIG_SOC_RK3188M)
+static void rk_camera_special_process_for_3188M(struct work_struct *work){
+ struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
+ struct rk_camera_dev *pcdev = camera_work->pcdev;
+ unsigned long flags = 0;
+ unsigned long tmp_cifctrl;
+ tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+ mdelay(300);
+ rk_videobuf_capture(pcdev->active,pcdev);
+ 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);
+
+ if(((tmp_cifctrl & ENABLE_CAPTURE) == 0)){
+
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
+ }
+ return;
+}
+#endif
+
+static void rk_camera_soft_reset(struct rk_camera_dev *pcdev){
+#if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
+ mdelay(100);
+ if(IS_CIF0()){
+ // pmu_set_idle_request(IDLE_REQ_VIO, true);
+ cru_set_soft_reset(SOFT_RST_CIF0, true);
+ udelay(5);
+ cru_set_soft_reset(SOFT_RST_CIF0, false);
+ // pmu_set_idle_request(IDLE_REQ_VIO, false);
+
+ }else{
+ // pmu_set_idle_request(IDLE_REQ_VIO, true);
+ cru_set_soft_reset(SOFT_RST_CIF1, true);
+ udelay(5);
+ cru_set_soft_reset(SOFT_RST_CIF1, false);
+ // pmu_set_idle_request(IDLE_REQ_VIO, false);
+ }
+#elif defined(CONFIG_ARCH_RK3188)
+ // pmu_set_idle_request(IDLE_REQ_VIO, true);
+ cru_set_soft_reset(SOFT_RST_CIF0, true);
+ udelay(5);
+ cru_set_soft_reset(SOFT_RST_CIF0, false);
+ // pmu_set_idle_request(IDLE_REQ_VIO, false);
+
+#endif
+ return;
+}
static irqreturn_t rk_camera_irq(int irq, void *data)
{
struct rk_camera_dev *pcdev = data;
tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
+#if (CONFIG_CIF_STOP_SYNC == 0)
if(pcdev->stop_cif == true)
{
printk("cif has stopped by app,needn't to deal this irq\n");
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)
/* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
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 */
+
+ // write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0); //capture complete interrupt enable
+ rk_camera_soft_reset(pcdev);
+ pcdev->cif_stopped = true;
+ wake_up(&pcdev->cif_stop_done);
+
+ return IRQ_HANDLED;
+ }
+#endif
if (!pcdev->fps) {
do_gettimeofday(&pcdev->first_tv);
}
pcdev->fps++;
if (!pcdev->active)
goto RK_CAMERA_IRQ_END;
+#if defined(CONFIG_SOC_RK3188M)
+ //for 3188M
+
+ if(pcdev->fps == 1){
+ if (CAM_WORKQUEUE_IS_EN()) {
+ if (!list_empty(&pcdev->camera_work_queue)) {
+ pcdev->frame_inval--;
+ wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
+ list_del_init(&wk->queue);
+ INIT_WORK(&(wk->work), rk_camera_special_process_for_3188M);
+ wk->vb = pcdev->active;
+ wk->pcdev = pcdev;
+ queue_work(pcdev->camera_wq, &(wk->work));
+
+ return IRQ_HANDLED;
+ }
+ }
+ }
+#endif
if (pcdev->frame_inval>0) {
pcdev->frame_inval--;
rk_videobuf_capture(pcdev->active,pcdev);
struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
struct rk_camera_dev *pcdev = fps_timer->pcdev;
int rec_flag,i;
+ unsigned long flags;
// static unsigned int last_fps = 0;
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);
if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
+
+ spin_lock_irqsave(&pcdev->lock, flags);
+ if(((pcdev->active==NULL) && !(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE))||
+ (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01)){
+ RKCAMERA_TR("%s:no active buffer,wait app enque buffer!\n",__func__);
+ }
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+ goto fps_end;
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);
pcdev->camera_reinit_work.pcdev = pcdev;
//INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
}
}
}
+
+fps_end:
pcdev->last_fps = pcdev->fps ;
pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
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);
- pcdev->stop_cif = true;
- spin_unlock_irqrestore(&pcdev->lock, flags);
+ pcdev->stop_cif = true;
+#if CONFIG_CIF_STOP_SYNC
+
+ init_waitqueue_head(&pcdev->cif_stop_done);
+ if (wait_event_interruptible_timeout(pcdev->cif_stop_done, pcdev->cif_stopped, msecs_to_jiffies(300)) == 0) {
+ RKCAMERA_DG("%s:%d, wait cif stop timeout!\n",__func__,__LINE__);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+ mdelay(300);
+ rk_camera_soft_reset(pcdev);
+ }
+#else
+ spin_lock_irqsave(&pcdev->lock, flags);
+ write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+
+#endif
flush_workqueue((pcdev->camera_wq));
RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
}