|
@@ -64,6 +64,7 @@
|
|
|
#define OV5640_REG_TIMING_DVPVO 0x380a
|
|
|
#define OV5640_REG_TIMING_HTS 0x380c
|
|
|
#define OV5640_REG_TIMING_VTS 0x380e
|
|
|
+#define OV5640_REG_TIMING_TC_REG20 0x3820
|
|
|
#define OV5640_REG_TIMING_TC_REG21 0x3821
|
|
|
#define OV5640_REG_AEC_CTRL00 0x3a00
|
|
|
#define OV5640_REG_AEC_B50_STEP 0x3a08
|
|
@@ -199,6 +200,8 @@ struct ov5640_ctrls {
|
|
|
struct v4l2_ctrl *contrast;
|
|
|
struct v4l2_ctrl *hue;
|
|
|
struct v4l2_ctrl *test_pattern;
|
|
|
+ struct v4l2_ctrl *hflip;
|
|
|
+ struct v4l2_ctrl *vflip;
|
|
|
};
|
|
|
|
|
|
struct ov5640_dev {
|
|
@@ -341,7 +344,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
|
|
|
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -360,7 +363,7 @@ static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -379,7 +382,7 @@ static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
|
|
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -399,7 +402,7 @@ static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -418,7 +421,7 @@ static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
|
|
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -437,7 +440,7 @@ static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -456,7 +459,7 @@ static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
|
|
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -475,7 +478,7 @@ static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -494,7 +497,7 @@ static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
|
|
{0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -513,7 +516,7 @@ static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -532,7 +535,7 @@ static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
|
|
|
static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
|
|
{0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -551,7 +554,7 @@ static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
|
|
|
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
|
@@ -571,7 +574,7 @@ static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
|
|
|
{0x3008, 0x42, 0, 0},
|
|
|
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
|
@@ -591,7 +594,7 @@ static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
|
|
|
static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
|
|
{0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
|
|
|
+ {0x3814, 0x31, 0, 0},
|
|
|
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
|
@@ -611,7 +614,7 @@ static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
|
|
|
{0x3008, 0x42, 0, 0},
|
|
|
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
|
|
|
+ {0x3814, 0x11, 0, 0},
|
|
|
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
|
@@ -644,7 +647,7 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
|
|
{0x3008, 0x42, 0, 0},
|
|
|
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
|
|
|
+ {0x3814, 0x11, 0, 0},
|
|
|
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
|
@@ -673,10 +676,9 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
|
|
};
|
|
|
|
|
|
static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
|
|
- {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
|
|
|
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
|
|
|
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
|
|
- {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
|
|
|
+ {0x3814, 0x11, 0, 0},
|
|
|
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
|
|
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
|
|
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
|
@@ -1340,6 +1342,27 @@ static int ov5640_binning_on(struct ov5640_dev *sensor)
|
|
|
return temp ? 1 : 0;
|
|
|
}
|
|
|
|
|
|
+static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * TIMING TC REG21:
|
|
|
+ * - [0]: Horizontal binning enable
|
|
|
+ */
|
|
|
+ ret = ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG21,
|
|
|
+ BIT(0), enable ? BIT(0) : 0);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ /*
|
|
|
+ * TIMING TC REG20:
|
|
|
+ * - [0]: Undocumented, but hardcoded init sequences
|
|
|
+ * are always setting REG21/REG20 bit 0 to same value...
|
|
|
+ */
|
|
|
+ return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG20,
|
|
|
+ BIT(0), enable ? BIT(0) : 0);
|
|
|
+}
|
|
|
+
|
|
|
static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
|
|
|
{
|
|
|
struct i2c_client *client = sensor->i2c_client;
|
|
@@ -1640,6 +1663,9 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
+ ret = ov5640_set_binning(sensor, dn_mode != SCALING);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
ret = ov5640_set_ae_target(sensor, sensor->ae_target);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
@@ -2193,6 +2219,37 @@ static int ov5640_set_ctrl_light_freq(struct ov5640_dev *sensor, int value)
|
|
|
BIT(2) : 0);
|
|
|
}
|
|
|
|
|
|
+static int ov5640_set_ctrl_hflip(struct ov5640_dev *sensor, int value)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Sensor is a BSI (Back Side Illuminated) one,
|
|
|
+ * so image captured is physically mirrored.
|
|
|
+ * This is why mirror logic is inversed in
|
|
|
+ * order to cancel this mirror effect.
|
|
|
+ */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * TIMING TC REG21:
|
|
|
+ * - [2]: ISP mirror
|
|
|
+ * - [1]: Sensor mirror
|
|
|
+ */
|
|
|
+ return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG21,
|
|
|
+ BIT(2) | BIT(1),
|
|
|
+ (!value) ? (BIT(2) | BIT(1)) : 0);
|
|
|
+}
|
|
|
+
|
|
|
+static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * TIMING TC REG20:
|
|
|
+ * - [2]: ISP vflip
|
|
|
+ * - [1]: Sensor vflip
|
|
|
+ */
|
|
|
+ return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG20,
|
|
|
+ BIT(2) | BIT(1),
|
|
|
+ value ? (BIT(2) | BIT(1)) : 0);
|
|
|
+}
|
|
|
+
|
|
|
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
|
|
{
|
|
|
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
|
|
@@ -2264,6 +2321,12 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
|
|
|
case V4L2_CID_POWER_LINE_FREQUENCY:
|
|
|
ret = ov5640_set_ctrl_light_freq(sensor, ctrl->val);
|
|
|
break;
|
|
|
+ case V4L2_CID_HFLIP:
|
|
|
+ ret = ov5640_set_ctrl_hflip(sensor, ctrl->val);
|
|
|
+ break;
|
|
|
+ case V4L2_CID_VFLIP:
|
|
|
+ ret = ov5640_set_ctrl_vflip(sensor, ctrl->val);
|
|
|
+ break;
|
|
|
default:
|
|
|
ret = -EINVAL;
|
|
|
break;
|
|
@@ -2325,6 +2388,10 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
|
|
v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
|
|
|
ARRAY_SIZE(test_pattern_menu) - 1,
|
|
|
0, 0, test_pattern_menu);
|
|
|
+ ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
|
|
|
+ 0, 1, 1, 0);
|
|
|
+ ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
|
|
|
+ 0, 1, 1, 0);
|
|
|
|
|
|
ctrls->light_freq =
|
|
|
v4l2_ctrl_new_std_menu(hdl, ops,
|