]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: i2c: ov01a10: Fix the horizontal flip control
authorHans de Goede <hansg@kernel.org>
Tue, 14 Oct 2025 17:40:09 +0000 (19:40 +0200)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Tue, 13 Jan 2026 11:28:48 +0000 (12:28 +0100)
During sensor calibration I noticed that with the hflip control set
to false/disabled the image was mirrored.

So it seems that the horizontal flip control is inverted and needs to
be set to 1 to not flip (just like the similar problem recently fixed
on the ov08x40 sensor).

Invert the hflip control to fix the sensor mirroring by default.

As the comment above the newly added OV01A10_MEDIA_BUS_FMT define explains
the control being inverted also means that the native Bayer-order of
the sensor actually is GBRG not BGGR, but so as to not break userspace
the Bayer-order is kept at BGGR.

Fixes: 0827b58dabff ("media: i2c: add ov01a10 image sensor driver")
Cc: stable@vger.kernel.org
Signed-off-by: Hans de Goede <hansg@kernel.org>
Tested-by: Mehdi Djait <mehdi.djait@linux.intel.com> # Dell XPS 9315
Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/i2c/ov01a10.c

index 141cb6f75b5550e9aa37192392f55f36a8321523..e5df01f979781419fe146c1c33c992d1ead12688 100644 (file)
 #define OV01A10_REG_X_WIN              0x3811
 #define OV01A10_REG_Y_WIN              0x3813
 
+/*
+ * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug enabling
+ * hflip/mirroring by default resulting in BGGR. Because of this bug Intel's
+ * proprietary IPU6 userspace stack expects BGGR. So we report BGGR to not break
+ * userspace and fix things up by shifting the crop window-x coordinate by 1
+ * when hflip is *disabled*.
+ */
+#define OV01A10_MEDIA_BUS_FMT          MEDIA_BUS_FMT_SBGGR10_1X10
+
 struct ov01a10_reg {
        u16 address;
        u8 val;
@@ -185,14 +194,14 @@ static const struct ov01a10_reg sensor_1280x800_setting[] = {
        {0x380e, 0x03},
        {0x380f, 0x80},
        {0x3810, 0x00},
-       {0x3811, 0x08},
+       {0x3811, 0x09},
        {0x3812, 0x00},
        {0x3813, 0x08},
        {0x3814, 0x01},
        {0x3815, 0x01},
        {0x3816, 0x01},
        {0x3817, 0x01},
-       {0x3820, 0xa0},
+       {0x3820, 0xa8},
        {0x3822, 0x13},
        {0x3832, 0x28},
        {0x3833, 0x10},
@@ -411,7 +420,7 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip)
        int ret;
        u32 val, offset;
 
-       offset = hflip ? 0x9 : 0x8;
+       offset = hflip ? 0x8 : 0x9;
        ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset);
        if (ret)
                return ret;
@@ -420,8 +429,8 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip)
        if (ret)
                return ret;
 
-       val = hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) :
-               val & ~OV01A10_HFLIP_MASK;
+       val = hflip ? val & ~OV01A10_HFLIP_MASK :
+                     val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1);
 
        return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val);
 }
@@ -610,7 +619,7 @@ static void ov01a10_update_pad_format(const struct ov01a10_mode *mode,
 {
        fmt->width = mode->width;
        fmt->height = mode->height;
-       fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+       fmt->code = OV01A10_MEDIA_BUS_FMT;
        fmt->field = V4L2_FIELD_NONE;
        fmt->colorspace = V4L2_COLORSPACE_RAW;
 }
@@ -751,7 +760,7 @@ static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd,
        if (code->index > 0)
                return -EINVAL;
 
-       code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+       code->code = OV01A10_MEDIA_BUS_FMT;
 
        return 0;
 }
@@ -761,7 +770,7 @@ static int ov01a10_enum_frame_size(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        if (fse->index >= ARRAY_SIZE(supported_modes) ||
-           fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
+           fse->code != OV01A10_MEDIA_BUS_FMT)
                return -EINVAL;
 
        fse->min_width = supported_modes[fse->index].width;