lede/target/linux/bcm27xx/patches-6.12/950-0145-media-i2c-imx296-Add-horizontal-vertical-flip-suppor.patch
=?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= d81c03f05e bcm27xx: add 6.12 patches from RPi repo
These patches were generated from:
https://github.com/raspberrypi/linux/commits/rpi-6.12.y
With the following command:
git format-patch -N v6.12.27..HEAD
(HEAD -> 8d3206ee456a5ecdf9ddbfd8e5e231e4f0cd716e)

Exceptions:
- (def)configs patches
- github workflows patches
- applied & reverted patches
- readme patches
- wireless patches

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2025-06-20 17:01:06 +08:00

158 lines
4.7 KiB
Diff

From 12b310f8b15c333aad345e1fa0e5d69f207ac8cc Mon Sep 17 00:00:00 2001
From: Naushir Patuck <naush@raspberrypi.com>
Date: Tue, 14 Mar 2023 11:00:48 +0000
Subject: [PATCH] media: i2c: imx296: Add horizontal/vertical flip support
Add support for setting horizontal and/or vertial flips in the IMX296
sensor through the V4L2_CID_HFLIP and V4L2_CID_VFLIP controls.
Add a new helper function to return the media bus format code that
depends on the sensor flips.
Grab the V4L2_CID_HFLIP and V4L2_CID_VFLIP controls on stream on, and
release on stream off to ensure flips cannot be changed while the sensor
is streaming.
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
---
drivers/media/i2c/imx296.c | 65 +++++++++++++++++++++++++++++++++++---
1 file changed, 60 insertions(+), 5 deletions(-)
--- a/drivers/media/i2c/imx296.c
+++ b/drivers/media/i2c/imx296.c
@@ -212,6 +212,8 @@ struct imx296 {
struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *hflip;
};
static inline struct imx296 *to_imx296(struct v4l2_subdev *sd)
@@ -253,6 +255,36 @@ static int imx296_write(struct imx296 *s
return ret;
}
+/*
+ * The supported formats.
+ * This table MUST contain 4 entries per format, to cover the various flip
+ * combinations in the order
+ * - no flip
+ * - h flip
+ * - v flip
+ * - h&v flips
+ */
+static const u32 mbus_codes[] = {
+ /* 10-bit modes. */
+ MEDIA_BUS_FMT_SRGGB10_1X10,
+ MEDIA_BUS_FMT_SGRBG10_1X10,
+ MEDIA_BUS_FMT_SGBRG10_1X10,
+ MEDIA_BUS_FMT_SBGGR10_1X10,
+};
+
+static u32 imx296_mbus_code(const struct imx296 *sensor)
+{
+ unsigned int i = 0;
+
+ if (sensor->mono)
+ return MEDIA_BUS_FMT_Y10_1X10;
+
+ if (sensor->vflip && sensor->hflip)
+ i = (sensor->vflip->val ? 2 : 0) | (sensor->hflip->val ? 1 : 0);
+
+ return mbus_codes[i];
+}
+
static int imx296_power_on(struct imx296 *sensor)
{
int ret;
@@ -347,6 +379,13 @@ static int imx296_s_ctrl(struct v4l2_ctr
&ret);
break;
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ imx296_write(sensor, IMX296_CTRL0E,
+ sensor->vflip->val | (sensor->hflip->val << 1),
+ &ret);
+ break;
+
case V4L2_CID_TEST_PATTERN:
if (ctrl->val) {
imx296_write(sensor, IMX296_PGHPOS, 8, &ret);
@@ -432,6 +471,16 @@ static int imx296_ctrls_init(struct imx2
V4L2_CID_ANALOGUE_GAIN, IMX296_GAIN_MIN,
IMX296_GAIN_MAX, 1, IMX296_GAIN_MIN);
+ sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ if (sensor->hflip && !sensor->mono)
+ sensor->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+
+ sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ if (sensor->vflip && !sensor->mono)
+ sensor->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+
imx296_setup_hblank(sensor, IMX296_PIXEL_ARRAY_WIDTH);
sensor->vblank = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
@@ -609,6 +658,10 @@ static int imx296_stream_on(struct imx29
imx296_write(sensor, IMX296_CTRL0A, 0, &ret);
+ /* vflip and hflip cannot change during streaming */
+ __v4l2_ctrl_grab(sensor->vflip, 1);
+ __v4l2_ctrl_grab(sensor->hflip, 1);
+
return ret;
}
@@ -619,6 +672,9 @@ static int imx296_stream_off(struct imx2
imx296_write(sensor, IMX296_CTRL0A, IMX296_CTRL0A_XMSTA, &ret);
imx296_write(sensor, IMX296_CTRL00, IMX296_CTRL00_STANDBY, &ret);
+ __v4l2_ctrl_grab(sensor->vflip, 0);
+ __v4l2_ctrl_grab(sensor->hflip, 0);
+
return ret;
}
@@ -679,8 +735,7 @@ static int imx296_enum_mbus_code(struct
if (code->index != 0)
return -EINVAL;
- code->code = sensor->mono ? MEDIA_BUS_FMT_Y10_1X10
- : MEDIA_BUS_FMT_SBGGR10_1X10;
+ code->code = imx296_mbus_code(sensor);
return 0;
}
@@ -690,6 +745,7 @@ static int imx296_enum_frame_size(struct
struct v4l2_subdev_frame_size_enum *fse)
{
const struct v4l2_mbus_framefmt *format;
+ struct imx296 *sensor = to_imx296(sd);
format = v4l2_subdev_state_get_format(state, fse->pad);
@@ -697,7 +753,7 @@ static int imx296_enum_frame_size(struct
* Binning does not seem to work on either mono or colour sensor
* variants. Disable enumerating the binned frame size for now.
*/
- if (fse->index >= 1 || fse->code != format->code)
+ if (fse->index >= 1 || fse->code != imx296_mbus_code(sensor))
return -EINVAL;
fse->min_width = IMX296_PIXEL_ARRAY_WIDTH / (fse->index + 1);
@@ -724,8 +780,7 @@ static int imx296_set_format(struct v4l2
imx296_setup_hblank(sensor, format->width);
- format->code = sensor->mono ? MEDIA_BUS_FMT_Y10_1X10
- : MEDIA_BUS_FMT_SBGGR10_1X10;
+ format->code = imx296_mbus_code(sensor);
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_RAW;
format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;