Ejemplo n.º 1
0
int fimc_hwset_input_colorspace(struct fimc_control *ctrl, u32 pixelformat)
{
	u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
	cfg &= ~S3C_MSCTRL_INFORMAT_RGB;

	/* Color format setting */
	switch (pixelformat) {
	case V4L2_PIX_FMT_YUV420:	/* fall through */
	case V4L2_PIX_FMT_NV12:		/* fall through */
	case V4L2_PIX_FMT_NV12T:
		cfg |= S3C_MSCTRL_INFORMAT_YCBCR420;
		break;
	case V4L2_PIX_FMT_YUYV:
		cfg |= S3C_MSCTRL_INFORMAT_YCBCR422_1PLANE;
		break;
	case V4L2_PIX_FMT_RGB565:	/* fall through */
	case V4L2_PIX_FMT_RGB32:
		cfg |= S3C_MSCTRL_INFORMAT_RGB;
		break;
	default:
		fimc_err("%s: Invalid pixelformt : %d\n",
				__func__, pixelformat);
		return -EINVAL;
	}

	writel(cfg, ctrl->regs + S3C_MSCTRL);

	return 0;
}
Ejemplo n.º 2
0
int fimc_hwset_camera_polarity(struct fimc_control *ctrl)
{
	struct s3c_platform_camera *cam = ctrl->cam;
	u32 cfg;

	if (!cam) {
		fimc_err("%s: no active camera\n", __func__);
		return -ENODEV;
	}

	cfg = readl(ctrl->regs + S3C_CIGCTRL);

	cfg &= ~(S3C_CIGCTRL_INVPOLPCLK | S3C_CIGCTRL_INVPOLVSYNC |
		 S3C_CIGCTRL_INVPOLHREF | S3C_CIGCTRL_INVPOLHSYNC);

	if (cam->inv_pclk)
		cfg |= S3C_CIGCTRL_INVPOLPCLK;

	if (cam->inv_vsync)
		cfg |= S3C_CIGCTRL_INVPOLVSYNC;

	if (cam->inv_href)
		cfg |= S3C_CIGCTRL_INVPOLHREF;

	if (cam->inv_hsync)
		cfg |= S3C_CIGCTRL_INVPOLHSYNC;

	writel(cfg, ctrl->regs + S3C_CIGCTRL);

	return 0;
}
Ejemplo n.º 3
0
int fimc_hw_wait_stop_input_dma(struct fimc_control *ctrl)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
	u32 status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
	int i = FIMC_FIFOOFF_CNT, j = FIMC_FIFOOFF_CNT;

	if (pdata->hw_ver == 0x40)
		return 0;

	while (status && i--) {
		cfg = readl(ctrl->regs + S3C_MSCTRL);
		status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
	}

	cfg = readl(ctrl->regs + S3C_CISTATUS);
	status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
	while (status && j--) {
		cfg = readl(ctrl->regs + S3C_CISTATUS);
		status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
	}

	if ((i < 1) || (j < 1)) {
		fimc_err("Fail : %s\n", __func__);
		return -EBUSY;
	} else {
		return 0;
	}
}
Ejemplo n.º 4
0
static int fimc_check_pos(struct fimc_control *ctrl,
			  struct fimc_ctx *ctx,
			  struct v4l2_format *f)
{
	if (ctx->win.w.width != f->fmt.win.w.width) {
		fimc_err("%s: cannot change width(%d,%d)\n", __func__,
				ctx->win.w.width, f->fmt.win.w.width);
		return -EINVAL;
	} else if (ctx->win.w.height != f->fmt.win.w.height) {
		fimc_err("%s: cannot change height(%d,%d)\n", __func__,
				ctx->win.w.height, f->fmt.win.w.height);
		return -EINVAL;
	}

	return 0;
}
Ejemplo n.º 5
0
int fimc_hwset_camera_offset(struct fimc_control *ctrl)
{
	struct s3c_platform_camera *cam = ctrl->cam;
	struct v4l2_rect *rect = &cam->window;
	u32 cfg, h1, h2, v1, v2;

	if (!cam) {
		fimc_err("%s: no active camera\n", __func__);
		return -ENODEV;
	}

	h1 = rect->left;
	h2 = cam->width - rect->width - rect->left;
	v1 = rect->top;
	v2 = cam->height - rect->height - rect->top;

	cfg = readl(ctrl->regs + S3C_CIWDOFST);
	cfg &= ~(S3C_CIWDOFST_WINHOROFST_MASK | S3C_CIWDOFST_WINVEROFST_MASK);
	cfg |= S3C_CIWDOFST_WINHOROFST(h1);
	cfg |= S3C_CIWDOFST_WINVEROFST(v1);
	cfg |= S3C_CIWDOFST_WINOFSEN;
	writel(cfg, ctrl->regs + S3C_CIWDOFST);

	cfg = 0;
	cfg |= S3C_CIWDOFST2_WINHOROFST2(h2);
	cfg |= S3C_CIWDOFST2_WINVEROFST2(v2);
	writel(cfg, ctrl->regs + S3C_CIWDOFST2);

	return 0;
}
Ejemplo n.º 6
0
int fimc_hwset_input_yuv(struct fimc_control *ctrl, u32 pixelformat)
{
	u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
	cfg &= ~(S3C_MSCTRL_ORDER2P_SHIFT_MASK | S3C_MSCTRL_C_INT_IN_2PLANE |
						S3C_MSCTRL_ORDER422_YCBYCR);

	switch (pixelformat) {
	case V4L2_PIX_FMT_YUV420:
		cfg |= S3C_MSCTRL_C_INT_IN_3PLANE;
		break;
	case V4L2_PIX_FMT_YUYV:		/* fall through */
		cfg |= S3C_MSCTRL_ORDER422_YCBYCR;
		break;
	case V4L2_PIX_FMT_NV12:		/* fall through */
	case V4L2_PIX_FMT_NV12T:
		cfg |= S3C_MSCTRL_ORDER2P_LSB_CBCR;
		cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
		break;
	case V4L2_PIX_FMT_RGB565:	/* fall through */
	case V4L2_PIX_FMT_RGB32:
		break;
	default:
		fimc_err("%s: Invalid pixelformt : %d\n",
				__func__, pixelformat);
	}

	writel(cfg, ctrl->regs + S3C_MSCTRL);

	return 0;
}
int fimc43_hwset_camera_type(struct fimc_control *ctrl)
{
	struct s3c_platform_camera *cam = ctrl->cam;
	u32 cfg;

	if (!cam) {
		fimc_err("%s: no active camera\n", __func__);
		return -ENODEV;
	}

	cfg = readl(ctrl->regs + S3C_CIGCTRL);
	cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
		S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK |
		S3C_CIGCTRL_SELWB_CAMIF_MASK);

	/* Interface selection */
	if (cam->id == CAMERA_WB) {
		cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
	} else if (cam->type == CAM_TYPE_MIPI) {
		cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;

		/* C110/V210 Support only MIPI A support */
		cfg |= S3C_CIGCTRL_SELCAM_MIPI_A;

		/* FIXME: Temporary MIPI CSIS Data 32 bit aligned */
		if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
			writel((MIPI_USER_DEF_PACKET_1 | (0x1 << 8)),
					ctrl->regs + S3C_CSIIMGFMT);
		else
			writel(cam->fmt | (0x1 << 8),
					ctrl->regs + S3C_CSIIMGFMT);
	} else if (cam->type == CAM_TYPE_ITU) {
		if (cam->id == CAMERA_PAR_A)
			cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
		else
			cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
		/* switch to ITU interface */
		cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
	} else {
		fimc_err("%s: invalid camera bus type selected\n", __func__);
		return -EINVAL;
	}

	writel(cfg, ctrl->regs + S3C_CIGCTRL);

	return 0;
}
Ejemplo n.º 8
0
int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg;

	if (pdata->hw_ver != 0x40) {
		if (pixelformat == V4L2_PIX_FMT_YUV444) {
			cfg = readl(ctrl->regs + S3C_CIEXTEN);
			cfg |= S3C_CIEXTEN_YUV444_OUT;
			writel(cfg, ctrl->regs + S3C_CIEXTEN);

			return 0;
		} else {
			cfg = readl(ctrl->regs + S3C_CIEXTEN);
			cfg &= ~S3C_CIEXTEN_YUV444_OUT;
			writel(cfg, ctrl->regs + S3C_CIEXTEN);
		}
	}

	cfg = readl(ctrl->regs + S3C_CITRGFMT);
	cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK;

	switch (pixelformat) {
	case V4L2_PIX_FMT_JPEG:
		break;
	case V4L2_PIX_FMT_RGB565: /* fall through */
	case V4L2_PIX_FMT_RGB32:
		cfg |= S3C_CITRGFMT_OUTFORMAT_RGB;
		break;

	case V4L2_PIX_FMT_YUYV:		/* fall through */
	case V4L2_PIX_FMT_UYVY:		/* fall through */
	case V4L2_PIX_FMT_VYUY:		/* fall through */
	case V4L2_PIX_FMT_YVYU:
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
		break;

	case V4L2_PIX_FMT_NV16:		/* fall through */
	case V4L2_PIX_FMT_NV61:		/* fall through */
	case V4L2_PIX_FMT_YUV422P:
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422;
		break;

	case V4L2_PIX_FMT_YUV420:	/* fall through */
	case V4L2_PIX_FMT_NV12:		/* fall through */
	case V4L2_PIX_FMT_NV12T:	/* fall through */
	case V4L2_PIX_FMT_NV21:
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420;
		break;

	default:
		fimc_err("%s: invalid pixel format\n", __func__);
		break;
	}

	writel(cfg, ctrl->regs + S3C_CITRGFMT);

	return 0;
}
Ejemplo n.º 9
0
int fimc50_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
			      struct v4l2_rect *bounds,
			      struct v4l2_rect *crop)
{
	u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;

	if (crop->left || crop->top ||
		(bounds->width != crop->width) ||
		(bounds->height != crop->height)) {
		switch (pixelformat) {
		case V4L2_PIX_FMT_YUYV:		/* fall through */
		case V4L2_PIX_FMT_UYVY:		/* fall through */
		case V4L2_PIX_FMT_YVYU:		/* fall through */
		case V4L2_PIX_FMT_VYUY:		/* fall through */
		case V4L2_PIX_FMT_RGB565:
			cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
			cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
			break;
		case V4L2_PIX_FMT_RGB32:
			cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
			cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
			break;
		case V4L2_PIX_FMT_NV12: /* fall through*/
		case V4L2_PIX_FMT_NV21: /* fall through*/
		case V4L2_PIX_FMT_NV12T:
			cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
			cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
			cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
			cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
			break;
		case V4L2_PIX_FMT_NV16:		/* fall through */
		case V4L2_PIX_FMT_NV61:		
			cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
			cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
			cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
			cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
			break;
		case V4L2_PIX_FMT_YUV420:
			cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
			cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
			cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
			cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
			cfg_cr |= S3C_CIICROFF_HORIZONTAL(crop->left);
			cfg_cr |= S3C_CIICROFF_VERTICAL(crop->top);
			break;
		default:
			fimc_err("%s: Invalid pixelformt : %d\n",
					__func__, pixelformat);
		}
	}

	writel(cfg_y, ctrl->regs + S3C_CIIYOFF);
	writel(cfg_cb, ctrl->regs + S3C_CIICBOFF);
	writel(cfg_cr, ctrl->regs + S3C_CIICROFF);

	return 0;
}
Ejemplo n.º 10
0
int fimc_s_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
	struct fimc_ctx *ctx;
	int ret = -1;
	ctx = &ctrl->out->ctx[ctx_id];

	fimc_info1("%s: called\n", __func__);

	switch (ctx->status) {
	case FIMC_STREAMON:
		ret = fimc_check_pos(ctrl, ctx, f);
		if (ret < 0) {
			fimc_err("When FIMC is running, "
				"you can only move the position.\n");
			return -EBUSY;
		}

		ret = fimc_try_fmt_overlay(filp, fh, f);
		if (ret < 0)
			return ret;

		ctx->win = f->fmt.win;
		fimc_change_fifo_position(ctrl, ctx);

		break;
	case FIMC_STREAMOFF:
		ret = fimc_try_fmt_overlay(filp, fh, f);
		if (ret < 0)
			return ret;
		ctx->win = f->fmt.win;

		break;

	default:
		fimc_err("FIMC is running\n");
		fimc_err("%s::FIMC is running(%d)\n", __func__, ctx->status);
		return -EBUSY;
	}

	return ret;
}
Ejemplo n.º 11
0
static inline int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma)
{
	struct fimc_control *ctrl = filp->private_data;
	u32 start_phy_addr = 0;
	u32 size = vma->vm_end - vma->vm_start;
	u32 pfn, idx = vma->vm_pgoff;
	u32 buf_length = 0;
	int pri_data = 0;

	buf_length = ctrl->out->src[idx].length[FIMC_ADDR_Y] + \
				ctrl->out->src[idx].length[FIMC_ADDR_CB] + \
				ctrl->out->src[idx].length[FIMC_ADDR_CR];
	if (size > buf_length) {
		fimc_err("Requested mmap size is too big\n");
		return -EINVAL;
	}

	pri_data = (ctrl->id * 0x10) + idx;
	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	vma->vm_flags |= VM_RESERVED;
	vma->vm_ops = &fimc_mmap_ops;
	vma->vm_private_data = (void *)pri_data;

	if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
		fimc_err("writable mapping must be shared\n");
		return -EINVAL;
	}

	start_phy_addr = ctrl->out->src[idx].base[FIMC_ADDR_Y];
	pfn = __phys_to_pfn(start_phy_addr);

	if (remap_pfn_range(vma, vma->vm_start, pfn, size,
						vma->vm_page_prot)) {
		fimc_err("mmap fail\n");
		return -EINVAL;
	}

	vma->vm_ops->open(vma);

	ctrl->out->src[idx].flags |= V4L2_BUF_FLAG_MAPPED;

	return 0;
}
Ejemplo n.º 12
0
int fimc_hwset_camera_type(struct fimc_control *ctrl)
{
	struct s3c_platform_camera *cam = ctrl->cam;
	u32 cfg;

	if (!cam) {
		fimc_err("%s: no active camera\n", __func__);
		return -ENODEV;
	}

	cfg = readl(ctrl->regs + S3C_CIGCTRL);
	cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
		S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK |
		S3C_CIGCTRL_SELWB_CAMIF_MASK);

	/* Interface selection */
	if (cam->id == CAMERA_WB) {
		cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
	} else if (cam->type == CAM_TYPE_MIPI) {
		cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;

		/* FIXME: temporary only A support */
		cfg |= S3C_CIGCTRL_SELCAM_MIPI_A;

		/* FIXME: temporary hardcoded value used */
		writel(cam->fmt | (0x1 << 8), ctrl->regs + S3C_CSIIMGFMT);
	} else if (cam->type == CAM_TYPE_ITU) {
		if (cam->id == CAMERA_PAR_A)
			cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
		else
			cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
		/* switch to ITU interface */
		cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
	} else {
		fimc_err("%s: invalid camera bus type selected\n", __func__);
		return -EINVAL;
	}

	writel(cfg, ctrl->regs + S3C_CIGCTRL);

	return 0;
}
Ejemplo n.º 13
0
static int fimc_g_ext_ctrls(struct file *filp, void *fh, struct v4l2_ext_controls *c)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ret = -1;

	if (ctrl->cap != NULL) {
		ret = fimc_g_ext_ctrls_capture(fh, c);
	} else {
		fimc_err("%s: Invalid case\n", __func__);
		return -EINVAL;
	}
	return ret;
}
Ejemplo n.º 14
0
static int fimc_streamoff(struct file *filp, void *fh, enum v4l2_buf_type i)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ret = -1;

	if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		ret = fimc_streamoff_capture(ctrl);
	} else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		ret = fimc_streamoff_output(fh);
	} else {
		fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
			"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
		ret = -EINVAL;
	}

	return ret;
}
Ejemplo n.º 15
0
static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ret = -1;

	if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		ret = fimc_querybuf_capture(ctrl, b);
	} else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		ret = fimc_querybuf_output(fh, b);
	} else {
		fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
			"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
		ret = -EINVAL;
	}

	return ret;
}
Ejemplo n.º 16
0
static int fimc_s_crop(struct file *filp, void *fh, struct v4l2_crop *a)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ret = -1;

	if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		ret = fimc_s_crop_capture(fh, a);
	} else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		ret = fimc_s_crop_output(fh, a);
	} else {
		fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
			"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
		ret = -EINVAL;
	}

	return ret;
}
Ejemplo n.º 17
0
static inline int fimc_mmap_out_dst(struct file *filp, struct vm_area_struct *vma, u32 idx)
{
	struct fimc_control *ctrl = filp->private_data;
	unsigned long pfn = 0, size;
	int ret = 0;

	size = vma->vm_end - vma->vm_start;

	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	vma->vm_flags |= VM_RESERVED;

	pfn = __phys_to_pfn(ctrl->out->dst[idx].base[0]);
	ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
	if (ret != 0)
		fimc_err("remap_pfn_range fail.\n");

	return ret;
}
Ejemplo n.º 18
0
static int fimc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	struct s3c_platform_fimc *pdata;
	int ret = -1;

	pdata = to_fimc_plat(ctrl->dev);

	if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		ret = fimc_streamon_capture(fh);
	} else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		ret = fimc_streamon_output(fh);
	} else {
		fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
			"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
		ret = -EINVAL;
	}

	return ret;
}
Ejemplo n.º 19
0
int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat)
{
	u32 cfg;

	cfg = readl(ctrl->regs + S3C_CITRGFMT);
	cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK;

	switch (pixelformat) {
	case V4L2_PIX_FMT_RGB565:	/* fall through */
	case V4L2_PIX_FMT_RGB32:
		cfg |= S3C_CITRGFMT_OUTFORMAT_RGB;
		break;

	case V4L2_PIX_FMT_YUYV:		/* fall through */
	case V4L2_PIX_FMT_UYVY:		/* fall through */
	case V4L2_PIX_FMT_VYUY:		/* fall through */
	case V4L2_PIX_FMT_YVYU:		/* fall through */
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
		break;

	case V4L2_PIX_FMT_YUV422P:
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422;
		break;

	case V4L2_PIX_FMT_YUV420:	/* fall through */
	case V4L2_PIX_FMT_NV12:		/* fall through */
	case V4L2_PIX_FMT_NV21:		/* fall through */
	case V4L2_PIX_FMT_NV16:		/* fall through */
	case V4L2_PIX_FMT_NV61:
		cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420;
		break;

	default:
		fimc_err("%s: invalid pixel format\n", __func__);
		break;
	}

	writel(cfg, ctrl->regs + S3C_CITRGFMT);

	return 0;
}
Ejemplo n.º 20
0
int fimc_hw_wait_winoff(struct fimc_control *ctrl)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg = readl(ctrl->regs + S3C_CISTATUS);
	u32 status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
	int i = FIMC_FIFOOFF_CNT;

	if (pdata->hw_ver == 0x40)
		return 0;

	while (status && i--) {
		cfg = readl(ctrl->regs + S3C_CISTATUS);
		status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
	}

	if (i < 1) {
		fimc_err("Fail : %s\n", __func__);
		return -EBUSY;
	} else
		return 0;
}
static int fimc_g_ctrl(struct file *filp, void *fh, struct v4l2_control *c)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	struct s3c_platform_fimc *pdata	= to_fimc_plat(ctrl->dev);
	int ret = -1;

	/* can get hw version at any time */
	if (c->id == V4L2_CID_FIMC_VERSION) {
		c->value = pdata->hw_ver;
		return 0;
	}

	if (ctrl->cap != NULL) {
		ret = fimc_g_ctrl_capture(fh, c);
	} else if (ctrl->out != NULL) {
		ret = fimc_g_ctrl_output(fh, c);
	} else {
		fimc_err("%s: Invalid case\n", __func__);
		return -EINVAL;
	}

	return ret;
}
Ejemplo n.º 22
0
static inline int fimc_resume_out(struct fimc_control *ctrl)
{
        int index = -1, ret = -1;

	switch (ctrl->out->overlay.mode) {
	case FIMC_OVERLAY_NONE:
		if (ctrl->status == FIMC_ON_IDLE_SLEEP) {
		        ret = fimc_outdev_set_param(ctrl);
		        if (ret < 0)
		                fimc_err("Fail: fimc_outdev_set_param\n");

			ctrl->status = FIMC_STREAMON_IDLE;
		} else if (ctrl->status == FIMC_OFF_SLEEP) {
			ctrl->status = FIMC_STREAMOFF;
		} else {
			fimc_err("%s: Undefined status : %d\n", 
						__func__, ctrl->status);
		}
		break;

	case FIMC_OVERLAY_DMA_AUTO:
		if (ctrl->status == FIMC_ON_IDLE_SLEEP) {
			fimc_outdev_resume_dma(ctrl);
		        ret = fimc_outdev_set_param(ctrl);
		        if (ret < 0)
		                fimc_err("Fail: fimc_outdev_set_param\n");

			ctrl->status = FIMC_STREAMON_IDLE;

		} else if (ctrl->status == FIMC_OFF_SLEEP) {
			ctrl->status = FIMC_STREAMOFF;
		} else {
			fimc_err("%s: Undefined status : %d\n", 
						__func__, ctrl->status);
		}

		break;

	case FIMC_OVERLAY_DMA_MANUAL:
		if (ctrl->status == FIMC_ON_IDLE_SLEEP) {
		        ret = fimc_outdev_set_param(ctrl);
		        if (ret < 0)
		                fimc_err("Fail: fimc_outdev_set_param\n");

			ctrl->status = FIMC_STREAMON_IDLE;

		} else if (ctrl->status == FIMC_OFF_SLEEP) {
			ctrl->status = FIMC_STREAMOFF;
		} else {
			fimc_err("%s: Undefined status : %d\n", 
						__func__, ctrl->status);
		}

		break;

	case FIMC_OVERLAY_FIFO:
		if (ctrl->status == FIMC_ON_SLEEP) {
		        ctrl->status = FIMC_READY_ON;

		        ret = fimc_outdev_set_param(ctrl);
		        if (ret < 0)
		                fimc_err("Fail: fimc_outdev_set_param\n");

#if defined(CONFIG_VIDEO_IPC)
	                if (ctrl->out->pix.field == V4L2_FIELD_INTERLACED_TB)
	                        ipc_start();
#endif
			index = ctrl->out->idx.active;
	                fimc_outdev_set_src_addr(ctrl, ctrl->out->src[index].base);

	                ret = fimc_start_fifo(ctrl);
	                if (ret < 0)
	                        fimc_err("Fail: fimc_start_fifo\n");

	                ctrl->status = FIMC_STREAMON;
		} else if (ctrl->status == FIMC_OFF_SLEEP) {
			ctrl->status = FIMC_STREAMOFF;
		} else {
			fimc_err("%s: Undefined status : %d\n", __func__, ctrl->status);
		}

		break;
	}

	return 0;
}
Ejemplo n.º 23
0
static inline u32 fimc_irq_out_dma(struct fimc_control *ctrl)
{
	struct fimc_buf_set buf_set;
	u32 next = 0, wakeup = 1;
	int idx = ctrl->out->idx.active;
	int ret = -1, i;

	if (ctrl->status == FIMC_READY_OFF) {
		ctrl->out->idx.active = -1;
		ctrl->status = FIMC_STREAMOFF;
		return wakeup;
	}

	/* Attach done buffer to outgoing queue. */
	ret = fimc_attach_out_queue(ctrl, idx);
	if (ret < 0)
		fimc_err("Failed: fimc_attach_out_queue\n");

	if(ctrl->out->overlay.mode == FIMC_OVERLAY_DMA_AUTO) {
		ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_WIN_ADDR, \
				(unsigned long)ctrl->out->dst[idx].base[FIMC_ADDR_Y]);
		if (ret < 0) {
			fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
			return -EINVAL;
		}

		if(ctrl->fb.is_enable == 0) {
			ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_WIN_ON, \
								(unsigned long)NULL);
			if (ret < 0) {
				fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n");
				return -EINVAL;
			}

			ctrl->fb.is_enable = 1;
		}
	}

	/* Detach buffer from incomming queue. */
	ret =  fimc_detach_in_queue(ctrl, &next);
	if (ret == 0) {	/* There is a buffer in incomming queue. */
		fimc_outdev_set_src_addr(ctrl, ctrl->out->src[next].base);

		memset(&buf_set, 0x00, sizeof(buf_set));
		buf_set.base[FIMC_ADDR_Y] = ctrl->out->dst[next].base[FIMC_ADDR_Y];

		for (i = 0; i < FIMC_PHYBUFS; i++)
			fimc_hwset_output_address(ctrl, &buf_set, i);
		
		ret = fimc_outdev_start_camif(ctrl);
		if (ret < 0)
			fimc_err("Fail: fimc_start_camif\n");

		ctrl->out->idx.active = next;
		ctrl->status = FIMC_STREAMON;
	} else {	/* There is no buffer in incomming queue. */
		ctrl->out->idx.active = -1;
		ctrl->status = FIMC_STREAMON_IDLE;
	}

	return wakeup;
}
Ejemplo n.º 24
0
static
struct fimc_control *fimc_register_controller(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct fimc_control *ctrl;
	struct resource *res;
	int id, mdev_id;

	id = pdev->id;
	mdev_id = S3C_MDEV_FIMC0 + id;
	pdata = to_fimc_plat(&pdev->dev);

	ctrl = get_fimc_ctrl(id);
	ctrl->id = id;
	ctrl->dev = &pdev->dev;
	ctrl->vd = &fimc_video_device[id];
	ctrl->vd->minor = id;

	/* alloc from bank1 as default */
	ctrl->mem.base = s3c_get_media_memory_bank(mdev_id, 1);
	ctrl->mem.size = s3c_get_media_memsize_bank(mdev_id, 1);
	ctrl->mem.curr = ctrl->mem.base;

	ctrl->status = FIMC_STREAMOFF;
	ctrl->limit = &fimc_limits[id];
	ctrl->log = FIMC_LOG_DEFAULT;

	sprintf(ctrl->name, "%s%d", FIMC_NAME, id);
	strcpy(ctrl->vd->name, ctrl->name);

	atomic_set(&ctrl->in_use, 0);
	mutex_init(&ctrl->lock);
	mutex_init(&ctrl->v4l2_lock);
	spin_lock_init(&ctrl->lock_in);
	spin_lock_init(&ctrl->lock_out);
	init_waitqueue_head(&ctrl->wq);

	/* get resource for io memory */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		fimc_err("%s: failed to get io memory region\n", __func__);
		return NULL;
	}

	/* request mem region */
	res = request_mem_region(res->start, res->end - res->start + 1,
			pdev->name);
	if (!res) {
		fimc_err("%s: failed to request io memory region\n", __func__);
		return NULL;
	}

	/* ioremap for register block */
	ctrl->regs = ioremap(res->start, res->end - res->start + 1);
	if (!ctrl->regs) {
		fimc_err("%s: failed to remap io region\n", __func__);
		return NULL;
	}

	/* irq */
	ctrl->irq = platform_get_irq(pdev, 0);
	if (request_irq(ctrl->irq, fimc_irq, IRQF_DISABLED, ctrl->name, ctrl))
		fimc_err("%s: request_irq failed\n", __func__);

	fimc_hwset_reset(ctrl);

	return ctrl;
}
Ejemplo n.º 25
0
/*
 * Assign v4l2 device and subdev to fimc
 * it is called per every fimc ctrl registering
 */
static int fimc_configure_subdev(struct platform_device *pdev, int id)
{
	struct s3c_platform_fimc *pdata;
	struct s3c_platform_camera *cam;
	struct i2c_adapter *i2c_adap;
	struct i2c_board_info *i2c_info;
	struct v4l2_subdev *sd;
	struct fimc_control *ctrl;
	unsigned short addr;
	char *name;

	ctrl = get_fimc_ctrl(id);
	pdata = to_fimc_plat(&pdev->dev);
	cam = pdata->camera[id];

	/* Subdev registration */
	if (cam) {
		i2c_adap = i2c_get_adapter(cam->i2c_busnum);
		if (!i2c_adap) {
			fimc_info1("subdev i2c_adapter missing-skip "
							"registration\n");
		}

		i2c_info = cam->info;
		if (!i2c_info) {
			fimc_err("%s: subdev i2c board info missing\n",
								__func__);
			return -ENODEV;
		}

		name = i2c_info->type;
		if (!name) {
			fimc_info1("subdev i2c dirver name missing-skip "
				"registration\n");
			return -ENODEV;
		}

		addr = i2c_info->addr;
		if (!addr) {
			fimc_info1("subdev i2c address missing-skip "
							"registration\n");
			return -ENODEV;
		}

		/*
		 * NOTE: first time subdev being registered,
		 * s_config is called and try to initialize subdev device
		 * but in this point, we are not giving MCLK and power to subdev
		 * so nothing happens but pass platform data through
		 */
		sd = v4l2_i2c_new_subdev_board(&ctrl->v4l2_dev, i2c_adap,
				name, i2c_info, &addr);
		if (!sd) {
			fimc_err("%s: v4l2 subdev board registering failed\n",
				__func__);
		}

		/* Assign camera device to fimc */
		fimc_dev->camera[cam->id] = cam;

		/* Assign subdev to proper camera device pointer */
		fimc_dev->camera[cam->id]->sd = sd;
	}

	return 0;
}
Ejemplo n.º 26
0
static int fimc_release(struct file *filp)
{
	struct fimc_control *ctrl = filp->private_data;
	struct s3c_platform_fimc *pdata;
	struct fimc_overlay_buf *buf;
	struct mm_struct *mm = current->mm;

	int ret = 0, i;

	ctrl->mem.curr = ctrl->mem.base;

	atomic_dec(&ctrl->in_use);
	filp->private_data = NULL;

	pdata = to_fimc_plat(ctrl->dev);

	/* FIXME: turning off actual working camera */
	if (ctrl->cam) {
		/* shutdown the MCLK */
		clk_disable(ctrl->cam->clk);

		/* shutdown */
		if (ctrl->cam->cam_power)
			ctrl->cam->cam_power(0);

		/* should be initialized at the next open */
		ctrl->cam->initialized = 0;
	}

	if (ctrl->cap) {
		for (i = 0; i < FIMC_CAPBUFS; i++) {
			fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 0);
			fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 1);
		}

		kfree(ctrl->cap);
		ctrl->cap = NULL;
	}

	if (ctrl->out) {
		if (ctrl->status != FIMC_STREAMOFF) {
			ret = fimc_outdev_stop_streaming(ctrl);
			if (ret < 0)
				fimc_err("Fail: fimc_stop_streaming\n");
			ctrl->status = FIMC_STREAMOFF;
		}

		buf = &ctrl->out->overlay.buf;

		for (i = 0; i < FIMC_OUTBUFS; i++) {
			if (buf->vir_addr[i]) {
				ret = do_munmap(mm, buf->vir_addr[i], buf->size[i]);
				if (ret < 0)
					fimc_err("%s: do_munmap fail\n", __func__);
			}
		}

		kfree(ctrl->out);
		ctrl->out = NULL;
	}

	if (pdata->clk_off)
		pdata->clk_off(to_platform_device(ctrl->dev), ctrl->clk);

	fimc_info1("%s: successfully released\n", __func__);

	return 0;
}
Ejemplo n.º 27
0
int fimc_s_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
	int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
	struct fimc_ctx *ctx;
	u32 bpp = 1;
	u32 format = fb->fmt.pixelformat;
	ctx = &ctrl->out->ctx[ctx_id];

	fimc_info1("%s: called. width(%d), height(%d)\n",
			__func__, fb->fmt.width, fb->fmt.height);

	ctx->fbuf.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
	ctx->fbuf.flags = 0;
	ctx->fbuf.base = fb->base;

	if (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF) {
		ctx->fbuf.fmt.width = fb->fmt.width;
		ctx->fbuf.fmt.height = fb->fmt.height;
		ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;

		switch (format) {
		case V4L2_PIX_FMT_YUV420: /* fall through */
		case V4L2_PIX_FMT_NV12:
			bpp = 1;
			break;
		case V4L2_PIX_FMT_RGB565:
			bpp = 2;
			break;
		case V4L2_PIX_FMT_RGB32:
			bpp = 4;
			break;
		}

		ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
		ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
		ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
		ctx->fbuf.fmt.priv = 0;
	} else if (fb->base) {
		ctx->fbuf.fmt.width = fb->fmt.width;
		ctx->fbuf.fmt.height = fb->fmt.height;
		ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;

		switch (format) {
		case V4L2_PIX_FMT_YUV420:	/* fall through */
		case V4L2_PIX_FMT_NV12:
			bpp = 1;
			break;
		case V4L2_PIX_FMT_RGB565:
			bpp = 2;
			break;
		case V4L2_PIX_FMT_RGB32:
			bpp = 4;
			break;
		}

		ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
		ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
		ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
		ctx->fbuf.fmt.priv = 0;

		ctx->overlay.mode = FIMC_OVLY_NONE_SINGLE_BUF;
	} else {
		int i;
		unsigned int bits_per_pixel = 0;
		struct s3cfb_window *win = NULL;
		ctx->overlay.fb_id = -1;

		for (i = 0; i < num_registered_fb; i++) {
			win = (struct s3cfb_window *)registered_fb[i]->par;
			if (win->id == ctrl->id) {
				ctx->overlay.fb_id = i;
				bits_per_pixel = registered_fb[i]->var.bits_per_pixel;
				fimc_info2("%s: overlay.fb_id = %d\n",
						__func__, ctx->overlay.fb_id);
				break;
			}
		}

		if (-1 == ctx->overlay.fb_id) {
			fimc_err("%s: fb[%d] is not registered. " \
					"must be registered for overlay\n",
					__func__, ctrl->id);
			return -1;
		}

		if (1 == win->enabled) {
			fimc_err("%s: fb[%d] is already being used. " \
					"must be not used for overlay\n",
					__func__, ctrl->id);
			return -1;
		}

		ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;

		switch (ctx->rotate) {
		case 0:
		case 180:
			ctx->fbuf.fmt.width = ctrl->fb.lcd_hres;
			ctx->fbuf.fmt.height = ctrl->fb.lcd_vres;
			break;

		case 90:
		case 270:
			ctx->fbuf.fmt.width = ctrl->fb.lcd_vres;
			ctx->fbuf.fmt.height = ctrl->fb.lcd_hres;
			break;
		}

		if (bits_per_pixel == 32)
			ctx->fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB32;
		else
			ctx->fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
	}

	return 0;
}
Ejemplo n.º 28
0
static int __devinit fimc_probe(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct fimc_control *ctrl;
	int ret;

	if (!fimc_dev) {
		fimc_dev = kzalloc(sizeof(*fimc_dev), GFP_KERNEL);
		if (!fimc_dev) {
			dev_err(&pdev->dev, "%s: not enough memory\n",
				__func__);
			goto err_fimc;
		}
	}

	ctrl = fimc_register_controller(pdev);
	if (!ctrl) {
		printk(KERN_ERR "%s: cannot register fimc\n", __func__);
		goto err_fimc;
	}

	pdata = to_fimc_plat(&pdev->dev);
	if (pdata->cfg_gpio)
		pdata->cfg_gpio(pdev);

	/* V4L2 device-subdev registration */
	ret = v4l2_device_register(&pdev->dev, &ctrl->v4l2_dev);
	if (ret) {
		fimc_err("%s: v4l2 device register failed\n", __func__);
		goto err_v4l2;
	}

	/* things to initialize once */
	if (!fimc_dev->initialized) {
		ret = fimc_init_global(pdev);
		if (ret)
			goto err_global;
	}

	/* v4l2 subdev configuration */
	ret = fimc_configure_subdev(pdev, ctrl->id);
	if (ret) {
		fimc_err("%s: subdev[%d] registering failed\n",
							__func__, ctrl->id);
	}

	/* video device register */
	ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);
	if (ret) {
		fimc_err("%s: cannot register video driver\n", __func__);
		goto err_global;
	}

	video_set_drvdata(ctrl->vd, ctrl);

	ret = device_create_file(&(pdev->dev), &dev_attr_log_level);
	if (ret < 0)
		fimc_err("failed to add sysfs entries\n");

	fimc_info1("controller %d registered successfully\n", ctrl->id);

	return 0;

err_global:
	clk_disable(ctrl->clk);
	clk_put(ctrl->clk);

err_v4l2:
	fimc_unregister_controller(pdev);

err_fimc:
	return -EINVAL;

}