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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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, ®_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; }
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); }
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; }
/* 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; }
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; }
/****************************************************************************** * * 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; }