Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8da8c03 authored by Russell King's avatar Russell King Committed by Mauro Carvalho Chehab
Browse files

[media] media: imx: csi: add support for bayer formats



Bayer formats must be treated as generic data and passthrough mode must
be used.  Add the correct setup for these formats.

- added check to csi_link_validate() to verify that destination is
  IDMAC output pad when passthrough conditions exist: bayer formats
  and 16-bit parallel buses.

Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarSteve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent f5138526
Loading
Loading
Loading
Loading
+57 −17
Original line number Original line Diff line number Diff line
@@ -288,10 +288,11 @@ static int csi_idmac_setup_channel(struct csi_priv *priv)
	struct imx_media_video_dev *vdev = priv->vdev;
	struct imx_media_video_dev *vdev = priv->vdev;
	struct v4l2_fwnode_endpoint *sensor_ep;
	struct v4l2_fwnode_endpoint *sensor_ep;
	struct v4l2_mbus_framefmt *infmt;
	struct v4l2_mbus_framefmt *infmt;
	unsigned int burst_size;
	struct ipu_image image;
	struct ipu_image image;
	u32 passthrough_bits;
	dma_addr_t phys[2];
	dma_addr_t phys[2];
	bool passthrough;
	bool passthrough;
	u32 burst_size;
	int ret;
	int ret;


	infmt = &priv->format_mbus[CSI_SINK_PAD];
	infmt = &priv->format_mbus[CSI_SINK_PAD];
@@ -309,24 +310,52 @@ static int csi_idmac_setup_channel(struct csi_priv *priv)
	image.phys0 = phys[0];
	image.phys0 = phys[0];
	image.phys1 = phys[1];
	image.phys1 = phys[1];


	ret = ipu_cpmem_set_image(priv->idmac_ch, &image);
	if (ret)
		goto unsetup_vb2;

	burst_size = (image.pix.width & 0xf) ? 8 : 16;

	ipu_cpmem_set_burstsize(priv->idmac_ch, burst_size);

	/*
	/*
	 * If the sensor uses 16-bit parallel CSI bus, we must handle
	 * Check for conditions that require the IPU to handle the
	 * the data internally in the IPU as 16-bit generic, aka
	 * data internally as generic data, aka passthrough mode:
	 * passthrough mode.
	 * - raw bayer formats
	 * - the sensor bus is 16-bit parallel
	 */
	 */
	switch (image.pix.pixelformat) {
	case V4L2_PIX_FMT_SBGGR8:
	case V4L2_PIX_FMT_SGBRG8:
	case V4L2_PIX_FMT_SGRBG8:
	case V4L2_PIX_FMT_SRGGB8:
		burst_size = 8;
		passthrough = true;
		passthrough_bits = 8;
		break;
	case V4L2_PIX_FMT_SBGGR16:
	case V4L2_PIX_FMT_SGBRG16:
	case V4L2_PIX_FMT_SGRBG16:
	case V4L2_PIX_FMT_SRGGB16:
		burst_size = 4;
		passthrough = true;
		passthrough_bits = 16;
		break;
	default:
		burst_size = (image.pix.width & 0xf) ? 8 : 16;
		passthrough = (sensor_ep->bus_type != V4L2_MBUS_CSI2 &&
		passthrough = (sensor_ep->bus_type != V4L2_MBUS_CSI2 &&
			       sensor_ep->bus.parallel.bus_width >= 16);
			       sensor_ep->bus.parallel.bus_width >= 16);
		passthrough_bits = 16;
		break;
	}


	if (passthrough)
	if (passthrough) {
		ipu_cpmem_set_format_passthrough(priv->idmac_ch, 16);
		ipu_cpmem_set_resolution(priv->idmac_ch, image.rect.width,
					 image.rect.height);
		ipu_cpmem_set_stride(priv->idmac_ch, image.pix.bytesperline);
		ipu_cpmem_set_buffer(priv->idmac_ch, 0, image.phys0);
		ipu_cpmem_set_buffer(priv->idmac_ch, 1, image.phys1);
		ipu_cpmem_set_format_passthrough(priv->idmac_ch,
						 passthrough_bits);
	} else {
		ret = ipu_cpmem_set_image(priv->idmac_ch, &image);
		if (ret)
			goto unsetup_vb2;
	}

	ipu_cpmem_set_burstsize(priv->idmac_ch, burst_size);


	/*
	/*
	 * Set the channel for the direct CSI-->memory via SMFC
	 * Set the channel for the direct CSI-->memory via SMFC
@@ -800,6 +829,7 @@ static int csi_link_validate(struct v4l2_subdev *sd,
{
{
	struct csi_priv *priv = v4l2_get_subdevdata(sd);
	struct csi_priv *priv = v4l2_get_subdevdata(sd);
	struct v4l2_fwnode_endpoint *sensor_ep;
	struct v4l2_fwnode_endpoint *sensor_ep;
	const struct imx_media_pixfmt *incc;
	struct imx_media_subdev *sensor;
	struct imx_media_subdev *sensor;
	bool is_csi2;
	bool is_csi2;
	int ret;
	int ret;
@@ -820,6 +850,16 @@ static int csi_link_validate(struct v4l2_subdev *sd,
	priv->sensor = sensor;
	priv->sensor = sensor;
	sensor_ep = &priv->sensor->sensor_ep;
	sensor_ep = &priv->sensor->sensor_ep;
	is_csi2 = (sensor_ep->bus_type == V4L2_MBUS_CSI2);
	is_csi2 = (sensor_ep->bus_type == V4L2_MBUS_CSI2);
	incc = priv->cc[CSI_SINK_PAD];

	if (priv->dest != IPU_CSI_DEST_IDMAC &&
	    (incc->bayer || (!is_csi2 &&
			     sensor_ep->bus.parallel.bus_width >= 16))) {
		v4l2_err(&priv->sd,
			 "bayer/16-bit parallel buses must go to IDMAC pad\n");
		ret = -EINVAL;
		goto out;
	}


	if (is_csi2) {
	if (is_csi2) {
		int vc_num = 0;
		int vc_num = 0;
@@ -844,7 +884,7 @@ static int csi_link_validate(struct v4l2_subdev *sd,


	/* select either parallel or MIPI-CSI2 as input to CSI */
	/* select either parallel or MIPI-CSI2 as input to CSI */
	ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
	ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);

out:
	mutex_unlock(&priv->lock);
	mutex_unlock(&priv->lock);
	return ret;
	return ret;
}
}