diff options
Diffstat (limited to 'drivers/media/video/mxc/capture/mxc_v4l2_capture.c')
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c index b5fa53bf2c03..fa3b2a34ac0b 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c @@ -40,6 +40,8 @@ #include "ipu_prp_sw.h" #define init_MUTEX(sem) sema_init(sem, 1) +#define MXC_SENSOR_NUM 2 +static int sensor_index; static int video_nr = -1, local_buf_num; static cam_data *g_cam; @@ -308,7 +310,7 @@ static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) pr_debug("In MVC:mxc_v4l2_prepare_bufs\n"); if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < - PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) { + cam->v2f.fmt.pix.sizeimage) { pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers " "not allocated,index=%d, length=%d\n", buf->index, buf->length); @@ -1033,8 +1035,9 @@ static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c) */ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) { - int ret = 0; + int i, ret = 0; int tmp_rotation = IPU_ROTATE_NONE; + struct sensor_data *sensor_data; pr_debug("In MVC:mxc_v4l2_s_ctrl\n"); @@ -1203,6 +1206,25 @@ static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) ipu_csi_flash_strobe(true); #endif break; + case V4L2_CID_MXC_SWITCH_CAM: + if (cam->sensor != cam->all_sensors[c->value]) { + /* power down other cameraes before enable new one */ + for (i = 0; i < sensor_index; i++) { + if (i != c->value) { + vidioc_int_dev_exit(cam->all_sensors[i]); + vidioc_int_s_power(cam->all_sensors[i], 0); + } + } + sensor_data = cam->all_sensors[c->value]->priv; + if (sensor_data->io_init) + sensor_data->io_init(); + cam->sensor = cam->all_sensors[c->value]; + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, true, true); + vidioc_int_s_power(cam->sensor, 1); + vidioc_int_dev_init(cam->sensor); + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, false, false); + } + break; default: pr_debug(" default case\n"); ret = -EINVAL; @@ -1227,6 +1249,7 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) struct v4l2_format cam_fmt; struct v4l2_streamparm currentparm; ipu_csi_signal_cfg_t csi_param; + u32 current_fps, parm_fps; int err = 0; pr_debug("In mxc_v4l2_s_param\n"); @@ -1251,18 +1274,18 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) goto exit; } + current_fps = currentparm.parm.capture.timeperframe.denominator + / currentparm.parm.capture.timeperframe.numerator; + parm_fps = parm->parm.capture.timeperframe.denominator + / parm->parm.capture.timeperframe.numerator; + pr_debug(" Current capabilities are %x\n", currentparm.parm.capture.capability); pr_debug(" Current capturemode is %d change to %d\n", currentparm.parm.capture.capturemode, parm->parm.capture.capturemode); pr_debug(" Current framerate is %d change to %d\n", - currentparm.parm.capture.timeperframe.denominator, - parm->parm.capture.timeperframe.denominator); - - if (parm->parm.capture.capturemode == currentparm.parm.capture.capturemode) { - return 0; - } + current_fps, parm_fps); /* This will change any camera settings needed. */ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, true, true); @@ -1293,10 +1316,16 @@ static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) csi_param.csi = 0; csi_param.mclk = 0; - /* This may not work on other platforms. Check when adding a new one.*/ + /*This may not work on other platforms. Check when adding a new one.*/ + /*The mclk clock was never set correclty in the ipu register*/ + /*for now we are going to use this mclk as pixel clock*/ + /*to set csi0_data_dest register.*/ + /*This is a workaround which should be fixed*/ pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr); if (ifparm.u.bt656.clock_curr == 0) { csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED; + /*protocol bt656 use 27Mhz pixel clock */ + csi_param.mclk = 27000000; } else { csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK; } @@ -1566,6 +1595,7 @@ static int mxc_v4l_open(struct file *file) csi_param.pack_tight = 0; csi_param.force_eof = 0; csi_param.data_en_pol = 0; + csi_param.mclk = ifparm.u.bt656.clock_curr; csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv; @@ -2810,17 +2840,32 @@ static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) { cam_data *cam = slave->u.slave->master->priv; struct v4l2_format cam_fmt; + int i; pr_debug("In MVC: mxc_v4l2_master_attach\n"); pr_debug(" slave.name = %s\n", slave->name); pr_debug(" master.name = %s\n", slave->u.slave->master->name); - cam->sensor = slave; if (slave == NULL) { pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); return -1; } + cam->sensor = slave; + + if (sensor_index < MXC_SENSOR_NUM) { + cam->all_sensors[sensor_index] = slave; + sensor_index++; + } else { + pr_err("ERROR: v4l2 capture: slave number exceeds the maximum.\n"); + return -1; + } + + for (i = 0; i < sensor_index - 1; i++) { + vidioc_int_dev_exit(cam->all_sensors[i]); + vidioc_int_s_power(cam->all_sensors[i], 0); + } + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi, true, true); vidioc_int_s_power(cam->sensor, 1); vidioc_int_dev_init(slave); |