📄 ov5640.c
字号:
case V4L2_CID_EXPOSURE_AUTO: ov5640_set_exposure_auto(sd, ctrl->value); break;// case V4L2_CID_EXPOSURE_ABSOLUTE:// case V4L2_CID_EXPOSURE_AUTO_PRIORITY:// case V4L2_CID_PAN_RELATIVE:// case V4L2_CID_TILT_RELATIVE:// case V4L2_CID_PAN_RESET:// case V4L2_CID_TILT_RESET:// case V4L2_CID_PAN_ABSOLUTE:// case V4L2_CID_TILT_ABSOLUTE:// case V4L2_CID_FOCUS_ABSOLUTE:// case V4L2_CID_FOCUS_RELATIVE:// case V4L2_CID_FOCUS_AUTO:// case V4L2_CID_ZOOM_ABSOLUTE:// case V4L2_CID_ZOOM_RELATIVE:// case V4L2_CID_ZOOM_CONTINUOUS:// case V4L2_CID_IRIS_ABSOLUTE:// case V4L2_CID_IRIS_RELATIVE:// case V4L2_CID_PRIVACY: case V4L2_CID_SCENE_EXPOSURE: ov5640_set_scene_exposure(sd, ctrl->value); break;#endif default: OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(ctrl->id)); return (-EINVAL); } return (ret);}static int ov5640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl){ struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov5640_priv *priv = to_ov5640(client); OV_INFO("%s: control ctrl- %s\n", __func__, v4l2_ctrl_get_name(ctrl->id)); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = priv->brightness; break; case V4L2_CID_CONTRAST: ctrl->value = priv->contrast; break; case V4L2_CID_SATURATION: ctrl->value = priv->saturation; break; case V4L2_CID_HUE: ctrl->value = priv->hue; break; // case V4L2_CID_BLACK_LEVEL: // ctrl->value = priv->black_level; // break;#if 0 case V4L2_CID_AUTO_WHITE_BALANCE: ctrl->value = priv->auto_white_balance; break; // case V4L2_CID_DO_WHITE_BALANCE: // ctrl->value = priv->do_white_balance; // break; // case V4L2_CID_RED_BALANCE: // ctrl->value = priv->red_balance; // break; // case V4L2_CID_BLUE_BALANCE: // ctrl->value = priv->blue_balance; // break; // case V4L2_CID_GAMMA: // ctrl->value = priv->gamma; // break;#endif case V4L2_CID_EXPOSURE: ctrl->value = priv->exposure; break;#if 0 case V4L2_CID_AUTOGAIN: ctrl->value = priv->autogain; break; case V4L2_CID_GAIN: ctrl->value = priv->gain; break;#endif case V4L2_CID_HFLIP: ctrl->value = !!(priv->flip_flag & OV5640_HFLIP); break; case V4L2_CID_VFLIP: ctrl->value = !!(priv->flip_flag & OV5640_VFLIP); break;#if 0 case V4L2_CID_POWER_LINE_FREQUENCY: ctrl->value = priv->power_line_frequency; break; // case V4L2_CID_HUE_AUTO: // ctrl->value = priv->hue_auto; // break; case V4L2_CID_WHITE_BALANCE_TEMPERATURE: ctrl->value = priv->white_balance_temperature; break;#endif case V4L2_CID_SHARPNESS: ctrl->value = priv->sharpness; break; // case V4L2_CID_BACKLIGHT_COMPENSATION: // ctrl->value = priv->backlight_compensation; // break; // case V4L2_CID_CHROMA_AGC: // ctrl->value = priv->chroma_agc; // break; // case V4L2_CID_CHROMA_GAIN: // ctrl->value = priv->chroma_gain; // break; // case V4L2_CID_COLOR_KILLER: // ctrl->value = priv->color_killer; // break; case V4L2_CID_COLORFX: ctrl->value = priv->colorfx; break;#if 0 // case V4L2_CID_AUTOBRIGHTNESS: // ctrl->value = priv->autobrightness; // break; case V4L2_CID_BAND_STOP_FILTER: ctrl->value = priv->band_stop_filter; break; // case V4L2_CID_ROTATE: // ctrl->value = priv->rotate; // break; // case V4L2_CID_BG_COLOR: // ctrl->value = priv->bg_color; // break; case V4L2_CID_EXPOSURE_AUTO: ctrl->value = priv->exposure_auto; break; // case V4L2_CID_EXPOSURE_ABSOLUTE: // case V4L2_CID_EXPOSURE_AUTO_PRIORITY: // case V4L2_CID_PAN_RELATIVE: // case V4L2_CID_TILT_RELATIVE: // case V4L2_CID_PAN_RESET: // case V4L2_CID_TILT_RESET: // case V4L2_CID_PAN_ABSOLUTE: // case V4L2_CID_TILT_ABSOLUTE: // case V4L2_CID_FOCUS_ABSOLUTE: // case V4L2_CID_FOCUS_RELATIVE: // case V4L2_CID_FOCUS_AUTO: // case V4L2_CID_ZOOM_ABSOLUTE: // case V4L2_CID_ZOOM_RELATIVE: // case V4L2_CID_ZOOM_CONTINUOUS: // case V4L2_CID_IRIS_ABSOLUTE: // case V4L2_CID_IRIS_RELATIVE: // case V4L2_CID_PRIVACY: case V4L2_CID_SCENE_EXPOSURE: ctrl->value = priv->scene_exposure; break;#endif default: OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(ctrl->id)); return (-EINVAL); } return (0);}static int ov5640_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls){ //struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_control ctrl; int i; int err = 0; if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER) && (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) { OV_ERR("ctrl class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class)); return (-EINVAL); } for (i = 0; i < ctrls->count; i++) { ctrl.id = ctrls->controls[i].id; ctrl.value = ctrls->controls[i].value; err = ov5640_s_ctrl(sd, &ctrl); //ctrls->controls[i].value = ctrl.value; if (err) { ctrls->error_idx = i; break; } } return (err);}static int ov5640_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls){ //struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_control ctrl; int i; int err = 0; if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER) && (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) { OV_ERR("ctrl class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class)); return (-EINVAL); } for (i = 0; i < ctrls->count; i++) { ctrl.id = ctrls->controls[i].id; //ctrl.value = ctrls->controls[i].value; err = ov5640_g_ctrl(sd, &ctrl); ctrls->controls[i].value = ctrl.value; if (err) { ctrls->error_idx = i; break; } } return (err);}static int ov5640_try_ctrl(struct v4l2_subdev *sd, struct v4l2_ext_control *ctrl){ struct v4l2_queryctrl qctrl; const char **menu_items = NULL; int err; qctrl.id = ctrl->id; err = ov5640_queryctrl(sd, &qctrl); if (err) return (err); if (qctrl.type == V4L2_CTRL_TYPE_MENU) menu_items = v4l2_ctrl_get_menu(qctrl.id); return v4l2_ctrl_check(ctrl, &qctrl, menu_items);}static int ov5640_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls){ //struct i2c_client *client = v4l2_get_subdevdata(sd); int i; int err = 0; if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER) && (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) { OV_ERR("ctrl_class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class)); return (-EINVAL); } for (i = 0; i < ctrls->count; i++) { err = ov5640_try_ctrl(sd, &ctrls->controls[i]); if (err) { ctrls->error_idx = i; break; } } return (err);}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int ov5640_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg){ struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned char val; int err; reg->size = 2; if (reg->reg > 0x603f) { return (-EINVAL); } err = i2cc_get_reg(client, reg->reg, &val); if (err) { return (err); } reg->val = val; return (0);}static int ov5640_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg){ struct i2c_client *client = v4l2_get_subdevdata(sd); if (reg->reg > 0x603f) { return (-EINVAL); } return (i2cc_set_reg(client, (unsigned short)reg->reg,(unsigned char)reg->val));}#endifstatic struct soc_camera_ops ov5640_ops = { .set_bus_param = ov5640_set_bus_param, .query_bus_param = ov5640_query_bus_param, //.controls = ov5640_controls, //.num_controls = ARRAY_SIZE(ov5640_controls),};static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = { .g_ctrl = ov5640_g_ctrl, .s_ctrl = ov5640_s_ctrl, .queryctrl = ov5640_queryctrl, .g_ext_ctrls = ov5640_g_ext_ctrls, .s_ext_ctrls = ov5640_s_ext_ctrls, .try_ext_ctrls = ov5640_try_ext_ctrls, .g_chip_ident = ov5640_g_chip_ident,#ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov5640_g_register, .s_register = ov5640_s_register,#endif};static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = { .s_stream = ov5640_s_stream, .g_mbus_fmt = ov5640_g_fmt, .s_mbus_fmt = ov5640_s_fmt, .try_mbus_fmt = ov5640_try_fmt, .cropcap = ov5640_cropcap, .g_crop = ov5640_g_crop, .enum_mbus_fmt = ov5640_enum_fmt,};static struct v4l2_subdev_ops ov5640_subdev_ops = { .core = &ov5640_subdev_core_ops, .video = &ov5640_subdev_video_ops,};static int ov5640_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { struct ov5640_priv *priv = to_ov5640(client); unsigned char pid; unsigned char version; /* * We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ if (NULL == icd->dev.parent || to_soc_camera_host(icd->dev.parent)->nr != icd->iface) { OV_ERR("error : has a wrong parent\n"); return (-ENODEV); } // check and show product ID and manufacturer ID i2cc_get_reg(client, 0x300a, &pid); i2cc_get_reg(client, 0x300b, &version); if (OV5640 != VERSION(pid, version)) { OV_ERR("ov5640 probed failed!!\n"); return (-ENODEV); } priv->model = V4L2_IDENT_OV5640; INFO_BLUE("ov5640 device probed success\n"); return (0);}static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *did){ struct ov5640_priv *priv; struct soc_camera_device *icd = client->dev.platform_data; //struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_link *icl; int ret = 0; OV_INFO("ov5640 probe start...\n"); if (NULL == icd) { ret = -EINVAL; OV_ERR("error: missing soc camera device\n"); goto failed; } icl = to_soc_camera_link(icd); if (NULL == icl) { ret = -EINVAL; OV_ERR("error: missing soc camera link"); goto failed; } ret = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); if (0 == ret) { ret = -EINVAL; OV_ERR("I2C DOESN'T support I2C_FUNC_SMBUS_BYTE_DATA\n"); goto failed; } priv = (struct ov5640_priv *)kzalloc(sizeof(struct ov5640_priv), GFP_KERNEL); if (NULL == priv) { ret = -ENOMEM; OV_ERR("alloc ov5640_priv struct failed!\n"); goto failed; } v4l2_i2c_subdev_init(&priv->subdev, client, &ov5640_subdev_ops); icd->ops = &ov5640_ops; ret = ov5640_video_probe(icd, client); if (ret) { icd->ops = NULL; kfree(priv); OV_ERR("error : failed to probe camera device"); } failed: return (ret);}static int ov5640_remove(struct i2c_client *client){ struct ov5640_priv *priv = to_ov5640(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; kfree(priv); INFO_RED("ov5640 device removed!\n"); return (0);}#if 0static int ov5640_detect(struct i2c_client *client, struct i2c_board_info *info){ strcpy(info->type, OV5640_I2C_NAME); return 0;}#endifstatic const struct i2c_device_id ov5640_id[] = { { OV5640_I2C_NAME, 0 }, { }};MODULE_DEVICE_TABLE(i2c, ov5640_id);static const unsigned short ov5640_addrs[] = { OV5640_I2C_ADDR, I2C_CLIENT_END,};#if 0struct i2c_board_info ov5640_info = { I2C_BOARD_INFO(OV5640_I2C_NAME, OV5640_I2C_ADDR),};#endifstatic struct i2c_driver ov5640_i2c_driver = { .driver = { .name = OV5640_I2C_NAME, .owner = THIS_MODULE, }, .class = I2C_CLASS_HWMON, .probe = ov5640_probe, .remove = ov5640_remove, .id_table = ov5640_id, .address_list = ov5640_addrs,};/* * module function */static int __init ov5640_module_init(void){ OV_INFO("install module\n"); OV_INFO("--------------------- 2011-12-13-11:20 ---------------------\n"); return i2c_add_driver(&ov5640_i2c_driver);}static void __exit ov5640_module_exit(void){ OV_INFO("uninstall module\n"); i2c_del_driver(&ov5640_i2c_driver);}module_init(ov5640_module_init);module_exit(ov5640_module_exit);MODULE_DESCRIPTION("SoC Camera driver for ov5640");MODULE_AUTHOR("cfyun@actions-semi.com ");MODULE_LICENSE("GPL v2");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -