Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: imx335: Support vertical flip

Support vertical flip by setting REG_VREVERSE.
Additional registers also needs to be set per mode, according
to the readout direction (normal/inverted) as mentioned in the
data sheet.

Since the register IMX335_REG_AREA3_ST_ADR_1 is based on the
flip (and is set via vflip related registers), it has been
moved out of the 2592x1944 mode regs.

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Tommaso Merciai <tomm.merciai@gmail.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Umang Jain and committed by
Hans Verkuil
2581a401 554f7b8d

+62 -2
+62 -2
drivers/media/i2c/imx335.c
··· 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) ··· 158 155 * @vblank_max: Maximum vertical blanking in lines 159 156 * @pclk: Sensor pixel clock 160 157 * @reg_list: Register list for sensor mode 158 + * @vflip_normal: Register list vflip (normal readout) 159 + * @vflip_inverted: Register list vflip (inverted readout) 161 160 */ 162 161 struct imx335_mode { 163 162 u32 width; ··· 171 166 u32 vblank_max; 172 167 u64 pclk; 173 168 struct imx335_reg_list reg_list; 169 + struct imx335_reg_list vflip_normal; 170 + struct imx335_reg_list vflip_inverted; 174 171 }; 175 172 176 173 /** ··· 190 183 * @pclk_ctrl: Pointer to pixel clock control 191 184 * @hblank_ctrl: Pointer to horizontal blanking control 192 185 * @vblank_ctrl: Pointer to vertical blanking control 186 + * @vflip: Pointer to vertical flip control 193 187 * @exp_ctrl: Pointer to exposure control 194 188 * @again_ctrl: Pointer to analog gain control 195 189 * @vblank: Vertical blanking in lines ··· 215 207 struct v4l2_ctrl *pclk_ctrl; 216 208 struct v4l2_ctrl *hblank_ctrl; 217 209 struct v4l2_ctrl *vblank_ctrl; 210 + struct v4l2_ctrl *vflip; 218 211 struct { 219 212 struct v4l2_ctrl *exp_ctrl; 220 213 struct v4l2_ctrl *again_ctrl; ··· 268 259 { IMX335_REG_HTRIMMING_START, 48 }, 269 260 { IMX335_REG_HNUM, 2592 }, 270 261 { IMX335_REG_Y_OUT_SIZE, 1944 }, 271 - { IMX335_REG_AREA3_ST_ADR_1, 176 }, 272 262 { IMX335_REG_AREA3_WIDTH_1, 3928 }, 273 263 { IMX335_REG_OPB_SIZE_V, 0 }, 274 264 { IMX335_REG_XVS_XHS_DRV, 0x00 }, ··· 339 331 { CCI_REG8(0x3796), 0xa1 }, 340 332 { CCI_REG8(0x37b0), 0x36 }, 341 333 { CCI_REG8(0x3a00), 0x00 }, 334 + }; 335 + 336 + static const struct cci_reg_sequence mode_2592x1944_vflip_normal[] = { 337 + { IMX335_REG_AREA3_ST_ADR_1, 176 }, 338 + 339 + /* Undocumented V-Flip related registers on Page 55 of datasheet. */ 340 + { CCI_REG8(0x3081), 0x02, }, 341 + { CCI_REG8(0x3083), 0x02, }, 342 + { CCI_REG16_LE(0x30b6), 0x00 }, 343 + { CCI_REG16_LE(0x3116), 0x08 }, 344 + }; 345 + 346 + static const struct cci_reg_sequence mode_2592x1944_vflip_inverted[] = { 347 + { IMX335_REG_AREA3_ST_ADR_1, 4112 }, 348 + 349 + /* Undocumented V-Flip related registers on Page 55 of datasheet. */ 350 + { CCI_REG8(0x3081), 0xfe, }, 351 + { CCI_REG8(0x3083), 0xfe, }, 352 + { CCI_REG16_LE(0x30b6), 0x1fa }, 353 + { CCI_REG16_LE(0x3116), 0x002 }, 342 354 }; 343 355 344 356 static const struct cci_reg_sequence raw10_framefmt_regs[] = { ··· 447 419 .num_of_regs = ARRAY_SIZE(mode_2592x1944_regs), 448 420 .regs = mode_2592x1944_regs, 449 421 }, 422 + .vflip_normal = { 423 + .num_of_regs = ARRAY_SIZE(mode_2592x1944_vflip_normal), 424 + .regs = mode_2592x1944_vflip_normal, 425 + }, 426 + .vflip_inverted = { 427 + .num_of_regs = ARRAY_SIZE(mode_2592x1944_vflip_inverted), 428 + .regs = mode_2592x1944_vflip_inverted, 429 + }, 450 430 }; 451 431 452 432 /** ··· 526 490 ret = ret_hold; 527 491 528 492 return ret; 493 + } 494 + 495 + static int imx335_update_vertical_flip(struct imx335 *imx335, u32 vflip) 496 + { 497 + const struct imx335_reg_list * const vflip_regs = 498 + vflip ? &imx335->cur_mode->vflip_inverted : 499 + &imx335->cur_mode->vflip_normal; 500 + int ret = 0; 501 + 502 + cci_multi_reg_write(imx335->cci, vflip_regs->regs, 503 + vflip_regs->num_of_regs, &ret); 504 + 505 + return cci_write(imx335->cci, IMX335_REG_VREVERSE, vflip, &ret); 529 506 } 530 507 531 508 static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_index) ··· 641 592 exposure, analog_gain); 642 593 643 594 ret = imx335_update_exp_gain(imx335, exposure, analog_gain); 595 + 596 + break; 597 + case V4L2_CID_VFLIP: 598 + ret = imx335_update_vertical_flip(imx335, ctrl->val); 644 599 645 600 break; 646 601 case V4L2_CID_TEST_PATTERN: ··· 1228 1175 return ret; 1229 1176 1230 1177 /* v4l2_fwnode_device_properties can add two more controls */ 1231 - ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9); 1178 + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); 1232 1179 if (ret) 1233 1180 return ret; 1234 1181 ··· 1262 1209 IMX335_AGAIN_DEFAULT); 1263 1210 1264 1211 v4l2_ctrl_cluster(2, &imx335->exp_ctrl); 1212 + 1213 + imx335->vflip = v4l2_ctrl_new_std(ctrl_hdlr, 1214 + &imx335_ctrl_ops, 1215 + V4L2_CID_VFLIP, 1216 + 0, 1, 1, 0); 1217 + if (imx335->vflip) 1218 + imx335->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 1265 1219 1266 1220 imx335->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 1267 1221 &imx335_ctrl_ops,