static int unicam_videobuf_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
				 unsigned int *count, unsigned int *numplanes,
				 unsigned int sizes[], void *alloc_ctxs[])
{
	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct unicam_camera_dev *unicam_dev =
	    (struct unicam_camera_dev *)ici->priv;
	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
						     icd->
						     current_fmt->host_fmt);

	dprintk("-enter");

	if (bytes_per_line < 0)
		return bytes_per_line;

	*numplanes = 1;

	unicam_dev->sequence = 0;

	sizes[0] = bytes_per_line * icd->user_height;
	alloc_ctxs[0] = unicam_dev->alloc_ctx;

	if (!*count)
		*count = 2;

	iprintk("no_of_buf=%d size=%u", *count, sizes[0]);
	dprintk("-exit");
	return 0;
}
static int unicam_camera_set_fmt(struct soc_camera_device *icd,
				 struct v4l2_format *f)
{
	struct device *dev = icd->dev.parent;
	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct unicam_camera_dev *unicam_dev = ici->priv;
	const struct soc_camera_format_xlate *xlate = NULL;
	struct v4l2_pix_format *pix = &f->fmt.pix;
	struct v4l2_mbus_framefmt mf;
	int ret;
	u32 skip_frames = 0;

	dprintk("-enter");
	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
	if (!xlate) {
		dev_warn(dev, "Format %x not found\n", pix->pixelformat);
		return -EINVAL;
	}

	mf.width = pix->width;
	mf.height = pix->height;
	mf.field = pix->field;
	mf.colorspace = pix->colorspace;
	mf.code = xlate->code;

	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);

	if (mf.code != xlate->code)
		return -EINVAL;

	if (ret < 0) {
		dev_warn(dev, "Failed to configure for format %x\n",
			 pix->pixelformat);
		return ret;
	}
	/*TODO limit here any maximum size */

	ret = v4l2_subdev_call(sd, sensor, g_skip_frames, &skip_frames);
	if (ret < 0) {
		dev_warn(dev,
			 "sensor driver doesn't implement g_skip_frames operation\n");
		dev_warn(dev, "assuming zero skip frames\n");
		skip_frames = 0;
		ret = 0;
	}

	unicam_dev->skip_frames = skip_frames;

	pix->width = mf.width;
	pix->height = mf.height;
	pix->field = mf.field;
	pix->colorspace = mf.colorspace;
	icd->current_fmt = xlate;
	iprintk("format set to %c%c%c%c res=%dx%d success=%d",
		pixfmtstr(pix->pixelformat), pix->width, pix->height, ret);
	dprintk("-exit");
	return ret;
}
Example #3
0
int boot_dmsg (uint64_t tty, const char *fmt, ...)
{
   va_list ap;
   int count;

   va_start (ap, fmt);
   
   count = iprintk (tty, 0, (char *) fmt, ap);

   va_end (ap);
   return count;
}
static int unicam_camera_try_fmt(struct soc_camera_device *icd,
				 struct v4l2_format *f)
{
	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
	const struct soc_camera_format_xlate *xlate;
	struct v4l2_pix_format *pix = &f->fmt.pix;
	struct v4l2_mbus_framefmt mf;
	struct v4l2_format thumb_fmt;
	struct v4l2_pix_format *thumb_pix;
	__u32 pixfmt = pix->pixelformat;
	int thumb=0;
	int ret;

	dprintk("-enter");
	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
	if (!xlate) {
		dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
		return -EINVAL;
	}

	pix->sizeimage = pix->height * pix->bytesperline;

	/* limit to sensor capabilities */
	mf.width = pix->width;
	mf.height = pix->height;
	mf.field = pix->field;
	mf.colorspace = pix->colorspace;
	mf.code = xlate->code;

	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
	if (ret < 0)
		return ret;

	pix->width = mf.width;
	pix->height = mf.height;
	pix->colorspace = mf.colorspace;

	switch (mf.field) {
	case V4L2_FIELD_ANY:
	case V4L2_FIELD_NONE:
		pix->field = V4L2_FIELD_NONE;
		break;
	default:
		dev_err(icd->dev.parent, "Field type %d unsupported.\n",
			mf.field);
		return -EINVAL;
	}

	/* what format can unicam support */
	switch (mf.code) {
	case V4L2_MBUS_FMT_JPEG_1X8:
		/* check here if thumbnail is supported
		and check thumbnail format */
		ret =
		    v4l2_subdev_call(sd, core, ioctl, VIDIOC_THUMB_SUPPORTED,
				     (void *)&thumb);
		if ((!ret) && thumb) {
			ret =
			    v4l2_subdev_call(sd, core, ioctl,
					     VIDIOC_THUMB_G_FMT,
					     (void *)&thumb_fmt);
			if (ret < 0) {
				dev_err(icd->dev.parent,
					"sensor driver should report thumbnail format\n");
				return -EINVAL;
			}
			thumb_pix = &thumb_fmt.fmt.pix;
			switch (thumb_pix->pixelformat) {
			case V4L2_PIX_FMT_YUYV:
			case V4L2_PIX_FMT_UYVY:
				iprintk
				    ("sensor supports thumbnail %c%c%c%c format",
				     pixfmtstr(thumb_pix->pixelformat));
				break;
			default:
				dev_err(icd->dev.parent,
					"sensor thumbnail format %c%c%c%c not supported\n",
					pixfmtstr(thumb_pix->pixelformat));
				return -EINVAL;
			}
		} else
			iprintk
			    ("sensor doesnot support thumbnail (thumb=%d, ret=%d)\n",
			     thumb, ret);

	case V4L2_MBUS_FMT_YUYV8_2X8:
	case V4L2_MBUS_FMT_UYVY8_2X8:
		/* Above formats are supported */
		break;
	default:
		dev_err(icd->dev.parent, "Sensor format code %d unsupported.\n",
			mf.code);
		return -EINVAL;
	}
	iprintk("trying format=%c%c%c%c res=%dx%d success=%d",
		pixfmtstr(pixfmt), mf.width, mf.height, ret);
	dprintk("-exit");
	return ret;
}
int unicam_videobuf_stop_streaming(struct vb2_queue *q)
{
	struct soc_camera_device *icd = soc_camera_from_vb2q(q);
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
	struct unicam_camera_dev *unicam_dev = ici->priv;
	CSL_CAM_FRAME_st_t cslCamFrame;
	int ret = 0;
	unsigned long flags;

	if (down_interruptible(&unicam_dev->stop_processing_sem) == 0) {
		if (unicam_dev->streaming)
			csl_cam_register_display(unicam_dev->cslCamHandle);
	} else
		dev_err(unicam_dev->dev, "Unable to dump regs because stop_processing_sem acquire failed\n");

	/* grab the lock */
	spin_lock_irqsave(&unicam_dev->lock, flags);
	dprintk("-enter");
	dprintk("disabling csi");
	iprintk("stopping stream");
	if (!unicam_dev->streaming) {
		dev_err(unicam_dev->dev, "stream already turned off\n");
		goto out;
	}
	/*
	 * stop streaming before grabing spin lock
	 * since this function can sleep.
	 * */
	if (unicam_dev->active) {
		unicam_dev->stopping = true;
		spin_unlock_irqrestore(&unicam_dev->lock, flags);
		ret = down_timeout(&unicam_dev->stop_sem,
				msecs_to_jiffies(500));
		if (ret == -ETIME)
			pr_err("Unicam: semaphore timed out waiting to STOP\n");
	} else {
		spin_unlock_irqrestore(&unicam_dev->lock, flags);
	}
	usleep_range(50, 60); /*TODO: Need to double-check with ASIC team*/
	spin_lock_irqsave(&unicam_dev->lock, flags);

	/* disable frame interrupts */
	cslCamFrame.int_enable = CSL_CAM_INT_DISABLE;
	cslCamFrame.int_line_count = 0;
	cslCamFrame.capture_mode = UNICAM_CAPTURE_MODE;
	cslCamFrame.capture_size = 0;

	if (csl_cam_set_frame_control(unicam_dev->cslCamHandle, &cslCamFrame)) {
		dev_err(unicam_dev->dev,
			"csl_cam_set_frame_control(): FAILED\n");
		ret = -1;
	}

	/* disable receiver */
	if (csl_cam_rx_stop(unicam_dev->cslCamHandle)) {
		dev_err(unicam_dev->dev, "csl_cam_rx_stop(): FAILED\n");
		ret = -1;
	}

	if (csl_cam_close(unicam_dev->cslCamHandle)) {
		dev_err(unicam_dev->dev, "cals_cam_exit(): FAILED\n");
		ret = -1;
	}

	if (csl_cam_exit()) {
		dev_err(unicam_dev->dev, "csl_cam_exit(): FAILED\n");
		ret = -1;
	}

	unicam_dev->active = NULL;
	unicam_dev->streaming = 0;
out:
	dprintk("-exit");
	spin_unlock_irqrestore(&unicam_dev->lock, flags);
	up(&unicam_dev->stop_processing_sem);

	/* Stopping stream after stopping unicam */
	ret = v4l2_subdev_call(sd, video, s_stream, 0);
	if (ret < 0 && ret != -ENOIOCTLCMD) {
		dev_err(unicam_dev->dev, "failed to stop sensor streaming\n");
		ret = -1;
	}
	return ret;
}
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;
}