static int init_fim_controls(struct imx_media_fim *fim)
{
	struct v4l2_ctrl_handler *hdlr = &fim->ctrl_handler;
	int i, ret;

	v4l2_ctrl_handler_init(hdlr, FIM_NUM_CONTROLS + FIM_NUM_ICAP_CONTROLS);

	for (i = 0; i < FIM_NUM_CONTROLS; i++)
		fim->ctrl[i] = v4l2_ctrl_new_custom(hdlr,
						    &fim_ctrl[i],
						    NULL);
	for (i = 0; i < FIM_NUM_ICAP_CONTROLS; i++)
		fim->icap_ctrl[i] = v4l2_ctrl_new_custom(hdlr,
							 &fim_icap_ctrl[i],
							 NULL);
	if (hdlr->error) {
		ret = hdlr->error;
		goto err_free;
	}

	v4l2_ctrl_cluster(FIM_NUM_CONTROLS, fim->ctrl);
	v4l2_ctrl_cluster(FIM_NUM_ICAP_CONTROLS, fim->icap_ctrl);

	return 0;
err_free:
	v4l2_ctrl_handler_free(hdlr);
	return ret;
}
/*
 * m5mols_init_controls - initialization using v4l2_ctrl.
 */
static int m5mols_init_controls(struct m5mols_info *info)
{
	struct v4l2_subdev *sd = &info->sd;
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	u16 max_ex_mon;
	int ret;

	/* check minimum & maximum of M5MOLS controls */
	ret = i2c_r16_ae(sd, CAT3_MAX_GAIN_MON, (u32 *)&max_ex_mon);
	if (ret)
		return ret;

	/* set the controls using v4l2 control frameworks */
	v4l2_ctrl_handler_init(&info->handle, 9);

	info->colorfx = v4l2_ctrl_new_std_menu(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_COLORFX,
			9, 1, V4L2_COLORFX_NONE);
	info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
			1, 0, V4L2_EXPOSURE_AUTO);
	info->exposure = v4l2_ctrl_new_std(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
			0, max_ex_mon, 1, (int)max_ex_mon/2);
	info->autofocus = v4l2_ctrl_new_std(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_FOCUS_AUTO,
			0, 1, 1, 0);
	info->autowb = v4l2_ctrl_new_std(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
			0, 1, 1, 1);
	info->saturation = v4l2_ctrl_new_std(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_SATURATION,
			0, 6, 1, 3);
	info->zoom = v4l2_ctrl_new_std(&info->handle,
			&m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE,
			0, 70, 1, 0);
	info->jpeg_size = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[0],
			NULL);
	info->encoded_size = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[1],
			NULL);

	sd->ctrl_handler = &info->handle;

	if (info->handle.error) {
		dev_err(&client->dev, "Failed to init controls, %d\n", ret);
		v4l2_ctrl_handler_free(&info->handle);
		return info->handle.error;
	}

	v4l2_ctrl_cluster(2, &info->autoexposure);
	/* If above ctrl value is not good image, so it is better that not set */
	v4l2_ctrl_handler_setup(&info->handle);

	return 0;
}
Exemple #3
0
static int adv7180_init_controls(struct adv7180_state *state)
{
	v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);

	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN,
			  ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_CONTRAST, ADV7180_CON_MIN,
			  ADV7180_CON_MAX, 1, ADV7180_CON_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_SATURATION, ADV7180_SAT_MIN,
			  ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_HUE, ADV7180_HUE_MIN,
			  ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
	v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);

	state->sd.ctrl_handler = &state->ctrl_hdl;
	if (state->ctrl_hdl.error) {
		int err = state->ctrl_hdl.error;

		v4l2_ctrl_handler_free(&state->ctrl_hdl);
		return err;
	}
	v4l2_ctrl_handler_setup(&state->ctrl_hdl);

	return 0;
}
Exemple #4
0
static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc)
{
	struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler;
	struct v4l2_subdev *sd = &fimc->subdev;
	int ret;

	v4l2_subdev_init(sd, &fimc_lite_subdev_ops);
	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
	snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index);

	fimc->subdev_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	fimc->subdev_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
				fimc->subdev_pads, 0);
	if (ret)
		return ret;

	v4l2_ctrl_handler_init(handler, 1);
	fimc->test_pattern = v4l2_ctrl_new_custom(handler, &fimc_lite_ctrl,
						  NULL);
	if (handler->error) {
		media_entity_cleanup(&sd->entity);
		return handler->error;
	}

	sd->ctrl_handler = handler;
	sd->internal_ops = &fimc_lite_subdev_internal_ops;
	sd->entity.ops = &fimc_lite_subdev_media_ops;
	v4l2_set_subdevdata(sd, fimc);

	return 0;
}
Exemple #5
0
/*
 * i2c_driver function
 */
static int aksensor_probe(struct i2c_client *client,
			const struct i2c_device_id *did)
{
	struct aksensor_priv        *priv;
	struct soc_camera_link	*icl = soc_camera_i2c_to_link(client);
	struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
	int i, ret;

	SENDBG("entry %s\n", __func__);

	if (!icl || !icl->priv) {
		dev_err(&client->dev, "AKSENSOR: missing platform data!\n");
		return -EINVAL;
	}

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

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		return -ENOMEM;
	}	

	priv->info = icl->priv;
	v4l2_i2c_subdev_init(&priv->subdev, client, &aksensor_subdev_ops);

	ret = aksensor_video_probe(client);
	
	if (ret) {
		kfree(priv);
		return ret;
	}

	v4l2_ctrl_handler_init(&priv->hdl, cur_sensor_info->nr_ctrls);
	for (i = 0; i < cur_sensor_info->nr_ctrls; i++)
		v4l2_ctrl_new_custom(&priv->hdl, &cur_sensor_info->ctrls[i], NULL);
	priv->subdev.ctrl_handler = &priv->hdl;
	if (priv->hdl.error) {
		int err = priv->hdl.error;
		v4l2_ctrl_handler_free(&priv->hdl);
		kfree(priv);
		return err;
	}

	// init sensor resolution, default VGA
	for (i = 0; i < cur_sensor_info->num_resolution; i++)
		if (!strcmp(cur_sensor_info->resolution[i].name, "VGA")) {
		priv->win.width = cur_sensor_info->resolution[i].width; 
		priv->win.height = cur_sensor_info->resolution[i].height;
	}
	sensor_dbg("%s: priv->win.width=%d priv->win.height=%d\n",
			__func__, priv->win.width, priv->win.height);
	return ret;
}
Exemple #6
0
struct vsp1_clu *vsp1_clu_create(struct vsp1_device *vsp1)
{
	struct vsp1_clu *clu;
	int ret;

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

	spin_lock_init(&clu->lock);

	clu->entity.ops = &clu_entity_ops;
	clu->entity.type = VSP1_ENTITY_CLU;

	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 2, &clu_ops,
			       MEDIA_ENT_F_PROC_VIDEO_LUT);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Initialize the control handler. */
	v4l2_ctrl_handler_init(&clu->ctrls, 2);
	v4l2_ctrl_new_custom(&clu->ctrls, &clu_table_control, NULL);
	v4l2_ctrl_new_custom(&clu->ctrls, &clu_mode_control, NULL);

	clu->entity.subdev.ctrl_handler = &clu->ctrls;

	if (clu->ctrls.error) {
		dev_err(vsp1->dev, "clu: failed to initialize controls\n");
		ret = clu->ctrls.error;
		vsp1_entity_destroy(&clu->entity);
		return ERR_PTR(ret);
	}

	v4l2_ctrl_handler_setup(&clu->ctrls);

	return clu;
}
Exemple #7
0
static int msm_gesture_init_ctrl(struct v4l2_subdev *sd,
	struct msm_gesture_ctrl *p_gesture_ctrl)
{
	int rc = 0;
	p_gesture_ctrl->num_ctrls = 1;
	p_gesture_ctrl->ctrl_handler.error = 0;
	v4l2_ctrl_handler_init(&p_gesture_ctrl->ctrl_handler,
		p_gesture_ctrl->num_ctrls);
	v4l2_ctrl_new_custom(&p_gesture_ctrl->ctrl_handler,
		&msm_gesture_ctrl_filter, p_gesture_ctrl);
	if (p_gesture_ctrl->ctrl_handler.error) {
		int err = p_gesture_ctrl->ctrl_handler.error;
		D("%s: error adding control %d", __func__, err);
		p_gesture_ctrl->ctrl_handler.error = 0;
	}
	sd->ctrl_handler = &p_gesture_ctrl->ctrl_handler;
	return rc;
}
Exemple #8
0
int mt9m111_init_controls(struct sd *sd)
{
	struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;

	sd->gspca_dev.vdev.ctrl_handler = hdl;
	v4l2_ctrl_handler_init(hdl, 7);

	sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
					       V4L2_CID_AUTO_WHITE_BALANCE,
					       0, 1, 1, 0);
	sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
	sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
					V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
					MT9M111_RED_GAIN_DEFAULT);
	sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
					V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
					MT9M111_BLUE_GAIN_DEFAULT);

	v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
			  (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
			  MT9M111_DEFAULT_GAIN);

	sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
				      0, 1, 1, 0);
	sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
				      0, 1, 1, 0);

	if (hdl->error) {
		pr_err("Could not initialize controls\n");
		return hdl->error;
	}

	v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
	v4l2_ctrl_cluster(2, &sd->hflip);

	return 0;
}
Exemple #9
0
struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
{
	struct vsp1_lut *lut;
	int ret;

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

	spin_lock_init(&lut->lock);

	lut->entity.ops = &lut_entity_ops;
	lut->entity.type = VSP1_ENTITY_LUT;

	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops,
			       MEDIA_ENT_F_PROC_VIDEO_LUT);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Initialize the control handler. */
	v4l2_ctrl_handler_init(&lut->ctrls, 1);
	v4l2_ctrl_new_custom(&lut->ctrls, &lut_table_control, NULL);

	lut->entity.subdev.ctrl_handler = &lut->ctrls;

	if (lut->ctrls.error) {
		dev_err(vsp1->dev, "lut: failed to initialize controls\n");
		ret = lut->ctrls.error;
		vsp1_entity_destroy(&lut->entity);
		return ERR_PTR(ret);
	}

	v4l2_ctrl_handler_setup(&lut->ctrls);

	return lut;
}
/*
 * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
 * @asd: ISP CCDC module
 *
 * Return 0 on success and a negative error code on failure.
 */
static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
{
	struct v4l2_subdev *sd = &asd->subdev;
	struct media_pad *pads = asd->pads;
	struct media_entity *me = &sd->entity;
	int ret;

	asd->input = ATOMISP_SUBDEV_INPUT_NONE;

	v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
	strlcpy(sd->name, "ATOM ISP SUBDEV", sizeof(sd->name));
	v4l2_set_subdevdata(sd, asd);
	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;

	pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
	pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
	pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;

	asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
		V4L2_MBUS_FMT_SBGGR10_1X10;
	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
		V4L2_MBUS_FMT_SBGGR10_1X10;
	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
		V4L2_MBUS_FMT_SBGGR10_1X10;
	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
		V4L2_MBUS_FMT_SBGGR10_1X10;

	me->ops = &isp_subdev_media_ops;
	me->type = MEDIA_ENT_T_V4L2_SUBDEV;
	ret = media_entity_init(me, ATOMISP_SUBDEV_PADS_NUM, pads, 0);
	if (ret < 0)
		return ret;

	atomisp_init_subdev_pipe(asd, &asd->video_in,
			V4L2_BUF_TYPE_VIDEO_OUTPUT);

	atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
			V4L2_BUF_TYPE_VIDEO_CAPTURE);

	atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
			V4L2_BUF_TYPE_VIDEO_CAPTURE);

	atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
			V4L2_BUF_TYPE_VIDEO_CAPTURE);

	ret = atomisp_video_init(&asd->video_in, "MEMORY");
	if (ret < 0)
		return ret;

	ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE");
	if (ret < 0)
		return ret;

	ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER");
	if (ret < 0)
		return ret;

	ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW");
	if (ret < 0)
		return ret;

	/* Connect the isp subdev to the video node. */
	ret = media_entity_create_link(&asd->video_in.vdev.entity,
		0, &asd->subdev.entity, ATOMISP_SUBDEV_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	ret = media_entity_create_link(&asd->subdev.entity,
		ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
		&asd->video_out_preview.vdev.entity, 0, 0);
	if (ret < 0)
		return ret;

	ret = media_entity_create_link(&asd->subdev.entity,
		ATOMISP_SUBDEV_PAD_SOURCE_VF,
		&asd->video_out_vf.vdev.entity, 0, 0);
	if (ret < 0)
		return ret;

	ret = media_entity_create_link(&asd->subdev.entity,
		ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
		&asd->video_out_capture.vdev.entity, 0, 0);
	if (ret < 0)
		return ret;

	ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
	if (ret)
		return ret;

	asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
						    &ctrl_fmt_auto, NULL);
	asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
						    &ctrl_run_mode, NULL);
	asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
						&ctrl_vfpp, NULL);
	asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
					     &ctrl_continuous_mode, NULL);
	asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
					     &ctrl_continuous_viewfinder,
					     NULL);
	asd->continuous_raw_buffer_size =
			v4l2_ctrl_new_custom(&asd->ctrl_handler,
					     &ctrl_continuous_raw_buffer_size,
					     NULL);

	/* Make controls visible on subdev as well. */
	asd->subdev.ctrl_handler = &asd->ctrl_handler;

	return asd->ctrl_handler.error;
}
static int ov5693_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct ov5693_device *dev;
	int i;
	int ret;

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

	mutex_init(&dev->input_lock);

	/*
	 * Initialize related res members of dev.
	 */
	dev->fmt_idx = 0;
	dev->ov5693_res = ov5693_res_preview;
	dev->curr_res_num = N_RES_PREVIEW;

	v4l2_i2c_subdev_init(&(dev->sd), client, &ov5693_ops);

	if (client->dev.platform_data) {
		ret = ov5693_s_config(&dev->sd, client->irq,
				       client->dev.platform_data);
		if (ret)
			goto out_free;
	}

	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
	dev->format.code = V4L2_MBUS_FMT_SBGGR10_1X10;
	dev->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
	dev->vcm_driver = &ov5693_vcm_ops;

	ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, ARRAY_SIZE(ctrls) + 1);
	if (ret) {
		ov5693_remove(client);
		return ret;
	}

	dev->run_mode = v4l2_ctrl_new_custom(&dev->ctrl_handler,
					     &ctrl_run_mode, NULL);

	for (i = 0; i < ARRAY_SIZE(ctrls); i++)
		v4l2_ctrl_new_custom(&dev->ctrl_handler, &ctrls[i], NULL);

	if (dev->ctrl_handler.error) {
		ov5693_remove(client);
		return dev->ctrl_handler.error;
	}

	dev->ctrl_handler.lock = &dev->input_lock;
	dev->sd.ctrl_handler = &dev->ctrl_handler;
	v4l2_ctrl_handler_setup(&dev->ctrl_handler);

	ret = media_entity_init(&dev->sd.entity, 1, &dev->pad, 0);
	if (ret)
		ov5693_remove(client);

	/* vcm initialization */
	if (dev->vcm_driver && dev->vcm_driver->init)
		ret = dev->vcm_driver->init(&dev->sd);
	if (ret) {
		dev_err(&client->dev, "vcm init failed.\n");
		ov5693_remove(client);
	}

	return ret;
out_free:
	v4l2_device_unregister_subdev(&dev->sd);
	devm_kfree(&client->dev, dev);
	return ret;
}
static int pixter_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct pixter_device *dev;
	const struct atomisp_camera_caps *caps = NULL;
	char *pixter_name = NULL;
	struct pixter_setting *settings;
	struct pixter_dbgfs_data *dbgfs_data;
	u32 reg_val, i, j;
	int ret;

	/* allocate sensor device & init sub device */
	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	mutex_init(&dev->input_lock);

	dev->dbg_timing.mipi_clk = PIXTER_DEF_CLOCK;

	v4l2_i2c_subdev_init(&dev->sd, client, &pixter_ops);

	if (client->dev.platform_data) {
		dev->platform_data = client->dev.platform_data;
		ret = dev->platform_data->csi_cfg(&dev->sd, 1);
		if (ret)
			goto out_free;
		if (dev->platform_data->get_camera_caps)
			caps = dev->platform_data->get_camera_caps();
		else
			caps = atomisp_get_default_camera_caps();
		dev->caps = caps;
	}

	dev->mipi_info = v4l2_get_subdev_hostdata(&dev->sd);
	if (!dev->mipi_info) {
		dev_err(&client->dev, "Faild to get mipi info.\n");
		goto out_free;
	}

	/* Get the number of mipi lanes */
	dev->dbg_timing.mipi_lanes_num = dev->mipi_info->num_lanes;

	dev->regmap = devm_regmap_init_i2c(client,
					   &pixter_reg_config);
	if (IS_ERR(dev->regmap)) {
		ret = PTR_ERR(dev->regmap);
		dev_err(&client->dev,
			"Failed to allocate register map: %d\n", ret);
		goto out_free;
	}

	/* Load Pixter settings */
	pixter_write_reg(&dev->sd, PIXTER_SDRAM_BASE, 0);
	pixter_read_reg(&dev->sd, PIXTER_MAGIC_ADDR, &reg_val);
	if (reg_val != PIXTER_MAGIC) {
		dev_err(&client->dev,
			"PIXTER magic does not match. Got 0x%X\n", reg_val);
		ret = -EIO;
		goto out_free;
	}
	pixter_read_reg(&dev->sd, PIXTER_SETTING_NUM, &dev->setting_num);
	dev->settings = devm_kzalloc(&client->dev,
		sizeof(struct pixter_setting) *
		dev->setting_num, GFP_KERNEL);
	if (!dev->settings) {
		dev_err(&client->dev, "OOM when allocating settings.\n");
		ret = -ENOMEM;
		goto out_free;
	}
	settings = dev->settings;

	ret = pixter_read_buf(&dev->sd, PIXTER_SETTING_START,
			sizeof(struct pixter_setting) * dev->setting_num,
			settings);
	if (ret) {
		dev_err(&client->dev, "Failed to read Pixter settings\n");
		goto out_free;
	}

	/* Find settings that match the current device. */
	for (i = 0, j = 0; i < dev->setting_num; i++) {
		if (caps->sensor[0].stream_num == settings[i].valid_vc_num)
			settings[j++] = settings[i];
	}
	dev->setting_num = j;
	dev_info(&client->dev, "Setting num=%d\n", dev->setting_num);
	if (!dev->setting_num) {
		dev_err(&client->dev, "No matched settings loaded.\n");
		ret = -ENODEV;
		goto out_free;
	}

	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
	dev->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
	dev->format.code = format_bridge[
		settings[0].vc[settings[0].def_vc].format].v4l2_format;

	/*
	 * sd->name is updated with sensor driver name by the v4l2.
	 * change it to sensor name in this case.
	 */
	if (dev->mipi_info->port == ATOMISP_CAMERA_PORT_PRIMARY)
		pixter_name = PIXTER_0;
	else if(dev->mipi_info->port == ATOMISP_CAMERA_PORT_SECONDARY)
		pixter_name = PIXTER_1;
	else
		pixter_name = PIXTER_2;
	snprintf(dev->sd.name, sizeof(dev->sd.name), "%s %d-%04x",
		pixter_name, i2c_adapter_id(client->adapter), client->addr);

        dev_info(&client->dev, "%s dev->sd.name: %s\n", __func__, dev->sd.name);

	dev->sd.entity.ops = &pixter_entity_ops;
	dev->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;

	ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, ARRAY_SIZE(ctrls));
	if (ret)
		goto out_free;

	for (i = 0; i < ARRAY_SIZE(ctrls); i++)
		v4l2_ctrl_new_custom(&dev->ctrl_handler, &ctrls[i], NULL);

	if (dev->ctrl_handler.error) {
		ret = -EINVAL;
		goto out_free;
	}

	/* Use same lock for controls as for everything else. */
	dev->ctrl_handler.lock = &dev->input_lock;
	dev->sd.ctrl_handler = &dev->ctrl_handler;
	v4l2_ctrl_handler_setup(&dev->ctrl_handler);

	ret = media_entity_init(&dev->sd.entity, 1, &dev->pad, 0);
	if (ret)
		goto out_free;

	/* Create debugfs nodes. */
	dev->dbgfs_data = devm_kzalloc(&client->dev,
		sizeof(struct pixter_dbgfs_data) *
		(ARRAY_SIZE(dbgfs) + dev->setting_num + 1), GFP_KERNEL);
	if (!dev->dbgfs_data)
		goto out_free;
	dbgfs_data = dev->dbgfs_data;
	dbgfs_data[0].entry = debugfs_create_dir(pixter_name, NULL);
	for (i = 1; i < ARRAY_SIZE(dbgfs); i++) {
		struct dentry *parent;
		for (j = 0; j < i; j++) {
			if (!strcmp(dbgfs[i].parent, dbgfs[j].name))
				break;
		}
		if (j == i)
			continue;
		parent = dbgfs_data[j].entry;
		dbgfs_data[i].dev = dev;
		dbgfs_data[i].ptr = (u8*)dev + dbgfs[i].offset;
		if (dbgfs[i].type == DBGFS_DIR)
			dbgfs_data[i].entry = debugfs_create_dir(dbgfs[i].name,
				parent);
		else
			dbgfs_data[i].entry = debugfs_create_file(dbgfs[i].name,
				dbgfs[i].mode, parent,
				&dbgfs_data[i], &pixter_dbgfs_fops);
	}
	/* Create setting nodes. */
	dev->setting_en = devm_kzalloc(&client->dev,
		sizeof(u32) * dev->setting_num, GFP_KERNEL);
	if (!dev->setting_en)
		goto out_free;
	dbgfs_data[i].entry = debugfs_create_dir("settings",
		dbgfs_data[0].entry);
	for (j = 0; j < dev->setting_num; j++) {
		char setting_name[32];
		u32 idx = i + j + 1;
		struct pixter_vc_setting *vc =
			&settings[j].vc[settings[j].def_vc];

		dev->setting_en[j] = 1;
		snprintf(setting_name, 32, "%d.%dx%d_%s@%d", j, vc->width,
			vc->height, format_bridge[vc->format].name, vc->fps);
		dbgfs_data[idx].dev = dev;
		dbgfs_data[idx].ptr = &dev->setting_en[j];
		dbgfs_data[idx].entry = debugfs_create_file(setting_name,
				S_IRUSR|S_IWUSR, dbgfs_data[i].entry,
				&dbgfs_data[idx], &pixter_dbgfs_fops);
	}
	pixter_read_mipi_timing(&dev->sd);

	return 0;

out_free:
	pixter_remove(client);
	return ret;
}
Exemple #13
0
int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
		bool show_ccs_out, bool no_error_inj,
		bool has_sdtv, bool has_hdmi)
{
	struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
	struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
	struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
	struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
	struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
	struct v4l2_ctrl_handler *hdl_loop_out = &dev->ctrl_hdl_loop_out;
	struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
	struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
	struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
	struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
	struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
	struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
	struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
	struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
		.ops = &vivid_vid_cap_ctrl_ops,
		.id = VIVID_CID_DV_TIMINGS,
		.name = "DV Timings",
		.type = V4L2_CTRL_TYPE_MENU,
	};
	int i;

	v4l2_ctrl_handler_init(hdl_user_gen, 10);
	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_user_vid, 9);
	v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_user_aud, 2);
	v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_streaming, 8);
	v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
	v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_loop_out, 1);
	v4l2_ctrl_new_custom(hdl_loop_out, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_vid_cap, 55);
	v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_vid_out, 26);
	v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
	v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_vbi_out, 19);
	v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_radio_rx, 17);
	v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_radio_tx, 17);
	v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
	v4l2_ctrl_handler_init(hdl_sdr_cap, 18);
	v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);

	/* User Controls */
	dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
		V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
	dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
	if (dev->has_vid_cap) {
		dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
		for (i = 0; i < MAX_INPUTS; i++)
			dev->input_brightness[i] = 128;
		dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_CONTRAST, 0, 255, 1, 128);
		dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_SATURATION, 0, 255, 1, 128);
		dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_HUE, -128, 128, 1, 0);
		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_HFLIP, 0, 1, 1, 0);
		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_VFLIP, 0, 1, 1, 0);
		dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
		dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_GAIN, 0, 255, 1, 100);
		dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
			V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
	}
	dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
	dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
	dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
	dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
	dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
	dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
	dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
	dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);

	if (dev->has_vid_cap) {
		/* Image Processing Controls */
		struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
			.ops = &vivid_vid_cap_ctrl_ops,
			.id = VIVID_CID_TEST_PATTERN,
			.name = "Test Pattern",
			.type = V4L2_CTRL_TYPE_MENU,
			.max = TPG_PAT_NOISE,
			.qmenu = tpg_pattern_strings,
		};

		dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
				&vivid_ctrl_test_pattern, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
		if (show_ccs_cap) {
			dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
				&vivid_ctrl_has_crop_cap, NULL);
			dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
				&vivid_ctrl_has_compose_cap, NULL);
			dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
				&vivid_ctrl_has_scaler_cap, NULL);
		}

		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
		dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
			&vivid_ctrl_colorspace, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
	}

	if (dev->has_vid_out && show_ccs_out) {
		dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
			&vivid_ctrl_has_crop_out, NULL);
		dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
			&vivid_ctrl_has_compose_out, NULL);
		dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
			&vivid_ctrl_has_scaler_out, NULL);
	}

	/*
	 * Testing this driver with v4l2-compliance will trigger the error
	 * injection controls, and after that nothing will work as expected.
	 * So we have a module option to drop these error injecting controls
	 * allowing us to run v4l2_compliance again.
	 */
	if (!no_error_inj) {
		v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
	}

	if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
		if (dev->has_vid_cap)
			v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
		dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
			&vivid_ctrl_std_signal_mode, NULL);
		dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
			&vivid_ctrl_standard, NULL);
		if (dev->ctrl_std_signal_mode)
			v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
		if (dev->has_raw_vbi_cap)
			v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
	}

	if (has_hdmi && dev->has_vid_cap) {
		dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
					&vivid_ctrl_dv_timings_signal_mode, NULL);

		vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
		vivid_ctrl_dv_timings.qmenu =
			(const char * const *)dev->query_dv_timings_qmenu;
		dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
			&vivid_ctrl_dv_timings, NULL);
		if (dev->ctrl_dv_timings_signal_mode)
			v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);

		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
		dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
			&vivid_ctrl_limited_rgb_range, NULL);
		dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
			&vivid_vid_cap_ctrl_ops,
			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
			0, V4L2_DV_RGB_RANGE_AUTO);
	}
	if (has_hdmi && dev->has_vid_out) {
		/*
		 * We aren't doing anything with this at the moment, but
		 * HDMI outputs typically have this controls.
		 */
		dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
			V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
			0, V4L2_DV_RGB_RANGE_AUTO);
		dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
			0, V4L2_DV_TX_MODE_HDMI);
	}
	if ((dev->has_vid_cap && dev->has_vid_out) ||
	    (dev->has_vbi_cap && dev->has_vbi_out))
		v4l2_ctrl_new_custom(hdl_loop_out, &vivid_ctrl_loop_video, NULL);

	if (dev->has_fb)
		v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_clear_fb, NULL);

	if (dev->has_radio_rx) {
		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
		v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
		dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
		dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
		dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
		dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
		dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
		dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
			&vivid_radio_rx_ctrl_ops,
			V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
	}
	if (dev->has_radio_tx) {
		v4l2_ctrl_new_custom(hdl_radio_tx,
			&vivid_ctrl_radio_tx_rds_blockio, NULL);
		dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
		dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
		dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
		if (dev->radio_tx_rds_psname)
			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
		dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
		if (dev->radio_tx_rds_radiotext)
			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
			       "This is a VIVID default Radio Text template text, change at will");
		dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
		dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
		dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
		dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
		dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
		dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
		dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
			&vivid_radio_tx_ctrl_ops,
			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
	}
	if (hdl_user_gen->error)
		return hdl_user_gen->error;
	if (hdl_user_vid->error)
		return hdl_user_vid->error;
	if (hdl_user_aud->error)
		return hdl_user_aud->error;
	if (hdl_streaming->error)
		return hdl_streaming->error;
	if (hdl_sdr_cap->error)
		return hdl_sdr_cap->error;
	if (hdl_loop_out->error)
		return hdl_loop_out->error;

	if (dev->autogain)
		v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);

	if (dev->has_vid_cap) {
		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL);
		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL);
		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL);
		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL);
		if (hdl_vid_cap->error)
			return hdl_vid_cap->error;
		dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
	}
	if (dev->has_vid_out) {
		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL);
		v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL);
		v4l2_ctrl_add_handler(hdl_vid_out, hdl_loop_out, NULL);
		if (hdl_vid_out->error)
			return hdl_vid_out->error;
		dev->vid_out_dev.ctrl_handler = hdl_vid_out;
	}
	if (dev->has_vbi_cap) {
		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL);
		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL);
		if (hdl_vbi_cap->error)
			return hdl_vbi_cap->error;
		dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
	}
	if (dev->has_vbi_out) {
		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL);
		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_loop_out, NULL);
		if (hdl_vbi_out->error)
			return hdl_vbi_out->error;
		dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
	}
	if (dev->has_radio_rx) {
		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL);
		if (hdl_radio_rx->error)
			return hdl_radio_rx->error;
		dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
	}
	if (dev->has_radio_tx) {
		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL);
		if (hdl_radio_tx->error)
			return hdl_radio_tx->error;
		dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
	}
	if (dev->has_sdr_cap) {
		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL);
		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL);
		if (hdl_sdr_cap->error)
			return hdl_sdr_cap->error;
		dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
	}
	return 0;
}

void vivid_free_controls(struct vivid_dev *dev)
{
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
	v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_out);
}
Exemple #14
0
int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
{
	int ret;
	int i;

	init_waitqueue_head(&solo_dev->disp_thread_wait);
	spin_lock_init(&solo_dev->slock);
	mutex_init(&solo_dev->lock);
	INIT_LIST_HEAD(&solo_dev->vidq_active);

	solo_dev->vfd = video_device_alloc();
	if (!solo_dev->vfd)
		return -ENOMEM;

	*solo_dev->vfd = solo_v4l2_template;
	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
	solo_dev->vfd->queue = &solo_dev->vidq;
	solo_dev->vfd->lock = &solo_dev->lock;
	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
	if (solo_dev->disp_hdl.error) {
		ret = solo_dev->disp_hdl.error;
		goto fail;
	}
	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;

	video_set_drvdata(solo_dev->vfd, solo_dev);

	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
	solo_dev->vidq.ops = &solo_video_qops;
	solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
	solo_dev->vidq.drv_priv = solo_dev;
	solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	solo_dev->vidq.gfp_flags = __GFP_DMA32;
	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
	solo_dev->vidq.lock = &solo_dev->lock;
	ret = vb2_queue_init(&solo_dev->vidq);
	if (ret < 0)
		goto fail;

	solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
	if (IS_ERR(solo_dev->alloc_ctx)) {
		dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
		return PTR_ERR(solo_dev->alloc_ctx);
	}

	/* Cycle all the channels and clear */
	for (i = 0; i < solo_dev->nr_chans; i++) {
		solo_v4l2_set_ch(solo_dev, i);
		while (erase_off(solo_dev))
			/* Do nothing */;
	}

	/* Set the default display channel */
	solo_v4l2_set_ch(solo_dev, 0);
	while (erase_off(solo_dev))
		/* Do nothing */;

	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
	if (ret < 0)
		goto fail;

	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
		 SOLO6X10_NAME, solo_dev->vfd->num);

	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
		 solo_dev->nr_chans, solo_dev->nr_ext);

	return 0;

fail:
	video_device_release(solo_dev->vfd);
	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
	solo_dev->vfd = NULL;
	return ret;
}
static int lm3554_probe(struct i2c_client *client)
{
	int err = 0;
	struct lm3554 *flash;
	unsigned int i;
	int ret;

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

	flash->pdata = lm3554_platform_data_func(client);

	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;
	ret =
	    v4l2_ctrl_handler_init(&flash->ctrl_handler,
				   ARRAY_SIZE(lm3554_controls));
	if (ret) {
		dev_err(&client->dev, "error initialize a ctrl_handler.\n");
		goto fail2;
	}

	for (i = 0; i < ARRAY_SIZE(lm3554_controls); i++)
		v4l2_ctrl_new_custom(&flash->ctrl_handler, &lm3554_controls[i],
				     NULL);

	if (flash->ctrl_handler.error) {

		dev_err(&client->dev, "ctrl_handler error.\n");
		goto fail2;
	}

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

	flash->sd.entity.function = MEDIA_ENT_F_FLASH;

	mutex_init(&flash->power_lock);

	timer_setup(&flash->flash_off_delay, lm3554_flash_off_delay, 0);

	err = lm3554_gpio_init(client);
	if (err) {
		dev_err(&client->dev, "gpio request/direction_output fail");
		goto fail2;
	}
	return atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH);
fail2:
	media_entity_cleanup(&flash->sd.entity);
	v4l2_ctrl_handler_free(&flash->ctrl_handler);
fail1:
	v4l2_device_unregister_subdev(&flash->sd);
	kfree(flash);

	return err;
}
Exemple #16
0
/* si4713_probe - probe for the device */
static int si4713_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	struct si4713_device *sdev;
	struct v4l2_ctrl_handler *hdl;
	struct si4713_platform_data *pdata = client->dev.platform_data;
	struct device_node *np = client->dev.of_node;
	struct radio_si4713_platform_data si4713_pdev_pdata;
	struct platform_device *si4713_pdev;
	int rval;

	sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
	if (!sdev) {
		dev_err(&client->dev, "Failed to alloc video device.\n");
		rval = -ENOMEM;
		goto exit;
	}

	sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(sdev->gpio_reset)) {
		rval = PTR_ERR(sdev->gpio_reset);
		dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
		goto exit;
	}

	sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
	if (IS_ERR(sdev->vdd)) {
		rval = PTR_ERR(sdev->vdd);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
		sdev->vdd = NULL;
	}

	sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
	if (IS_ERR(sdev->vio)) {
		rval = PTR_ERR(sdev->vio);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
		sdev->vio = NULL;
	}

	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);

	init_completion(&sdev->work);

	hdl = &sdev->ctrl_handler;
	v4l2_ctrl_handler_init(hdl, 20);
	sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);

	sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
	sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
	sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
	sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
	sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
	sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
	sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
	sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
	sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
	sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
	sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
	sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
			10, DEFAULT_RDS_DEVIATION);
	/*
	 * Report step as 8. From RDS spec, psname
	 * should be 8. But there are receivers which scroll strings
	 * sized as 8xN.
	 */
	sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
	/*
	 * Report step as 32 (2A block). From RDS spec,
	 * radio text should be 32 for 2A block. But there are receivers
	 * which scroll strings sized as 32xN. Setting default to 32.
	 */
	sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);

	sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
	sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
			MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
	sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
			MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);

	sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
	sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
			DEFAULT_ACOMP_GAIN);
	sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
			MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1,
			DEFAULT_ACOMP_THRESHOLD);
	sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
			MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
	sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
			MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);

	sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
	sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
			10, DEFAULT_PILOT_DEVIATION);
	sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
			1, DEFAULT_PILOT_FREQUENCY);

	sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_PREEMPHASIS,
			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
	sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_POWER_LEVEL, 0, SI4713_MAX_POWER,
			1, DEFAULT_POWER_LEVEL);
	sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, SI4713_MAX_ANTCAP,
			1, 0);

	if (hdl->error) {
		rval = hdl->error;
		goto free_ctrls;
	}
	v4l2_ctrl_cluster(29, &sdev->mute);
	sdev->sd.ctrl_handler = hdl;

	if (client->irq) {
		rval = devm_request_irq(&client->dev, client->irq,
			si4713_handler, IRQF_TRIGGER_FALLING,
			client->name, sdev);
		if (rval < 0) {
			v4l2_err(&sdev->sd, "Could not request IRQ\n");
			goto free_ctrls;
		}
		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
	} else {
		v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
	}

	rval = si4713_initialize(sdev);
	if (rval < 0) {
		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
		goto free_ctrls;
	}

	if (!np && (!pdata || !pdata->is_platform_device))
		return 0;

	si4713_pdev = platform_device_alloc("radio-si4713", -1);
	if (!si4713_pdev) {
		rval = -ENOMEM;
		goto put_main_pdev;
	}

	si4713_pdev_pdata.subdev = client;
	rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
					sizeof(si4713_pdev_pdata));
	if (rval)
		goto put_main_pdev;

	rval = platform_device_add(si4713_pdev);
	if (rval)
		goto put_main_pdev;

	sdev->pd = si4713_pdev;

	return 0;

put_main_pdev:
	platform_device_put(si4713_pdev);
	v4l2_device_unregister_subdev(&sdev->sd);
free_ctrls:
	v4l2_ctrl_handler_free(hdl);
exit:
	return rval;
}
static int ov2680_probe(struct i2c_client *client)
{
	struct ov2680_device *dev;
	int ret;
	void *pdata;
	unsigned int i;

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

	mutex_init(&dev->input_lock);

	dev->fmt_idx = 0;
	v4l2_i2c_subdev_init(&(dev->sd), client, &ov2680_ops);

	pdata = gmin_camera_platform_data(&dev->sd,
					  ATOMISP_INPUT_FORMAT_RAW_10,
					  atomisp_bayer_order_bggr);
	if (!pdata) {
		ret = -EINVAL;
		goto out_free;
        }

	ret = ov2680_s_config(&dev->sd, client->irq, pdata);
	if (ret)
		goto out_free;

	ret = atomisp_register_i2c_module(&dev->sd, pdata, RAW_CAMERA);
	if (ret)
		goto out_free;

	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
	dev->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
	dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
	ret =
	    v4l2_ctrl_handler_init(&dev->ctrl_handler,
				   ARRAY_SIZE(ov2680_controls));
	if (ret) {
		ov2680_remove(client);
		return ret;
	}

	for (i = 0; i < ARRAY_SIZE(ov2680_controls); i++)
		v4l2_ctrl_new_custom(&dev->ctrl_handler, &ov2680_controls[i],
				     NULL);

	if (dev->ctrl_handler.error) {
		ov2680_remove(client);
		return dev->ctrl_handler.error;
	}

	/* Use same lock for controls as for everything else. */
	dev->ctrl_handler.lock = &dev->input_lock;
	dev->sd.ctrl_handler = &dev->ctrl_handler;

	ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
	if (ret)
	{
		ov2680_remove(client);
		dev_dbg(&client->dev, "+++ remove ov2680 \n");
	}
	return ret;
out_free:
	dev_dbg(&client->dev, "+++ out free \n");
	v4l2_device_unregister_subdev(&dev->sd);
	kfree(dev);
	return ret;
}
Exemple #18
0
int pwc_init_controls(struct pwc_device *pdev)
{
	struct v4l2_ctrl_handler *hdl;
	struct v4l2_ctrl_config cfg;
	int r, def;

	hdl = &pdev->ctrl_handler;
	r = v4l2_ctrl_handler_init(hdl, 20);
	if (r)
		return r;

	/* Brightness, contrast, saturation, gamma */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def);
	if (r || def > 127)
		def = 63;
	pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_BRIGHTNESS, 0, 127, 1, def);

	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def);
	if (r || def > 63)
		def = 31;
	pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_CONTRAST, 0, 63, 1, def);

	if (pdev->type >= 675) {
		if (pdev->type < 730)
			pdev->saturation_fmt = SATURATION_MODE_FORMATTER2;
		else
			pdev->saturation_fmt = SATURATION_MODE_FORMATTER1;
		r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt,
				    &def);
		if (r || def < -100 || def > 100)
			def = 0;
		pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				      V4L2_CID_SATURATION, -100, 100, 1, def);
	}

	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
	if (r || def > 31)
		def = 15;
	pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_GAMMA, 0, 31, 1, def);

	/* auto white balance, red gain, blue gain */
	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def);
	if (r || def > awb_auto)
		def = awb_auto;
	cfg = pwc_auto_white_balance_cfg;
	cfg.name = v4l2_ctrl_get_name(cfg.id);
	cfg.def = def;
	pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
	/* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
	if (!pdev->auto_white_balance)
		return hdl->error;

	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
			    PRESET_MANUAL_RED_GAIN_FORMATTER, &def);
	if (r)
		def = 127;
	pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_RED_BALANCE, 0, 255, 1, def);

	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
			    PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def);
	if (r)
		def = 127;
	pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);

	v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);

	/* autogain, gain */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
	if (r || (def != 0 && def != 0xff))
		def = 0;
	/* Note a register value if 0 means auto gain is on */
	pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
	if (!pdev->autogain)
		return hdl->error;

	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def);
	if (r || def > 63)
		def = 31;
	pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_GAIN, 0, 63, 1, def);

	/* auto exposure, exposure */
	if (DEVICE_USE_CODEC2(pdev->type)) {
		r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER,
				    &def);
		if (r || (def != 0 && def != 0xff))
			def = 0;
		/*
		 * def = 0 auto, def = ff manual
		 * menu idx 0 = auto, idx 1 = manual
		 */
		pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl,
					&pwc_ctrl_ops,
					V4L2_CID_EXPOSURE_AUTO,
					1, 0, def != 0);
		if (!pdev->exposure_auto)
			return hdl->error;

		/* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
		r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
				     READ_SHUTTER_FORMATTER, &def);
		if (r || def > 655)
			def = 655;
		pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
					V4L2_CID_EXPOSURE, 0, 655, 1, def);
		/* CODEC2: separate auto gain & auto exposure */
		v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
		v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto,
				       V4L2_EXPOSURE_MANUAL, true);
	} else if (DEVICE_USE_CODEC3(pdev->type)) {
		/* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
		r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
				     READ_SHUTTER_FORMATTER, &def);
		if (r || def > 255)
			def = 255;
		pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
					V4L2_CID_EXPOSURE, 0, 255, 1, def);
		/* CODEC3: both gain and exposure controlled by autogain */
		pdev->autogain_expo_cluster[0] = pdev->autogain;
		pdev->autogain_expo_cluster[1] = pdev->gain;
		pdev->autogain_expo_cluster[2] = pdev->exposure;
		v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster,
				       0, true);
	}

	/* color / bw setting */
	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER,
			 &def);
	if (r || (def != 0 && def != 0xff))
		def = 0xff;
	/* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
	pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
				V4L2_CID_COLORFX, 1, 0, def == 0);

	/* autocontour, contour */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def);
	if (r || (def != 0 && def != 0xff))
		def = 0;
	cfg = pwc_autocontour_cfg;
	cfg.def = def == 0;
	pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
	if (!pdev->autocontour)
		return hdl->error;

	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def);
	if (r || def > 63)
		def = 31;
	cfg = pwc_contour_cfg;
	cfg.def = def;
	pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);

	/* backlight */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
			    BACK_LIGHT_COMPENSATION_FORMATTER, &def);
	if (r || (def != 0 && def != 0xff))
		def = 0;
	cfg = pwc_backlight_cfg;
	cfg.name = v4l2_ctrl_get_name(cfg.id);
	cfg.def = def == 0;
	pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	/* flikker rediction */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
			    FLICKERLESS_MODE_FORMATTER, &def);
	if (r || (def != 0 && def != 0xff))
		def = 0;
	cfg = pwc_flicker_cfg;
	cfg.name = v4l2_ctrl_get_name(cfg.id);
	cfg.def = def == 0;
	pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	/* Dynamic noise reduction */
	r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
			    DYNAMIC_NOISE_CONTROL_FORMATTER, &def);
	if (r || def > 3)
		def = 2;
	cfg = pwc_noise_reduction_cfg;
	cfg.def = def;
	pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	/* Save / Restore User / Factory Settings */
	pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
	pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
						  NULL);
	if (pdev->restore_user)
		pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
	pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
						     &pwc_restore_factory_cfg,
						     NULL);
	if (pdev->restore_factory)
		pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;

	/* Auto White Balance speed & delay */
	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
			    AWB_CONTROL_SPEED_FORMATTER, &def);
	if (r || def < 1 || def > 32)
		def = 1;
	cfg = pwc_awb_speed_cfg;
	cfg.def = def;
	pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
			    AWB_CONTROL_DELAY_FORMATTER, &def);
	if (r || def > 63)
		def = 0;
	cfg = pwc_awb_delay_cfg;
	cfg.def = def;
	pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);

	if (!(pdev->features & FEATURE_MOTOR_PANTILT))
		return hdl->error;

	/* Motor pan / tilt / reset */
	pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
	if (!pdev->motor_pan)
		return hdl->error;
	pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
	pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_PAN_RESET, 0, 0, 0, 0);
	pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
				V4L2_CID_TILT_RESET, 0, 0, 0, 0);
	v4l2_ctrl_cluster(4, &pdev->motor_pan);

	return hdl->error;
}
/*
 * sensor_init_controls - initialization using v4l2_ctrl.
 */
static int sensor_init_controls(struct sensor_info *info)
{
	struct v4l2_subdev *sd = &info->sd;
	int num_of_ctl_hint = ARRAY_SIZE(ctrl_private);

	/* set the controls using v4l2 control frameworks */
	v4l2_ctrl_handler_init(&info->handle, num_of_ctl_hint);

	/* Vision mode only support simple AE */
	info->ae_target = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[0], NULL);
	info->ae_weight[0] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[1], NULL);
	info->ae_weight[1] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[2], NULL);
	info->ae_weight[2] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[3], NULL);
	info->ae_weight[3] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[4], NULL);
	info->ae_weight[4] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[5], NULL);
	info->ae_weight[5] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[6], NULL);
	info->ae_weight[6] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[7], NULL);
	info->ae_weight[7] = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[8], NULL);
	info->rg_weight = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[9], NULL);
	info->ae_speed = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[10], NULL);
	info->shutter = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[11], NULL);
	info->gain = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[12], NULL);
	info->bit_converting = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[13], NULL);
	info->autoexposure = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[14], NULL);
	info->framerate = v4l2_ctrl_new_custom(&info->handle,
			&ctrl_private[15], NULL);

	sd->ctrl_handler = &info->handle;

	if (info->handle.error) {
		sensor_err("Failed to init controls, %d\n", info->handle.error);
		v4l2_ctrl_handler_free(&info->handle);
		return info->handle.error;
	}

	return 0;
}
Exemple #20
0
/******************************************************************************
 *
 *  cpia2_register_camera
 *
 *****************************************************************************/
int cpia2_register_camera(struct camera_data *cam)
{
	struct v4l2_ctrl_handler *hdl = &cam->hdl;
	struct v4l2_ctrl_config cpia2_usb_alt = {
		.ops = &cpia2_ctrl_ops,
		.id = CPIA2_CID_USB_ALT,
		.name = "USB Alternate",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.min = USBIF_ISO_1,
		.max = USBIF_ISO_6,
		.step = 1,
	};
	int ret;

	v4l2_ctrl_handler_init(hdl, 12);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_BRIGHTNESS,
			cam->params.pnp_id.device_type == DEVICE_STV_672 ? 1 : 0,
			255, 1, DEFAULT_BRIGHTNESS);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_CONTRAST, 0, 255, 1, DEFAULT_CONTRAST);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_SATURATION, 0, 255, 1, DEFAULT_SATURATION);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_HFLIP, 0, 1, 1, 0);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_JPEG_ACTIVE_MARKER, 0,
			V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
			V4L2_JPEG_ACTIVE_MARKER_DHT);
	v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_JPEG_COMPRESSION_QUALITY, 1,
			100, 1, 100);
	cpia2_usb_alt.def = alternate;
	cam->usb_alt = v4l2_ctrl_new_custom(hdl, &cpia2_usb_alt, NULL);
	/* VP5 Only */
	if (cam->params.pnp_id.device_type != DEVICE_STV_672)
		v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
			V4L2_CID_VFLIP, 0, 1, 1, 0);
	/* Flicker control only valid for 672 */
	if (cam->params.pnp_id.device_type == DEVICE_STV_672)
		v4l2_ctrl_new_std_menu(hdl, &cpia2_ctrl_ops,
			V4L2_CID_POWER_LINE_FREQUENCY,
			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
	/* Light control only valid for the QX5 Microscope */
	if (cam->params.pnp_id.product == 0x151) {
		cam->top_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
				V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
		cam->bottom_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
				V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
		v4l2_ctrl_cluster(2, &cam->top_light);
	}

	if (hdl->error) {
		ret = hdl->error;
		v4l2_ctrl_handler_free(hdl);
		return ret;
	}

	cam->vdev = cpia2_template;
	video_set_drvdata(&cam->vdev, cam);
	cam->vdev.lock = &cam->v4l2_lock;
	cam->vdev.ctrl_handler = hdl;
	cam->vdev.v4l2_dev = &cam->v4l2_dev;

	reset_camera_struct_v4l(cam);

	/* register v4l device */
	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
		ERR("video_register_device failed\n");
		return -ENODEV;
	}

	return 0;
}

/******************************************************************************
 *
 *  cpia2_unregister_camera
 *
 *****************************************************************************/
void cpia2_unregister_camera(struct camera_data *cam)
{
	video_unregister_device(&cam->vdev);
}
static int ap1302_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct ap1302_device *dev;
	int ret;
	unsigned int i;

	dev_info(&client->dev, "ap1302 probe called.\n");

	/* allocate device & init sub device */
	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
	if (!dev) {
		dev_err(&client->dev, "%s: out of memory\n", __func__);
		return -ENOMEM;
	}

	mutex_init(&dev->input_lock);

	v4l2_i2c_subdev_init(&(dev->sd), client, &ap1302_ops);

	ret = ap1302_request_firmware(&(dev->sd));
	if (ret) {
		dev_err(&client->dev, "Cannot request ap1302 firmware.\n");
		goto out_free;
	}

	dev->regmap16 = devm_regmap_init_i2c(client, &ap1302_reg16_config);
	if (IS_ERR(dev->regmap16)) {
		ret = PTR_ERR(dev->regmap16);
		dev_err(&client->dev,
			"Failed to allocate 16bit register map: %d\n", ret);
		return ret;
	}

	dev->regmap32 = devm_regmap_init_i2c(client, &ap1302_reg32_config);
	if (IS_ERR(dev->regmap32)) {
		ret = PTR_ERR(dev->regmap32);
		dev_err(&client->dev,
			"Failed to allocate 32bit register map: %d\n", ret);
		return ret;
	}

	if (client->dev.platform_data) {
		ret = ap1302_s_config(&dev->sd, client->dev.platform_data);
		if (ret)
			goto out_free;
	}

	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
	dev->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;

	dev->cntx_res[CONTEXT_PREVIEW].res_num = ARRAY_SIZE(ap1302_preview_res);
	dev->cntx_res[CONTEXT_PREVIEW].res_table = ap1302_preview_res;
	dev->cntx_res[CONTEXT_SNAPSHOT].res_num =
		ARRAY_SIZE(ap1302_snapshot_res);
	dev->cntx_res[CONTEXT_SNAPSHOT].res_table = ap1302_snapshot_res;
	dev->cntx_res[CONTEXT_VIDEO].res_num = ARRAY_SIZE(ap1302_video_res);
	dev->cntx_res[CONTEXT_VIDEO].res_table = ap1302_video_res;

	ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, ARRAY_SIZE(ctrls));
	if (ret) {
		ap1302_remove(client);
		return ret;
	}

	for (i = 0; i < ARRAY_SIZE(ctrls); i++)
		v4l2_ctrl_new_custom(&dev->ctrl_handler, &ctrls[i], NULL);

	if (dev->ctrl_handler.error) {
		ap1302_remove(client);
		return dev->ctrl_handler.error;
	}

	/* Use same lock for controls as for everything else. */
	dev->ctrl_handler.lock = &dev->input_lock;
	dev->sd.ctrl_handler = &dev->ctrl_handler;
	v4l2_ctrl_handler_setup(&dev->ctrl_handler);

	dev->run_mode = v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RUN_MODE);
	v4l2_ctrl_s_ctrl(dev->run_mode, ATOMISP_RUN_MODE_PREVIEW);

	ret = media_entity_init(&dev->sd.entity, 1, &dev->pad, 0);
	if (ret)
		ap1302_remove(client);
	return ret;
out_free:
	v4l2_device_unregister_subdev(&dev->sd);
	return ret;
}