📄 ov5640.c
字号:
reg3a11 = 0x30; break; case -3: /* -1.0EV */ reg3a11 = 0x41; break; case -2: /* -0.7EV */ reg3a11 = 0x51; break; case -1: /* -0.3EV */ reg3a11 = 0x61; break; case 0: /* 0EV, default */ reg3a11 = 0x61; break; case 1: /* 0.3EV */ reg3a11 = 0x71; break; case 2: /* 0.7EV */ reg3a11 = 0x80; reg3a1f = 0x20; break; case 3: /* 1.0EV */ reg3a11 = 0x90; reg3a1f = 0x20; break; case 4: /* 1.3EV */ reg3a11 = 0x91; reg3a1f = 0x20; break; case 5: /* 1.7EV */ reg3a11 = 0xa0; reg3a1f = 0x20; break; default: OV_ERR("exposure - %d is out of range[-5, 5]\n", level); return (-ERANGE); } OV_INFO("exposure: %d, 0x3a0f:0x%x, 0x3a10:0x%x\n", level, reg3a0f, reg3a10); //OV_INFO("0x3a1b:0x%x, 0x3a1e:0x%x\n", reg3a1b, reg3a1e); OV_INFO("0x3a11:0x%x, 0x3a1f:0x%x\n\n", reg3a11, reg3a1f); i2cc_set_reg(client, 0x3a0f, reg3a0f); /* stable range high limit(enter) */ i2cc_set_reg(client, 0x3a10, reg3a10); /* stable range low limit(enter) */ i2cc_set_reg(client, 0x3a11, reg3a11); /* fast zone high limit */ i2cc_set_reg(client, 0x3a1b, reg3a1b); /* stable range high limit(go out) */ i2cc_set_reg(client, 0x3a1e, reg3a1e); /* stable range low limit(go out) */ i2cc_set_reg(client, 0x3a1f, reg3a1f); /* fast zone low limit */ priv->exposure = level; return (0);}#define OV5640_FLIP_VAL ((unsigned char)0x06)#define OV5640_FLIP_MASK (~(OV5640_FLIP_VAL))static int ov5640_set_flip(struct i2c_client *client, struct v4l2_control *ctrl){ struct ov5640_priv *priv = to_ov5640(client); unsigned char reg3820, reg3821; OV_INFO("old flag: %d\n", priv->flip_flag); switch (ctrl->id) { case V4L2_CID_HFLIP: if (ctrl->value) { priv->flip_flag |= OV5640_HFLIP; } else { priv->flip_flag &= ~OV5640_HFLIP; } break; case V4L2_CID_VFLIP: if (ctrl->value) { priv->flip_flag |= OV5640_VFLIP; } else { priv->flip_flag &= ~OV5640_VFLIP; } break; default: OV_ERR("set flip out of range\n"); return (-ERANGE); } OV_INFO("new flag: %d\n", priv->flip_flag); i2cc_get_reg(client, 0x3820, ®3820); i2cc_get_reg(client, 0x3821, ®3821); if (priv->flip_flag & OV5640_VFLIP) { reg3820 |= OV5640_FLIP_VAL; } else { reg3820 &= OV5640_FLIP_MASK; } if (priv->flip_flag & OV5640_HFLIP) { reg3821 |= OV5640_FLIP_VAL; } else { reg3821 &= OV5640_FLIP_MASK; } /* have a bug which flip a half picture only. */ //i2cc_set_reg(client, 0x3212, 0x00); /* enable group0, when add no flip */ i2cc_set_reg(client, 0x3820, reg3820); i2cc_set_reg(client, 0x3821, reg3821); //i2cc_set_reg(client, 0x3212, 0x10); /* end group0 */ //i2cc_set_reg(client, 0x3212, 0xa1); /* launch group1 */ OV_INFO("0x3820:0x%x, 0x3821:0x%x\n", reg3820, reg3821); return (0);}static int ov5640_set_sharpness(struct i2c_client *client, int sharp){ struct ov5640_priv *priv = to_ov5640(client); unsigned char reg5302; switch (sharp) { case -1: /*auto sharpness*/ break; case 0: /* sharpness off */ reg5302 = 0x00; break; case 1: reg5302 = 0x02; break; case 2: reg5302 = 0x04; break; case 3: reg5302 = 0x08; break; case 4: reg5302 = 0x0c; break; case 5: reg5302 = 0x10; break; case 6: reg5302 = 0x14; break; case 7: reg5302 = 0x18; break; case 8: reg5302 = 0x20; break; default: OV_ERR("set sharpness is out of range - %d[-1,8]\n", sharp); return (-ERANGE); } if (0 <= sharp) { i2cc_set_reg(client, 0x5308, 0x65); i2cc_set_reg(client, 0x5302, reg5302); OV_INFO("sharp:%d, 5302:0x%x\n", sharp, reg5302); } else { const struct regval ov5640_auto_sharpness[] = { {0x5308, 0x25}, {0x5300, 0x08}, {0x5301, 0x30}, {0x5302, 0x10}, {0x5303, 0x00}, {0x5309, 0x08}, {0x530a, 0x30}, {0x530b, 0x04}, {0x530c, 0x06}, }; int len = ARRAY_SIZE(ov5640_auto_sharpness); write_regs(client, ov5640_auto_sharpness, len); OV_INFO("sharp:%d, len:%d\n", sharp, len); } priv->sharpness = sharp; return (0);}static int ov5640_set_colorfx(struct i2c_client *client, int effect){ struct ov5640_priv *priv = to_ov5640(client); unsigned char reg5583, reg5584, reg5001, reg5580; reg5001 = 0xff; reg5580 = 0x18; switch (effect) { case 0: /* normal */ reg5001 = 0x7f; reg5580 = 0x00; break; case 1: /* black and white */ reg5583 = 0x80; reg5584 = 0x80; break; case 2: /* sepia , antique */ reg5583 = 0x40; reg5584 = 0xa0; break; case 3: /* negative */ reg5001 = 0xff; reg5580 = 0x40; break; case 4: /* bluish */ reg5583 = 0xa0; reg5584 = 0x40; break; case 5: /* greenish */ reg5583 = 0x60; reg5584 = 0x60; break; case 6: /* reddish */ reg5583 = 0x80; reg5584 = 0xc0; break; default: OV_ERR("set color effects out of range - %d[0,6]\n", effect); return (-ERANGE); } i2cc_set_reg(client, 0x5001, reg5001); i2cc_set_reg(client, 0x5580, reg5580); OV_INFO("effect:%d, 0x5001:0x%x, 0x5580:0x%x\n", effect, reg5001, reg5580); if (0 != effect && 3 != effect) { i2cc_set_reg(client, 0x5583, reg5583); i2cc_set_reg(client, 0x5584, reg5584); OV_INFO("0x5583:0x%x, 0x5584:0x%x\n", reg5583, reg5584); } priv->colorfx = effect; return (0);}/* Must be sorted from low to high control ID! */static const u32 ov5640_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE,// V4L2_CID_BLACK_LEVEL, V4L2_CID_AUTO_WHITE_BALANCE,// V4L2_CID_DO_WHITE_BALANCE,// V4L2_CID_RED_BALANCE,// V4L2_CID_BLUE_BALANCE,// V4L2_CID_GAMMA, V4L2_CID_EXPOSURE, V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, V4L2_CID_HFLIP, V4L2_CID_VFLIP, V4L2_CID_POWER_LINE_FREQUENCY,// V4L2_CID_HUE_AUTO, V4L2_CID_WHITE_BALANCE_TEMPERATURE, V4L2_CID_SHARPNESS,// V4L2_CID_BACKLIGHT_COMPENSATION,// V4L2_CID_CHROMA_AGC,// V4L2_CID_CHROMA_GAIN,// V4L2_CID_COLOR_KILLER, V4L2_CID_COLORFX,// V4L2_CID_AUTOBRIGHTNESS, V4L2_CID_BAND_STOP_FILTER,// V4L2_CID_ROTATE,// V4L2_CID_BG_COLOR, 0,};static const u32 ov5640_camera_ctrls[] = { V4L2_CID_CAMERA_CLASS, V4L2_CID_EXPOSURE_AUTO,// V4L2_CID_EXPOSURE_ABSOLUTE,// V4L2_CID_EXPOSURE_AUTO_PRIORITY,// V4L2_CID_PAN_RELATIVE,// V4L2_CID_TILT_RELATIVE,// V4L2_CID_PAN_RESET,// V4L2_CID_TILT_RESET,// V4L2_CID_PAN_ABSOLUTE,// V4L2_CID_TILT_ABSOLUTE,// V4L2_CID_FOCUS_ABSOLUTE,// V4L2_CID_FOCUS_RELATIVE,// V4L2_CID_FOCUS_AUTO,// V4L2_CID_ZOOM_ABSOLUTE,// V4L2_CID_ZOOM_RELATIVE,// V4L2_CID_ZOOM_CONTINUOUS,// V4L2_CID_IRIS_ABSOLUTE,// V4L2_CID_IRIS_RELATIVE,// V4L2_CID_PRIVACY, V4L2_CID_SCENE_EXPOSURE, 0,};static const u32 *ov5640_ctrl_classes[] = { ov5640_user_ctrls, ov5640_camera_ctrls, NULL,};static int ov5640_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc){ //struct i2c_client *client = v4l2_get_subdevdata(sd); qc->id = v4l2_ctrl_next(ov5640_ctrl_classes, qc->id); if (qc->id == 0) { return (-EINVAL); } OV_INFO("%s: id-%s\n", __func__, v4l2_ctrl_get_name(qc->id)); /* Fill in min, max, step and default value for these controls. */ switch (qc->id) { /* Standard V4L2 controls */ case V4L2_CID_USER_CLASS: return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); case V4L2_CID_BRIGHTNESS: return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0); case V4L2_CID_CONTRAST: return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, -180, 150, 30, 0);#if 0// case V4L2_CID_BLACK_LEVEL: case V4L2_CID_AUTO_WHITE_BALANCE: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);// case V4L2_CID_DO_WHITE_BALANCE:// case V4L2_CID_RED_BALANCE:// case V4L2_CID_BLUE_BALANCE:// case V4L2_CID_GAMMA:#endif case V4L2_CID_EXPOSURE: return v4l2_ctrl_query_fill(qc, -5, 5, 1, 0);#if 0 case V4L2_CID_AUTOGAIN: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); case V4L2_CID_GAIN: return v4l2_ctrl_query_fill(qc, 0, 0xFFU, 1, 128);#endif case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);#if 0 case V4L2_CID_POWER_LINE_FREQUENCY: return v4l2_ctrl_query_fill(qc, 0, 2, 1, 1);// case V4L2_CID_HUE_AUTO: case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return v4l2_ctrl_query_fill(qc, 0, 3, 1, 0);#endif case V4L2_CID_SHARPNESS: return v4l2_ctrl_query_fill(qc, -1, 8, 1, -1);// case V4L2_CID_BACKLIGHT_COMPENSATION:// case V4L2_CID_CHROMA_AGC:// case V4L2_CID_CHROMA_GAIN:// case V4L2_CID_COLOR_KILLER: case V4L2_CID_COLORFX: return v4l2_ctrl_query_fill(qc, 0, 6, 1, 0);// case V4L2_CID_AUTOBRIGHTNESS:#if 0 case V4L2_CID_BAND_STOP_FILTER: return v4l2_ctrl_query_fill(qc, 0, 63, 1, 2);// case V4L2_CID_ROTATE:// case V4L2_CID_BG_COLOR:#endif case V4L2_CID_CAMERA_CLASS: return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);#if 0 case V4L2_CID_EXPOSURE_AUTO: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);// 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: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);#endif default: OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(qc->id)); qc->flags |= V4L2_CTRL_FLAG_DISABLED; return (-EINVAL); } return (0);}static int ov5640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl){ struct i2c_client *client = v4l2_get_subdevdata(sd); //struct ov5640_priv *priv = to_ov5640(client); int ret = 0; //int val = 0; OV_INFO("%s: control ctrl- %s\n", __func__, v4l2_ctrl_get_name(ctrl->id)); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ov5640_set_brightness(client, ctrl->value); break; case V4L2_CID_CONTRAST: ov5640_set_contrast(client, ctrl->value); break; case V4L2_CID_SATURATION: ov5640_set_saturation(client, ctrl->value); break; case V4L2_CID_HUE: ov5640_set_hue(client, ctrl->value); break;#if 0// case V4L2_CID_BLACK_LEVEL:// ov5640_set_black_level(sd, ctrl->value);// break; case V4L2_CID_AUTO_WHITE_BALANCE: ov5640_set_awb(client, ctrl->value); break;// case V4L2_CID_DO_WHITE_BALANCE:// ov5640_set_do_white_balance(sd, ctrl->value);// break;// case V4L2_CID_RED_BALANCE:// ov5640_set_red_balance(sd, ctrl->value);// break;// case V4L2_CID_BLUE_BALANCE:// ov5640_set_blue_balance(sd, ctrl->value);// break;// case V4L2_CID_GAMMA:// ov5640_set_gamma(sd, ctrl->value);// break;#endif case V4L2_CID_EXPOSURE: ov5640_set_exposure_level(client, ctrl->value); break;#if 0 case V4L2_CID_AUTOGAIN: ov5640_set_autogain(sd, ctrl->value); break; case V4L2_CID_GAIN: ov5640_set_gain(sd, ctrl->value); break;#endif case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: ov5640_set_flip(client, ctrl); break;#if 0 case V4L2_CID_POWER_LINE_FREQUENCY: ov5640_set_power_line_frequency(sd, ctrl->value); break;// case V4L2_CID_HUE_AUTO:// ov5640_set_hue_auto(sd, ctrl->value);// break; case V4L2_CID_WHITE_BALANCE_TEMPERATURE: set_white_balance_temperature(client, ctrl->value); break;#endif case V4L2_CID_SHARPNESS: ov5640_set_sharpness(client, ctrl->value); break;// case V4L2_CID_BACKLIGHT_COMPENSATION:// ov5640_set_backlight_compensation(sd, ctrl->value);// break;// case V4L2_CID_CHROMA_AGC:// ov5640_set_chroma_agc(sd, ctrl->value);// break;// case V4L2_CID_CHROMA_GAIN:// ov5640_set_chroma_gain(sd, ctrl->value);// break;// case V4L2_CID_COLOR_KILLER:// ov5640_set_color_killer(sd, ctrl->value);// break; case V4L2_CID_COLORFX: ov5640_set_colorfx(client, ctrl->value); break;#if 0// case V4L2_CID_AUTOBRIGHTNESS:// ov5640_set_autobrightness(sd, ctrl->value);// break; case V4L2_CID_BAND_STOP_FILTER: ov5640_set_band_stop_filter(sd, ctrl->value); break;// case V4L2_CID_ROTATE:// ov5640_set_rotate(sd, ctrl->value);// break;// case V4L2_CID_BG_COLOR:// ov5640_set_bg_color(sd, ctrl->value);// break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -