@@ -163,6 +163,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
163163#define DBLV_X6 0x10 /* clock x6 */
164164#define DBLV_X8 0x11 /* clock x8 */
165165
166+ #define REG_SCALING_XSC 0x70 /* Test pattern and horizontal scale factor */
167+ #define TEST_PATTTERN_0 0x80
168+ #define REG_SCALING_YSC 0x71 /* Test pattern and vertical scale factor */
169+ #define TEST_PATTTERN_1 0x80
170+
166171#define REG_REG76 0x76 /* OV's name */
167172#define R76_BLKPCOR 0x80 /* Black pixel correction enable */
168173#define R76_WHTPCOR 0x40 /* White pixel correction enable */
@@ -292,7 +297,8 @@ static struct regval_list ov7670_default_regs[] = {
292297
293298 { REG_COM3 , 0 }, { REG_COM14 , 0 },
294299 /* Mystery scaling numbers */
295- { 0x70 , 0x3a }, { 0x71 , 0x35 },
300+ { REG_SCALING_XSC , 0x3a },
301+ { REG_SCALING_YSC , 0x35 },
296302 { 0x72 , 0x11 }, { 0x73 , 0xf0 },
297303 { 0xa2 , 0x02 }, { REG_COM10 , 0x0 },
298304
@@ -568,6 +574,19 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
568574 return ov7670_write_i2c (sd , reg , value );
569575}
570576
577+ static int ov7670_update_bits (struct v4l2_subdev * sd , unsigned char reg ,
578+ unsigned char mask , unsigned char value )
579+ {
580+ unsigned char orig ;
581+ int ret ;
582+
583+ ret = ov7670_read (sd , reg , & orig );
584+ if (ret )
585+ return ret ;
586+
587+ return ov7670_write (sd , reg , (orig & ~mask ) | (value & mask ));
588+ }
589+
571590/*
572591 * Write a list of register settings; ff/ff stops the process.
573592 */
@@ -1470,6 +1489,25 @@ static int ov7670_s_autoexp(struct v4l2_subdev *sd,
14701489 return ret ;
14711490}
14721491
1492+ static const char * const ov7670_test_pattern_menu [] = {
1493+ "No test output" ,
1494+ "Shifting \"1\"" ,
1495+ "8-bar color bar" ,
1496+ "Fade to gray color bar" ,
1497+ };
1498+
1499+ static int ov7670_s_test_pattern (struct v4l2_subdev * sd , int value )
1500+ {
1501+ int ret ;
1502+
1503+ ret = ov7670_update_bits (sd , REG_SCALING_XSC , TEST_PATTTERN_0 ,
1504+ value & BIT (0 ) ? TEST_PATTTERN_0 : 0 );
1505+ if (ret )
1506+ return ret ;
1507+
1508+ return ov7670_update_bits (sd , REG_SCALING_YSC , TEST_PATTTERN_1 ,
1509+ value & BIT (1 ) ? TEST_PATTTERN_1 : 0 );
1510+ }
14731511
14741512static int ov7670_g_volatile_ctrl (struct v4l2_ctrl * ctrl )
14751513{
@@ -1516,6 +1554,8 @@ static int ov7670_s_ctrl(struct v4l2_ctrl *ctrl)
15161554 return ov7670_s_exp (sd , info -> exposure -> val );
15171555 }
15181556 return ov7670_s_autoexp (sd , ctrl -> val );
1557+ case V4L2_CID_TEST_PATTERN :
1558+ return ov7670_s_test_pattern (sd , ctrl -> val );
15191559 }
15201560 return - EINVAL ;
15211561}
@@ -1770,6 +1810,10 @@ static int ov7670_probe(struct i2c_client *client,
17701810 info -> auto_exposure = v4l2_ctrl_new_std_menu (& info -> hdl , & ov7670_ctrl_ops ,
17711811 V4L2_CID_EXPOSURE_AUTO , V4L2_EXPOSURE_MANUAL , 0 ,
17721812 V4L2_EXPOSURE_AUTO );
1813+ v4l2_ctrl_new_std_menu_items (& info -> hdl , & ov7670_ctrl_ops ,
1814+ V4L2_CID_TEST_PATTERN ,
1815+ ARRAY_SIZE (ov7670_test_pattern_menu ) - 1 , 0 , 0 ,
1816+ ov7670_test_pattern_menu );
17731817 sd -> ctrl_handler = & info -> hdl ;
17741818 if (info -> hdl .error ) {
17751819 ret = info -> hdl .error ;
0 commit comments