From cd95f006d0a9bb9acdcfebfc0478edc4fe77d195 Mon Sep 17 00:00:00 2001 From: zyc Date: Fri, 19 Jul 2013 16:56:02 +0800 Subject: [PATCH] camera:cif support rk3188M --- drivers/media/video/nt99252_3way.c | 32 +++-- drivers/media/video/nt99340_2way.c | 32 +++-- drivers/media/video/rk30_camera_oneframe.c | 135 +++++++++++++++++++-- 3 files changed, 170 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/nt99252_3way.c b/drivers/media/video/nt99252_3way.c index 4ac781e8618d..9984824f9ebf 100755 --- a/drivers/media/video/nt99252_3way.c +++ b/drivers/media/video/nt99252_3way.c @@ -1,12 +1,14 @@ #include "generic_sensor.h" -/* +/* * Driver Version Note *v0.0.1: this driver is compatible with generic_sensor *v0.1.1: * add sensor_focus_af_const_pause_usr_cb; +*v0.1.2: + crop for rk3188m */ -static int version = KERNEL_VERSION(0,1,1); +static int version = KERNEL_VERSION(0,1,2); module_param(version, int, S_IRUGO); static int debug =1; @@ -23,8 +25,13 @@ module_param(debug, int, S_IRUGO|S_IWUSR); #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 800 -#define SENSOR_PREVIEW_H 600 +#if defined(CONFIG_SOC_RK3188M) +#define SENSOR_PREVIEW_W (800 - 20) +#define SENSOR_PREVIEW_H (600 - 20) +#else +#define SENSOR_PREVIEW_W (800) +#define SENSOR_PREVIEW_H (600) +#endif #define SENSOR_PREVIEW_FPS 15000 // 15fps #define SENSOR_FULLRES_L_FPS 5000 // 7.5fps #define SENSOR_FULLRES_H_FPS 10000 // 7.5fps @@ -714,8 +721,8 @@ static struct rk_sensor_reg sensor_Exposure14[]= SensorEnd }; -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure04,sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00, - sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,sensor_Exposure14,NULL, +static struct rk_sensor_reg *sensor_ExposureSeqe[] = {/*sensor_Exposure04,*/sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00, + sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,/*sensor_Exposure14,*/NULL, }; @@ -882,7 +889,7 @@ static struct v4l2_querymenu sensor_menus[] = static struct sensor_v4l2ctrl_usr_s sensor_controls[] = { 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), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe), new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 6, 1, 0,sensor_v4l2ctrl_default_cb, sensor_EffectSeqe), new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ContrastSeqe), }; @@ -952,6 +959,11 @@ static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framef if (capture) { //sensor_ae_transfer(client); } +#if defined(CONFIG_SOC_RK3188M) + mf->width-=20; + mf->height-=20; + msleep(300); +#endif return 0; } @@ -1088,9 +1100,9 @@ static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ 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_const_pause_usr_cb(struct i2c_client *client) +{ + return 0; } static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ return 0; diff --git a/drivers/media/video/nt99340_2way.c b/drivers/media/video/nt99340_2way.c index 0df32184822c..c99efcbf6e87 100755 --- a/drivers/media/video/nt99340_2way.c +++ b/drivers/media/video/nt99340_2way.c @@ -1,12 +1,14 @@ #include "generic_sensor.h" -/* +/* * Driver Version Note *v0.0.1: this driver is compatible with generic_sensor *v0.1.1: * add sensor_focus_af_const_pause_usr_cb; +*v0.1.2: + crop for rk3188m */ -static int version = KERNEL_VERSION(0,1,1); +static int version = KERNEL_VERSION(0,1,2); module_param(version, int, S_IRUGO); static int debug =1; @@ -24,8 +26,13 @@ module_param(debug, int, S_IRUGO|S_IWUSR); SOCAM_HSYNC_ACTIVE_HIGH| SOCAM_VSYNC_ACTIVE_HIGH|\ SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8 |SOCAM_MCLK_24MHZ) -#define SENSOR_PREVIEW_W 800 -#define SENSOR_PREVIEW_H 600 +#if defined(CONFIG_SOC_RK3188M) +#define SENSOR_PREVIEW_W (800 - 20) +#define SENSOR_PREVIEW_H (600 - 20) +#else +#define SENSOR_PREVIEW_W (800) +#define SENSOR_PREVIEW_H (600) +#endif #define SENSOR_PREVIEW_FPS 15000 // 15fps #define SENSOR_FULLRES_L_FPS 5000 // 7.5fps #define SENSOR_FULLRES_H_FPS 10000 // 7.5fps @@ -769,8 +776,8 @@ static struct rk_sensor_reg sensor_Exposure14[]= SensorEnd }; -static struct rk_sensor_reg *sensor_ExposureSeqe[] = {sensor_Exposure04,sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00, - sensor_Exposure11, sensor_Exposure12,sensor_Exposure13,sensor_Exposure14,NULL, +static struct rk_sensor_reg *sensor_ExposureSeqe[] = {/*sensor_Exposure04,*/sensor_Exposure03, sensor_Exposure02, sensor_Exposure01, sensor_Exposure00, + sensor_Exposure11, sensor_Exposure12,sensor_Exposure13/*,sensor_Exposure14*/,NULL, }; static struct rk_sensor_reg sensor_Saturation0[]= @@ -928,7 +935,7 @@ static struct v4l2_querymenu sensor_menus[] = static struct sensor_v4l2ctrl_usr_s sensor_controls[] = { 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), - new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe), + new_user_v4l2ctrl(V4L2_CID_EXPOSURE,V4L2_CTRL_TYPE_INTEGER,"Exposure Control", -3, 3, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ExposureSeqe), new_user_v4l2ctrl(V4L2_CID_EFFECT,V4L2_CTRL_TYPE_MENU,"Effect Control", 0, 6, 1, 0,sensor_v4l2ctrl_default_cb, sensor_EffectSeqe), new_user_v4l2ctrl(V4L2_CID_CONTRAST,V4L2_CTRL_TYPE_INTEGER,"Contrast Control", -4, 4, 1, 0,sensor_v4l2ctrl_default_cb, sensor_ContrastSeqe), }; @@ -1003,6 +1010,11 @@ static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framef if (capture) { // sensor_ae_transfer(client); } +#if defined(CONFIG_SOC_RK3188M) + mf->width-=20; + mf->height-=20; + msleep(300); +#endif return 0; } @@ -1143,9 +1155,9 @@ static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){ 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_const_pause_usr_cb(struct i2c_client *client) +{ + return 0; } static int sensor_focus_af_close_usr_cb(struct i2c_client *client){ return 0; diff --git a/drivers/media/video/rk30_camera_oneframe.c b/drivers/media/video/rk30_camera_oneframe.c index 2d2fd857b3e8..6c0d15de4925 100755 --- a/drivers/media/video/rk30_camera_oneframe.c +++ b/drivers/media/video/rk30_camera_oneframe.c @@ -305,9 +305,13 @@ module_param(debug, int, S_IRUGO|S_IWUSR); *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); @@ -398,6 +402,11 @@ struct rk_camera_timer{ 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************/ @@ -468,6 +477,10 @@ struct rk_camera_dev 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; @@ -496,7 +509,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); 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 */ @@ -673,9 +686,7 @@ static void rk_camera_store_register(struct rk_camera_dev *pcdev) 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) { @@ -1244,6 +1255,54 @@ rk_camera_capture_process_end: 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; @@ -1255,12 +1314,14 @@ static irqreturn_t rk_camera_irq(int irq, void *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) @@ -1271,12 +1332,45 @@ static irqreturn_t rk_camera_irq(int irq, void *data) /* 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); @@ -2606,12 +2700,21 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) 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); @@ -2676,6 +2779,8 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) } } } + +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))); @@ -2717,10 +2822,22 @@ static int rk_camera_s_stream(struct soc_camera_device *icd, int enable) 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); } -- 2.34.1