예제 #1
0
파일: adv7180.c 프로젝트: 513855417/linux
static int adv7180_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct adv7180_state *state = to_state(sd);

	v4l2_async_unregister_subdev(sd);

	if (state->irq > 0)
		free_irq(client->irq, state);

	media_entity_cleanup(&sd->entity);
	adv7180_exit_controls(state);

	if (state->chip_info->flags & ADV7180_FLAG_I2P)
		i2c_unregister_device(state->vpp_client);
	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
		i2c_unregister_device(state->csi_client);

	mutex_destroy(&state->mutex);

	return 0;
}
예제 #2
0
static int lm3554_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct lm3554_priv *p_lm3554_priv = to_lm3554_priv(sd);
	struct camera_flash_platform_data *pdata = p_lm3554_priv->platform_data;
	int ret;

	media_entity_cleanup(&p_lm3554_priv->sd.entity);
	v4l2_device_unregister_subdev(sd);

	del_timer_sync(&p_lm3554_priv->flash_off_delay);

	ret = set_gpio_output(pdata->gpio_strobe, "flash", 0);
	if (ret < 0)
		goto fail;

	kfree(p_lm3554_priv);

	return 0;
fail:
	dev_err(&client->dev, "gpio request/direction_output fail");
	return ret;
}
예제 #3
0
static int lm3556_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct lm3556_priv *p_lm3556_priv = to_lm3556_priv(sd);
	int ret;

	media_entity_cleanup(&p_lm3556_priv->sd.entity);
	v4l2_device_unregister_subdev(sd);

	ret = gpio_direction_output(GP_LM3556_FLASH_STROBE, 0);
	if (ret < 0)
		dev_err(&client->dev, "failed to set strobe on remove");

	ret = gpio_direction_output(GP_LM3556_FLASH_RESET, 0);
	if (ret < 0)
		dev_err(&client->dev, "failed to set reset on remove");

	gpio_free(GP_LM3556_FLASH_RESET);
	gpio_free(GP_LM3556_FLASH_STROBE);

	kfree(p_lm3556_priv);

	return 0;
}
예제 #4
0
int
hwcam_dev_create(
        struct device* dev,
        int* dev_num)
{
	int rc = 0;
    struct v4l2_device* v4l2 = NULL;
    struct video_device* vdev = NULL;
    struct media_device* mdev = NULL;
    hwcam_dev_t* cam = NULL;

    cam = kzalloc(sizeof(hwcam_dev_t), GFP_KERNEL);
	if (WARN_ON(!cam)) {
		rc = -ENOMEM;
		goto init_end;
	}
    v4l2 = &cam->v4l2;

    vdev = video_device_alloc();
    if (!vdev) {
		rc = -ENOMEM;
		goto video_alloc_fail;
    }

    mdev = kzalloc(sizeof(struct media_device), GFP_KERNEL);
	if (!mdev) {
		rc = -ENOMEM;
		goto media_alloc_fail;
	}

	strlcpy(mdev->model, HWCAM_MODEL_USER, sizeof(mdev->model));
	mdev->dev = dev;
	rc = media_device_register(mdev);
	if (rc < 0) {
		goto media_register_fail;
    }

	rc = media_entity_init(&vdev->entity, 0, NULL, 0);
	if (rc < 0) {
		goto entity_init_fail;
    }

    v4l2->mdev = mdev;
	v4l2->notify = NULL;
	rc = v4l2_device_register(dev, v4l2);
	if (rc < 0) {
		goto v4l2_register_fail;
    }

	strlcpy(vdev->name, "hwcam-userdev", sizeof(vdev->name));
	vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
	vdev->entity.group_id = HWCAM_DEVICE_GROUP_ID;
	vdev->v4l2_dev = v4l2;
	vdev->release = video_device_release;
	vdev->fops = &s_fops_hwcam_dev;
	vdev->ioctl_ops = &s_iops_hwcam_dev;
	vdev->minor = -1;
	vdev->vfl_type = VFL_TYPE_GRABBER;
	rc = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
	if (rc < 0) {
		goto video_register_fail;
    }
	cam_debug("video dev name %s %s",vdev->dev.kobj.name,vdev->name);
    mutex_init(&cam->lock);
    vdev->lock = &cam->lock;
	vdev->entity.name = video_device_node_name(vdev);
	video_set_drvdata(vdev, cam);
    cam->vdev = vdev;
    cam->mdev = mdev;
    cam->intf.vtbl = &s_vtbl_hwcam_dev;
    *dev_num = vdev->num;

	goto init_end;

video_register_fail:
	v4l2_device_unregister(v4l2);

v4l2_register_fail:
	media_entity_cleanup(&vdev->entity);

entity_init_fail:
	media_device_unregister(mdev);

media_register_fail:
    kzfree(mdev);

media_alloc_fail:
	video_device_release(vdev);

video_alloc_fail:
	kzfree(cam);

init_end:
	return rc;
}
int camera_init_v4l2(struct device *dev, unsigned int *session)
{
	struct msm_video_device *pvdev;
	struct v4l2_device *v4l2_dev;
	int rc = 0;

	pvdev = kzalloc(sizeof(struct msm_video_device),
		GFP_KERNEL);
	if (WARN_ON(!pvdev)) {
		rc = -ENOMEM;
		goto init_end;
	}

	pvdev->vdev = video_device_alloc();
	if (WARN_ON(!pvdev->vdev)) {
		rc = -ENOMEM;
		goto video_fail;
	}

	v4l2_dev = kzalloc(sizeof(struct v4l2_device), GFP_KERNEL);
	if (WARN_ON(!v4l2_dev)) {
		rc = -ENOMEM;
		goto v4l2_fail;
	}

#if defined(CONFIG_MEDIA_CONTROLLER)
	v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
							 GFP_KERNEL);
	if (!v4l2_dev->mdev) {
		rc = -ENOMEM;
		goto mdev_fail;
	}
	strlcpy(v4l2_dev->mdev->model, MSM_CAMERA_NAME,
			sizeof(v4l2_dev->mdev->model));

	v4l2_dev->mdev->dev = dev;

	rc = media_device_register(v4l2_dev->mdev);
	if (WARN_ON(rc < 0))
		goto media_fail;

	rc = media_entity_init(&pvdev->vdev->entity, 0, NULL, 0);
	if (WARN_ON(rc < 0))
		goto entity_fail;
	pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
	pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
#endif

	v4l2_dev->notify = NULL;
	pvdev->vdev->v4l2_dev = v4l2_dev;

	rc = v4l2_device_register(dev, pvdev->vdev->v4l2_dev);
	if (WARN_ON(rc < 0))
		goto register_fail;

	strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name));
	pvdev->vdev->release  = video_device_release;
	pvdev->vdev->fops     = &camera_v4l2_fops;
	pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
	pvdev->vdev->minor     = -1;
	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
	rc = video_register_device(pvdev->vdev,
		VFL_TYPE_GRABBER, -1);
	if (WARN_ON(rc < 0))
		goto video_register_fail;
#if defined(CONFIG_MEDIA_CONTROLLER)
	/* FIXME: How to get rid of this messy? */
	pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
#endif

	*session = pvdev->vdev->num;
	atomic_set(&pvdev->opened, 0);
	atomic_set(&pvdev->stream_cnt, 0);
	video_set_drvdata(pvdev->vdev, pvdev);
	device_init_wakeup(&pvdev->vdev->dev, 1);
    if(!cam_wakelock_init)
    {
        cam_wakelock_init = 1;
        wake_lock_init(&cam_wakelock, WAKE_LOCK_SUSPEND, "cam_wakelock");
    }
	goto init_end;

video_register_fail:
	v4l2_device_unregister(pvdev->vdev->v4l2_dev);
register_fail:
#if defined(CONFIG_MEDIA_CONTROLLER)
	media_entity_cleanup(&pvdev->vdev->entity);
entity_fail:
	media_device_unregister(v4l2_dev->mdev);
media_fail:
	kzfree(v4l2_dev->mdev);
mdev_fail:
#endif
	kzfree(v4l2_dev);
v4l2_fail:
	video_device_release(pvdev->vdev);
video_fail:
	kzfree(pvdev);
init_end:
	return rc;
}
예제 #6
0
파일: iss_ipipe.c 프로젝트: 020gzh/linux
/*
 * omap4iss_ipipe_cleanup - IPIPE module cleanup.
 * @iss: Device pointer specific to the OMAP4 ISS.
 */
void omap4iss_ipipe_cleanup(struct iss_device *iss)
{
	struct iss_ipipe_device *ipipe = &iss->ipipe;

	media_entity_cleanup(&ipipe->subdev.entity);
}
예제 #7
0
int fimc_isp_video_device_register(struct fimc_isp *isp,
				   struct v4l2_device *v4l2_dev,
				   enum v4l2_buf_type type)
{
	struct vb2_queue *q = &isp->video_capture.vb_queue;
	struct fimc_is_video *iv;
	struct video_device *vdev;
	int ret;

	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
		iv = &isp->video_capture;
	else
		return -ENOSYS;

	mutex_init(&isp->video_lock);
	INIT_LIST_HEAD(&iv->pending_buf_q);
	INIT_LIST_HEAD(&iv->active_buf_q);
	iv->format = fimc_isp_find_format(NULL, NULL, 0);
	iv->pixfmt.width = IS_DEFAULT_WIDTH;
	iv->pixfmt.height = IS_DEFAULT_HEIGHT;
	iv->pixfmt.pixelformat = iv->format->fourcc;
	iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB;
	iv->reqbufs_count = 0;

	memset(q, 0, sizeof(*q));
	q->type = type;
	q->io_modes = VB2_MMAP | VB2_USERPTR;
	q->ops = &isp_video_capture_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->buf_struct_size = sizeof(struct isp_video_buf);
	q->drv_priv = isp;
	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	q->lock = &isp->video_lock;

	ret = vb2_queue_init(q);
	if (ret < 0)
		return ret;

	vdev = &iv->ve.vdev;
	memset(vdev, 0, sizeof(*vdev));
	snprintf(vdev->name, sizeof(vdev->name), "fimc-is-isp.%s",
			type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
			"capture" : "output");
	vdev->queue = q;
	vdev->fops = &isp_video_fops;
	vdev->ioctl_ops = &isp_video_ioctl_ops;
	vdev->v4l2_dev = v4l2_dev;
	vdev->minor = -1;
	vdev->release = video_device_release_empty;
	vdev->lock = &isp->video_lock;

	iv->pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad);
	if (ret < 0)
		return ret;

	video_set_drvdata(vdev, isp);

	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
	if (ret < 0) {
		media_entity_cleanup(&vdev->entity);
		return ret;
	}

	v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
		  vdev->name, video_device_node_name(vdev));

	return 0;
}
static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
{
	v4l2_ctrl_handler_free(&asd->ctrl_handler);

	media_entity_cleanup(&asd->subdev.entity);
}
예제 #9
0
int fimc_isp_subdev_create(struct fimc_isp *isp)
{
	const struct v4l2_ctrl_ops *ops = &fimc_isp_ctrl_ops;
	struct v4l2_ctrl_handler *handler = &isp->ctrls.handler;
	struct v4l2_subdev *sd = &isp->subdev;
	struct fimc_isp_ctrls *ctrls = &isp->ctrls;
	int ret;

	mutex_init(&isp->subdev_lock);

	v4l2_subdev_init(sd, &fimc_is_subdev_ops);

	sd->owner = THIS_MODULE;
	sd->grp_id = GRP_ID_FIMC_IS;
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP");

	isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE;
	isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_init(&sd->entity, FIMC_ISP_SD_PADS_NUM,
				isp->subdev_pads, 0);
	if (ret)
		return ret;

	v4l2_ctrl_handler_init(handler, 20);

	ctrls->saturation = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SATURATION,
						-2, 2, 1, 0);
	ctrls->brightness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_BRIGHTNESS,
						-4, 4, 1, 0);
	ctrls->contrast = v4l2_ctrl_new_std(handler, ops, V4L2_CID_CONTRAST,
						-2, 2, 1, 0);
	ctrls->sharpness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SHARPNESS,
						-2, 2, 1, 0);
	ctrls->hue = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HUE,
						-2, 2, 1, 0);

	ctrls->auto_wb = v4l2_ctrl_new_std_menu(handler, ops,
					V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
					8, ~0x14e, V4L2_WHITE_BALANCE_AUTO);

	ctrls->exposure = v4l2_ctrl_new_std(handler, ops,
					V4L2_CID_EXPOSURE_ABSOLUTE,
					-4, 4, 1, 0);

	ctrls->exp_metering = v4l2_ctrl_new_std_menu(handler, ops,
					V4L2_CID_EXPOSURE_METERING, 3,
					~0xf, V4L2_EXPOSURE_METERING_AVERAGE);

	v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_POWER_LINE_FREQUENCY,
					V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
					V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
	/* ISO sensitivity */
	ctrls->auto_iso = v4l2_ctrl_new_std_menu(handler, ops,
			V4L2_CID_ISO_SENSITIVITY_AUTO, 1, 0,
			V4L2_ISO_SENSITIVITY_AUTO);

	ctrls->iso = v4l2_ctrl_new_int_menu(handler, ops,
			V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
			ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);

	ctrls->aewb_lock = v4l2_ctrl_new_std(handler, ops,
					V4L2_CID_3A_LOCK, 0, 0x3, 0, 0);

	/* TODO: Add support for NEGATIVE_COLOR option */
	ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_COLORFX,
			V4L2_COLORFX_SET_CBCR + 1, ~0x1000f, V4L2_COLORFX_NONE);

	if (handler->error) {
		media_entity_cleanup(&sd->entity);
		return handler->error;
	}

	v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso,
			V4L2_ISO_SENSITIVITY_MANUAL, false);

	sd->ctrl_handler = handler;
	sd->internal_ops = &fimc_is_subdev_internal_ops;
	sd->entity.ops = &fimc_is_subdev_media_ops;
	v4l2_set_subdevdata(sd, isp);

	__isp_subdev_set_default_format(isp);

	return 0;
}
예제 #10
0
static int __devinit lm3556_probe(struct i2c_client *client,
					 const struct i2c_device_id *id)
{
	int err;
	struct lm3556_priv *p_lm3556_priv;

	p_lm3556_priv = kzalloc(sizeof(*p_lm3556_priv), GFP_KERNEL);
	if (!p_lm3556_priv) {
		dev_err(&client->dev, "out of memory\n");
		return -ENOMEM;
	}

	v4l2_i2c_subdev_init(&(p_lm3556_priv->sd), client, &lm3556_ops);
	p_lm3556_priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	p_lm3556_priv->sd.entity.ops = &lm3556_entity_ops;
	p_lm3556_priv->timeout = LM3556_DEFAULT_TIMEOUT;
	p_lm3556_priv->mode = ATOMISP_FLASH_MODE_OFF;

	err = media_entity_init(&p_lm3556_priv->sd.entity, 0, NULL, 0);
	if (err) {
		dev_err(&client->dev, "error initialize a media entity.\n");
		goto fail1;
	}

	mutex_init(&p_lm3556_priv->i2c_mutex);

	err = gpio_request(GP_LM3556_FLASH_STROBE, "lm3556 strobe");
	if (err) {
		dev_err(&client->dev, "unable to claim lm3556 strobe gpio\n");
		goto fail2;
	}
	err = gpio_export(GP_LM3556_FLASH_STROBE, 0);
	if (err) {
		dev_err(&client->dev, "unable to export lm3556 strobe gpio\n");
		goto fail3;
	}

	err = gpio_request(GP_LM3556_FLASH_RESET, "lm3556 reset");
	if (err) {
		dev_err(&client->dev, "unable to claim flash lm3556 reset gpio\n");
		goto fail3;
	}
	err = gpio_export(GP_LM3556_FLASH_RESET, 0);
	if (err) {
		dev_err(&client->dev, "unable to export lm3556 reset gpio\n");
		goto fail4;
	}

	err = lm3556_detect(client);
	if (err) {
		dev_err(&client->dev, "device not found\n");
		goto fail4;
	}

	return 0;

fail4:
	gpio_free(GP_LM3556_FLASH_RESET);
fail3:
	gpio_free(GP_LM3556_FLASH_STROBE);
fail2:
	media_entity_cleanup(&p_lm3556_priv->sd.entity);
fail1:
	v4l2_device_unregister_subdev(&p_lm3556_priv->sd);
	kfree(p_lm3556_priv);

	return err;
}
예제 #11
0
파일: vsp1_entity.c 프로젝트: 7799/linux
void vsp1_entity_destroy(struct vsp1_entity *entity)
{
	if (entity->subdev.ctrl_handler)
		v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
	media_entity_cleanup(&entity->subdev.entity);
}
int register_tx_isp_vic_device(struct platform_device *pdev, struct v4l2_device *v4l2_dev)
{
	struct tx_isp_subdev_platform_data *pdata = pdev->dev.platform_data;
	struct tx_isp_vic_driver *vsd = NULL;
	struct resource *res = NULL;
	struct v4l2_subdev *sd = NULL;
	struct media_pad *pads = NULL;
	struct media_entity *me = NULL;
	struct proc_dir_entry *proc;
	int ret;

	if(!pdata){
		v4l2_err(v4l2_dev, "The platform_data of csi is NULL!\n");
		ret = -ISP_ERROR;
		goto exit;
	};
	vsd = (struct tx_isp_vic_driver *)kzalloc(sizeof(*vsd), GFP_KERNEL);
	if(!vsd){
		v4l2_err(v4l2_dev, "Failed to allocate sensor device\n");
		ret = -ISP_ERROR;
		goto exit;
	}
	vsd->pdata = pdata;
	vsd->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if(res){
		res = request_mem_region(res->start,
				res->end - res->start + 1, dev_name(&pdev->dev));
		if (!res) {
			v4l2_err(v4l2_dev, "Not enough memory for resources\n");
			ret = -EBUSY;
			goto mem_region_failed;
		}
		vsd->base = ioremap(res->start, res->end - res->start + 1);
		if (!vsd->base) {
			v4l2_err(v4l2_dev, "Unable to ioremap registers!\n");
			ret = -ENXIO;
			goto ioremap_failed;
		}
	}
	vsd->res = res;
	sd = &vsd->sd;
	pads = vsd->pads;
	me = &sd->entity;

	v4l2_subdev_init(sd, &vic_subdev_ops);
	strlcpy(sd->name, "TX-ISP-VIC-SUBDEV ", sizeof(sd->name));

	sd->grp_id = pdata->grp_id ;	/* group ID for isp subdevs */
	v4l2_set_subdevdata(sd, vsd);

	pads[TX_ISP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
	pads[TX_ISP_PAD_LINK].flags = MEDIA_PAD_FL_SINK;

	me->ops = &vic_media_ops;
//	me->parent = v4l2_dev->mdev;
	ret = media_entity_init(me, TX_ISP_PADS_NUM, pads, 0);
	if (ret < 0){
		v4l2_err(v4l2_dev, "Failed to init media entity!\n");
		ret = -ISP_ERROR;
		goto entity_init_failed;
	}
	ret = v4l2_device_register_subdev(v4l2_dev, sd);
	if (ret < 0){
		v4l2_err(v4l2_dev, "Failed to register vic-subdev!\n");
		ret = -ISP_ERROR;
		goto register_failed;
	}

	ret = isp_vic_init_clk(vsd);
	if(ret < 0){
		v4l2_err(v4l2_dev, "Failed to init isp's clks!\n");
		ret = -ISP_ERROR;
	}
	dump_vsd=vsd;

	/* creat the node of printing isp info */
	proc = jz_proc_mkdir("vic");
	if (!proc) {
		vsd->proc_vic = NULL;
		v4l2_err(v4l2_dev, "create dev_attr_isp_info failed!\n");
	} else {
		vsd->proc_vic = proc;
	}
	proc_create_data("isp_vic_frd", S_IRUGO, proc, &isp_vic_frd_fops, (void *)vsd);

	return ISP_SUCCESS;
register_failed:
	media_entity_cleanup(me);
entity_init_failed:
	if(vsd->base)
		iounmap(vsd->base);
ioremap_failed:
	if(res)
		release_mem_region(res->start,res->end - res->start + 1);
mem_region_failed:
	kfree(vsd);
exit:
	return ret;
}
예제 #13
0
static int mt9m032_setup_pll(struct mt9m032 *sensor)
{
	static const struct aptina_pll_limits limits = {
		.ext_clock_min = 8000000,
		.ext_clock_max = 16500000,
		.int_clock_min = 2000000,
		.int_clock_max = 24000000,
		.out_clock_min = 322000000,
		.out_clock_max = 693000000,
		.pix_clock_max = 99000000,
		.n_min = 1,
		.n_max = 64,
		.m_min = 16,
		.m_max = 255,
		.p1_min = 6,
		.p1_max = 7,
	};

	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
	struct mt9m032_platform_data *pdata = sensor->pdata;
	struct aptina_pll pll;
	u16 reg_val;
	int ret;

	pll.ext_clock = pdata->ext_clock;
	pll.pix_clock = pdata->pix_clock;

	ret = aptina_pll_calculate(&client->dev, &limits, &pll);
	if (ret < 0)
		return ret;

	sensor->pix_clock = pdata->pix_clock;

	ret = mt9m032_write(client, MT9M032_PLL_CONFIG1,
			    (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) |
			    ((pll.n - 1) & MT9M032_PLL_CONFIG1_PREDIV_MASK));
	if (!ret)
		ret = mt9m032_write(client, MT9P031_PLL_CONTROL,
				    MT9P031_PLL_CONTROL_PWRON |
				    MT9P031_PLL_CONTROL_USEPLL);
	if (!ret)		/* more reserved, Continuous, Master Mode */
		ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8000 |
				    MT9M032_READ_MODE1_STROBE_START_EXP |
				    MT9M032_READ_MODE1_STROBE_END_SHUTTER);
	if (!ret) {
		reg_val = (pll.p1 == 6 ? MT9M032_FORMATTER1_PLL_P1_6 : 0)
			| MT9M032_FORMATTER1_PARALLEL | 0x001e; /* 14-bit */
		ret = mt9m032_write(client, MT9M032_FORMATTER1, reg_val);
	}

	return ret;
}

/* -----------------------------------------------------------------------------
 * Subdev pad operations
 */

static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
				  struct v4l2_subdev_fh *fh,
				  struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index != 0)
		return -EINVAL;

	code->code = V4L2_MBUS_FMT_Y8_1X8;
	return 0;
}

static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
				   struct v4l2_subdev_fh *fh,
				   struct v4l2_subdev_frame_size_enum *fse)
{
	if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8)
		return -EINVAL;

	fse->min_width = MT9M032_COLUMN_SIZE_DEF;
	fse->max_width = MT9M032_COLUMN_SIZE_DEF;
	fse->min_height = MT9M032_ROW_SIZE_DEF;
	fse->max_height = MT9M032_ROW_SIZE_DEF;

	return 0;
}

/**
 * __mt9m032_get_pad_crop() - get crop rect
 * @sensor: pointer to the sensor struct
 * @fh: file handle for getting the try crop rect from
 * @which: select try or active crop rect
 *
 * Returns a pointer the current active or fh relative try crop rect
 */
static struct v4l2_rect *
__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
		       enum v4l2_subdev_format_whence which)
{
	switch (which) {
	case V4L2_SUBDEV_FORMAT_TRY:
		return v4l2_subdev_get_try_crop(fh, 0);
	case V4L2_SUBDEV_FORMAT_ACTIVE:
		return &sensor->crop;
	default:
		return NULL;
	}
}

/**
 * __mt9m032_get_pad_format() - get format
 * @sensor: pointer to the sensor struct
 * @fh: file handle for getting the try format from
 * @which: select try or active format
 *
 * Returns a pointer the current active or fh relative try format
 */
static struct v4l2_mbus_framefmt *
__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
			 enum v4l2_subdev_format_whence which)
{
	switch (which) {
	case V4L2_SUBDEV_FORMAT_TRY:
		return v4l2_subdev_get_try_format(fh, 0);
	case V4L2_SUBDEV_FORMAT_ACTIVE:
		return &sensor->format;
	default:
		return NULL;
	}
}

static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
				  struct v4l2_subdev_fh *fh,
				  struct v4l2_subdev_format *fmt)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);

	mutex_lock(&sensor->lock);
	fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
	mutex_unlock(&sensor->lock);

	return 0;
}

static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
				  struct v4l2_subdev_fh *fh,
				  struct v4l2_subdev_format *fmt)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);
	int ret;

	mutex_lock(&sensor->lock);

	if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
		ret = -EBUSY;
		goto done;
	}

	/* Scaling is not supported, the format is thus fixed. */
	fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
	ret = 0;

done:
	mutex_unlock(&sensor->lock);
	return ret;
}

static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev,
				struct v4l2_subdev_fh *fh,
				struct v4l2_subdev_crop *crop)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);

	mutex_lock(&sensor->lock);
	crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which);
	mutex_unlock(&sensor->lock);

	return 0;
}

static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
				struct v4l2_subdev_fh *fh,
				struct v4l2_subdev_crop *crop)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);
	struct v4l2_mbus_framefmt *format;
	struct v4l2_rect *__crop;
	struct v4l2_rect rect;
	int ret = 0;

	mutex_lock(&sensor->lock);

	if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
		ret = -EBUSY;
		goto done;
	}

	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
	 * pixels to ensure a GRBG Bayer pattern.
	 */
	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN,
			  MT9M032_COLUMN_START_MAX);
	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN,
			 MT9M032_ROW_START_MAX);
	rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN,
			   MT9M032_COLUMN_SIZE_MAX);
	rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN,
			    MT9M032_ROW_SIZE_MAX);

	rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left);
	rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);

	__crop = __mt9m032_get_pad_crop(sensor, fh, crop->which);

	if (rect.width != __crop->width || rect.height != __crop->height) {
		/* Reset the output image size if the crop rectangle size has
		 * been modified.
		 */
		format = __mt9m032_get_pad_format(sensor, fh, crop->which);
		format->width = rect.width;
		format->height = rect.height;
	}

	*__crop = rect;
	crop->rect = rect;

	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
		ret = mt9m032_update_geom_timing(sensor);

done:
	mutex_unlock(&sensor->lock);
	return ret;
}

static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev,
				      struct v4l2_subdev_frame_interval *fi)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);

	mutex_lock(&sensor->lock);
	memset(fi, 0, sizeof(*fi));
	fi->interval = sensor->frame_interval;
	mutex_unlock(&sensor->lock);

	return 0;
}

static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev,
				      struct v4l2_subdev_frame_interval *fi)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);
	int ret;

	mutex_lock(&sensor->lock);

	if (sensor->streaming) {
		ret = -EBUSY;
		goto done;
	}

	/* Avoid divisions by 0. */
	if (fi->interval.denominator == 0)
		fi->interval.denominator = 1;

	ret = mt9m032_update_timing(sensor, &fi->interval);
	if (!ret)
		sensor->frame_interval = fi->interval;

done:
	mutex_unlock(&sensor->lock);
	return ret;
}

static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming)
{
	struct mt9m032 *sensor = to_mt9m032(subdev);
	int ret;

	mutex_lock(&sensor->lock);
	ret = update_formatter2(sensor, streaming);
	if (!ret)
		sensor->streaming = streaming;
	mutex_unlock(&sensor->lock);

	return ret;
}

/* -----------------------------------------------------------------------------
 * V4L2 subdev core operations
 */

#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9m032_g_register(struct v4l2_subdev *sd,
			      struct v4l2_dbg_register *reg)
{
	struct mt9m032 *sensor = to_mt9m032(sd);
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
	int val;

	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
		return -EINVAL;
	if (reg->match.addr != client->addr)
		return -ENODEV;

	val = mt9m032_read(client, reg->reg);
	if (val < 0)
		return -EIO;

	reg->size = 2;
	reg->val = val;

	return 0;
}

static int mt9m032_s_register(struct v4l2_subdev *sd,
			      const struct v4l2_dbg_register *reg)
{
	struct mt9m032 *sensor = to_mt9m032(sd);
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);

	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
		return -EINVAL;

	if (reg->match.addr != client->addr)
		return -ENODEV;

	return mt9m032_write(client, reg->reg, reg->val);
}
#endif

/* -----------------------------------------------------------------------------
 * V4L2 subdev control operations
 */

static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
	int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT)
		    | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT)
		    | MT9M032_READ_MODE2_ROW_BLC
		    | 0x0007;

	return mt9m032_write(client, MT9M032_READ_MODE2, reg_val);
}

static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
	int digital_gain_val;	/* in 1/8th (0..127) */
	int analog_mul;		/* 0 or 1 */
	int analog_gain_val;	/* in 1/16th. (0..63) */
	u16 reg_val;

	digital_gain_val = 51; /* from setup example */

	if (val < 63) {
		analog_mul = 0;
		analog_gain_val = val;
	} else {
		analog_mul = 1;
		analog_gain_val = val / 2;
	}

	/* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */
	/* overall_gain = a_gain * (1 + digital_gain_val / 8) */

	reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK)
		   << MT9M032_GAIN_DIGITAL_SHIFT)
		| ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT)
		| (analog_gain_val & MT9M032_GAIN_ANALOG_MASK);

	return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val);
}

static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl)
{
	if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) {
		/* round because of multiplier used for values >= 63 */
		ctrl->val &= ~1;
	}

	return 0;
}

static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl)
{
	struct mt9m032 *sensor =
		container_of(ctrl->handler, struct mt9m032, ctrls);
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
	int ret;

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		return mt9m032_set_gain(sensor, ctrl->val);

	case V4L2_CID_HFLIP:
	/* case V4L2_CID_VFLIP: -- In the same cluster */
		return update_read_mode2(sensor, sensor->vflip->val,
					 sensor->hflip->val);

	case V4L2_CID_EXPOSURE:
		ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH,
				    (ctrl->val >> 16) & 0xffff);
		if (ret < 0)
			return ret;

		return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW,
				     ctrl->val & 0xffff);
	}

	return 0;
}

static struct v4l2_ctrl_ops mt9m032_ctrl_ops = {
	.s_ctrl = mt9m032_set_ctrl,
	.try_ctrl = mt9m032_try_ctrl,
};

/* -------------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops mt9m032_core_ops = {
#ifdef CONFIG_VIDEO_ADV_DEBUG
	.g_register = mt9m032_g_register,
	.s_register = mt9m032_s_register,
#endif
};

static const struct v4l2_subdev_video_ops mt9m032_video_ops = {
	.s_stream = mt9m032_s_stream,
	.g_frame_interval = mt9m032_get_frame_interval,
	.s_frame_interval = mt9m032_set_frame_interval,
};

static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
	.enum_mbus_code = mt9m032_enum_mbus_code,
	.enum_frame_size = mt9m032_enum_frame_size,
	.get_fmt = mt9m032_get_pad_format,
	.set_fmt = mt9m032_set_pad_format,
	.set_crop = mt9m032_set_pad_crop,
	.get_crop = mt9m032_get_pad_crop,
};

static const struct v4l2_subdev_ops mt9m032_ops = {
	.core = &mt9m032_core_ops,
	.video = &mt9m032_video_ops,
	.pad = &mt9m032_pad_ops,
};

/* -----------------------------------------------------------------------------
 * Driver initialization and probing
 */

static int mt9m032_probe(struct i2c_client *client,
			 const struct i2c_device_id *devid)
{
	struct mt9m032_platform_data *pdata = client->dev.platform_data;
	struct i2c_adapter *adapter = client->adapter;
	struct mt9m032 *sensor;
	int chip_version;
	int ret;

	if (pdata == NULL) {
		dev_err(&client->dev, "No platform data\n");
		return -EINVAL;
	}

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
		dev_warn(&client->dev,
			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
		return -EIO;
	}

	if (!client->dev.platform_data)
		return -ENODEV;

	sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
	if (sensor == NULL)
		return -ENOMEM;

	mutex_init(&sensor->lock);

	sensor->pdata = pdata;

	v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
	sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;

	chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION);
	if (chip_version != MT9M032_CHIP_VERSION_VALUE) {
		dev_err(&client->dev, "MT9M032 not detected, wrong version "
			"0x%04x\n", chip_version);
		ret = -ENODEV;
		goto error_sensor;
	}

	dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n",
		 client->addr);

	sensor->frame_interval.numerator = 1;
	sensor->frame_interval.denominator = 30;

	sensor->crop.left = MT9M032_COLUMN_START_DEF;
	sensor->crop.top = MT9M032_ROW_START_DEF;
	sensor->crop.width = MT9M032_COLUMN_SIZE_DEF;
	sensor->crop.height = MT9M032_ROW_SIZE_DEF;

	sensor->format.width = sensor->crop.width;
	sensor->format.height = sensor->crop.height;
	sensor->format.code = V4L2_MBUS_FMT_Y8_1X8;
	sensor->format.field = V4L2_FIELD_NONE;
	sensor->format.colorspace = V4L2_COLORSPACE_SRGB;

	v4l2_ctrl_handler_init(&sensor->ctrls, 5);

	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
			  V4L2_CID_GAIN, 0, 127, 1, 64);

	sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls,
					  &mt9m032_ctrl_ops,
					  V4L2_CID_HFLIP, 0, 1, 1, 0);
	sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls,
					  &mt9m032_ctrl_ops,
					  V4L2_CID_VFLIP, 0, 1, 1, 0);

	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
			  V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
			  MT9M032_SHUTTER_WIDTH_MAX, 1,
			  MT9M032_SHUTTER_WIDTH_DEF);
	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
			  V4L2_CID_PIXEL_RATE, pdata->pix_clock,
			  pdata->pix_clock, 1, pdata->pix_clock);

	if (sensor->ctrls.error) {
		ret = sensor->ctrls.error;
		dev_err(&client->dev, "control initialization error %d\n", ret);
		goto error_ctrl;
	}

	v4l2_ctrl_cluster(2, &sensor->hflip);

	sensor->subdev.ctrl_handler = &sensor->ctrls;
	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0);
	if (ret < 0)
		goto error_ctrl;

	ret = mt9m032_write(client, MT9M032_RESET, 1);	/* reset on */
	if (ret < 0)
		goto error_entity;
	ret = mt9m032_write(client, MT9M032_RESET, 0);	/* reset off */
	if (ret < 0)
		goto error_entity;

	ret = mt9m032_setup_pll(sensor);
	if (ret < 0)
		goto error_entity;
	usleep_range(10000, 11000);

	ret = v4l2_ctrl_handler_setup(&sensor->ctrls);
	if (ret < 0)
		goto error_entity;

	/* SIZE */
	ret = mt9m032_update_geom_timing(sensor);
	if (ret < 0)
		goto error_entity;

	ret = mt9m032_write(client, 0x41, 0x0000);	/* reserved !!! */
	if (ret < 0)
		goto error_entity;
	ret = mt9m032_write(client, 0x42, 0x0003);	/* reserved !!! */
	if (ret < 0)
		goto error_entity;
	ret = mt9m032_write(client, 0x43, 0x0003);	/* reserved !!! */
	if (ret < 0)
		goto error_entity;
	ret = mt9m032_write(client, 0x7f, 0x0000);	/* reserved !!! */
	if (ret < 0)
		goto error_entity;
	if (sensor->pdata->invert_pixclock) {
		ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL,
				    MT9M032_PIX_CLK_CTRL_INV_PIXCLK);
		if (ret < 0)
			goto error_entity;
	}

	ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */
	if (ret < 0)
		goto error_entity;
	msleep(100);
	ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */
	if (ret < 0)
		goto error_entity;
	msleep(100);
	ret = update_formatter2(sensor, false);
	if (ret < 0)
		goto error_entity;

	return ret;

error_entity:
	media_entity_cleanup(&sensor->subdev.entity);
error_ctrl:
	v4l2_ctrl_handler_free(&sensor->ctrls);
error_sensor:
	mutex_destroy(&sensor->lock);
	kfree(sensor);
	return ret;
}

static int mt9m032_remove(struct i2c_client *client)
{
	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
	struct mt9m032 *sensor = to_mt9m032(subdev);

	v4l2_device_unregister_subdev(subdev);
	v4l2_ctrl_handler_free(&sensor->ctrls);
	media_entity_cleanup(&subdev->entity);
	mutex_destroy(&sensor->lock);
	kfree(sensor);
	return 0;
}

static const struct i2c_device_id mt9m032_id_table[] = {
	{ MT9M032_NAME, 0 },
	{ }
};

MODULE_DEVICE_TABLE(i2c, mt9m032_id_table);

static struct i2c_driver mt9m032_i2c_driver = {
	.driver = {
		.name = MT9M032_NAME,
	},
	.probe = mt9m032_probe,
	.remove = mt9m032_remove,
	.id_table = mt9m032_id_table,
};
예제 #14
0
struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
{
	struct v4l2_subdev *subdev;
	struct vsp1_video *video;
	struct vsp1_rwpf *wpf;
	unsigned int flags;
	int ret;

	wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
	if (wpf == NULL)
		return ERR_PTR(-ENOMEM);

	wpf->max_width = WPF_MAX_WIDTH;
	wpf->max_height = WPF_MAX_HEIGHT;

	wpf->entity.type = VSP1_ENTITY_WPF;
	wpf->entity.index = index;

	ret = vsp1_entity_init(vsp1, &wpf->entity, 2);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Initialize the V4L2 subdev. */
	subdev = &wpf->entity.subdev;
	v4l2_subdev_init(subdev, &wpf_ops);

	subdev->entity.ops = &vsp1_media_ops;
	subdev->internal_ops = &vsp1_subdev_internal_ops;
	snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u",
		 dev_name(vsp1->dev), index);
	v4l2_set_subdevdata(subdev, wpf);
	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;

	vsp1_entity_init_formats(subdev, NULL);

	/* Initialize the video device. */
	video = &wpf->video;

	video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	video->vsp1 = vsp1;
	video->ops = &wpf_vdev_ops;

	ret = vsp1_video_init(video, &wpf->entity);
	if (ret < 0)
		goto error_video;

	/* Connect the video device to the WPF. All connections are immutable
	 * except for the WPF0 source link if a LIF is present.
	 */
	flags = MEDIA_LNK_FL_ENABLED;
	if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0)
		flags |= MEDIA_LNK_FL_IMMUTABLE;

	ret = media_entity_create_link(&wpf->entity.subdev.entity,
				       RWPF_PAD_SOURCE,
				       &wpf->video.video.entity, 0, flags);
	if (ret < 0)
		goto error_link;

	wpf->entity.sink = &wpf->video.video.entity;

	return wpf;

error_link:
	vsp1_video_cleanup(video);
error_video:
	media_entity_cleanup(&wpf->entity.subdev.entity);
	return ERR_PTR(ret);
}
예제 #15
0
static int lm3554_probe(struct i2c_client *client,
				  const struct i2c_device_id *id)
{
	int err;
	struct lm3554 *flash;

#ifndef CONFIG_GMIN_INTEL_MID
	if (client->dev.platform_data == NULL) {
		dev_err(&client->dev, "no platform data\n");
		return -ENODEV;
	}
#endif

	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
	if (!flash) {
		dev_err(&client->dev, "out of memory\n");
		return -ENOMEM;
	}

	flash->pdata = client->dev.platform_data;

#ifdef CONFIG_GMIN_INTEL_MID
	if (!flash->pdata || ACPI_COMPANION(&client->dev))
		flash->pdata = lm3554_platform_data_func(client);
#endif

	v4l2_i2c_subdev_init(&flash->sd, client, &lm3554_ops);
	flash->sd.internal_ops = &lm3554_internal_ops;
	flash->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	flash->mode = ATOMISP_FLASH_MODE_OFF;
	flash->timeout = LM3554_MAX_TIMEOUT / LM3554_TIMEOUT_STEPSIZE - 1;

	err = media_entity_init(&flash->sd.entity, 0, NULL, 0);
	if (err) {
		dev_err(&client->dev, "error initialize a media entity.\n");
		goto fail1;
	}

	flash->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;

	mutex_init(&flash->power_lock);

	setup_timer(&flash->flash_off_delay, lm3554_flash_off_delay,
		    (unsigned long)client);

	err = lm3554_gpio_init(client);
	if (err) {
		dev_err(&client->dev, "gpio request/direction_output fail");
		goto fail2;
	}

#ifdef CONFIG_GMIN_INTEL_MID
	if (ACPI_HANDLE(&client->dev))
		err = atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH);
#endif
	return 0;
fail2:
	media_entity_cleanup(&flash->sd.entity);
fail1:
	v4l2_device_unregister_subdev(&flash->sd);
	kfree(flash);

	return err;
}
예제 #16
0
static int __init msm_sensor_init_module(void)
{
	struct msm_sensor_init_t *s_init = NULL;
	struct device			*cam_dev_back;
	struct device			*cam_dev_front;
	int rc = 0;
	camera_class = class_create(THIS_MODULE, "camera");
	if (IS_ERR(camera_class))
		pr_err("failed to create device cam_dev_rear!\n");

	/* Allocate memory for msm_sensor_init control structure */
	s_init = kzalloc(sizeof(struct msm_sensor_init_t), GFP_KERNEL);
	if (!s_init) {
		class_destroy(camera_class);
		pr_err("failed: no memory s_init %p", NULL);
		return -ENOMEM;
	}

	pr_err("MSM_SENSOR_INIT_MODULE %p", NULL);

	/* Initialize mutex */
	mutex_init(&s_init->imutex);

	/* Create /dev/v4l-subdevX for msm_sensor_init */
	v4l2_subdev_init(&s_init->msm_sd.sd, &msm_sensor_init_subdev_ops);
	snprintf(s_init->msm_sd.sd.name, sizeof(s_init->msm_sd.sd.name), "%s",
		"msm_sensor_init");
	v4l2_set_subdevdata(&s_init->msm_sd.sd, s_init);
	s_init->msm_sd.sd.internal_ops = &msm_sensor_init_internal_ops;
	s_init->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	rc = media_entity_init(&s_init->msm_sd.sd.entity, 0, NULL, 0);
	if (rc < 0)
		goto entity_fail;
	s_init->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
	s_init->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR_INIT;
	s_init->msm_sd.sd.entity.name = s_init->msm_sd.sd.name;
	s_init->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x6;
	rc = msm_sd_register(&s_init->msm_sd);
	if (rc < 0)
		goto msm_sd_register_fail;

	cam_dev_back = device_create(camera_class, NULL,
			1, NULL, "rear");
	if (IS_ERR(cam_dev_back)) {
		printk("Failed to create cam_dev_back device!\n");
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_rear_camtype) < 0) {
		printk("Failed to create device file!(%s)!\n",
				dev_attr_rear_camtype.attr.name);
		goto device_create_fail;
	}
	if (device_create_file(cam_dev_back, &dev_attr_rear_camfw) < 0) {
		printk("Failed to create device file!(%s)!\n",
				dev_attr_rear_camfw.attr.name);
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_rear_checkfw_user) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_rear_checkfw_user.attr.name);
		rc = -ENODEV;
		goto device_create_fail;
	}
	if (device_create_file(cam_dev_back, &dev_attr_rear_checkfw_factory) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_rear_checkfw_factory.attr.name);
		rc = -ENODEV;
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_isp_core) < 0) {
		printk("Failed to create device file!(%s)!\n",
				dev_attr_isp_core.attr.name);
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_rear_camfw_load) < 0) {
		printk("Failed to create device file!(%s)!\n",
				dev_attr_rear_camfw_load.attr.name);
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_rear_camfw_full) < 0) {
		printk("Failed to create device file!(%s)!\n",
				dev_attr_rear_camfw_full.attr.name);
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_back, &dev_attr_rear_vendorid) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_rear_vendorid.attr.name);
		goto device_create_fail;
	}

	cam_dev_front = device_create(camera_class, NULL,
		2, NULL, "front");
	if (IS_ERR(cam_dev_front)) {
		printk("Failed to create cam_dev_front device!");
		goto device_create_fail;
	}

	if (device_create_file(cam_dev_front, &dev_attr_front_camtype) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_front_camtype.attr.name);
		goto device_create_fail;
	}
	if (device_create_file(cam_dev_front, &dev_attr_front_camfw) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_front_camfw.attr.name);
		goto device_create_fail;
	}
	if (device_create_file(cam_dev_front, &dev_attr_front_camfw_load) < 0) {
		printk("Failed to create device file!(%s)!\n",
			dev_attr_rear_camfw_load.attr.name);
		goto device_create_fail;
	}
	if (device_create_file(cam_dev_front, &dev_attr_front_camfw_full) < 0) {
	    printk("Failed to create device file!(%s)!\n",
		    dev_attr_rear_camfw_full.attr.name);
		goto device_create_fail;
	}

	init_waitqueue_head(&s_init->state_wait);

	return 0;
device_create_fail:
	msm_sd_unregister(&s_init->msm_sd);
msm_sd_register_fail:
	media_entity_cleanup(&s_init->msm_sd.sd.entity);
entity_fail:
	mutex_destroy(&s_init->imutex);
	kfree(s_init);
	class_destroy(camera_class);
	return rc;
}
예제 #17
0
static int ov13858_probe(struct i2c_client *client,
			 const struct i2c_device_id *devid)
{
	struct ov13858 *ov13858;
	int ret;
	u32 val = 0;

	device_property_read_u32(&client->dev, "clock-frequency", &val);
	if (val != 19200000)
		return -EINVAL;

	ov13858 = devm_kzalloc(&client->dev, sizeof(*ov13858), GFP_KERNEL);
	if (!ov13858)
		return -ENOMEM;

	/* Initialize subdev */
	v4l2_i2c_subdev_init(&ov13858->sd, client, &ov13858_subdev_ops);

	/* Check module identity */
	ret = ov13858_identify_module(ov13858);
	if (ret) {
		dev_err(&client->dev, "failed to find sensor: %d\n", ret);
		return ret;
	}

	/* Set default mode to max resolution */
	ov13858->cur_mode = &supported_modes[0];

	ret = ov13858_init_controls(ov13858);
	if (ret)
		return ret;

	/* Initialize subdev */
	ov13858->sd.internal_ops = &ov13858_internal_ops;
	ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	ov13858->sd.entity.ops = &ov13858_subdev_entity_ops;
	ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

	/* Initialize source pad */
	ov13858->pad.flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_pads_init(&ov13858->sd.entity, 1, &ov13858->pad);
	if (ret) {
		dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
		goto error_handler_free;
	}

	ret = v4l2_async_register_subdev_sensor_common(&ov13858->sd);
	if (ret < 0)
		goto error_media_entity;

	/*
	 * Device is already turned on by i2c-core with ACPI domain PM.
	 * Enable runtime PM and turn off the device.
	 */
	pm_runtime_set_active(&client->dev);
	pm_runtime_enable(&client->dev);
	pm_runtime_idle(&client->dev);

	return 0;

error_media_entity:
	media_entity_cleanup(&ov13858->sd.entity);

error_handler_free:
	ov13858_free_controls(ov13858);
	dev_err(&client->dev, "%s failed:%d\n", __func__, ret);

	return ret;
}
예제 #18
0
int gsc_register_capture_device(struct gsc_dev *gsc)
{
	struct video_device *vfd;
	struct gsc_capture_device *gsc_cap;
	struct gsc_ctx *ctx;
	struct vb2_queue *q;
	struct exynos_platform_gscaler *pdata = gsc->pdata;
	struct exynos_isp_info *isp_info;
	int ret = -ENOMEM;
	int i;

	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	ctx->gsc_dev	 = gsc;
	ctx->in_path	 = GSC_CAMERA;
	ctx->out_path	 = GSC_DMA;
	ctx->state	 = GSC_CTX_CAP;

	vfd = video_device_alloc();
	if (!vfd) {
		printk("Failed to allocate video device\n");
		goto err_ctx_alloc;
	}

	snprintf(vfd->name, sizeof(vfd->name), "%s.capture",
		 dev_name(&gsc->pdev->dev));

	vfd->fops	= &gsc_capture_fops;
	vfd->ioctl_ops	= &gsc_capture_ioctl_ops;
	vfd->v4l2_dev	= &gsc->mdev[MDEV_CAPTURE]->v4l2_dev;
	vfd->minor	= -1;
	vfd->release	= video_device_release;
	vfd->lock	= &gsc->lock;
	video_set_drvdata(vfd, gsc);

	gsc_cap	= &gsc->cap;
	gsc_cap->vfd = vfd;
	gsc_cap->refcnt = 0;
	gsc_cap->active_buf_cnt = 0;
	gsc_cap->reqbufs_cnt  = 0;

	spin_lock_init(&ctx->slock);
	gsc_cap->ctx = ctx;

	q = &gsc->cap.vbq;
	memset(q, 0, sizeof(*q));
	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
	q->drv_priv = gsc->cap.ctx;
	q->ops = &gsc_capture_qops;
	q->mem_ops = gsc->vb2->ops;

	vb2_queue_init(q);

	/* Get mipi-csis and fimc-lite subdev ptr using mdev */
	for (i = 0; i < FLITE_MAX_ENTITIES; i++)
		gsc->cap.sd_flite[i] = gsc->mdev[MDEV_CAPTURE]->flite_sd[i];

	for (i = 0; i < CSIS_MAX_ENTITIES; i++)
		gsc->cap.sd_csis[i] = gsc->mdev[MDEV_CAPTURE]->csis_sd[i];

	if (soc_is_exynos5250()) {
		for (i = 0; i < pdata->num_clients; i++) {
			isp_info = pdata->isp_info[i];
			ret = gsc_cap_config_camclk(gsc, isp_info, i);
			if (ret) {
				gsc_err("failed setup cam clk");
				goto err_ctx_alloc;
			}
		}
	}

	ret = gsc_cap_register_sensor_entities(gsc);
	if (ret) {
		gsc_err("failed register sensor entities");
		goto err_clk;
	}

	ret = video_register_device(vfd, VFL_TYPE_GRABBER,
				    EXYNOS_VIDEONODE_GSC_CAP(gsc->id));
	if (ret) {
		gsc_err("failed to register video device");
		goto err_clk;
	}

	gsc->cap.vd_pad.flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_init(&vfd->entity, 1, &gsc->cap.vd_pad, 0);
	if (ret) {
		gsc_err("failed to initialize entity");
		goto err_ent;
	}

	ret = gsc_capture_create_subdev(gsc);
	if (ret) {
		gsc_err("failed create subdev");
		goto err_sd_reg;
	}

	ret = gsc_capture_create_link(gsc);
	if (ret) {
		gsc_err("failed create link");
		goto err_sd_reg;
	}

	vfd->ctrl_handler = &ctx->ctrl_handler;
	gsc_dbg("gsc capture driver registered as /dev/video%d", vfd->num);

	return 0;

err_sd_reg:
	media_entity_cleanup(&vfd->entity);
err_ent:
	video_device_release(vfd);
err_clk:
	if (soc_is_exynos5250()) {
		for (i = 0; i < pdata->num_clients; i++)
			clk_put(gsc_cap->sensor[i].camclk);
	}
err_ctx_alloc:
	kfree(ctx);

	return ret;
}
예제 #19
0
void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
{
    media_entity_cleanup(&ipipe->subdev.entity);

    v4l2_device_unregister_subdev(&ipipe->subdev);
}
예제 #20
0
void omap4iss_video_cleanup(struct iss_video *video)
{
	media_entity_cleanup(&video->video.entity);
	mutex_destroy(&video->stream_lock);
	mutex_destroy(&video->mutex);
}
예제 #21
0
static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
{
	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
	struct vb2_queue *q = &fimc->vb_queue;
	struct video_device *vfd;
	int ret;

	fimc->fmt = &fimc_lite_formats[0];
	fimc->out_path = FIMC_IO_DMA;

	vfd = video_device_alloc();
	if (!vfd) {
		v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n");
		return -ENOMEM;
	}

	snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
		 fimc->index);

	vfd->fops = &fimc_lite_fops;
	vfd->ioctl_ops = &fimc_lite_ioctl_ops;
	vfd->v4l2_dev = sd->v4l2_dev;
	vfd->minor = -1;
	vfd->release = video_device_release;
	vfd->lock = &fimc->lock;
	fimc->vfd = vfd;
	fimc->ref_count = 0;
	fimc->reqbufs_count = 0;

	INIT_LIST_HEAD(&fimc->pending_buf_q);
	INIT_LIST_HEAD(&fimc->active_buf_q);

	memset(q, 0, sizeof(*q));
	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	q->io_modes = VB2_MMAP | VB2_USERPTR;
	q->ops = &fimc_lite_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->buf_struct_size = sizeof(struct flite_buffer);
	q->drv_priv = fimc;

	vb2_queue_init(q);

	fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
	if (ret)
		goto err;

	video_set_drvdata(vfd, fimc);

	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
	if (ret)
		goto err_vd;

	v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
		  vfd->name, video_device_node_name(vfd));
	return 0;

 err_vd:
	media_entity_cleanup(&vfd->entity);
 err:
	video_device_release(vfd);
	return ret;
}
예제 #22
0
void
atomisp_mipi_csi2_unregister_entities(struct atomisp_mipi_csi2_device *csi2)
{
	media_entity_cleanup(&csi2->subdev.entity);
	v4l2_device_unregister_subdev(&csi2->subdev);
}
예제 #23
0
static int xdmsc_probe(struct platform_device *pdev)
{
	struct xdmsc_dev *xdmsc;
	struct v4l2_subdev *subdev;
	struct v4l2_mbus_framefmt *def_fmt;
	int rval;

	xdmsc = devm_kzalloc(&pdev->dev, sizeof(*xdmsc), GFP_KERNEL);
	if (!xdmsc)
		return -ENOMEM;
	xdmsc->xvip.dev = &pdev->dev;
	rval = xdmsc_parse_of(xdmsc);
	if (rval < 0)
		return rval;
	rval = xvip_init_resources(&xdmsc->xvip);

	/* Reset Demosaic IP */
	gpiod_set_value_cansleep(xdmsc->rst_gpio,
				 XDEMOSAIC_RESET_DEASSERT);

	/* Init V4L2 subdev */
	subdev = &xdmsc->xvip.subdev;
	v4l2_subdev_init(subdev, &xdmsc_ops);
	subdev->dev = &pdev->dev;
	subdev->internal_ops = &xdmsc_internal_ops;
	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;

	/* Default Formats Initialization */
	def_fmt = &xdmsc->default_formats[XVIP_PAD_SINK];
	def_fmt->field = V4L2_FIELD_NONE;
	def_fmt->colorspace = V4L2_COLORSPACE_SRGB;
	def_fmt->width = XDEMOSAIC_DEF_WIDTH;
	def_fmt->height = XDEMOSAIC_DEF_HEIGHT;

	/*
	 * Sink Pad can be any Bayer format.
	 * Default Sink Pad format is RGGB.
	 */
	def_fmt->code = MEDIA_BUS_FMT_SRGGB8_1X8;
	xdmsc->formats[XVIP_PAD_SINK] = *def_fmt;

	def_fmt = &xdmsc->default_formats[XVIP_PAD_SOURCE];
	*def_fmt = xdmsc->default_formats[XVIP_PAD_SINK];

	/* Source Pad has a fixed media bus format of RGB */
	def_fmt->code = MEDIA_BUS_FMT_RBG888_1X24;
	xdmsc->formats[XVIP_PAD_SOURCE] = *def_fmt;

	xdmsc->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	xdmsc->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;

	/* Init Media Entity */
	subdev->entity.ops = &xdmsc_media_ops;
	rval = media_entity_pads_init(&subdev->entity, 2, xdmsc->pads);
	if (rval < 0)
		goto media_error;

	platform_set_drvdata(pdev, xdmsc);
	rval = v4l2_async_register_subdev(subdev);
	if (rval < 0) {
		dev_err(&pdev->dev, "failed to register subdev");
		goto v4l2_subdev_error;
	}
	dev_info(&pdev->dev,
		 "Xilinx Video Demosaic Probe Successful");
	return 0;

v4l2_subdev_error:
	media_entity_cleanup(&subdev->entity);
media_error:
	xvip_cleanup_resources(&xdmsc->xvip);
	return rval;
}
예제 #24
0
static int32_t cam_dummy_platform_probe(struct platform_device *pdev)
{
	int32_t rc = 0;
	const struct of_device_id *match;
	struct msm_video_device *pvdev;

	/* init_waitqueue_head(&cam_dummy_queue.state_wait);*/
	pr_err("%s:%d\n", __func__, __LINE__);
	match = of_match_device(cam_dummy_dt_match, &pdev->dev);

	msm_v4l2_dev = kzalloc(sizeof(*msm_v4l2_dev),
		GFP_KERNEL);
	if (WARN_ON(!msm_v4l2_dev)) {
		rc = -ENOMEM;
		goto probe_end;
	}

	pvdev = kzalloc(sizeof(struct msm_video_device),
		GFP_KERNEL);
	if (WARN_ON(!pvdev)) {
		rc = -ENOMEM;
		goto pvdev_fail;
	}

	pvdev->vdev = video_device_alloc();
	if (WARN_ON(!pvdev->vdev)) {
		rc = -ENOMEM;
		goto video_fail;
	}

#if defined(CONFIG_MEDIA_CONTROLLER)
	msm_v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
		GFP_KERNEL);
	if (!msm_v4l2_dev->mdev) {
		rc = -ENOMEM;
		goto mdev_fail;
	}
	strlcpy(msm_v4l2_dev->mdev->model, MSM_CAMERA_DUMMY_NAME,
			sizeof(msm_v4l2_dev->mdev->model));
	msm_v4l2_dev->mdev->dev = &(pdev->dev);

	rc = media_device_register(msm_v4l2_dev->mdev);
	if (WARN_ON(rc < 0))
		goto media_fail;

	if (WARN_ON((rc == media_entity_init(&pvdev->vdev->entity,
			0, NULL, 0)) < 0))
		goto entity_fail;

	pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
	pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
#endif

	pvdev->vdev->v4l2_dev = msm_v4l2_dev;

	rc = v4l2_device_register(&(pdev->dev), pvdev->vdev->v4l2_dev);
	if (WARN_ON(rc < 0))
		goto register_fail;

	strlcpy(pvdev->vdev->name, "msm-camdummy", sizeof(pvdev->vdev->name));
	pvdev->vdev->release  = video_device_release;
	pvdev->vdev->fops     = &msm_fops_config;
	pvdev->vdev->minor     = -1;
	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
	rc = video_register_device(pvdev->vdev,
		VFL_TYPE_GRABBER, -1);
	if (WARN_ON(rc < 0))
		goto v4l2_fail;

#if defined(CONFIG_MEDIA_CONTROLLER)
	/* FIXME: How to get rid of this messy? */
	pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
#endif

	atomic_set(&pvdev->opened, 0);
	video_set_drvdata(pvdev->vdev, pvdev);

	goto probe_end;

v4l2_fail:
	v4l2_device_unregister(pvdev->vdev->v4l2_dev);
register_fail:
#if defined(CONFIG_MEDIA_CONTROLLER)
	media_entity_cleanup(&pvdev->vdev->entity);
entity_fail:
	media_device_unregister(msm_v4l2_dev->mdev);
media_fail:
	kzfree(msm_v4l2_dev->mdev);
mdev_fail:
#endif
	video_device_release(pvdev->vdev);
video_fail:
	kzfree(pvdev);
pvdev_fail:
	kzfree(msm_v4l2_dev);
probe_end:
	return rc;
}
예제 #25
0
void ispstat_unregister_entities(struct ispstat *stat)
{
	media_entity_cleanup(&stat->subdev.entity);
	v4l2_device_unregister_subdev(&stat->subdev);
}
예제 #26
0
파일: iss_ipipeif.c 프로젝트: 19Dan01/linux
/*
 * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup.
 * @iss: Device pointer specific to the OMAP4 ISS.
 */
void omap4iss_ipipeif_cleanup(struct iss_device *iss)
{
	struct iss_ipipeif_device *ipipeif = &iss->ipipeif;

	media_entity_cleanup(&ipipeif->subdev.entity);
}
예제 #27
0
void atomisp_tpg_unregister_entities(struct atomisp_tpg_device *tpg)
{
	media_entity_cleanup(&tpg->sd.entity);
	v4l2_device_unregister_subdev(&tpg->sd);
}
예제 #28
0
struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
{
	struct v4l2_subdev *subdev;
	struct vsp1_video *video;
	struct vsp1_rwpf *rpf;
	int ret;

	rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL);
	if (rpf == NULL)
		return ERR_PTR(-ENOMEM);

	rpf->max_width = RPF_MAX_WIDTH;
	rpf->max_height = RPF_MAX_HEIGHT;

	rpf->entity.type = VSP1_ENTITY_RPF;
	rpf->entity.index = index;

	ret = vsp1_entity_init(vsp1, &rpf->entity, 2);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Initialize the V4L2 subdev. */
	subdev = &rpf->entity.subdev;
	v4l2_subdev_init(subdev, &rpf_ops);

	subdev->entity.ops = &vsp1_media_ops;
	subdev->internal_ops = &vsp1_subdev_internal_ops;
	snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u",
		 dev_name(vsp1->dev), index);
	v4l2_set_subdevdata(subdev, rpf);
	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;

	vsp1_entity_init_formats(subdev, NULL);

	/* Initialize the video device. */
	video = &rpf->video;

	video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
	video->vsp1 = vsp1;
	video->ops = &rpf_vdev_ops;

	ret = vsp1_video_init(video, &rpf->entity);
	if (ret < 0)
		goto error_video;

	/* Connect the video device to the RPF. */
	ret = media_entity_create_link(&rpf->video.video.entity, 0,
				       &rpf->entity.subdev.entity,
				       RWPF_PAD_SINK,
				       MEDIA_LNK_FL_ENABLED |
				       MEDIA_LNK_FL_IMMUTABLE);
	if (ret < 0)
		goto error_link;

	return rpf;

error_link:
	vsp1_video_cleanup(video);
error_video:
	media_entity_cleanup(&rpf->entity.subdev.entity);
	return ERR_PTR(ret);
}
예제 #29
0
파일: adv7180.c 프로젝트: 020gzh/linux
static int adv7180_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct adv7180_state *state;
	struct v4l2_subdev *sd;
	int ret;

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -EIO;

	v4l_info(client, "chip found @ 0x%02x (%s)\n",
		 client->addr, client->adapter->name);

	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
	if (state == NULL)
		return -ENOMEM;

	state->client = client;
	state->field = V4L2_FIELD_INTERLACED;
	state->chip_info = (struct adv7180_chip_info *)id->driver_data;

	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		state->csi_client = i2c_new_dummy(client->adapter,
				ADV7180_DEFAULT_CSI_I2C_ADDR);
		if (!state->csi_client)
			return -ENOMEM;
	}

	if (state->chip_info->flags & ADV7180_FLAG_I2P) {
		state->vpp_client = i2c_new_dummy(client->adapter,
				ADV7180_DEFAULT_VPP_I2C_ADDR);
		if (!state->vpp_client) {
			ret = -ENOMEM;
			goto err_unregister_csi_client;
		}
	}

	state->irq = client->irq;
	mutex_init(&state->mutex);
	state->autodetect = true;
	if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
		state->powered = true;
	else
		state->powered = false;
	state->input = 0;
	sd = &state->sd;
	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;

	ret = adv7180_init_controls(state);
	if (ret)
		goto err_unregister_vpp_client;

	state->pad.flags = MEDIA_PAD_FL_SOURCE;
	sd->entity.flags |= MEDIA_ENT_F_ATV_DECODER;
	ret = media_entity_pads_init(&sd->entity, 1, &state->pad);
	if (ret)
		goto err_free_ctrl;

	ret = init_device(state);
	if (ret)
		goto err_media_entity_cleanup;

	if (state->irq) {
		ret = request_threaded_irq(client->irq, NULL, adv7180_irq,
					   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
					   KBUILD_MODNAME, state);
		if (ret)
			goto err_media_entity_cleanup;
	}

	ret = v4l2_async_register_subdev(sd);
	if (ret)
		goto err_free_irq;

	return 0;

err_free_irq:
	if (state->irq > 0)
		free_irq(client->irq, state);
err_media_entity_cleanup:
	media_entity_cleanup(&sd->entity);
err_free_ctrl:
	adv7180_exit_controls(state);
err_unregister_vpp_client:
	if (state->chip_info->flags & ADV7180_FLAG_I2P)
		i2c_unregister_device(state->vpp_client);
err_unregister_csi_client:
	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
		i2c_unregister_device(state->csi_client);
	mutex_destroy(&state->mutex);
	return ret;
}
예제 #30
0
static int m5mols_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	const struct m5mols_platform_data *pdata = client->dev.platform_data;
	struct m5mols_info *info;
	struct v4l2_subdev *sd;
	int ret;

	if (pdata == NULL) {
		dev_err(&client->dev, "No platform data\n");
		return -EINVAL;
	}

	if (!gpio_is_valid(pdata->gpio_reset)) {
		dev_err(&client->dev, "No valid RESET GPIO specified\n");
		return -EINVAL;
	}

	if (!client->irq) {
		dev_err(&client->dev, "Interrupt not assigned\n");
		return -EINVAL;
	}

	info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	info->pdata = pdata;
	info->set_power	= pdata->set_power;

	ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST");
	if (ret) {
		dev_err(&client->dev, "Failed to request gpio: %d\n", ret);
		goto out_free;
	}
	gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity);

	ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies);
	if (ret) {
		dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
		goto out_gpio;
	}

	sd = &info->sd;
	v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
	strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;

	sd->internal_ops = &m5mols_subdev_internal_ops;
	info->pad.flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
	if (ret < 0)
		goto out_reg;
	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;

	init_waitqueue_head(&info->irq_waitq);
	mutex_init(&info->lock);

	ret = request_irq(client->irq, m5mols_irq_handler,
			  IRQF_TRIGGER_RISING, MODULE_NAME, sd);
	if (ret) {
		dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
		goto out_me;
	}
	info->res_type = M5MOLS_RESTYPE_MONITOR;
	info->ffmt[0] = m5mols_default_ffmt[0];
	info->ffmt[1] =	m5mols_default_ffmt[1];

	ret = m5mols_sensor_power(info, true);
	if (ret)
		goto out_irq;

	ret = m5mols_fw_start(sd);
	if (!ret)
		ret = m5mols_init_controls(sd);

	ret = m5mols_sensor_power(info, false);
	if (!ret)
		return 0;
out_irq:
	free_irq(client->irq, sd);
out_me:
	media_entity_cleanup(&sd->entity);
out_reg:
	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
out_gpio:
	gpio_free(pdata->gpio_reset);
out_free:
	kfree(info);
	return ret;
}