Exemplo n.º 1
0
static int fimc_querycap(struct file *filp, void *fh,
			 struct v4l2_capability *cap)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;

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

	strcpy(cap->driver, "SEC FIMC Driver");
	strlcpy(cap->card, ctrl->vd->name, sizeof(cap->card));
	sprintf(cap->bus_info, "FIMC AHB-bus");

	cap->version = 0;
#ifdef CONFIG_SLP
#ifdef CONFIG_SLP_DMABUF
	cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
			V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING |
			V4L2_CAP_VIDEO_OUTPUT_MPLANE |
			V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_SHARE_FD);
#else
	cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
				V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING |
				V4L2_CAP_SHARE_PADDR);
#endif
#else
	cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
				V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING);
#endif

	return 0;
}
Exemplo n.º 2
0
int fimc_g_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;

	ctx = &ctrl->out->ctx[ctx_id];

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

	f->fmt.win = ctx->win;

	return 0;
}
Exemplo n.º 3
0
int fimc_try_fmt_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;

	u32 is_rotate = 0;
	ctx = &ctrl->out->ctx[ctx_id];

	fimc_info1("%s: top(%d) left(%d) width(%d) height(%d)\n", __func__,
			f->fmt.win.w.top, f->fmt.win.w.left,
			f->fmt.win.w.width, f->fmt.win.w.height);

	if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF ||
		(ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF))
		return 0;

	/* Check Overlay Size : Overlay size must be smaller than LCD size. */
	is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
	if (is_rotate & FIMC_ROT) {	/* Landscape mode */
		if (f->fmt.win.w.width > ctrl->fb.lcd_vres) {
			fimc_warn("The width is changed %d -> %d\n",
				f->fmt.win.w.width, ctrl->fb.lcd_vres);
				f->fmt.win.w.width = ctrl->fb.lcd_vres;
		}

		if (f->fmt.win.w.height > ctrl->fb.lcd_hres) {
			fimc_warn("The height is changed %d -> %d\n",
				f->fmt.win.w.height, ctrl->fb.lcd_hres);
				f->fmt.win.w.height = ctrl->fb.lcd_hres;
		}
	} else {			/* Portrait mode */
		if (f->fmt.win.w.width > ctrl->fb.lcd_hres) {
			fimc_warn("The width is changed %d -> %d\n",
				f->fmt.win.w.width, ctrl->fb.lcd_hres);
				f->fmt.win.w.width = ctrl->fb.lcd_hres;
		}

		if (f->fmt.win.w.height > ctrl->fb.lcd_vres) {
			fimc_warn("The height is changed %d -> %d\n",
				f->fmt.win.w.height, ctrl->fb.lcd_vres);
				f->fmt.win.w.height = ctrl->fb.lcd_vres;
		}
	}

	return 0;
}
Exemplo n.º 4
0
static int fimc_querycap(struct file *filp, void *fh,
			 struct v4l2_capability *cap)
{
	struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;

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

	strcpy(cap->driver, "SEC FIMC Driver");
	strlcpy(cap->card, ctrl->vd->name, sizeof(cap->card));
	sprintf(cap->bus_info, "FIMC AHB-bus");

	cap->version = 0;
	cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
				V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING);

	return 0;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int fimc_g_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, format;

	ctx = &ctrl->out->ctx[ctx_id];

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

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

	fb->fmt.width = ctx->fbuf.fmt.width;
	fb->fmt.height = ctx->fbuf.fmt.height;
	fb->fmt.pixelformat = ctx->fbuf.fmt.pixelformat;
	format = ctx->fbuf.fmt.pixelformat;

	switch (format) {
	case V4L2_PIX_FMT_YUV420: /* fall through */
	case V4L2_PIX_FMT_YVU420: /* 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;
	fb->fmt.bytesperline = ctx->fbuf.fmt.bytesperline;
	fb->fmt.sizeimage = ctx->fbuf.fmt.sizeimage;
	fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
	fb->fmt.priv = 0;

	return 0;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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;

}
Exemplo n.º 11
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_NV21: 	/* fall through */
		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_NV21:		/* fall through */
		case V4L2_PIX_FMT_YUV420:	/* fall through */
		case V4L2_PIX_FMT_YVU420:	/* 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 {
		ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
	}

	return 0;
}