diff mbox series

[5/5] media: ox05b1s: Add support for Omnivision OS08A20 raw sensor

Message ID 20241028190628.257249-6-mirela.rabulea@nxp.com (mailing list archive)
State New
Headers show
Series media: i2c: Add OX05B1S camera sensor driver | expand

Commit Message

Mirela Rabulea Oct. 28, 2024, 7:06 p.m. UTC
This is an 8 megapixel raw10/raw12 sensor with HDR capabilities.
HDR mode control is supported, with one hdr mode: staggered HDR with
2 exposures on separate virtual channels.
Supported resolutions:
   - 1920 x 1080 @ 60fps (SBGGR10, no HDR)
   - 1920 x 1080 @ 30fps (SBGGR10, HDR)
   - 3840 x 2160 @ 30fps (SBGGR12, no HDR)
   - 3840 x 2160 @ 15fps (SBGGR10, HDR)
   - 3840 x 2160 @ 15fps (SBGGR12, HDR)
   - 3840 x 2160 @ 30fps (SBGGR12, no HDR)
   - 3840 x 2160 @ 30fps (SBGGR10, no HDR)

Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com>
---
 .../media/i2c/ox05b1s/os08a20_regs_1080p.h    | 201 +++++++++++++++++
 drivers/media/i2c/ox05b1s/os08a20_regs_4k.h   | 209 ++++++++++++++++++
 .../media/i2c/ox05b1s/os08a20_regs_4k_hdr.h   | 199 +++++++++++++++++
 drivers/media/i2c/ox05b1s/ox05b1s_mipi.c      | 189 ++++++++++++++++
 4 files changed, 798 insertions(+)
 create mode 100644 drivers/media/i2c/ox05b1s/os08a20_regs_1080p.h
 create mode 100644 drivers/media/i2c/ox05b1s/os08a20_regs_4k.h
 create mode 100644 drivers/media/i2c/ox05b1s/os08a20_regs_4k_hdr.h
diff mbox series

Patch

diff --git a/drivers/media/i2c/ox05b1s/os08a20_regs_1080p.h b/drivers/media/i2c/ox05b1s/os08a20_regs_1080p.h
new file mode 100644
index 000000000000..ab9977c56a10
--- /dev/null
+++ b/drivers/media/i2c/ox05b1s/os08a20_regs_1080p.h
@@ -0,0 +1,201 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * A register configuration for Omnivision OS08A20 raw camera, 1920 x 1080 @60fps BGGR10
+ * Copyright (C) 2024, NXP
+ * Copyright (C) 2024, Omnivision
+ * Copyright (C) 2024, Verisilicon
+ *
+ */
+#ifndef _OS08A20_REGS_1080P_H_
+#define _OS08A20_REGS_1080P_H_
+
+static struct ox05b1s_reg os08a20_init_setting_1080p[] = {
+	{0x0100, 0x00},
+	{0x0103, 0x01},
+	{0x0303, 0x01},
+	{0x0304, 0x00}, /* PLL_CTRL_04 (default 0x00) */
+	{0x0305, 0x2d}, /* PLL_CTRL_05 (default 0x3c) */
+	{0x0306, 0x00},
+	{0x0308, 0x03},
+	{0x0309, 0x04},
+	{0x0325, 0x45}, /* PLL_CTRL_25 (default 0x3c) */
+	{0x0327, 0x05}, /* PLL_CTRL_27 (default 0x07) */
+	{0x0328, 0x02}, /* PLL_CTRL_28 (default 0x07) */
+	{0x032a, 0x02}, /* PLL_CTRL_2a (default 0x00) */
+	{0x300f, 0x11},
+	{0x3010, 0x01},
+	{0x3011, 0x04},
+	{0x3012, 0x41},
+	{0x3016, 0xf0},
+	{0x301e, 0x98},
+	{0x3031, 0xa9},
+	{0x3103, 0x92},
+	{0x3104, 0x01},
+	{0x3106, 0x10},
+	{0x3400, 0x04}, /* PSV CTRL (default 0x00) bit[2]=r_psv_mode_en */
+	{0x3025, 0x03}, /* PSV MODE OPT (default 0x02) not used */
+	{0x3425, 0x01}, /* R ASP PD SEL bit[1:0]=stream blanking */
+	{0x3428, 0x01}, /* R ASP PD SEL bit[1:0]=bpg1 N-pump1 bypass to AGND */
+	{0x3408, 0x03}, /* CTRL08 (default 0x01) bit[3:0]=r_clk_winp_off */
+	{0x340c, 0xff},
+	{0x340d, 0xff},
+	{0x031e, 0x09},
+	{0x3501, 0x04}, /* Long exposure */
+	{0x3502, 0x62}, /* Long exposure */
+	{0x3505, 0x83},
+	{0x3508, 0x00}, /* Long gain */
+	{0x3509, 0x80}, /* Long gain */
+	{0x350a, 0x04},
+	{0x350b, 0x00},
+	{0x350c, 0x00},
+	{0x350d, 0x80},
+	{0x350e, 0x04},
+	{0x350f, 0x00},
+	{0x3600, 0x09}, /* CORE0 bit[0]=stg_hdr_align_en, bit[3]=new_stgr_hdr_en */
+	{0x3603, 0x2c},
+	{0x3605, 0x50},
+	{0x3609, 0xb5},
+	{0x3610, 0x39},
+	{0x360c, 0x01},
+	{0x3628, 0xa4},
+	{0x362d, 0x10},
+	{0x3660, 0x43}, /* CORE0 bit[0]=rip_sof_vifo_en, bit[1]=stg_hdr_long_en debug mode */
+	{0x3662, 0x00},
+	{0x3663, 0x28},
+	{0x3664, 0x0d},
+	{0x366a, 0x38},
+	{0x366b, 0xa0},
+	{0x366d, 0x00},
+	{0x366e, 0x00},
+	{0x3680, 0x00},
+	{0x36c0, 0x00},
+	{0x3701, 0x02}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x373b, 0x02},
+	{0x373c, 0x02},
+	{0x3736, 0x02},
+	{0x3737, 0x02},
+	{0x3705, 0x00},
+	{0x3706, 0x39},
+	{0x370a, 0x00},
+	{0x370b, 0x98},
+	{0x3709, 0x49},
+	{0x3714, 0x22},  /* Sensor timing control registers 0x3700-0x37ff */
+	{0x371c, 0x00},
+	{0x371d, 0x08},
+	{0x3740, 0x1b},
+	{0x3741, 0x04},
+	{0x375e, 0x0b},
+	{0x3760, 0x10},
+	{0x3776, 0x10},
+	{0x3781, 0x02},
+	{0x3782, 0x04},
+	{0x3783, 0x02},
+	{0x3784, 0x08},
+	{0x3785, 0x08},
+	{0x3788, 0x01},
+	{0x3789, 0x01},
+	{0x3797, 0x04},
+	{0x3762, 0x11},  /* Sensor timing control registers 0x3700-0x37ff */
+	{0x3800, 0x00},
+	{0x3801, 0x00},
+	{0x3802, 0x00},
+	{0x3803, 0x0c},
+	{0x3804, 0x0e},
+	{0x3805, 0xff},
+	{0x3806, 0x08},
+	{0x3807, 0x6f},
+	{0x3808, 0x07}, /* X output size (default 0x07) */
+	{0x3809, 0x80}, /* X output size (default 0x80) */
+	{0x380a, 0x04}, /* Y output size (default 0x04) */
+	{0x380b, 0x38}, /* Y output size (default 0x38) */
+	{0x380c, 0x07}, /* HTS[15:8], total horizontal timing size */
+	{0x380d, 0x90}, /* HTS[7:0],  total horizontal timing size */
+	{0x380e, 0x04}, /* VTS[15:8], total vertical timing (default 0x04) */
+	{0x380f, 0xa4}, /* VTS[7:0],  total vertical timing (default 0xA0) */
+	{0x3813, 0x08}, /* ISP_Y_WIN ISP vertical windowing offset */
+	{0x3814, 0x03}, /* X INC ODD (default 0x01) */
+	{0x3815, 0x01}, /* X INC EVEN (default 0x01) */
+	{0x3816, 0x03}, /* Y INC ODD (default 0x01) */
+	{0x3817, 0x01}, /* Y INC EVEN (default 0x01) */
+	{0x381c, 0x00}, /* BLC_NUM_OPTION (default 0x0e) */
+	{0x3820, 0x01}, /* FORMAT1 (default 0x80) bit[0]=vertical bining */
+	{0x3821, 0x05}, /* FORMAT2 bit[2]=mirror, bit[0]=horizontal bining */
+	{0x3823, 0x08},
+	{0x3826, 0x00},
+	{0x3827, 0x08},
+	{0x382d, 0x08},
+	{0x3832, 0x02},
+	{0x3833, 0x00}, /* REG33 (bit[0]=r_stg_hdr_grp_wr_opt, bit[2]=r_stg_grphold_nomask) */
+	{0x383c, 0x48},
+	{0x383d, 0xff},
+	{0x3d85, 0x0b},
+	{0x3d84, 0x40},
+	{0x3d8c, 0x63},
+	{0x3d8d, 0xd7},
+	{0x4000, 0xf8},
+	{0x4001, 0x2b},
+	{0x4004, 0x00},
+	{0x4005, 0x40},
+	{0x400a, 0x01},
+	{0x400f, 0xa0},
+	{0x4010, 0x12},
+	{0x4018, 0x00},
+	{0x4008, 0x02},
+	{0x4009, 0x05}, /* BLC CTRL09 (default 0x0f) bl_end */
+	{0x401a, 0x58},
+	{0x4050, 0x00},
+	{0x4051, 0x01},
+	{0x4028, 0x2f},
+	{0x4052, 0x00},
+	{0x4053, 0x80},
+	{0x4054, 0x00},
+	{0x4055, 0x80},
+	{0x4056, 0x00},
+	{0x4057, 0x80},
+	{0x4058, 0x00},
+	{0x4059, 0x80},
+	{0x430b, 0xff},
+	{0x430c, 0xff},
+	{0x430d, 0x00},
+	{0x430e, 0x00},
+	{0x4501, 0x98}, /* R1 (default 0x18) bit[4:2]=not used */
+	{0x4502, 0x00},
+	{0x4643, 0x00},
+	{0x4640, 0x01},
+	{0x4641, 0x04},
+	{0x4800, 0x64},
+	{0x4809, 0x2b},
+	{0x4813, 0x90}, /* MIPI CTRL 13 (bit[5:4]=VC1=1, bit[7:6]=VC2=2) */
+	{0x4817, 0x04},
+	{0x4833, 0x18},
+	{0x4837, 0x16}, /* PCLK PERIOD (default 0x08) */
+	{0x483b, 0x00},
+	{0x484b, 0x03},
+	{0x4850, 0x7c},
+	{0x4852, 0x06},
+	{0x4856, 0x58},
+	{0x4857, 0xaa},
+	{0x4862, 0x0a},
+	{0x4869, 0x18},
+	{0x486a, 0xaa},
+	{0x486e, 0x03}, /* MIPI CTRL 6E (default 0x03) */
+	{0x486f, 0x55},
+	{0x4875, 0xf0},
+	{0x5000, 0x89},
+	{0x5001, 0x42},
+	{0x5004, 0x40},
+	{0x5005, 0x00},
+	{0x5180, 0x00},
+	{0x5181, 0x10},
+	{0x580b, 0x03},
+	{0x4d00, 0x03},
+	{0x4d01, 0xc9},
+	{0x4d02, 0xbc},
+	{0x4d03, 0xc6},
+	{0x4d04, 0x4a},
+	{0x4d05, 0x25},
+	{0x4700, 0x2b},
+	{0x4e00, 0x2b},
+};
+
+#endif
diff --git a/drivers/media/i2c/ox05b1s/os08a20_regs_4k.h b/drivers/media/i2c/ox05b1s/os08a20_regs_4k.h
new file mode 100644
index 000000000000..f3d5f0fe1b61
--- /dev/null
+++ b/drivers/media/i2c/ox05b1s/os08a20_regs_4k.h
@@ -0,0 +1,209 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * A register configuration for Omnivision OS08A20 raw camera, 3840 x 2160 @30fps BGGR12
+ * Copyright (C) 2024, NXP
+ * Copyright (C) 2024, Omnivision
+ * Copyright (C) 2024, Verisilicon
+ *
+ */
+
+#ifndef _OS08A20_REGS_4K_H_
+#define _OS08A20_REGS_4K_H_
+
+static struct ox05b1s_reg os08a20_init_setting_4k[] = {
+	{0x0100, 0x00},
+	{0x0103, 0x01},
+	{0x0303, 0x01},
+	{0x0305, 0x3c}, /* PLL_CTRL_05 (default 0x3c) */
+	{0x0306, 0x00},
+	{0x0308, 0x03},
+	{0x0309, 0x04},
+	{0x0325, 0x47}, /* PLL_CTRL_25 (default 0x3c) */
+	{0x032a, 0x00}, /* PLL_CTRL_2a (default 0x00) */
+	{0x300f, 0x11},
+	{0x3010, 0x01},
+	{0x3011, 0x04},
+	{0x3012, 0x41},
+	{0x3016, 0xf0},
+	{0x301e, 0x98},
+	{0x3031, 0xa9},
+	{0x3103, 0x92},
+	{0x3104, 0x01},
+	{0x3106, 0x10},
+	{0x3400, 0x04}, /* PSV CTRL (default 0x00) bit[2]=r_psv_mode_en */
+	{0x3025, 0x03}, /* PSV MODE OPT (default 0x02) not used */
+	{0x3425, 0x01}, /* R ASP PD SEL bit[1:0]=stream blanking */
+	{0x3428, 0x01}, /* R ASP PD SEL bit[1:0]=bpg1 N-pump1 bypass to AGND */
+	{0x3408, 0x03}, /* CTRL08 (default 0x01) bit[3:0]=r_clk_winp_off */
+	{0x340c, 0xff},
+	{0x340d, 0xff},
+	{0x031e, 0x0a},
+	{0x3501, 0x08}, /* Long exposure */
+	{0x3502, 0xe5}, /* Long exposure */
+	{0x3505, 0x83},
+	{0x3508, 0x00}, /* Long gain */
+	{0x3509, 0x80}, /* Long gain */
+	{0x350a, 0x04},
+	{0x350b, 0x00},
+	{0x350c, 0x00},
+	{0x350d, 0x80},
+	{0x350e, 0x04},
+	{0x350f, 0x00},
+	{0x3600, 0x00}, /* CORE0 bit[0]=stg_hdr_align_en, bit[3]=new_stgr_hdr_en */
+	{0x3603, 0x2c},
+	{0x3605, 0x50},
+	{0x3609, 0xdb},
+	{0x3610, 0x39},
+	{0x360c, 0x01},
+	{0x3628, 0xa4},
+	{0x362d, 0x10},
+	{0x3660, 0xd3}, /* CORE0 bit[0]=rip_sof_vifo_en, bit[1]=stg_hdr_long_en debug mode */
+	{0x3662, 0x00},
+	{0x3663, 0x28},
+	{0x3664, 0x0d},
+	{0x366a, 0x38},
+	{0x366b, 0xa0},
+	{0x366d, 0x00},
+	{0x366e, 0x00},
+	{0x3680, 0x00},
+	{0x36c0, 0x00},
+	{0x3701, 0x02}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x373b, 0x02},
+	{0x373c, 0x02},
+	{0x3736, 0x02},
+	{0x3737, 0x02},
+	{0x3705, 0x00},
+	{0x3706, 0x72},
+	{0x370a, 0x01},
+	{0x370b, 0x30},
+	{0x3709, 0x48},
+	{0x3714, 0x21}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x371c, 0x00},
+	{0x371d, 0x08},
+	{0x3740, 0x1b},
+	{0x3741, 0x04},
+	{0x375e, 0x0b},
+	{0x3760, 0x10},
+	{0x3776, 0x10},
+	{0x3781, 0x02},
+	{0x3782, 0x04},
+	{0x3783, 0x02},
+	{0x3784, 0x08},
+	{0x3785, 0x08},
+	{0x3788, 0x01},
+	{0x3789, 0x01},
+	{0x3797, 0x04},
+	{0x3762, 0x11},  /* Sensor timing control registers 0x3700-0x37ff */
+	{0x3800, 0x00},
+	{0x3801, 0x00},
+	{0x3802, 0x00},
+	{0x3803, 0x0c},
+	{0x3804, 0x0e},
+	{0x3805, 0xff},
+	{0x3806, 0x08},
+	{0x3807, 0x6f},
+	{0x3808, 0x0f}, /* X output size (default 0x07) */
+	{0x3809, 0x00}, /* X output size (default 0x80) */
+	{0x380a, 0x08}, /* Y output size (default 0x04) */
+	{0x380b, 0x70}, /* Y output size (default 0x38) */
+	{0x380c, 0x08}, /* HTS[15:8], total horizontal timing size */
+	{0x380d, 0x14}, /* HTS[7:0],  total horizontal timing size */
+	{0x380e, 0x08}, /* VTS[15:8], total vertical timing (default 0x04) */
+	{0x380f, 0xf0}, /* VTS[7:0],  total vertical timing (default 0xA0) */
+	{0x3813, 0x10}, /* ISP_Y_WIN ISP vertical windowing offset */
+	{0x3814, 0x01}, /* X INC ODD (default 0x01) */
+	{0x3815, 0x01}, /* X INC EVEN (default 0x01) */
+	{0x3816, 0x01}, /* Y INC ODD (default 0x01) */
+	{0x3817, 0x01}, /* Y INC EVEN (default 0x01) */
+	{0x381c, 0x00}, /* BLC_NUM_OPTION (default 0x0e) */
+	{0x3820, 0x00}, /* FORMAT1 (default 0x80) bit[0]=vertical bining */
+	{0x3821, 0x04}, /* FORMAT2 bit[2]=mirror, bit[0]=horizontal bining */
+	{0x3823, 0x08},
+	{0x3826, 0x00},
+	{0x3827, 0x08},
+	{0x382d, 0x08},
+	{0x3832, 0x02},
+	{0x3833, 0x00}, /* REG33 (bit[0]=r_stg_hdr_grp_wr_opt, bit[2]=r_stg_grphold_nomask) */
+	{0x383c, 0x48},
+	{0x383d, 0xff},
+	{0x3d85, 0x0b},
+	{0x3d84, 0x40},
+	{0x3d8c, 0x63},
+	{0x3d8d, 0xd7},
+	{0x4000, 0xf8},
+	{0x4001, 0x2b},
+	{0x4004, 0x00},
+	{0x4005, 0x40},
+	{0x400a, 0x01},
+	{0x400f, 0xa0},
+	{0x4010, 0x12},
+	{0x4018, 0x00},
+	{0x4008, 0x02},
+	{0x4009, 0x0d}, /* BLC CTRL09 (default 0x0f) bl_end */
+	{0x401a, 0x58},
+	{0x4050, 0x00},
+	{0x4051, 0x01},
+	{0x4028, 0x2f},
+	{0x4052, 0x00},
+	{0x4053, 0x80},
+	{0x4054, 0x00},
+	{0x4055, 0x80},
+	{0x4056, 0x00},
+	{0x4057, 0x80},
+	{0x4058, 0x00},
+	{0x4059, 0x80},
+	{0x430b, 0xff},
+	{0x430c, 0xff},
+	{0x430d, 0x00},
+	{0x430e, 0x00},
+	{0x4501, 0x18}, /* R1 (default 0x18) bit[4:2]=not used */
+	{0x4502, 0x00},
+	{0x4600, 0x00},
+	{0x4601, 0x20},
+	{0x4603, 0x01},
+	{0x4643, 0x00},
+	{0x4640, 0x01},
+	{0x4641, 0x04},
+	{0x4800, 0x64},
+	{0x4809, 0x2b},
+	{0x4813, 0x90}, /* MIPI CTRL 13 (bit[5:4]=VC1=1, bit[7:6]=VC2=2) */
+	{0x4817, 0x04},
+	{0x4833, 0x18},
+	{0x4837, 0x10}, /* PCLK PERIOD (default 0x08) */
+	{0x483b, 0x00},
+	{0x484b, 0x03},
+	{0x4850, 0x7c},
+	{0x4852, 0x06},
+	{0x4856, 0x58},
+	{0x4857, 0xaa},
+	{0x4862, 0x0a},
+	{0x4869, 0x18},
+	{0x486a, 0xaa},
+	{0x486e, 0x03}, /* MIPI CTRL 6E (default 0x03) */
+	{0x486f, 0x55},
+	{0x4875, 0xf0},
+	{0x5000, 0x89},
+	{0x5001, 0x42},
+	{0x5004, 0x40},
+	{0x5005, 0x00},
+	{0x5180, 0x00},
+	{0x5181, 0x10},
+	{0x580b, 0x03},
+	{0x4d00, 0x03},
+	{0x4d01, 0xc9},
+	{0x4d02, 0xbc},
+	{0x4d03, 0xc6},
+	{0x4d04, 0x4a},
+	{0x4d05, 0x25},
+	{0x4700, 0x2b},
+	{0x4e00, 0x2b},
+	{0x3501, 0x09}, /* Long exposure */
+	{0x3502, 0x01}, /* Long exposure */
+	{0x4028, 0x4f},
+	{0x4029, 0x1f},
+	{0x402a, 0x7f},
+	{0x402b, 0x01},
+	{0x0100, 0x01},
+};
+
+#endif
diff --git a/drivers/media/i2c/ox05b1s/os08a20_regs_4k_hdr.h b/drivers/media/i2c/ox05b1s/os08a20_regs_4k_hdr.h
new file mode 100644
index 000000000000..2ae79ebae436
--- /dev/null
+++ b/drivers/media/i2c/ox05b1s/os08a20_regs_4k_hdr.h
@@ -0,0 +1,199 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * A register configuration for Omnivision OS08A20 raw camera, 3840 x 2160 @30fps BGGR10 HDR
+ * Copyright (C) 2024, NXP
+ * Copyright (C) 2024, Omnivision
+ * Copyright (C) 2024, Verisilicon
+ *
+ */
+
+#ifndef _OS08A20_REGS_4K_HDR_H_
+#define _OS08A20_REGS_4K_HDR_H_
+
+static struct ox05b1s_reg os08a20_init_setting_4k_hdr[] = {
+	{0x0100, 0x00},
+	{0x0103, 0x01},
+	{0x0303, 0x01},
+	{0x0305, 0x3c}, /* PLL_CTRL_05 (default 0x3c) */
+	{0x0306, 0x00},
+	{0x0308, 0x03},
+	{0x0309, 0x04},
+	{0x032a, 0x00}, /* PLL_CTRL_2a (default 0x00) */
+	{0x300f, 0x11},
+	{0x3010, 0x01},
+	{0x3011, 0x04},
+	{0x3012, 0x41},
+	{0x3016, 0xf0},
+	{0x301e, 0x98},
+	{0x3031, 0xa9},
+	{0x3103, 0x92},
+	{0x3104, 0x01},
+	{0x3106, 0x10},
+	{0x340c, 0xff},
+	{0x340d, 0xff},
+	{0x031e, 0x09},
+	{0x3501, 0x08}, /* Long exposure */
+	{0x3502, 0xe5}, /* Long exposure */
+	{0x3505, 0x83},
+	{0x3508, 0x00}, /* Long gain */
+	{0x3509, 0x80}, /* Long gain */
+	{0x350a, 0x04},
+	{0x350b, 0x00},
+	{0x350c, 0x00},
+	{0x350d, 0x80},
+	{0x350e, 0x04},
+	{0x350f, 0x00},
+	{0x3600, 0x00}, /* CORE0 bit[0]=stg_hdr_align_en, bit[3]=new_stgr_hdr_en */
+	{0x3603, 0x2c},
+	{0x3605, 0x50},
+	{0x3609, 0xb5},
+	{0x3610, 0x39},
+	{0x360c, 0x01},
+	{0x3628, 0xa4},
+	{0x362d, 0x10},
+	{0x3660, 0x42}, /* CORE0 bit[0]=rip_sof_vifo_en, bit[1]=stg_hdr_long_en debug mode */
+	{0x3661, 0x07}, /* CORE1 (default 0x06) bit[0]=stg_hdr_align_en */
+	{0x3662, 0x00},
+	{0x3663, 0x28},
+	{0x3664, 0x0d},
+	{0x366a, 0x38},
+	{0x366b, 0xa0},
+	{0x366d, 0x00},
+	{0x366e, 0x00},
+	{0x3680, 0x00},
+	{0x36c0, 0x00},
+	{0x3701, 0x02}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x373b, 0x02},
+	{0x373c, 0x02},
+	{0x3736, 0x02},
+	{0x3737, 0x02},
+	{0x3705, 0x00},
+	{0x3706, 0x39},
+	{0x370a, 0x00},
+	{0x370b, 0x98},
+	{0x3709, 0x49},
+	{0x3714, 0x21}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x371c, 0x00},
+	{0x371d, 0x08},
+	{0x3740, 0x1b},
+	{0x3741, 0x04},
+	{0x375e, 0x0b},
+	{0x3760, 0x10},
+	{0x3776, 0x10},
+	{0x3781, 0x02},
+	{0x3782, 0x04},
+	{0x3783, 0x02},
+	{0x3784, 0x08},
+	{0x3785, 0x08},
+	{0x3788, 0x01},
+	{0x3789, 0x01},
+	{0x3797, 0x04},
+	{0x3762, 0x11}, /* Sensor timing control registers 0x3700-0x37ff */
+	{0x3800, 0x00},
+	{0x3801, 0x00},
+	{0x3802, 0x00},
+	{0x3803, 0x0c},
+	{0x3804, 0x0e},
+	{0x3805, 0xff},
+	{0x3806, 0x08},
+	{0x3807, 0x6f},
+	{0x3808, 0x0f}, /* X output size (default 0x07) */
+	{0x3809, 0x00}, /* X output size (default 0x80) */
+	{0x380a, 0x08}, /* Y output size (default 0x04) */
+	{0x380b, 0x70}, /* Y output size (default 0x38) */
+	{0x380c, 0x08}, /* HTS[15:8], total horizontal timing size */
+	{0x380d, 0x18}, /* HTS[7:0],  total horizontal timing size */
+	{0x380e, 0x09}, /* VTS[15:8], total vertical timing (default 0x04) */
+	{0x380f, 0x0a}, /* VTS[7:0],  total vertical timing (default 0xA0) */
+	{0x3813, 0x10}, /* ISP_Y_WIN ISP vertical windowing offset */
+	{0x3814, 0x01}, /* X INC ODD (default 0x01) */
+	{0x3815, 0x01}, /* X INC EVEN (default 0x01) */
+	{0x3816, 0x01}, /* Y INC ODD (default 0x01) */
+	{0x3817, 0x01}, /* Y INC EVEN (default 0x01) */
+	{0x381c, 0x08}, /* BLC_NUM_OPTION (default 0x0e) */
+	{0x3820, 0x00}, /* FORMAT1 (default 0x80) bit[0]=vertical bining */
+	{0x3821, 0x24}, /* FORMAT2 bit[5]=stagger hdr en, bit[2]=mirror */
+	{0x3823, 0x08},
+	{0x3826, 0x00},
+	{0x3827, 0x08},
+	{0x382d, 0x08},
+	{0x3832, 0x02},
+	{0x3833, 0x01}, /* REG33 (bit[0]=r_stg_hdr_grp_wr_opt, bit[2]=r_stg_grphold_nomask) */
+	{0x383c, 0x48},
+	{0x383d, 0xff},
+	{0x3d85, 0x0b},
+	{0x3d84, 0x40},
+	{0x3d8c, 0x63},
+	{0x3d8d, 0xd7},
+	{0x4000, 0xf8},
+	{0x4001, 0x2b},
+	{0x4004, 0x00},
+	{0x4005, 0x40},
+	{0x400a, 0x01},
+	{0x400f, 0xa0},
+	{0x4010, 0x12},
+	{0x4018, 0x00},
+	{0x4008, 0x02},
+	{0x4009, 0x0d}, /* BLC CTRL09 (default 0x0f) bl_end */
+	{0x401a, 0x58},
+	{0x4050, 0x00},
+	{0x4051, 0x01},
+	{0x4028, 0x2f},
+	{0x4052, 0x00},
+	{0x4053, 0x80},
+	{0x4054, 0x00},
+	{0x4055, 0x80},
+	{0x4056, 0x00},
+	{0x4057, 0x80},
+	{0x4058, 0x00},
+	{0x4059, 0x80},
+	{0x430b, 0xff},
+	{0x430c, 0xff},
+	{0x430d, 0x00},
+	{0x430e, 0x00},
+	{0x4501, 0x18}, /* R1 (default 0x18) bit[4:2]=not used */
+	{0x4502, 0x00},
+	{0x4643, 0x00},
+	{0x4640, 0x01},
+	{0x4641, 0x04},
+	{0x4800, 0x64},
+	{0x4809, 0x2b},
+	{0x4813, 0x98}, /* MIPI CTRL 13 (bit[5:4]=VC1=1, bit[7:6]=VC2=2) */
+	{0x4817, 0x04},
+	{0x4833, 0x18},
+	{0x4837, 0x10}, /* PCLK PERIOD (default 0x08) */
+	{0x483b, 0x00},
+	{0x484b, 0x03},
+	{0x4850, 0x7c},
+	{0x4852, 0x06},
+	{0x4856, 0x58},
+	{0x4857, 0xaa},
+	{0x4862, 0x0a},
+	{0x4869, 0x18},
+	{0x486a, 0xaa},
+	{0x486e, 0x07}, /* MIPI CTRL 6E (default 0x03) */
+	{0x486f, 0x55},
+	{0x4875, 0xf0},
+	{0x5000, 0x89},
+	{0x5001, 0x42},
+	{0x5004, 0x40},
+	{0x5005, 0x00},
+	{0x5180, 0x00},
+	{0x5181, 0x10},
+	{0x580b, 0x03},
+	{0x4d00, 0x03},
+	{0x4d01, 0xc9},
+	{0x4d02, 0xbc},
+	{0x4d03, 0xc6},
+	{0x4d04, 0x4a},
+	{0x4d05, 0x25},
+	{0x4700, 0x2b},
+	{0x4e00, 0x2b},
+	{0x3501, 0x08}, /* Long exposure */
+	{0x3502, 0xe1}, /* Long exposure */
+	{0x3511, 0x00}, /* Short exposure */
+	{0x3512, 0x20}, /* Short exposure */
+	{0x3833, 0x01},
+};
+
+#endif
diff --git a/drivers/media/i2c/ox05b1s/ox05b1s_mipi.c b/drivers/media/i2c/ox05b1s/ox05b1s_mipi.c
index 5b9c069af19b..15559265d8f0 100644
--- a/drivers/media/i2c/ox05b1s/ox05b1s_mipi.c
+++ b/drivers/media/i2c/ox05b1s/ox05b1s_mipi.c
@@ -42,6 +42,7 @@  struct ox05b1s_sizes {
 	u32	sizes[OX05B1S_MAX_SIZES][2];
 };
 
+struct ox05b1s;
 struct ox05b1s_plat_data {
 	char				name[20];
 	u32				chip_id;
@@ -56,6 +57,9 @@  struct ox05b1s_plat_data {
 	u32				default_mode_index;
 	const struct ox05b1s_sizes	*supported_codes;
 	u32				supported_codes_count;
+	const char * const		*hdr_modes;
+	u32				hdr_modes_count;
+	int (*set_hdr_mode)(struct ox05b1s *sensor, u32 hdr_mode);
 };
 
 struct ox05b1s_ctrls {
@@ -66,6 +70,7 @@  struct ox05b1s_ctrls {
 	struct v4l2_ctrl *vblank;
 	struct v4l2_ctrl *gain;
 	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *hdr_mode;
 };
 
 struct ox05b1s_reg {
@@ -73,6 +78,9 @@  struct ox05b1s_reg {
 	u32 data;
 };
 
+#include "os08a20_regs_1080p.h"
+#include "os08a20_regs_4k.h"
+#include "os08a20_regs_4k_hdr.h"
 #include "ox05b1s_regs_5mp.h"
 
 struct ox05b1s_mode {
@@ -104,6 +112,68 @@  struct ox05b1s {
 	struct ox05b1s_ctrls ctrls;
 };
 
+static struct ox05b1s_mode os08a20_supported_modes[] = {
+	{
+		/* 1080p BGGR10, no hdr, 60fps */
+		.index		= 0,
+		.width		= 1920,
+		.height		= 1080,
+		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp		= 10,
+		.vts		= 0x4a4,
+		.hts		= 0x790,
+		.exp		= 0x4a4 - 8,
+		.h_bin		= true,
+		.fps		= 60,
+		.reg_data	= os08a20_init_setting_1080p,
+		.reg_data_count	= ARRAY_SIZE(os08a20_init_setting_1080p),
+	},
+	{
+		/* 4k BGGR10, staggered hdr VC0/VC1, 15fps */
+		.index		= 1,
+		.width		= 3840,
+		.height		= 2160,
+		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp		= 10,
+		.vts		= 0x90a,
+		.hts		= 0x818,
+		.exp		= 0x90a - 8,
+		.h_bin		= false,
+		.fps		= 15,
+		.reg_data	= os08a20_init_setting_4k_hdr,
+		.reg_data_count	= ARRAY_SIZE(os08a20_init_setting_4k_hdr),
+	},
+	{
+		/* 4k BGGR12, no hdr, 30fps */
+		.index		= 2,
+		.width		= 3840,
+		.height		= 2160,
+		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.bpp		= 12,
+		.vts		= 0x8f0,
+		.hts		= 0x814,
+		.exp		= 0x8f0 - 8,
+		.h_bin		= false,
+		.fps		= 30,
+		.reg_data	= os08a20_init_setting_4k,
+		.reg_data_count	= ARRAY_SIZE(os08a20_init_setting_4k),
+	},
+};
+
+/* keep in sync with os08a20_supported_modes*/
+static const struct ox05b1s_sizes os08a20_supported_codes[] = {
+	{
+		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.sizes_count = 2,
+		.sizes = { {1920, 1080}, {3840, 2160} }
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.sizes_count = 1,
+		.sizes = { {3840, 2160} }
+	},
+};
+
 static struct ox05b1s_mode ox05b1s_supported_modes[] = {
 	{
 		.index		= 0,
@@ -210,6 +280,18 @@  static int ox05b1s_read_reg(struct ox05b1s *sensor, u16 reg, u8 *val)
 	return ret;
 }
 
+static int ox05b1s_update_bits(struct ox05b1s *sensor, u16 reg, unsigned int mask, u8 val)
+{
+	struct device *dev = &sensor->i2c_client->dev;
+	int ret = 0;
+
+	ret = regmap_update_bits(sensor->regmap, reg, mask, val);
+	if (ret < 0)
+		dev_err(dev, "Failed to update reg addr 0x%04x with 0x%02x\n", reg, val);
+
+	return ret;
+}
+
 #define OX05B1S_MAX_REG_BULK 16
 static int ox05b1s_write_reg_array(struct ox05b1s *sensor,
 				   struct ox05b1s_reg *reg_array,
@@ -239,6 +321,67 @@  static int ox05b1s_write_reg_array(struct ox05b1s *sensor,
 	return 0;
 }
 
+static const char * const os08a20_hdr_modes[] = {
+	"NO HDR",		/* No HDR, single exposure */
+	"HDR Staggered",	/* Staggered HDR mode, 2 exposures on separate virtual channels */
+};
+
+#define OS08A20_REG_CORE1		0x3661
+#define OS08A20_STG_HDR_ALIGN_EN	BIT(0)
+
+#define OS08A20_REG_FORMAT2		0x3821
+#define OS08A20_STG_HDR_EN		BIT(5)
+
+#define OS08A20_REG_MIPI_CTRL_13	0x4813
+#define OS08A20_MISTERY_BIT3		BIT(3)
+
+#define OS08A20_REG_MIPI_CTRL_6E	0x486e
+#define OS08A20_MIPI_VC_ENABLE		BIT(2)
+
+static int os08a20_enable_staggered_hdr(struct ox05b1s *sensor)
+{
+	int ret = 0;
+
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_CORE1, OS08A20_STG_HDR_ALIGN_EN,
+				   OS08A20_STG_HDR_ALIGN_EN);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_FORMAT2, OS08A20_STG_HDR_EN,
+				   OS08A20_STG_HDR_EN);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_MIPI_CTRL_13, OS08A20_MISTERY_BIT3,
+				   OS08A20_MISTERY_BIT3);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_MIPI_CTRL_6E, OS08A20_MIPI_VC_ENABLE,
+				   OS08A20_MIPI_VC_ENABLE);
+	if (ret)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int os08a20_disable_staggered_hdr(struct ox05b1s *sensor)
+{
+	int ret = 0;
+
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_CORE1, OS08A20_STG_HDR_ALIGN_EN, 0);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_FORMAT2, OS08A20_STG_HDR_EN, 0);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_MIPI_CTRL_13, OS08A20_MISTERY_BIT3, 0);
+	ret |= ox05b1s_update_bits(sensor, OS08A20_REG_MIPI_CTRL_6E, OS08A20_MIPI_VC_ENABLE, 0);
+	if (ret)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int os08a20_set_hdr_mode(struct ox05b1s *sensor, u32 hdr_mode)
+{
+	switch (hdr_mode) {
+	case 0:
+		return os08a20_disable_staggered_hdr(sensor);
+	case 1:
+		return os08a20_enable_staggered_hdr(sensor);
+	default:
+		return -EINVAL;
+	}
+}
+
 static int ox05b1s_set_hts(struct ox05b1s *sensor, u32 hts)
 {
 	u8 values[2] = { (u8)(hts >> 8) & 0xff, (u8)(hts & 0xff) };
@@ -307,6 +450,12 @@  static int ox05b1s_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_EXPOSURE:
 		ret = ox05b1s_set_exp(sensor, ctrl->val);
 		break;
+	case V4L2_CID_HDR_SENSOR_MODE:
+		if (sensor->model->set_hdr_mode)
+			ret = sensor->model->set_hdr_mode(sensor, ctrl->val);
+		else
+			ret = -EINVAL;
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -369,6 +518,13 @@  static int ox05b1s_init_controls(struct ox05b1s *sensor)
 	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
 					0, 0xFFFF, 1, 0x80);
 
+	if (sensor->model->hdr_modes)
+		ctrls->hdr_mode = v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_HDR_SENSOR_MODE,
+							       sensor->model->hdr_modes_count - 1,
+								0, 0, sensor->model->hdr_modes);
+	else
+		ctrls->hdr_mode = NULL;
+
 	if (hdl->error) {
 		ret = hdl->error;
 		goto free_ctrls;
@@ -670,7 +826,10 @@  static u8 ox05b1s_code2dt(const u32 code)
 {
 	switch (code) {
 	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
 		return MIPI_CSI2_DT_RAW10;
+	case MEDIA_BUS_FMT_SBGGR12_1X12:
+		return MIPI_CSI2_DT_RAW12;
 	default:
 		return MIPI_CSI2_DT_RAW10;
 	}
@@ -775,6 +934,9 @@  static int ox05b1s_read_chip_id(struct ox05b1s *sensor)
 	}
 
 	switch (chip_id) {
+	case 0x530841:
+		camera_name = "os08a20";
+		break;
 	case 0x580542:
 		camera_name = "ox05b1s";
 		break;
@@ -915,6 +1077,26 @@  static void ox05b1s_remove(struct i2c_client *client)
 static DEFINE_RUNTIME_DEV_PM_OPS(ox05b1s_pm_ops, ox05b1s_runtime_suspend,
 				 ox05b1s_runtime_resume, NULL);
 
+static const struct ox05b1s_plat_data os08a20_data = {
+	.name			= "os08a20",
+	.chip_id		= 0x530841,
+	.native_width		= 3872, /* 16 dummy + 3840 active pixels + 16 dummy */
+	.native_height		= 2192, /* 16 dummy + 2160 active lines + 16 dummy */
+	.active_top		= 16,
+	.active_left		= 16,
+	.active_width		= 3840,
+	.active_height		= 2160,
+	.supported_modes	= os08a20_supported_modes,
+	.supported_modes_count	= ARRAY_SIZE(os08a20_supported_modes),
+	.default_mode_index	= 0,
+	.supported_codes	= os08a20_supported_codes,
+	.supported_codes_count	= ARRAY_SIZE(os08a20_supported_codes),
+	.hdr_modes		= os08a20_hdr_modes,
+	.hdr_modes_count	= ARRAY_SIZE(os08a20_hdr_modes),
+	.set_hdr_mode		= os08a20_set_hdr_mode,
+
+};
+
 static const struct ox05b1s_plat_data ox05b1s_data = {
 	.name			= "ox05b1s",
 	.chip_id		= 0x580542,
@@ -929,9 +1111,16 @@  static const struct ox05b1s_plat_data ox05b1s_data = {
 	.default_mode_index	= 0,
 	.supported_codes	= ox05b1s_supported_codes,
 	.supported_codes_count	= ARRAY_SIZE(ox05b1s_supported_codes),
+	.hdr_modes		= NULL,
+	.hdr_modes_count	= 0,
+	.set_hdr_mode		= NULL,
 };
 
 static const struct of_device_id ox05b1s_of_match[] = {
+	{
+		.compatible = "ovti,os08a20",
+		.data = &os08a20_data,
+	},
 	{
 		.compatible = "ovti,ox05b1s",
 		.data = &ox05b1s_data,