56
56
#define IMX335_AGAIN_STEP 1
57
57
#define IMX335_AGAIN_DEFAULT 0
58
58
59
+ /* Vertical flip */
60
+ #define IMX335_REG_VREVERSE CCI_REG8(0x304f)
61
+
59
62
#define IMX335_REG_TPG_TESTCLKEN CCI_REG8(0x3148)
60
63
61
64
#define IMX335_REG_INCLKSEL1 CCI_REG16_LE(0x314c)
@@ -155,6 +158,8 @@ static const char * const imx335_supply_name[] = {
155
158
* @vblank_max: Maximum vertical blanking in lines
156
159
* @pclk: Sensor pixel clock
157
160
* @reg_list: Register list for sensor mode
161
+ * @vflip_normal: Register list vflip (normal readout)
162
+ * @vflip_inverted: Register list vflip (inverted readout)
158
163
*/
159
164
struct imx335_mode {
160
165
u32 width ;
@@ -166,6 +171,8 @@ struct imx335_mode {
166
171
u32 vblank_max ;
167
172
u64 pclk ;
168
173
struct imx335_reg_list reg_list ;
174
+ struct imx335_reg_list vflip_normal ;
175
+ struct imx335_reg_list vflip_inverted ;
169
176
};
170
177
171
178
/**
@@ -183,6 +190,7 @@ struct imx335_mode {
183
190
* @pclk_ctrl: Pointer to pixel clock control
184
191
* @hblank_ctrl: Pointer to horizontal blanking control
185
192
* @vblank_ctrl: Pointer to vertical blanking control
193
+ * @vflip: Pointer to vertical flip control
186
194
* @exp_ctrl: Pointer to exposure control
187
195
* @again_ctrl: Pointer to analog gain control
188
196
* @vblank: Vertical blanking in lines
@@ -207,6 +215,7 @@ struct imx335 {
207
215
struct v4l2_ctrl * pclk_ctrl ;
208
216
struct v4l2_ctrl * hblank_ctrl ;
209
217
struct v4l2_ctrl * vblank_ctrl ;
218
+ struct v4l2_ctrl * vflip ;
210
219
struct {
211
220
struct v4l2_ctrl * exp_ctrl ;
212
221
struct v4l2_ctrl * again_ctrl ;
@@ -259,7 +268,6 @@ static const struct cci_reg_sequence mode_2592x1944_regs[] = {
259
268
{ IMX335_REG_HTRIMMING_START , 48 },
260
269
{ IMX335_REG_HNUM , 2592 },
261
270
{ IMX335_REG_Y_OUT_SIZE , 1944 },
262
- { IMX335_REG_AREA3_ST_ADR_1 , 176 },
263
271
{ IMX335_REG_AREA3_WIDTH_1 , 3928 },
264
272
{ IMX335_REG_OPB_SIZE_V , 0 },
265
273
{ IMX335_REG_XVS_XHS_DRV , 0x00 },
@@ -333,6 +341,26 @@ static const struct cci_reg_sequence mode_2592x1944_regs[] = {
333
341
{ CCI_REG8 (0x3a00 ), 0x00 },
334
342
};
335
343
344
+ static const struct cci_reg_sequence mode_2592x1944_vflip_normal [] = {
345
+ { IMX335_REG_AREA3_ST_ADR_1 , 176 },
346
+
347
+ /* Undocumented V-Flip related registers on Page 55 of datasheet. */
348
+ { CCI_REG8 (0x3081 ), 0x02 , },
349
+ { CCI_REG8 (0x3083 ), 0x02 , },
350
+ { CCI_REG16_LE (0x30b6 ), 0x00 },
351
+ { CCI_REG16_LE (0x3116 ), 0x08 },
352
+ };
353
+
354
+ static const struct cci_reg_sequence mode_2592x1944_vflip_inverted [] = {
355
+ { IMX335_REG_AREA3_ST_ADR_1 , 4112 },
356
+
357
+ /* Undocumented V-Flip related registers on Page 55 of datasheet. */
358
+ { CCI_REG8 (0x3081 ), 0xfe , },
359
+ { CCI_REG8 (0x3083 ), 0xfe , },
360
+ { CCI_REG16_LE (0x30b6 ), 0x1fa },
361
+ { CCI_REG16_LE (0x3116 ), 0x002 },
362
+ };
363
+
336
364
static const struct cci_reg_sequence raw10_framefmt_regs [] = {
337
365
{ IMX335_REG_ADBIT , 0x00 },
338
366
{ IMX335_REG_MDBIT , 0x00 },
@@ -419,6 +447,14 @@ static const struct imx335_mode supported_mode = {
419
447
.num_of_regs = ARRAY_SIZE (mode_2592x1944_regs ),
420
448
.regs = mode_2592x1944_regs ,
421
449
},
450
+ .vflip_normal = {
451
+ .num_of_regs = ARRAY_SIZE (mode_2592x1944_vflip_normal ),
452
+ .regs = mode_2592x1944_vflip_normal ,
453
+ },
454
+ .vflip_inverted = {
455
+ .num_of_regs = ARRAY_SIZE (mode_2592x1944_vflip_inverted ),
456
+ .regs = mode_2592x1944_vflip_inverted ,
457
+ },
422
458
};
423
459
424
460
/**
@@ -492,6 +528,26 @@ static int imx335_update_exp_gain(struct imx335 *imx335, u32 exposure, u32 gain)
492
528
return ret ;
493
529
}
494
530
531
+ static int imx335_update_vertical_flip (struct imx335 * imx335 , u32 vflip )
532
+ {
533
+ int ret = 0 ;
534
+
535
+ if (vflip )
536
+ cci_multi_reg_write (imx335 -> cci ,
537
+ imx335 -> cur_mode -> vflip_inverted .regs ,
538
+ imx335 -> cur_mode -> vflip_inverted .num_of_regs ,
539
+ & ret );
540
+ else
541
+ cci_multi_reg_write (imx335 -> cci ,
542
+ imx335 -> cur_mode -> vflip_normal .regs ,
543
+ imx335 -> cur_mode -> vflip_normal .num_of_regs ,
544
+ & ret );
545
+ if (ret )
546
+ return ret ;
547
+
548
+ return cci_write (imx335 -> cci , IMX335_REG_VREVERSE , vflip , NULL );
549
+ }
550
+
495
551
static int imx335_update_test_pattern (struct imx335 * imx335 , u32 pattern_index )
496
552
{
497
553
int ret = 0 ;
@@ -584,6 +640,10 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
584
640
585
641
ret = imx335_update_exp_gain (imx335 , exposure , analog_gain );
586
642
643
+ break ;
644
+ case V4L2_CID_VFLIP :
645
+ ret = imx335_update_vertical_flip (imx335 , ctrl -> val );
646
+
587
647
break ;
588
648
case V4L2_CID_TEST_PATTERN :
589
649
ret = imx335_update_test_pattern (imx335 , ctrl -> val );
@@ -1166,7 +1226,7 @@ static int imx335_init_controls(struct imx335 *imx335)
1166
1226
return ret ;
1167
1227
1168
1228
/* v4l2_fwnode_device_properties can add two more controls */
1169
- ret = v4l2_ctrl_handler_init (ctrl_hdlr , 9 );
1229
+ ret = v4l2_ctrl_handler_init (ctrl_hdlr , 10 );
1170
1230
if (ret )
1171
1231
return ret ;
1172
1232
@@ -1201,6 +1261,13 @@ static int imx335_init_controls(struct imx335 *imx335)
1201
1261
1202
1262
v4l2_ctrl_cluster (2 , & imx335 -> exp_ctrl );
1203
1263
1264
+ imx335 -> vflip = v4l2_ctrl_new_std (ctrl_hdlr ,
1265
+ & imx335_ctrl_ops ,
1266
+ V4L2_CID_VFLIP ,
1267
+ 0 , 1 , 1 , 0 );
1268
+ if (imx335 -> vflip )
1269
+ imx335 -> vflip -> flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT ;
1270
+
1204
1271
imx335 -> vblank_ctrl = v4l2_ctrl_new_std (ctrl_hdlr ,
1205
1272
& imx335_ctrl_ops ,
1206
1273
V4L2_CID_VBLANK ,
0 commit comments