示例#1
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;
	}
}
示例#2
0
int fimc_hwset_output_scan(struct fimc_control *ctrl,
			   struct v4l2_pix_format *fmt)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg;

	/* nothing to do: FIMC40 not supported interlaced and weave output */
	if (pdata->hw_ver == 0x40)
		return 0;

	cfg = readl(ctrl->regs + S3C_CISCCTRL);
	cfg &= ~S3C_CISCCTRL_SCAN_MASK;

	if (fmt->field == V4L2_FIELD_INTERLACED ||
		fmt->field == V4L2_FIELD_INTERLACED_TB)
		cfg |= S3C_CISCCTRL_INTERLACE;
	else
		cfg |= S3C_CISCCTRL_PROGRESSIVE;

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

	cfg = readl(ctrl->regs + S3C_CIOCTRL);
	cfg &= ~S3C_CIOCTRL_WEAVE_MASK;

	if ((ctrl->cap) && (fmt->field == V4L2_FIELD_INTERLACED_TB))
		cfg |= S3C_CIOCTRL_WEAVE_OUT;

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

	return 0;
}
示例#3
0
int fimc_hwset_scaler(struct fimc_control *ctrl)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
	u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN);

	cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
		S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
		S3C_CISCCTRL_MAIN_V_RATIO_MASK |
		S3C_CISCCTRL_MAIN_H_RATIO_MASK);
	cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);

	cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
	cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;

	if (ctrl->sc.bypass)
		cfg |= S3C_CISCCTRL_SCALERBYPASS;

	if (ctrl->sc.scaleup_h)
		cfg |= S3C_CISCCTRL_SCALEUP_H;

	if (ctrl->sc.scaleup_v)
		cfg |= S3C_CISCCTRL_SCALEUP_V;

	if (pdata->hw_ver == 0x50) {
		cfg |= S3C_CISCCTRL_MAINHORRATIO((ctrl->sc.main_hratio >> 6));
		cfg |= S3C_CISCCTRL_MAINVERRATIO((ctrl->sc.main_vratio >> 6));

		cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(ctrl->sc.main_vratio);
		cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(ctrl->sc.main_vratio);

		writel(cfg_ext, ctrl->regs + S3C_CIEXTEN);
	} else {
示例#4
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;
}
示例#5
0
static int fimc_open(struct file *filp)
{
	struct fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
	int ret;

	ctrl = video_get_drvdata(video_devdata(filp));
	pdata = to_fimc_plat(ctrl->dev);

	mutex_lock(&ctrl->lock);

	if (atomic_read(&ctrl->in_use)) {
		ret = -EBUSY;
		goto resource_busy;
	} else {
		atomic_inc(&ctrl->in_use);
	}

	if (pdata->clk_on)
		pdata->clk_on(to_platform_device(ctrl->dev), ctrl->clk);
#if defined(CONFIG_VIDEO_FIMC_FIFO)
	fimc_hwset_clksrc(ctrl,FIMC_SCLK);
	fimc_hwset_sclk_enable(ctrl);
#endif
	if (pdata->hw_ver == 0x40)
		fimc_hw_reset_camera(ctrl);

	/* Apply things to interface register */
	fimc_hwset_reset(ctrl);
	filp->private_data = ctrl;

	ctrl->fb.open_fifo = s3cfb_open_fifo;
	ctrl->fb.close_fifo = s3cfb_close_fifo;

	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_WIDTH,
					(unsigned long)&ctrl->fb.lcd_hres);
	if (ret < 0)
		fimc_err("Fail: S3CFB_GET_LCD_WIDTH\n");

	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_HEIGHT,
					(unsigned long)&ctrl->fb.lcd_vres);
	if (ret < 0)
		fimc_err("Fail: S3CFB_GET_LCD_HEIGHT\n");

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

	mutex_unlock(&ctrl->lock);

	return 0;

resource_busy:
	mutex_unlock(&ctrl->lock);
	return ret;
}
示例#6
0
int fimc_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
			    struct v4l2_rect *bounds,
			    struct v4l2_rect *crop)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);

	if (pdata->hw_ver == 0x50)
		fimc50_hwset_input_offset(ctrl, pixelformat, bounds, crop);
	else
		fimc40_hwset_input_offset(ctrl, pixelformat, bounds, crop);

	return 0;
}
示例#7
0
static int fimc_init_global(struct platform_device *pdev)
{
	struct fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
	struct s3c_platform_camera *cam;
	struct clk *srclk;
	int id, i;

	pdata = to_fimc_plat(&pdev->dev);
	id = pdev->id;
	ctrl = get_fimc_ctrl(id);

	/* Registering external camera modules. re-arrange order to be sure */
	for (i = 0; i < FIMC_MAXCAMS; i++) {
		cam = pdata->camera[i];
		if (!cam)
			break;

		/* WriteBack doesn't need clock setting */
		if(cam->id == CAMERA_WB) { 
			fimc_dev->camera[cam->id] = cam;
			break;
		}
		
		srclk = clk_get(&pdev->dev, cam->srclk_name);
		if (IS_ERR(srclk)) {
			fimc_err("%s: failed to get mclk source\n", __func__);
			return -EINVAL;
		}

		/* mclk */
		cam->clk = clk_get(&pdev->dev, cam->clk_name);
		if (IS_ERR(cam->clk)) {
			fimc_err("%s: failed to get mclk source\n", __func__);
			return -EINVAL;
		}

		if (cam->clk->set_parent) {
			cam->clk->parent = srclk;
			cam->clk->set_parent(cam->clk, srclk);
		}

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

	fimc_dev->initialized = 1;

	return 0;
}
示例#8
0
int fimc_hwset_input_lineskip(struct fimc_control *ctrl)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg = 0;

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

	cfg = S3C_CIILINESKIP(ctrl->sc.skipline);

	writel(cfg, ctrl->regs + S3C_CIILINESKIP_Y);
	writel(cfg, ctrl->regs + S3C_CIILINESKIP_CB);
	writel(cfg, ctrl->regs + S3C_CIILINESKIP_CR);

	return 0;
}
示例#9
0
文件: fimc_dev.c 项目: Arakmar/G3MOD
static int fimc_init_global(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct s3c_platform_camera *cam;
	struct clk *srclk;
	int i;
#ifdef VIEW_FUNCTION_CALL
	printk("[FIMC_DEV] %s(%d)\n", __func__, __LINE__);
#endif

	pdata = to_fimc_plat(&pdev->dev);

	/* Registering external camera modules. re-arrange order to be sure */
	for (i = 0; i < FIMC_MAXCAMS; i++) {
		cam = pdata->camera[i];
		if (!cam)
			break;

		srclk = clk_get(&pdev->dev, cam->srclk_name);
		if (IS_ERR(srclk)) {
			dev_err(&pdev->dev, "%s: failed to get mclk source\n",
				__func__);
			return -EINVAL;
		}

		/* mclk */
		cam->clk = clk_get(&pdev->dev, cam->clk_name);
		if (IS_ERR(cam->clk)) {
			dev_err(&pdev->dev, "%s: failed to get mclk source\n",
				__func__);
			return -EINVAL;
		}

		if (cam->clk->set_parent) {
			cam->clk->parent = srclk;
			cam->clk->set_parent(cam->clk, srclk);
		}

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

	fimc_dev->initialized = 1;

	return 0;
}
示例#10
0
int fimc_hwset_camera_type(struct fimc_control *ctrl)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);

	switch (pdata->hw_ver) {
	case 0x40:
		fimc40_hwset_camera_type(ctrl);
		break;
	case 0x43:
	case 0x45:
		fimc43_hwset_camera_type(ctrl);
		break;
	default:
		fimc43_hwset_camera_type(ctrl);
		break;
	}

	return 0;
}
示例#11
0
static int s3c_fimc_unregister_controller(struct platform_device *pdev)
{
	struct s3c_fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
	int id = pdev->id;

	ctrl = &s3c_fimc.ctrl[id];

	s3c_fimc_free_output_memory(&ctrl->out_frame);

	pdata = to_fimc_plat(ctrl->dev);

	if (!pdata->shared_io)
		iounmap(ctrl->regs);

	memset(ctrl, 0, sizeof(*ctrl));
	
	return 0;
}
示例#12
0
int fimc_hwset_intput_field(struct fimc_control *ctrl, enum v4l2_field field)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg;

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

	cfg = readl(ctrl->regs + S3C_MSCTRL);
	cfg &= ~S3C_MSCTRL_FIELD_MASK;

	if (field == V4L2_FIELD_NONE)
		cfg |= S3C_MSCTRL_FIELD_NORMAL;
	else if (field == V4L2_FIELD_INTERLACED_TB)
		cfg |= S3C_MSCTRL_FIELD_WEAVE;

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

	return 0;
}
示例#13
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;
	struct s3c_platform_fimc *pdata;
	int ret = -1;

	pdata = to_fimc_plat(ctrl->dev);

	if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		ret = fimc_streamoff_capture(fh);
	} 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;
}
示例#14
0
文件: fimc_dev.c 项目: Arakmar/G3MOD
static int fimc_unregister_controller(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct fimc_control *ctrl;
	int id = pdev->id;
#ifdef VIEW_FUNCTION_CALL
	printk("[FIMC_DEV] %s(%d)\n", __func__, __LINE__);
#endif

	pdata = to_fimc_plat(&pdev->dev);
	ctrl = get_fimc_ctrl(id);
	
	if (pdata->clk_off)
		pdata->clk_off(pdev, ctrl->clk);

	iounmap(ctrl->regs);
	memset(ctrl, 0, sizeof(*ctrl));

	return 0;
}
示例#15
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;
}
示例#16
0
int fimc_resume(struct platform_device *pdev)
{
	struct fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
  	int id = pdev->id;

	ctrl = get_fimc_ctrl(id);
	pdata = to_fimc_plat(ctrl->dev);

	if (pdata->clk_on)
		pdata->clk_on(pdev, ctrl->clk);

	if (ctrl->out)
		fimc_resume_out(ctrl);

	else if (ctrl->cap)
		fimc_resume_cap(ctrl);
	else
		ctrl->status = FIMC_STREAMOFF;

	return 0;
}
示例#17
0
int fimc_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);

	switch (pdata->hw_ver) {
	case 0x40:
		fimc40_hwset_scaler(ctrl, sc);
		break;
	case 0x43:
	case 0x45:
		fimc43_hwset_scaler(ctrl, sc);
		break;
	case 0x50:
		fimc50_hwset_scaler(ctrl, sc);
		break;
	default:
		fimc43_hwset_scaler(ctrl, sc);
		break;
	}

	return 0;
}
示例#18
0
int fimc_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
	int id;

	id = pdev->id;
	ctrl = get_fimc_ctrl(id);
	pdata = to_fimc_plat(ctrl->dev);

	if (ctrl->out)
		fimc_suspend_out(ctrl);

	else if (ctrl->cap)
		fimc_suspend_cap(ctrl);
	else
		ctrl->status = FIMC_OFF_SLEEP;

	if (pdata->clk_off)
		pdata->clk_off(pdev, ctrl->clk);

	return 0;
}
示例#19
0
static int fimc_unregister_controller(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct fimc_control *ctrl;
	int id = pdev->id;

	pdata = to_fimc_plat(&pdev->dev);
	ctrl = get_fimc_ctrl(id);

	free_irq(ctrl->irq, ctrl);

	mutex_destroy(&ctrl->lock);
	mutex_destroy(&ctrl->v4l2_lock);
	kfree(&ctrl->wq);
	
	if (pdata->clk_off)
		pdata->clk_off(pdev, ctrl->clk);

	iounmap(ctrl->regs);
	memset(ctrl, 0, sizeof(*ctrl));

	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;
}
示例#21
0
int fimc_hwset_org_output_size(struct fimc_control *ctrl, u32 width, u32 height)
{
	struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
	u32 cfg = 0;

	cfg |= S3C_ORGOSIZE_HORIZONTAL(width);
	cfg |= S3C_ORGOSIZE_VERTICAL(height);

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

	if (pdata->hw_ver != 0x40) {
		cfg = readl(ctrl->regs + S3C_CIGCTRL);
		cfg &= ~S3C_CIGCTRL_CSC_MASK;

		if (width >= FIMC_HD_WIDTH)
			cfg |= S3C_CIGCTRL_CSC_ITU709;
		else
			cfg |= S3C_CIGCTRL_CSC_ITU601;

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

	return 0;
}
示例#22
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;
}
示例#23
0
文件: fimc_dev.c 项目: Arakmar/G3MOD
static int fimc_open(struct file *filp)
{
	struct fimc_control *ctrl;
	struct s3c_platform_fimc *pdata;
	unsigned long flags;
	int ret;
	u32 cfg;
	#ifdef VIEW_FUNCTION_CALL
	printk("[FIMC_DEV] %s(%d)\n", __func__, __LINE__);
#endif

	/* An ugly hack to make the i2c pins output low */
	if (unlikely(make_i2c_pin_low == 1)) {
	    cfg = readl(S5P64XX_GPD1DAT);
	    cfg &= ~(0x1 << 0);
	    writel(cfg, S5P64XX_GPD1DAT);
	    cfg = readl(S5P64XX_GPD1DAT);
	    cfg &= ~(0x1 << 1);
	    writel(cfg, S5P64XX_GPD1DAT);
	    make_i2c_pin_low = 0;
	}

	ctrl = video_get_drvdata(video_devdata(filp));

#ifdef S5P6442_POWER_GATING_CAM
	del_timer(&g_fimc_domain_timer);
//	fimc0 controller for Camera
	if(ctrl->id == CAM_ID){
	   spin_lock_irqsave(&fimc_domain_lock, flags);
	   gFIMC_CNT[CAM_ID]++;
	   s5p6442_idle_pm_gpiocfg(S5P6442_CAM_ID, S5P6442_ACTIVE_MODE); 
           s5p6442_pwrgate_config(S5P6442_CAM_ID, S5P6442_ACTIVE_MODE);
	   spin_unlock_irqrestore(&fimc_domain_lock, flags);
	}
//           gFIMC_CNT++;
//        }
#endif

#ifdef CONFIG_CPU_FREQ
	if(ctrl->id == CAM_ID){
	        set_dvfs_level(0);
	}
#endif /* CONFIG_CPU_FREQ */

	pdata = to_fimc_plat(ctrl->dev);

	mutex_lock(&ctrl->lock);

	if (atomic_read(&ctrl->in_use)) {
		ret = -EBUSY;
		goto resource_busy;
	} else {
		atomic_inc(&ctrl->in_use);
	}

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

	/* Apply things to interface register */
	fimc_hwset_reset(ctrl);
	filp->private_data = ctrl;

	ctrl->fb.open_fifo = s3cfb_open_fifo;
	ctrl->fb.close_fifo = s3cfb_close_fifo;

	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_WIDTH,
					(unsigned long)&ctrl->fb.lcd_hres);
	if (ret < 0)
		dev_err(ctrl->dev, "Fail: S3CFB_GET_LCD_WIDTH\n");

	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_GET_LCD_HEIGHT,
					(unsigned long)&ctrl->fb.lcd_vres);
	if (ret < 0)
		dev_err(ctrl->dev, "Fail: S3CFB_GET_LCD_HEIGHT\n");

	ctrl->status = FIMC_STREAMOFF;

#if 0
	/* To do : have to send ctrl to the fimd driver. */
	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_SUSPEND_FIFO,
			(unsigned long)fimc_sleep);
	if (ret < 0)
		dev_err(ctrl->dev,
			"s3cfb_direct_ioctl(S3CFB_SET_SUSPEND_FIFO) fail\n");

	ret = s3cfb_direct_ioctl(ctrl->id, S3CFB_SET_RESUME_FIFO,
			(unsigned long)fimc_wakeup);
	if (ret < 0)
		dev_err(ctrl->dev,
			"s3cfb_direct_ioctl(S3CFB_SET_SUSPEND_FIFO) fail\n");
#endif
	mutex_unlock(&ctrl->lock);

	return 0;

resource_busy:
	mutex_unlock(&ctrl->lock);
	return ret;
}
示例#24
0
文件: fimc_dev.c 项目: Arakmar/G3MOD
static int fimc_release(struct file *filp)
{
	struct fimc_control *ctrl = filp->private_data;
	struct s3c_platform_fimc *pdata;
	unsigned long flags;
	int ret = 0, i;
#ifdef VIEW_FUNCTION_CALL
	printk("[FIMC_DEV] %s(%d)\n", __func__, __LINE__);
#endif

	pdata = to_fimc_plat(ctrl->dev);

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

	/* 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)
				dev_err(ctrl->dev,
					"Fail: fimc_stop_streaming\n");
			ctrl->status = FIMC_STREAMOFF;
		}

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

	if (pdata->clk_off)
		pdata->clk_off(to_platform_device(ctrl->dev), ctrl->clk);
#ifdef S5P6442_POWER_GATING_CAM
//        gFIMC_CNT--;
	if(ctrl->id == CAM_ID){
	   spin_lock_irqsave(&fimc_domain_lock, flags);
	    s5p6442_idle_pm_gpiocfg(S5P6442_CAM_ID, S5P6442_LP_MODE);
		gFIMC_CNT[ctrl->id]--;
		if((gFIMC_CNT[0] <= 0) && (gFIMC_CNT[1] <= 0) && (gFIMC_CNT[2] <= 0)){
            s5p6442_pwrgate_config(S5P6442_CAM_ID, S5P6442_LP_MODE);
	}
	   spin_unlock_irqrestore(&fimc_domain_lock, flags);
	}
#endif
#ifdef CONFIG_CPU_FREQ
	if(ctrl->id == CAM_ID){
	        set_dvfs_level(1);
	}
#endif /* CONFIG_CPU_FREQ */

	dev_info(ctrl->dev, "%s: successfully released\n", __func__);

	return 0;
}
示例#25
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;

}
示例#26
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;
}
示例#27
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;
}
示例#28
0
static int fimc_init_camera(struct fimc_control *ctrl)
{
	struct fimc_global *fimc = get_fimc_dev();
	struct s3c_platform_fimc *pdata;
	struct s3c_platform_camera *cam;
	struct v4l2_streamparm stream;
	int ret;

	pdata = to_fimc_plat(ctrl->dev);
	if (pdata->default_cam >= FIMC_MAXCAMS) {
		dev_err(ctrl->dev, "%s: invalid camera index\n", __func__);
		return -EINVAL;
	}

	if (!fimc->camera[pdata->default_cam]) {
		dev_err(ctrl->dev, "no external camera device\n");
		return -ENODEV;
	}

	/*
	 * ctrl->cam may not be null if already s_input called,
	 * otherwise, that should be default_cam if ctrl->cam is null.
	*/
	if (!ctrl->cam)
		ctrl->cam = fimc->camera[pdata->default_cam];

	cam = ctrl->cam;

	/* do nothing if already initialized */
	if (cam->initialized)
		return 0;

	/* 
	 * WriteBack mode doesn't need to set clock and power,
	 * but it needs to set source width, height depend on LCD resolution.
	*/
	if (cam->id == CAMERA_WB) {
		s3cfb_direct_ioctl(0, S3CFB_GET_LCD_WIDTH, (unsigned long)&cam->width);	
		s3cfb_direct_ioctl(0, S3CFB_GET_LCD_HEIGHT, (unsigned long)&cam->height);
		cam->window.width = cam->width;
		cam->window.height = cam->height;
		cam->initialized = 1;
		return 0;
	}
	
	/* set rate for mclk */
	if (cam->clk->set_rate) {
		clk_disable(cam->clk);
		cam->clk->set_rate(cam->clk, cam->clk_rate);
		clk_enable(cam->clk);
		dev_info(ctrl->dev, "clock for camera: %d\n", cam->clk_rate);
	}

	/* enable camera power if needed */
	if (cam->cam_power)
		cam->cam_power(1);
	
	/* camera s/w reset*/
	fimc_hwset_hw_reset();


	/* subdev call for init */
	ret = v4l2_subdev_call(cam->sd, core, init, 0);
	if (ret == -ENOIOCTLCMD) {
		dev_err(ctrl->dev, "%s: init subdev api not supported\n",
			__func__);
		return ret;
	}

	/*set resolution SVGA*/
	stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	stream.parm.capture.capturemode = 0;

	ret = v4l2_subdev_call(cam->sd, video, s_parm, &stream);
	if (ret == -ENOIOCTLCMD) {
		dev_err(ctrl->dev, "%s: init subdev api not supported\n",
			__func__);
		return ret;
	}

	if (cam->type == CAM_TYPE_MIPI) {
		/* 
		 * subdev call for sleep/wakeup:
		 * no error although no s_stream api support
		*/
		v4l2_subdev_call(cam->sd, video, s_stream, 0);
		s3c_csis_start(cam->mipi_lanes, cam->mipi_settle, \
				cam->mipi_align, cam->width, cam->height);
		v4l2_subdev_call(cam->sd, video, s_stream, 1);
	}

	cam->initialized = 1;

	return 0;
}
示例#29
0
static
struct s3c_fimc_control *s3c_fimc_register_controller(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct s3c_fimc_control *ctrl;
	struct resource *res;
	int i = S3C_FIMC_MAX_CTRLS - 1;
	int id = pdev->id;

	pdata = to_fimc_plat(&pdev->dev);

	//printk("[CAM]s3c_fimc_register_controller.id=%d\n",id);

	ctrl = &s3c_fimc.ctrl[id];
	ctrl->id = id;
	ctrl->dev = &pdev->dev;
	ctrl->vd = &s3c_fimc_video_device[id];
	ctrl->rot90 = 0;
	ctrl->vd->minor = id;
	ctrl->out_frame.nr_frames = pdata->nr_frames;
	ctrl->out_frame.skip_frames = 0;
	ctrl->scaler.line_length = pdata->line_length;

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

	ctrl->open_lcdfifo = s3cfb_enable_local;
	ctrl->close_lcdfifo = s3cfb_enable_dma;

	atomic_set(&ctrl->in_use, 0);
	mutex_init(&ctrl->lock);
	init_waitqueue_head(&ctrl->waitq);

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

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

		/* ioremap for register block */
		ctrl->regs = ioremap(res->start, res->end - res->start + 1);
	} else {
		while (i >= 0 && ctrl->regs == NULL) {
			ctrl->regs = s3c_fimc.ctrl[i].regs;
			i--;
		}
	}

	if (!ctrl->regs) {
		err("failed to remap io region\n");
		return NULL;
	}

	/* irq */
	ctrl->irq = platform_get_irq(pdev, 0);
	if (request_irq(ctrl->irq, s3c_fimc_irq, IRQF_DISABLED, ctrl->name, ctrl))
		err("request_irq failed\n");

	s3c_fimc_reset(ctrl);
	s3c_fimc_set_active_camera(ctrl, 0);//note: only one camera type

	return ctrl;
}
示例#30
0
static int s3c_fimc_probe(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct s3c_fimc_control *ctrl;
	struct clk *srclk;
	int ret;

	ctrl = s3c_fimc_register_controller(pdev);
	if (!ctrl) {
		err("cannot register fimc controller\n");
		goto err_fimc;
	}

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

	/* fimc source clock */
	srclk = clk_get(&pdev->dev, pdata->srclk_name);
	if (IS_ERR(srclk)) {
		err("failed to get source clock of fimc\n");
		goto err_clk_io;
	}

	/* fimc clock */
	ctrl->clock = clk_get(&pdev->dev, pdata->clk_name);
	if (IS_ERR(ctrl->clock)) {
		err("failed to get fimc clock source\n");
		goto err_clk_io;
	}

	/* set parent clock */
	if (ctrl->clock->set_parent)
		ctrl->clock->set_parent(ctrl->clock, srclk);

	/* set clockrate for FIMC interface block */
	if (ctrl->clock->set_rate)
		ctrl->clock->set_rate(ctrl->clock, pdata->clockrate);

	clk_enable(ctrl->clock);

	/* things to initialize once */
	if (ctrl->id == 0) {
		ret = s3c_fimc_init_global(pdev);
		if (ret)
			goto err_global;
	}

	ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);
	if (ret) {
		err("cannot register video driver\n");
		goto err_video;
	}

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

	return 0;

err_video:
	clk_put(s3c_fimc.cam_clock);

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

err_clk_io:
	s3c_fimc_unregister_controller(pdev);

err_fimc:
	return -EINVAL;
	
}