Exemple #1
0
static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct sh_mobile_ceu_dev *pcdev = ici->priv;
	unsigned long camera_flags, common_flags;

	camera_flags = icd->ops->query_bus_param(icd);
	common_flags = soc_camera_bus_param_compatible(camera_flags,
						       make_bus_param(pcdev));
	if (!common_flags)
		return -EINVAL;

	return 0;
}
static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
				    const unsigned int depth)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct mx3_camera_dev *mx3_cam = ici->priv;
	unsigned long bus_flags, camera_flags;
	int ret = test_platform_param(mx3_cam, depth, &bus_flags);

	dev_dbg(icd->dev.parent, "request bus width %d bit: %d\n", depth, ret);

	if (ret < 0)
		return ret;

	camera_flags = icd->ops->query_bus_param(icd);

	ret = soc_camera_bus_param_compatible(camera_flags, bus_flags);
	if (ret < 0)
		dev_warn(icd->dev.parent,
			 "Flags incompatible: camera %lx, host %lx\n",
			 camera_flags, bus_flags);

	return ret;
}
Exemple #3
0
static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
	struct mx1_camera_dev *pcdev = ici->priv;
	unsigned long camera_flags, common_flags;
	unsigned int csicr1;
	int ret;

	camera_flags = icd->ops->query_bus_param(icd);

	/* MX1 supports only 8bit buswidth */
	common_flags = soc_camera_bus_param_compatible(camera_flags,
						       CSI_BUS_FLAGS);
	if (!common_flags)
		return -EINVAL;

	/* Make choises, based on platform choice */
	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
		(common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
			if (!pcdev->pdata ||
			     pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
				common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
			else
				common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
	}

	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
		(common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
			if (!pcdev->pdata ||
			     pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
				common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
			else
				common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
	}

	if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
		(common_flags & SOCAM_DATA_ACTIVE_LOW)) {
			if (!pcdev->pdata ||
			     pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
				common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
			else
				common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
	}

	ret = icd->ops->set_bus_param(icd, common_flags);
	if (ret < 0)
		return ret;

	csicr1 = __raw_readl(pcdev->base + CSICR1);

	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
		csicr1 |= CSICR1_REDGE;
	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
		csicr1 |= CSICR1_SOF_POL;
	if (common_flags & SOCAM_DATA_ACTIVE_LOW)
		csicr1 |= CSICR1_DATA_POL;

	__raw_writel(csicr1, pcdev->base + CSICR1);

	return 0;
}
static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
		__u32 pixfmt)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct omap1_cam_dev *pcdev = ici->priv;
	struct device *dev = icd->dev.parent;
	const struct soc_camera_format_xlate *xlate;
	const struct soc_mbus_pixelfmt *fmt;
	unsigned long camera_flags, common_flags;
	u32 ctrlclock, mode;
	int ret;

	camera_flags = icd->ops->query_bus_param(icd);

	common_flags = soc_camera_bus_param_compatible(camera_flags,
			SOCAM_BUS_FLAGS);
	if (!common_flags)
		return -EINVAL;

	/* Make choices, possibly based on platform configuration */
	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
			(common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
		if (!pcdev->pdata ||
				pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING)
			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
		else
			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
	}

	ret = icd->ops->set_bus_param(icd, common_flags);
	if (ret < 0)
		return ret;

	ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
	if (ctrlclock & LCLK_EN)
		CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);

	if (common_flags & SOCAM_PCLK_SAMPLE_RISING) {
		dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n");
		ctrlclock |= POLCLK;
	} else {
		dev_dbg(dev, "CTRLCLOCK_REG &= ~POLCLK\n");
		ctrlclock &= ~POLCLK;
	}
	CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);

	if (ctrlclock & LCLK_EN)
		CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);

	/* select bus endianess */
	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
	fmt = xlate->host_fmt;

	mode = CAM_READ(pcdev, MODE) & ~(RAZ_FIFO | IRQ_MASK | DMA);
	if (fmt->order == SOC_MBUS_ORDER_LE) {
		dev_dbg(dev, "MODE_REG &= ~ORDERCAMD\n");
		CAM_WRITE(pcdev, MODE, mode & ~ORDERCAMD);
	} else {
		dev_dbg(dev, "MODE_REG |= ORDERCAMD\n");
		CAM_WRITE(pcdev, MODE, mode | ORDERCAMD);
	}

	return 0;
}
Exemple #5
0
static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
		__u32 pixfmt)
{
	struct soc_camera_host *ici =
		to_soc_camera_host(icd->dev.parent);
	struct mx2_camera_dev *pcdev = ici->priv;
	unsigned long camera_flags, common_flags;
	int ret = 0;
	int bytesperline;
	u32 csicr1 = pcdev->csicr1;

	camera_flags = icd->ops->query_bus_param(icd);

	common_flags = soc_camera_bus_param_compatible(camera_flags,
				MX2_BUS_FLAGS);
	if (!common_flags)
		return -EINVAL;

	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
		if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
		else
			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
	}

	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
		if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
		else
			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
	}

	ret = icd->ops->set_bus_param(icd, common_flags);
	if (ret < 0)
		return ret;

	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
		csicr1 |= CSICR1_REDGE;
	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
		csicr1 |= CSICR1_INV_PCLK;
	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
		csicr1 |= CSICR1_SOF_POL;
	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
		csicr1 |= CSICR1_HSYNC_POL;
	if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
		csicr1 |= CSICR1_SWAP16_EN;
	if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
		csicr1 |= CSICR1_EXT_VSYNC;
	if (pcdev->platform_flags & MX2_CAMERA_CCIR)
		csicr1 |= CSICR1_CCIR_EN;
	if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE)
		csicr1 |= CSICR1_CCIR_MODE;
	if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK)
		csicr1 |= CSICR1_GCLK_MODE;
	if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
		csicr1 |= CSICR1_INV_DATA;
	if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB)
		csicr1 |= CSICR1_PACK_DIR;

	pcdev->csicr1 = csicr1;

	bytesperline = soc_mbus_bytes_per_line(icd->user_width,
			icd->current_fmt->host_fmt);
	if (bytesperline < 0)
		return bytesperline;

	if (mx27_camera_emma(pcdev)) {
		ret = mx27_camera_emma_prp_reset(pcdev);
		if (ret)
			return ret;

		if (pcdev->discard_buffer)
			dma_free_coherent(ici->v4l2_dev.dev,
				pcdev->discard_size, pcdev->discard_buffer,
				pcdev->discard_buffer_dma);

		/*
		 * I didn't manage to properly enable/disable the prp
		 * on a per frame basis during running transfers,
		 * thus we allocate a buffer here and use it to
		 * discard frames when no buffer is available.
		 * Feel free to work on this ;)
		 */
		pcdev->discard_size = icd->user_height * bytesperline;
		pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
				pcdev->discard_size, &pcdev->discard_buffer_dma,
				GFP_KERNEL);
		if (!pcdev->discard_buffer)
			return -ENOMEM;

		mx27_camera_emma_buf_init(icd, bytesperline);
	} else if (cpu_is_mx25()) {
		writel((bytesperline * icd->user_height) >> 2,
				pcdev->base_csi + CSIRXCNT);
		writel((bytesperline << 16) | icd->user_height,
				pcdev->base_csi + CSIIMAG_PARA);
	}

	writel(pcdev->csicr1, pcdev->base_csi + CSICR1);

	return 0;
}
static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct mx3_camera_dev *mx3_cam = ici->priv;
	unsigned long bus_flags, camera_flags, common_flags;
	u32 dw, sens_conf;
	const struct soc_mbus_pixelfmt *fmt;
	int buswidth;
	int ret;
	const struct soc_camera_format_xlate *xlate;
	struct device *dev = icd->dev.parent;

	fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
	if (!fmt)
		return -EINVAL;

	buswidth = fmt->bits_per_sample;
	ret = test_platform_param(mx3_cam, buswidth, &bus_flags);

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

	dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret);

	if (ret < 0)
		return ret;

	camera_flags = icd->ops->query_bus_param(icd);

	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
	dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
		camera_flags, bus_flags, common_flags);
	if (!common_flags) {
		dev_dbg(dev, "no common flags");
		return -EINVAL;
	}

	/* Make choices, based on platform preferences */
	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
		if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
		else
			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
	}

	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
		if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
		else
			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
	}

	if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
	    (common_flags & SOCAM_DATA_ACTIVE_LOW)) {
		if (mx3_cam->platform_flags & MX3_CAMERA_DP)
			common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
		else
			common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
	}

	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
		if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
		else
			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
	}

	/*
	 * Make the camera work in widest common mode, we'll take care of
	 * the rest
	 */
	if (common_flags & SOCAM_DATAWIDTH_15)
		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
			SOCAM_DATAWIDTH_15;
	else if (common_flags & SOCAM_DATAWIDTH_10)
		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
			SOCAM_DATAWIDTH_10;
	else if (common_flags & SOCAM_DATAWIDTH_8)
		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
			SOCAM_DATAWIDTH_8;
	else
		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
			SOCAM_DATAWIDTH_4;

	ret = icd->ops->set_bus_param(icd, common_flags);
	if (ret < 0) {
		dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n",
			common_flags, ret);
		return ret;
	}

	/*
	 * So far only gated clock mode is supported. Add a line
	 *	(3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) |
	 * below and select the required mode when supporting other
	 * synchronisation protocols.
	 */
	sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) &
		~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) |
		  (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) |
		  (1 << CSI_SENS_CONF_DATA_POL_SHIFT) |
		  (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) |
		  (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) |
		  (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT));

	/* TODO: Support RGB and YUV formats */

	/* This has been set in mx3_camera_activate(), but we clear it above */
	sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER;

	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
		sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
		sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
		sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
	if (common_flags & SOCAM_DATA_ACTIVE_LOW)
		sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;

	/* Just do what we're asked to do */
	switch (xlate->host_fmt->bits_per_sample) {
	case 4:
		dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
		break;
	case 8:
		dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
		break;
	case 10:
		dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
		break;
	default:
		/*
		 * Actually it can only be 15 now, default is just to silence
		 * compiler warnings
		 */
	case 15:
		dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
	}

	csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);

	dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw);

	return 0;
}
Exemple #7
0
static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
				       __u32 pixfmt)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	struct sh_mobile_ceu_dev *pcdev = ici->priv;
	int ret;
	unsigned long camera_flags, common_flags, value;
	int yuv_lineskip;
	struct sh_mobile_ceu_cam *cam = icd->host_priv;
	u32 capsr = capture_save_reset(pcdev);

	camera_flags = icd->ops->query_bus_param(icd);
	common_flags = soc_camera_bus_param_compatible(camera_flags,
						       make_bus_param(pcdev));
	if (!common_flags)
		return -EINVAL;

	ret = icd->ops->set_bus_param(icd, common_flags);
	if (ret < 0)
		return ret;

	switch (common_flags & SOCAM_DATAWIDTH_MASK) {
	case SOCAM_DATAWIDTH_8:
		pcdev->is_16bit = 0;
		break;
	case SOCAM_DATAWIDTH_16:
		pcdev->is_16bit = 1;
		break;
	default:
		return -EINVAL;
	}

	ceu_write(pcdev, CRCNTR, 0);
	ceu_write(pcdev, CRCMPR, 0);

	value = 0x00000010; 
	yuv_lineskip = 0;

	switch (icd->current_fmt->fourcc) {
	case V4L2_PIX_FMT_NV12:
	case V4L2_PIX_FMT_NV21:
		yuv_lineskip = 1; 
		
	case V4L2_PIX_FMT_NV16:
	case V4L2_PIX_FMT_NV61:
		switch (cam->camera_fmt->fourcc) {
		case V4L2_PIX_FMT_UYVY:
			value = 0x00000000; 
			break;
		case V4L2_PIX_FMT_VYUY:
			value = 0x00000100; 
			break;
		case V4L2_PIX_FMT_YUYV:
			value = 0x00000200; 
			break;
		case V4L2_PIX_FMT_YVYU:
			value = 0x00000300; 
			break;
		default:
			BUG();
		}
	}

	if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 ||
	    icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61)
		value ^= 0x00000100; 

	value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
	value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
	value |= pcdev->is_16bit ? 1 << 12 : 0;
	ceu_write(pcdev, CAMCR, value);

	ceu_write(pcdev, CAPCR, 0x00300000);
	ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0);

	sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height);
	mdelay(1);

	ceu_write(pcdev, CFLCR, pcdev->cflcr);

	
	value = 0x00000017;
	if (yuv_lineskip)
		value &= ~0x00000010; 

	ceu_write(pcdev, CDOCR, value);
	ceu_write(pcdev, CFWCR, 0); 

	dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u\n",
		pixfmt & 0xff, (pixfmt >> 8) & 0xff,
		(pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff,
		icd->user_width, icd->user_height);

	capture_restore(pcdev, capsr);

	
	return 0;
}