static void unicam_videobuf_queue(struct vb2_buffer *vb) { struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; struct unicam_camera_buffer *buf = to_unicam_camera_vb(vb); unsigned long flags; dprintk("-enter"); dprintk("vb=0x%p vbuf=0x%p pbuf=0x%p size=%lu", vb, vb2_plane_vaddr(vb, 0), (void *)vb2_dma_contig_plane_dma_addr(vb, 0), vb2_get_plane_payload(vb, 0)); spin_lock_irqsave(&unicam_dev->lock, flags); list_add_tail(&buf->queue, &unicam_dev->capture); if (!unicam_dev->active) { unicam_dev->active = vb; /* use this buffer to trigger capture */ /* Configure HW only is streamon has been done * else only update active, HW would be configured * by streamon */ if(unicam_dev->streaming){ unicam_camera_update_buf(unicam_dev); if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) unicam_camera_capture(unicam_dev); } } spin_unlock_irqrestore(&unicam_dev->lock, flags); dprintk("-exit"); }
static int unicam_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *crop) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; if(crop == NULL) return -EINVAL; unicam_dev->crop = *crop; return 0; #if 0 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); pr_info("Configuring crop to %d %d\n", crop->c.width, crop->c.height); pr_info("Configuring top left to %d %d\n", crop->c.top, crop->c.left); v4l2_subdev_call(sd, video, s_stream, 0); spin_lock_irqsave(&unicam_dev->lock, flags); unicam_dev->crop = *crop; if(unicam_dev->streaming){ pr_info("Stopping stream\n"); unicam_stop(); } /* Configure new crop parameters */ mm_csi0_set_windowing_vertical(unicam_dev->crop.c.top, (unicam_dev->crop.c.top + unicam_dev->crop.c.height)); mm_csi0_cfg_pipeline_unpack(PIX_UNPACK_NONE); mm_csi0_cfg_pipeline_dpcm_dec(DPCM_DEC_NONE); mm_csi0_set_windowing_horizontal(unicam_dev->crop.c.left, (unicam_dev->crop.c.left + unicam_dev->crop.c.width)); mm_csi0_cfg_pipeline_dpcm_enc(DPCM_ENC_NONE); mm_csi0_cfg_pipeline_pack(PIX_PACK_NONE); mm_csi0_start_rx(); /* Re-configure buffer parameters */ unicam_camera_update_buf(unicam_dev); /* set data capture */ if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) { idesc.fsi = 1; idesc.fei = 1; idesc.lci = 0; idesc.die = 1; idesc.dataline = 2; mm_csi0_config_int(&idesc, IMAGE_BUFFER); mm_csi0_config_int(&idesc, DATA_BUFFER); unicam_camera_capture(unicam_dev); } else { idesc.fsi = 0; idesc.fei = 0; idesc.lci = unicam_dev->icd->user_height; idesc.die = 0; idesc.dataline = 0; mm_csi0_config_int(&idesc, IMAGE_BUFFER); } spin_unlock_irqrestore(&unicam_dev->lock, flags); v4l2_subdev_call(sd, video, s_stream, 1); return 0; #endif }
static void unicam_videobuf_queue(struct vb2_buffer *vb) { struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; struct unicam_camera_buffer *buf = to_unicam_camera_vb(vb); unsigned long flags; struct int_desc idesc; pr_debug("-enter"); pr_debug("vb=0x%p pbuf=0x%p size=%lu", vb, (void *)vb2_plane_dma_addr(vb, 0), vb2_get_plane_payload(vb, 0)); /* pr_info("Q 0x%x\n", vb2_plane_paddr(vb, 0)); */ spin_lock_irqsave(&unicam_dev->lock, flags); list_add_tail(&buf->queue, &unicam_dev->capture); if(unicam_dev->cap_mode && unicam_dev->cap_done){ pr_info("Cap mode and already captured\n"); spin_unlock_irqrestore(&unicam_dev->lock, flags); return; } if ((!unicam_dev->active)) { unicam_dev->active = vb; unicam_camera_update_buf(unicam_dev); if (atomic_read(&unicam_dev->streaming)) { mm_csi0_start_rx(); /* set data capture */ if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) { idesc.fsi = 1; idesc.fei = 1; idesc.lci = 0; idesc.die = 1; idesc.dataline = 2; mm_csi0_config_int(&idesc, IMAGE_BUFFER); mm_csi0_config_int(&idesc, DATA_BUFFER); unicam_camera_capture(unicam_dev); } else { idesc.fsi = 0; idesc.fei = 0; idesc.lci = unicam_dev->icd->user_height; idesc.die = 0; idesc.dataline = 0; mm_csi0_config_int(&idesc, IMAGE_BUFFER); } } } spin_unlock_irqrestore(&unicam_dev->lock, flags); pr_debug("-exit"); }
int unicam_videobuf_start_streaming(struct vb2_queue *q, unsigned int count) { struct soc_camera_device *icd = soc_camera_from_vb2q(q); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct unicam_camera_dev *unicam_dev = ici->priv; struct v4l2_subdev_sensor_interface_parms if_params; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; int thumb; unsigned long flags; CSL_CAM_INTF_CFG_st_t csl_cam_intf_cfg_st; CSL_CAM_LANE_CONTROL_st_t cslCamLaneCtrl_st; CSL_CAM_PIPELINE_st_t cslCamPipeline; CSL_CAM_IMAGE_ID_st_t cslCamImageCtrl; CSL_CAM_DATA_st_t cslCamDataCtrl; CSL_CAM_FRAME_st_t cslCamFrame; dprintk("-enter"); iprintk("enabling csi"); spin_lock_irqsave(&unicam_dev->lock, flags); unicam_dev->stopping = false; spin_unlock_irqrestore(&unicam_dev->lock, flags); if (csl_cam_init()) { dev_err(unicam_dev->dev, "error initializing csl camera\n"); return -1; } ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret < 0 && ret != -ENOIOCTLCMD) { dev_err(unicam_dev->dev, "error on s_stream(%d)\n", ret); spin_lock_irqsave(&unicam_dev->lock, flags); unicam_dev->active = NULL; unicam_dev->stopping = true; spin_unlock_irqrestore(&unicam_dev->lock, flags); if (csl_cam_exit()) dev_err(unicam_dev->dev, "csl_cam_exit(): FAILED\n"); return ret; } /* get the sensor interface information */ ret = v4l2_subdev_call(sd, sensor, g_interface_parms, &if_params); if (ret < 0) { dev_err(unicam_dev->dev, "error on g_inferface_params(%d)\n", ret); return ret; } unicam_dev->if_params = if_params; /* set camera interface parameters */ memset(&csl_cam_intf_cfg_st, 0, sizeof(CSL_CAM_INTF_CFG_st_t)); /* we only support serial and csi2 sensor */ if ((unicam_dev->if_params.if_type == V4L2_SUBDEV_SENSOR_SERIAL) && (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2)) { csl_cam_intf_cfg_st.intf = CSL_CAM_INTF_CSI; } else if ((unicam_dev->if_params.if_type == V4L2_SUBDEV_SENSOR_SERIAL) && (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI1)) { csl_cam_intf_cfg_st.intf = CSL_CAM_INTF_CCP; } else { dev_err(unicam_dev->dev, "CSI2 iface only supported,requested iface %d mode=%d\n", unicam_dev->if_params.if_type, unicam_dev->if_params.if_mode); return -EINVAL; } if (unicam_dev->if_params.parms.serial.channel == 0) csl_cam_intf_cfg_st.afe_port = CSL_CAM_PORT_AFE_0; else if (unicam_dev->if_params.parms.serial.channel == 1) csl_cam_intf_cfg_st.afe_port = CSL_CAM_PORT_AFE_1; else { dev_err(unicam_dev->dev, "receiver only supports two channels, request channel=%d\n", unicam_dev->if_params.parms.serial.channel); return -EINVAL; } csl_cam_intf_cfg_st.frame_time_out = 1000; /* open camera interface */ csl_cam_intf_cfg_st.p_cpi_intf_st = NULL; if ((unicam_dev->if_params.if_type == V4L2_SUBDEV_SENSOR_SERIAL) && (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2)) { if (unicam_dev->if_params.parms.serial.lanes == 1) csl_cam_intf_cfg_st.input_mode = CSL_CAM_INPUT_SINGLE_LANE; else if (unicam_dev->if_params.parms.serial.lanes == 2) csl_cam_intf_cfg_st.input_mode = CSL_CAM_INPUT_DUAL_LANE; else { dev_err(unicam_dev->dev, "receiver only supports max 2 lanes, requested lanes(%d)\n", unicam_dev->if_params.parms.serial.lanes); return -EINVAL; } } else { csl_cam_intf_cfg_st.input_mode = CSL_CAM_INPUT_MODE_DATA_CLOCK; } if (csl_cam_open(&csl_cam_intf_cfg_st, &unicam_dev->cslCamHandle)) { dev_err(unicam_dev->dev, "%s: csl_cam_open(): ERROR\n", __func__); return -1; } /* set data lane timing */ cslCamLaneCtrl_st.lane_select = CSL_CAM_DATA_LANE_0; cslCamLaneCtrl_st.lane_control = CSL_CAM_LANE_HS_TERM_TIME; cslCamLaneCtrl_st.param = unicam_dev->if_params.parms.serial.hs_term_time; dprintk("hs_term_time is set to = %d\n", cslCamLaneCtrl_st.param); if (csl_cam_set_lane_control (unicam_dev->cslCamHandle, &cslCamLaneCtrl_st)) { dev_err(unicam_dev->dev, "csl_cam_set_lane_control(): FAILED\n"); return -1; } if (unicam_dev->if_params.parms.serial.hs_settle_time != 0) { cslCamLaneCtrl_st.lane_select = CSL_CAM_DATA_LANE_0; cslCamLaneCtrl_st.lane_control = CSL_CAM_LANE_HS_SETTLE_TIME; cslCamLaneCtrl_st.param = unicam_dev->if_params.parms.serial.hs_settle_time; dprintk("hs_settle_time is set to = %d\n", cslCamLaneCtrl_st.param); if (csl_cam_set_lane_control (unicam_dev->cslCamHandle, &cslCamLaneCtrl_st)) { dev_err(unicam_dev->dev, "csl_cam_set_lane_control(): FAILED\n"); return -1; } } /* pipelince decode */ cslCamPipeline.decode = CSL_CAM_DEC_NONE; cslCamPipeline.unpack = CSL_CAM_PIXEL_NONE; cslCamPipeline.pack = CSL_CAM_PIXEL_NONE; cslCamPipeline.dec_adv_predictor = FALSE; cslCamPipeline.encode = CSL_CAM_ENC_NONE; cslCamPipeline.enc_adv_predictor = FALSE; cslCamPipeline.encode_blk_size = 0x0000; /* set pipeline */ if (csl_cam_set_pipeline_control (unicam_dev->cslCamHandle, &cslCamPipeline)) { dev_err(unicam_dev->dev, "csl_cam_set_pipeline_control(): FAILE\n"); return -1; } /* set image identifier (CSI mode only) */ memset(&cslCamImageCtrl, 0, sizeof(CSL_CAM_IMAGE_ID_st_t)); /* if thumbnail is supported we expect * thumbnail to be in image ptr format of thumbnails is yuv422 * format is checked in try format. * in case where thumbnail is not supported we get jpeg * image in data pointer. so we set the id as 0 */ thumb = 0; ret = v4l2_subdev_call(sd, core, ioctl, VIDIOC_THUMB_SUPPORTED, (void *)&thumb); if (ret < 0) dev_warn(unicam_dev->dev, "sensor returns error(%d) for VIDIOC_THUMB_SUPPORTED\n", ret); if ((icd->current_fmt->code == V4L2_MBUS_FMT_JPEG_1X8) && (thumb == 0)) cslCamImageCtrl.image_data_id0 = 0x0; /* thumbnail not supported */ else cslCamImageCtrl.image_data_id0 = 0x1E; if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI1) cslCamImageCtrl.image_data_id0 = 0x0; /* CCP2 channel ID 0 */ if (csl_cam_set_image_type_control (unicam_dev->cslCamHandle, &cslCamImageCtrl)) { dev_err(unicam_dev->dev, "csl_cam_set_image_type_control(): FAILED\n"); return -1; } /* set data capture */ cslCamDataCtrl.int_enable = (CSL_CAM_INTERRUPT_t) (CSL_CAM_INT_DISABLE); if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) { cslCamDataCtrl.line_count = 2; cslCamDataCtrl.fsp_decode_enable = FALSE; } else { cslCamDataCtrl.line_count = 0; cslCamDataCtrl.fsp_decode_enable = TRUE; } cslCamDataCtrl.data_id = 0x00; cslCamDataCtrl.data_size = CSL_CAM_PIXEL_8BIT; if (csl_cam_set_data_type_control (unicam_dev->cslCamHandle, &cslCamDataCtrl)) { dev_err(unicam_dev->dev, "csl_cam_set_data_type_control(): FAILED\n"); return -1; } /* start receiver */ if (csl_cam_rx_start(unicam_dev->cslCamHandle)) { dev_err(unicam_dev->dev, "csl_cam_rx_start(): FAILED\n"); return -1; } /* Enabling sensor after enabling unicam */ /* ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret < 0 && ret != -ENOIOCTLCMD) { dev_err(unicam_dev->dev, "error on s_stream(%d)\n", ret); return ret; } */ if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI1) { cslCamFrame.int_enable = CSL_CAM_INT_LINE_COUNT; /* CSL_CAM_INT_FRAME_END | CSL_CAM_INT_FRAME_START; //CSL_CAM_INT_LINE_COUNT; cslCamFrame.int_line_count = (unicam_dev->icd->user_height - 1);*/ cslCamFrame.int_line_count = (unicam_dev->icd->user_height); cslCamFrame.capture_mode = CSL_CAM_CAPTURE_MODE_NORMAL; /* CSL_CAM_CAPTURE_MODE_NORMAL */ if (csl_cam_set_frame_control( unicam_dev->cslCamHandle, &cslCamFrame)) { dev_err(unicam_dev->dev, "csl_cam_set_frame_control(): FAILED\n"); return -1; } } /* Configure HW if buffer is queued ahead of streamon */ spin_lock_irqsave(&unicam_dev->lock, flags); if(unicam_dev->active){ unicam_camera_update_buf(unicam_dev); if (unicam_dev->if_params.if_mode == V4L2_SUBDEV_SENSOR_MODE_SERIAL_CSI2) unicam_camera_capture(unicam_dev); } unicam_dev->streaming = 1; spin_unlock_irqrestore(&unicam_dev->lock, flags); csl_cam_register_display(unicam_dev->cslCamHandle); dprintk("-exit"); return 0; }