From a6048e36f5e5d73a29d1f5096fc77286f8aa949d Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 11 Jun 2020 18:34:16 +0100 Subject: [PATCH] media: i2c: imx290: Add H and V flip controls The sensor supports horizontal and vertical flips, so support them through V4L2_CID_HFLIP and V4L2_CID_VFLIP. This sensor does NOT change the Bayer order when changing the direction of readout, therefore no special handling is required for that. Signed-off-by: Dave Stevenson --- drivers/media/i2c/imx290.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -34,6 +34,7 @@ enum imx290_clk_index { #define IMX290_STANDBY 0x3000 #define IMX290_REGHOLD 0x3001 #define IMX290_XMSTA 0x3002 +#define IMX290_FLIP_WINMODE 0x3007 #define IMX290_FR_FDG_SEL 0x3009 #define IMX290_BLKLEVEL_LOW 0x300a #define IMX290_BLKLEVEL_HIGH 0x300b @@ -107,6 +108,8 @@ struct imx290 { struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; struct v4l2_ctrl *exposure; struct mutex lock; @@ -600,6 +603,7 @@ static int imx290_set_ctrl(struct v4l2_c struct imx290 *imx290 = container_of(ctrl->handler, struct imx290, ctrls); int ret = 0; + u8 val; /* V4L2 controls values will be applied only when power is already up */ if (!pm_runtime_get_if_in_use(imx290->dev)) @@ -618,6 +622,16 @@ static int imx290_set_ctrl(struct v4l2_c case V4L2_CID_VBLANK: ret = imx290_set_vmax(imx290, ctrl->val); break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + /* WINMODE is in bits [6:4], so need to read-modify-write */ + ret = imx290_read_reg(imx290, IMX290_FLIP_WINMODE, &val); + if (ret) + break; + val &= ~0x03; + val |= imx290->vflip->val | (imx290->hflip->val << 1); + ret = imx290_write_reg(imx290, IMX290_FLIP_WINMODE, val); + break; case V4L2_CID_TEST_PATTERN: if (ctrl->val) { imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00); @@ -924,6 +938,9 @@ static int imx290_set_stream(struct v4l2 imx290_stop_streaming(imx290); pm_runtime_put(imx290->dev); } + /* vflip and hflip cannot change during streaming */ + __v4l2_ctrl_grab(imx290->vflip, enable); + __v4l2_ctrl_grab(imx290->hflip, enable); unlock_and_return: @@ -1217,6 +1234,11 @@ static int imx290_probe(struct i2c_clien IMX290_EXPOSURE_STEP, mode->vmax - 4); + imx290->hflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + imx290->vflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + imx290->link_freq = v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops, V4L2_CID_LINK_FREQ,