From 5d6ff8fed66d318031d82ed18aa41d068f471494 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Fri, 7 Nov 2025 16:43:42 -0800 Subject: [PATCH 01/12] WDR start --- drivers/media/i2c/imx678.c | 80 +++++++++++++++++++++-- drivers/media/i2c/imx678.h | 126 +++++++++++++++++++++++++++++++++++-- 2 files changed, 197 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index d645483babbf1b..01f471d4352e67 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -45,6 +45,11 @@ #define IMX678_ANA_GAIN_STEP 1 #define IMX678_ANA_GAIN_DEFAULT 0 +#define IMX678_EXP_GAIN_MIN 0 +#define IMX678_EXP_GAIN_MAX 5 +#define IMX678_EXP_GAIN_STEP 1 +#define IMX678_EXP_GAIN_DEFAULT 2 + #define IMX678_BLACK_LEVEL_MIN 0 #define IMX678_BLACK_LEVEL_STEP 1 #define IMX678_MAX_BLACK_LEVEL_10BPP 1023 @@ -60,6 +65,19 @@ enum pad_types { NUM_PADS }; +enum imx678_hdr_mode { + IMX678_HDR_MODE_LINEAR, + IMX678_HDR_MODE_CLEAR, + IMX678_HDR_MODE_DOL, + IMX678_HDR_MODE_COUNT, +}; + +static const char * const imx678_hdr_mode_menu[] = { + "Linear", + "DOL HDR (2-exp)", + "Clear HDR (DCG)", +}; + #define IMX678_NATIVE_WIDTH 3856U #define IMX678_NATIVE_HEIGHT 2180U #define IMX678_PIXEL_ARRAY_LEFT 0U @@ -70,6 +88,10 @@ enum pad_types { #define V4L2_CID_FRAME_RATE (V4L2_CID_USER_IMX_BASE + 1) #define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) #define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) +#define V4L2_CID_HDR_MODE (V4L2_CID_USER_IMX_BASE + 4) +#define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 5) +#define V4L2_CID_ANALOGUE_GAIN_SHORT (V4L2_CID_USER_IMX_BASE + 6) +#define V4L2_CID_EXPONENTIAL_GAIN (V4L2_CID_USER_IMX_BASE + 7) struct imx678_reg_list { unsigned int num_of_regs; @@ -77,7 +99,6 @@ struct imx678_reg_list { }; struct imx678_mode { - unsigned int width; unsigned int height; unsigned int linkfreq; @@ -283,6 +304,7 @@ struct imx678 { struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *link_freq; struct v4l2_ctrl *exposure; + struct v4l2_ctrl *gain; struct v4l2_ctrl *framerate; struct v4l2_ctrl *operation_mode; struct v4l2_ctrl *sync_mode; @@ -292,6 +314,18 @@ struct imx678 { struct v4l2_ctrl *hblank; struct v4l2_ctrl *blklvl; + // + // HDR controls + // + struct v4l2_ctrl *hdr_mode; + + // DOL mode + struct v4l2_ctrl *exposure_short; + struct v4l2_ctrl *gain_short; + + // Clear mode + struct v4l2_ctrl *exponential_gain; + u64 line_time; u32 frame_length; @@ -802,11 +836,14 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_ANALOGUE_GAIN: - ret = imx678_write_hold_reg(imx678, GAIN_LOW, 2, ctrl->val); + ret = imx678_write_hold_reg(imx678, GAIN_0_LOW, 2, ctrl->val); break; case V4L2_CID_EXPOSURE: ret = imx678_set_exposure(imx678, ctrl->val); break; + case V4L2_CID_HDR_SENSOR_MODE: + ret = imx678_set_hdr_mode(imx678, ctrl->val); + break; case V4L2_CID_TEST_PATTERN: imx678_set_test_pattern(imx678, ctrl->val); break; @@ -822,6 +859,15 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_BLACK_LEVEL: ret = imx678_set_blklvl(imx678, ctrl->val); break; + case V4L2_CID_EXPOSURE_SHORT: + ret = imx678_set_exposure_short(imx678, ctrl->val); + break; + case V4L2_CID_ANALOGUE_GAIN_SHORT: + ret = imx678_write_hold_reg(imx678, GAIN_1_LOW, 2, ctrl->val); + break; + case V4L2_CID_EXPONENTIAL_GAIN: + ret = imx678_write_hold_reg(imx678, EXP_GAIN, 1, ctrl->val); + break; case V4L2_CID_OPERATION_MODE: ret = imx678_set_operation_mode(imx678, ctrl->val); break; @@ -1245,7 +1291,7 @@ static int imx678_power_on(struct device *dev) struct imx678 *imx678 = to_imx678(sd); if (strcmp(imx678->gmsl, "gmsl")) { - gpiod_set_value_cansleep(imx678->reset_gpio, 1); + gpiod_set_value_cansleep(imx678->reset_gpio, 1); usleep_range(25000, 30000); } @@ -1433,6 +1479,13 @@ static int imx678_init_controls(struct imx678 *imx678) IMX678_MIN_INTEGRATION_LINES, 0xFF, 1, 0xFF); + imx678->hdr_mode = v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_HDR_SENSOR_MODE, + IMX678_HDR_MODE_COUNT - 1, + 0, + IMX678_HDR_MODE_LINEAR, + imx678_hdr_mode_menu); + imx678->framerate = v4l2_ctrl_new_custom(ctrl_hdlr, imx678_ctrl_framerate, NULL); @@ -1447,12 +1500,31 @@ static int imx678_init_controls(struct imx678 *imx678) IMX678_BLACK_LEVEL_MIN, 0xFF, IMX678_BLACK_LEVEL_STEP, 0xFF); - v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + imx678->gain = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, IMX678_ANA_GAIN_MIN, IMX678_ANA_GAIN_MAX, IMX678_ANA_GAIN_STEP, IMX678_ANA_GAIN_DEFAULT); + imx678->exposure_short = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_EXPOSURE_SHORT, + IMX678_MIN_INTEGRATION_LINES, + 0xFF, 1, IMX678_MIN_INTEGRATION_LINES); + + + imx678->gain_short = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_ANALOGUE_GAIN_SHORT, + IMX678_ANA_GAIN_MIN, + IMX678_ANA_GAIN_MAX, + IMX678_ANA_GAIN_STEP, + IMX678_ANA_GAIN_DEFAULT); + + imx678->exponential_gain = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_EXPONENTIAL_GAIN, + IMX678_EXP_GAIN_MIN, + IMX678_EXP_GAIN_MAX, + IMX678_EXP_GAIN_STEP, + IMX678_EXP_GAIN_DEFAULT); + imx678->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index aceb2777dd702b..416db31ebaf8f1 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -14,6 +14,7 @@ #define WINMODE 0x3018 #define WDMODE 0x301A #define ADDMODE 0x301B +#define THIN_V_EN 0x301C #define VCMODE 0x301E @@ -27,6 +28,7 @@ #define VMAX_HIGH 0x302A #define HMAX_LOW 0x302C #define HMAX_HIGH 0x302D +#define FDG_SEL0 0x3030 #define PIX_HST_LOW 0x303C #define PIX_HST_HIGH 0x303D @@ -40,17 +42,47 @@ #define PIX_VWIDTH_LOW 0x3046 #define PIX_VWIDTH_HIGH 0x3047 -#define SHR0_LOW 0x3050 -#define SHR0_MID 0x3051 -#define SHR0_HIGH 0x3052 +// Long exposure +#define SHR0_LOW 0x3050 +#define SHR0_MID 0x3051 +#define SHR0_HIGH 0x3052 -#define GAIN_LOW 0x3070 -#define GAIN_HIGH 0x3071 +// Short exposure +#define SHR1_LOW 0x3054 +#define SHR1_MID 0x3055 +#define SHR1_HIGH 0x3056 + +// Very short exposure +#define SHR2_LOW 0x3058 +#define SHR2_MID 0x3059 +#define SHR2_HIGH 0x305A + +// Long exposure +#define GAIN_0_LOW 0x3070 +#define GAIN_0_HIGH 0x3071 + +// Short exposure +#define GAIN_1_LOW 0x3072 +#define GAIN_1_HIGH 0x3073 + +// Very short exposure +#define GAIN_2_LOW 0x3074 +#define GAIN_2_HIGH 0x3075 + +#define RHS1_LOW 0x3060 +#define RHS1_MID 0x3061 +#define RHS1_HIGH 0x3062 +#define RHS2_LOW 0x3064 +#define RHS2_MID 0x3065 +#define RHS2_HIGH 0x3066 + +#define EXP_GAIN 0x3081 #define XVS_XHS_DRV 0x30A6 #define BLKLEVEL_LOW 0x30DC #define BLKLEVEL_HIGH 0x30DD +#define GAIN_PGC_FIDMD 0x3400 #define TPG_EN_DUOUT 0x30E0 #define TPG_PATSEL_DUOUT 0x30E2 @@ -523,6 +555,90 @@ static const struct imx678_reg mode_h2v2_binning[] = { }; +static struct imx678_reg imx678_setting_dol_hdr[] = { + {WINMODE, 0x00}, + {WDMODE, 0x01}, + {ADDMODE, 0x00}, + {THIN_V_EN, 0x01}, + + {GAIN_PGC_FIDMD, 0x00}, + + {SHR0_LOW, 0x40}, + {SHR0_MID, 0x0b}, + {SHR1_LOW, 0x05}, + + {RHS1_LOW, 0x49}, + {RHS1_MID, 0x00}, + + {0x355A, 0x64}, +}; + + +static struct imx678_reg imx678_setting_clear_hdr[] = { + {WINMODE, 0x00}, + {WDMODE, 0x08}, + {ADDMODE, 0x00}, + + {VMAX_LOW, 0x94}, + {VMAX_MID, 0x11}, + + {FDG_SEL0, 0x02}, + {SHR0_LOW, 0x06}, + {SHR0_MID, 0x00}, + + {0x306B, 0x04}, + {EXP_GAIN, 0x02}, + {0x355A, 0x00}, + {0x3A64, 0x01}, + + {0x3C37, 0x30}, + + {0x3CF2, 0x78}, + {0x3CF3, 0x00}, + + {0x3EB4, 0x7B}, + {0x3EB5, 0x00}, + {0x3EB7, 0x40}, + + {0x3F24, 0x17}, + {0x3FC4, 0x2D}, + + {0x4420, 0xFF}, + {0x4421, 0x03}, + {0x4422, 0x00}, + {0x4423, 0x08}, + + {0x44A4, 0x37}, + {0x44A6, 0x37}, + {0x44A8, 0x37}, + {0x44AA, 0x37}, + {0x44B4, 0x37}, + {0x44B6, 0x37}, + {0x44B8, 0x37}, + {0x44BA, 0x37}, + {0x44C4, 0x37}, + {0x44C6, 0x37}, + {0x44C8, 0x37}, + + {0x453D, 0x18}, + {0x453E, 0x18}, + {0x453F, 0x11}, + {0x4540, 0x11}, + {0x4541, 0x11}, + {0x4542, 0x11}, + {0x4543, 0x11}, + {0x4544, 0x11}, + {0x4549, 0x00}, + {0x454A, 0x00}, + {0x454B, 0x04}, + {0x454C, 0x04}, + {0x454D, 0x04}, + {0x454E, 0x04}, + {0x454F, 0x04}, + {0x4550, 0x04}, + {0x454A, 0x04}, +}; + static const struct imx678_reg mode_enable_pattern_generator[] = { {BLKLEVEL_LOW, 0x00}, From 8d63930b179555116a532470b6c866e8e47954ff Mon Sep 17 00:00:00 2001 From: Brady Law Date: Sat, 8 Nov 2025 08:30:53 -0800 Subject: [PATCH 02/12] remove space --- drivers/media/i2c/imx678.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 416db31ebaf8f1..530f0da625af53 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -112,7 +112,6 @@ struct imx678_reg { #define IMX678_TO_MID_BYTE(x) (x >> 8) static const struct imx678_reg mode_common_regs[] = { - {LANEMODE, 0x03}, {INCK_SEL, 0x01}, @@ -473,42 +472,32 @@ static const struct imx678_reg mode_common_regs[] = { {0x47C1, 0x01}, {0x47C2, 0x3E}, {0x47C3, 0x01}, - }; static const struct imx678_reg raw12_framefmt_regs[] = { - {ADBIT, 0x01}, {MDBIT, 0x01}, - }; static const struct imx678_reg raw10_framefmt_regs[] = { - {ADBIT, 0x00}, {MDBIT, 0x00}, - }; static const struct imx678_reg raw12_h2v2_framefmt_regs[] = { - {ADBIT, 0x00}, {MDBIT, 0x01}, - }; static const struct imx678_reg mode_3856x2180[] = { - {WINMODE, 0x00}, {ADDMODE, 0x00}, {WDMODE, 0x00}, {VCMODE, 0x01}, - }; static const struct imx678_reg mode_crop_2608x1964[] = { - {WINMODE, 0x04}, {ADDMODE, 0x00}, {WDMODE, 0x00}, @@ -523,12 +512,10 @@ static const struct imx678_reg mode_crop_2608x1964[] = { {PIX_VST_LOW, IMX678_TO_LOW_BYTE(108)}, {PIX_VWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_2608x1964_HEIGHT)}, {PIX_VWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_2608x1964_HEIGHT)}, - }; static const struct imx678_reg mode_crop_1920x1080[] = { - {WINMODE, 0x04}, {ADDMODE, 0x00}, {WDMODE, 0x00}, @@ -543,16 +530,13 @@ static const struct imx678_reg mode_crop_1920x1080[] = { {PIX_VST_LOW, IMX678_TO_LOW_BYTE(548)}, {PIX_VWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_1920x1080_HEIGHT)}, {PIX_VWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_1920x1080_HEIGHT)}, - }; static const struct imx678_reg mode_h2v2_binning[] = { - {WINMODE, 0x00}, {ADDMODE, 0x01}, {WDMODE, 0x00}, {VCMODE, 0x01}, - }; static struct imx678_reg imx678_setting_dol_hdr[] = { @@ -640,21 +624,17 @@ static struct imx678_reg imx678_setting_clear_hdr[] = { }; static const struct imx678_reg mode_enable_pattern_generator[] = { - {BLKLEVEL_LOW, 0x00}, {TPG_EN_DUOUT, 0x01}, {TPG_COLORWIDTH, 0x00}, {TESTCLKEN, 0x0A}, - }; static const struct imx678_reg mode_disable_pattern_generator[] = { - {BLKLEVEL_LOW, 0x32}, {TPG_EN_DUOUT, 0x00}, {TPG_COLORWIDTH, 0x00}, {TESTCLKEN, 0x02}, - }; enum { From 7defabaaf060099ee7b4fa1c2a382b25a977773f Mon Sep 17 00:00:00 2001 From: Brady Law Date: Mon, 10 Nov 2025 17:11:53 -0800 Subject: [PATCH 03/12] progress --- drivers/media/i2c/imx678.c | 255 +++++++++++-------------------------- drivers/media/i2c/imx678.h | 11 +- 2 files changed, 84 insertions(+), 182 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index 01f471d4352e67..f9f2384faaa630 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -29,10 +29,14 @@ #define IMX678_XCLK_FREQ 74250000 -#define GMSL_LINK_FREQ_1500 (1500000000/2) -#define IMX678_LINK_FREQ_1440 (1440000000/2) -#define IMX678_LINK_FREQ_1188 (1188000000/2) -#define IMX678_LINK_FREQ_891 (891000000/2) +#define IMX678_LINK_FREQ_2376 (2376000000/2) +#define IMX678_LINK_FREQ_2079 (2079000000/2) +#define IMX678_LINK_FREQ_1782 (1782000000/2) +#define IMX678_LINK_FREQ_1440 (1440000000/2) +#define IMX678_LINK_FREQ_1188 (1188000000/2) +#define IMX678_LINK_FREQ_891 (891000000/2) +#define IMX678_LINK_FREQ_720 (720000000/2) +#define IMX678_LINK_FREQ_594 (594000000/2) #define IMX678_MODE_STANDBY 0x01 #define IMX678_MODE_STREAMING 0x00 @@ -57,14 +61,30 @@ #define IMX678_DEFAULT_BLACK_LEVEL_10BPP 50 #define IMX678_DEFAULT_BLACK_LEVEL_12BPP 200 -#define IMX678_EMBEDDED_LINE_WIDTH 16384 -#define IMX678_NUM_EMBEDDED_LINES 1 - enum pad_types { IMAGE_PAD, NUM_PADS }; +enum imx678_camera_mode { + IMX678_CAMERA_MODE_ALL_3856_2180, + IMX678_CAMERA_MODE_CROP_2608_1964, + IMX678_CAMERA_MODE_CROP_1920_1080, + IMX678_CAMERA_MODE_H2V2, + IMX678_CAMERA_MODE_DOL_HDR, + IMX678_CAMERA_MODE_CLEAR_HDR, +}; + + +static const char * const imx678_camera_mode_menu[] = { + [IMX678_CAMERA_MODE_ALL_3856_2180] = "All 3856x2180", + [IMX678_CAMERA_MODE_CROP_2608_1964] = "Crop 2608x1964", + [IMX678_CAMERA_MODE_CROP_1920_1080] = "Crop 1920x1080", + [IMX678_CAMERA_MODE_H2V2] = "H2V2 1928x1090", + [IMX678_CAMERA_MODE_DOL_HDR] = "DOL HDR 3856x2180", + [IMX678_CAMERA_MODE_CLEAR_HDR] = "Clear HDR 3856x2180", +}; + enum imx678_hdr_mode { IMX678_HDR_MODE_LINEAR, IMX678_HDR_MODE_CLEAR, @@ -72,12 +92,6 @@ enum imx678_hdr_mode { IMX678_HDR_MODE_COUNT, }; -static const char * const imx678_hdr_mode_menu[] = { - "Linear", - "DOL HDR (2-exp)", - "Clear HDR (DCG)", -}; - #define IMX678_NATIVE_WIDTH 3856U #define IMX678_NATIVE_HEIGHT 2180U #define IMX678_PIXEL_ARRAY_LEFT 0U @@ -85,13 +99,13 @@ static const char * const imx678_hdr_mode_menu[] = { #define IMX678_PIXEL_ARRAY_WIDTH 3856U #define IMX678_PIXEL_ARRAY_HEIGHT 2180U -#define V4L2_CID_FRAME_RATE (V4L2_CID_USER_IMX_BASE + 1) -#define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) -#define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) -#define V4L2_CID_HDR_MODE (V4L2_CID_USER_IMX_BASE + 4) -#define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 5) -#define V4L2_CID_ANALOGUE_GAIN_SHORT (V4L2_CID_USER_IMX_BASE + 6) -#define V4L2_CID_EXPONENTIAL_GAIN (V4L2_CID_USER_IMX_BASE + 7) +#define V4L2_CID_CAMERA_MODE (V4L2_CID_USER_IMX_BASE + 0) +#define V4L2_CID_FRAME_RATE (V4L2_CID_USER_IMX_BASE + 1) +#define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) +#define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) +#define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 4) +#define V4L2_CID_ANALOGUE_GAIN_SHORT (V4L2_CID_USER_IMX_BASE + 5) +#define V4L2_CID_EXPONENTIAL_GAIN (V4L2_CID_USER_IMX_BASE + 6) struct imx678_reg_list { unsigned int num_of_regs; @@ -101,30 +115,26 @@ struct imx678_reg_list { struct imx678_mode { unsigned int width; unsigned int height; - unsigned int linkfreq; - unsigned int pixel_rate; - unsigned int min_fps; - unsigned int hmax; struct v4l2_rect crop; + enum imx678_hdr_mode hdr_mode; struct imx678_reg_list reg_list; - struct imx678_reg_list reg_list_format; }; static const s64 imx678_link_freq_menu[] = { - [_IMX678_LINK_FREQ_1440] = IMX678_LINK_FREQ_1440, - [_IMX678_LINK_FREQ_1188] = IMX678_LINK_FREQ_1188, - [_IMX678_LINK_FREQ_891] = IMX678_LINK_FREQ_891, + [IMX678_2376_MBPS] = IMX678_LINK_FREQ_2376, + [IMX678_2079_MBPS] = IMX678_LINK_FREQ_2079, + [IMX678_1782_MBPS] = IMX678_LINK_FREQ_1782, + [IMX678_1440_MBPS] = IMX678_LINK_FREQ_1440, + [IMX678_1188_MBPS] = IMX678_LINK_FREQ_1188, + [IMX678_891_MBPS] = IMX678_LINK_FREQ_891, + [IMX678_720_MBPS] = IMX678_LINK_FREQ_720, + [IMX678_594_MBPS] = IMX678_LINK_FREQ_594, }; -static const struct imx678_mode modes_12bit[] = { - { - /* All pixel mode */ +static const struct imx678_mode modes_frame[] = { + [IMX678_CAMERA_MODE_ALL_3856_2180] = { .width = IMX678_DEFAULT_WIDTH, .height = IMX678_DEFAULT_HEIGHT, - .hmax = 0x44C, - .linkfreq = _IMX678_LINK_FREQ_1188, - .pixel_rate = 260280000, - .min_fps = 1000000, .crop = { .left = 0, .top = 0, @@ -135,19 +145,11 @@ static const struct imx678_mode modes_12bit[] = { .num_of_regs = ARRAY_SIZE(mode_3856x2180), .regs = mode_3856x2180, }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw12_framefmt_regs), - .regs = raw12_framefmt_regs, - }, + .hdr_mode = IMX678_HDR_MODE_LINEAR, }, - { - /* Crop mode */ + [IMX678_CAMERA_MODE_CROP_2608_1964] = { .width = IMX678_CROP_2608x1964_WIDTH, .height = IMX678_CROP_2608x1964_HEIGHT, - .hmax = 0x294, - .linkfreq = _IMX678_LINK_FREQ_1440, - .pixel_rate = 293400000, - .min_fps = 1000000, .crop = { .left = 628, .top = 108, @@ -158,19 +160,11 @@ static const struct imx678_mode modes_12bit[] = { .num_of_regs = ARRAY_SIZE(mode_crop_2608x1964), .regs = mode_crop_2608x1964, }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw12_framefmt_regs), - .regs = raw12_framefmt_regs, - }, + .hdr_mode = IMX678_HDR_MODE_LINEAR, }, - { - /* Crop mode */ + [IMX678_CAMERA_MODE_CROP_1920_1080] = { .width = IMX678_CROP_1920x1080_WIDTH, .height = IMX678_CROP_1920x1080_HEIGHT, - .hmax = 0x294, - .linkfreq = _IMX678_LINK_FREQ_1440, - .pixel_rate = 216000000, - .min_fps = 1000000, .crop = { .left = 972, .top = 548, @@ -181,19 +175,11 @@ static const struct imx678_mode modes_12bit[] = { .num_of_regs = ARRAY_SIZE(mode_crop_1920x1080), .regs = mode_crop_1920x1080, }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw12_framefmt_regs), - .regs = raw12_framefmt_regs, - }, + .hdr_mode = IMX678_HDR_MODE_LINEAR, }, - { - /* h2v2 mode */ + [IMX678_CAMERA_MODE_H2V2] = { .width = IMX678_MODE_BINNING_H2V2_WIDTH, .height = IMX678_MODE_BINNING_H2V2_HEIGHT, - .hmax = 0x226, - .linkfreq = _IMX678_LINK_FREQ_1440, - .pixel_rate = 260280000, - .min_fps = 1000000, .crop = { .left = 0, .top = 0, @@ -204,22 +190,11 @@ static const struct imx678_mode modes_12bit[] = { .num_of_regs = ARRAY_SIZE(mode_h2v2_binning), .regs = mode_h2v2_binning, }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw12_h2v2_framefmt_regs), - .regs = raw12_h2v2_framefmt_regs, - }, + .hdr_mode = IMX678_HDR_MODE_LINEAR, }, -}; - -static const struct imx678_mode modes_10bit[] = { - { - /* All pixel mode */ + [IMX678_CAMERA_MODE_DOL_HDR] = { .width = IMX678_DEFAULT_WIDTH, .height = IMX678_DEFAULT_HEIGHT, - .hmax = 0x44C, - .linkfreq = _IMX678_LINK_FREQ_891, - .pixel_rate = 260280000, - .min_fps = 1000000, .crop = { .left = 0, .top = 0, @@ -227,68 +202,31 @@ static const struct imx678_mode modes_10bit[] = { .height = IMX678_DEFAULT_HEIGHT, }, .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_3856x2180), - .regs = mode_3856x2180, - }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw10_framefmt_regs), - .regs = raw10_framefmt_regs, - }, - }, - { - /* Crop mode */ - .width = IMX678_CROP_2608x1964_WIDTH, - .height = IMX678_CROP_2608x1964_HEIGHT, - .hmax = 0x294, - .linkfreq = _IMX678_LINK_FREQ_1440, - .pixel_rate = 293400000, - .min_fps = 1000000, - .crop = { - .left = 628, - .top = 108, - .width = IMX678_CROP_2608x1964_WIDTH, - .height = IMX678_CROP_2608x1964_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_crop_2608x1964), - .regs = mode_crop_2608x1964, - }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw10_framefmt_regs), - .regs = raw10_framefmt_regs, + .num_of_regs = ARRAY_SIZE(imx678_setting_dol_hdr), + .regs = imx678_setting_dol_hdr, }, + .hdr_mode = IMX678_HDR_MODE_DOL, }, - { - /* Crop mode */ - .width = IMX678_CROP_1920x1080_WIDTH, - .height = IMX678_CROP_1920x1080_HEIGHT, - .hmax = 0x226, - .linkfreq = _IMX678_LINK_FREQ_1440, - .pixel_rate = 259200000, - .min_fps = 1000000, + [IMX678_CAMERA_MODE_CLEAR_HDR] = { + .width = IMX678_DEFAULT_WIDTH, + .height = IMX678_DEFAULT_HEIGHT, .crop = { - .left = 972, - .top = 548, - .width = IMX678_CROP_1920x1080_WIDTH, - .height = IMX678_CROP_1920x1080_HEIGHT, + .left = 0, + .top = 0, + .width = IMX678_DEFAULT_WIDTH, + .height = IMX678_DEFAULT_HEIGHT, }, .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_crop_1920x1080), - .regs = mode_crop_1920x1080, - }, - .reg_list_format = { - .num_of_regs = ARRAY_SIZE(raw10_framefmt_regs), - .regs = raw10_framefmt_regs, + .num_of_regs = ARRAY_SIZE(imx678_setting_clear_hdr), + .regs = imx678_setting_clear_hdr, }, - }, + .hdr_mode = IMX678_HDR_MODE_CLEAR, + } }; static const u32 codes[] = { - MEDIA_BUS_FMT_SRGGB12_1X12, - MEDIA_BUS_FMT_SRGGB10_1X10, - }; struct imx678 { @@ -314,11 +252,6 @@ struct imx678 { struct v4l2_ctrl *hblank; struct v4l2_ctrl *blklvl; - // - // HDR controls - // - struct v4l2_ctrl *hdr_mode; - // DOL mode struct v4l2_ctrl *exposure_short; struct v4l2_ctrl *gain_short; @@ -341,27 +274,7 @@ static inline struct imx678 *to_imx678(struct v4l2_subdev *_sd) return container_of(_sd, struct imx678, sd); } -static inline void get_mode_table(unsigned int code, - const struct imx678_mode **mode_list, - unsigned int *num_modes) -{ - switch (code) { - case MEDIA_BUS_FMT_SRGGB12_1X12: - *mode_list = modes_12bit; - *num_modes = ARRAY_SIZE(modes_12bit); - break; - case MEDIA_BUS_FMT_SRGGB10_1X10: - *mode_list = modes_10bit; - *num_modes = ARRAY_SIZE(modes_10bit); - break; - default: - *mode_list = NULL; - *num_modes = 0; - } -} - static const char * const imx678_test_pattern_menu[] = { - [0] = "Disabled", [1] = "000h Pattern", [2] = "3FF(FFFh) Pattern", @@ -375,22 +288,17 @@ static const char * const imx678_test_pattern_menu[] = { [10] = "FFF/000h Pattern", [11] = "H Color-bar", [12] = "V Color-bar" - }; static const char * const imx678_operation_mode_menu[] = { - [MASTER_MODE] = "Master Mode", [SLAVE_MODE] = "Slave Mode", - }; static const char * const imx678_sync_mode_menu[] = { - [NO_SYNC] = "No Sync", [INTERNAL_SYNC] = "Internal Sync", [EXTERNAL_SYNC] = "External Sync", - }; static int imx678_read_reg(struct imx678 *imx678, u16 reg, u32 len, u32 *val) @@ -593,12 +501,10 @@ static int imx678_set_frame_rate(struct imx678 *imx678, u64 val) } return ret; - } static void imx678_update_frame_rate(struct imx678 *imx678, u64 val) { - const struct imx678_mode *mode = imx678->mode; u32 update_vblank; @@ -613,7 +519,6 @@ static void imx678_update_frame_rate(struct imx678 *imx678, u64 val) update_vblank, 1, update_vblank); __v4l2_ctrl_s_ctrl(imx678->vblank, update_vblank); - } static int imx678_set_hmax_register(struct imx678 *imx678) @@ -640,7 +545,7 @@ static int imx678_set_data_rate(struct imx678 *imx678) int ret; switch (imx678->mode->linkfreq) { - case _IMX678_LINK_FREQ_1440: + case IMX678_1440_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x03); if (ret) { dev_err(dev, "%s failed to write datarate reg.\n", @@ -648,7 +553,7 @@ static int imx678_set_data_rate(struct imx678 *imx678) return ret; } break; - case _IMX678_LINK_FREQ_1188: + case IMX678_1188_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x04); if (ret) { dev_err(dev, "%s failed to write datarate reg.\n", @@ -656,7 +561,7 @@ static int imx678_set_data_rate(struct imx678 *imx678) return ret; } break; - case _IMX678_LINK_FREQ_891: + case IMX678_891_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x05); if (ret) { dev_err(dev, "%s failed to write datarate reg.\n", @@ -699,7 +604,6 @@ static int imx678_set_test_pattern(struct imx678 *imx678, u32 val) fail: dev_err(dev, "%s: error setting test pattern\n", __func__); return ret; - } static void imx678_update_blklvl_range(struct imx678 *imx678) @@ -841,9 +745,6 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_EXPOSURE: ret = imx678_set_exposure(imx678, ctrl->val); break; - case V4L2_CID_HDR_SENSOR_MODE: - ret = imx678_set_hdr_mode(imx678, ctrl->val); - break; case V4L2_CID_TEST_PATTERN: imx678_set_test_pattern(imx678, ctrl->val); break; @@ -1130,7 +1031,6 @@ static int imx678_get_selection(struct v4l2_subdev *sd, static int imx678_set_mode(struct imx678 *imx678) { - struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; const struct imx678_reg_list *reg_list; @@ -1452,6 +1352,11 @@ static int imx678_init_controls(struct imx678 *imx678) mutex_init(&imx678->mutex); ctrl_hdlr->lock = &imx678->mutex; + v4l2_ctrl_new_std_menu(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_CAMERA_MODE, + ARRAY_SIZE(modes_frame), + 0, 0, imx678_camera_mode_menu); + imx678->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); if (imx678->pixel_rate) @@ -1479,13 +1384,6 @@ static int imx678_init_controls(struct imx678 *imx678) IMX678_MIN_INTEGRATION_LINES, 0xFF, 1, 0xFF); - imx678->hdr_mode = v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx678_ctrl_ops, - V4L2_CID_HDR_SENSOR_MODE, - IMX678_HDR_MODE_COUNT - 1, - 0, - IMX678_HDR_MODE_LINEAR, - imx678_hdr_mode_menu); - imx678->framerate = v4l2_ctrl_new_custom(ctrl_hdlr, imx678_ctrl_framerate, NULL); @@ -1511,7 +1409,6 @@ static int imx678_init_controls(struct imx678 *imx678) IMX678_MIN_INTEGRATION_LINES, 0xFF, 1, IMX678_MIN_INTEGRATION_LINES); - imx678->gain_short = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_ANALOGUE_GAIN_SHORT, IMX678_ANA_GAIN_MIN, IMX678_ANA_GAIN_MAX, @@ -1761,6 +1658,6 @@ static struct i2c_driver imx678_i2c_driver = { module_i2c_driver(imx678_i2c_driver); -MODULE_AUTHOR("FRAMOS GmbH"); +MODULE_AUTHOR("FRAMOS GmbH, Brady Law"); MODULE_DESCRIPTION("Sony IMX678 sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 530f0da625af53..6803e2e0fc7bd5 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -638,9 +638,14 @@ static const struct imx678_reg mode_disable_pattern_generator[] = { }; enum { - _IMX678_LINK_FREQ_1440, - _IMX678_LINK_FREQ_1188, - _IMX678_LINK_FREQ_891, + IMX678_2376_MBPS, + IMX678_2079_MBPS, + IMX678_1782_MBPS, + IMX678_1440_MBPS, + IMX678_1188_MBPS, + IMX678_891_MBPS, + IMX678_720_MBPS, + IMX678_594_MBPS, } link_freq; enum { From fe44e4f8a1e1bda4991b5e5832c9609cc921cef5 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Wed, 12 Nov 2025 14:31:21 -0800 Subject: [PATCH 04/12] progress --- drivers/media/i2c/imx678.c | 164 ++++++++++++++----------------------- 1 file changed, 60 insertions(+), 104 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index f9f2384faaa630..eaef43e66d1972 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -5,8 +5,6 @@ * imx678.c - Framos imx678.c driver */ -//#define DEBUG 1 - #include #include #include @@ -41,18 +39,18 @@ #define IMX678_MODE_STANDBY 0x01 #define IMX678_MODE_STREAMING 0x00 -#define IMX678_MIN_SHR0_LENGTH 3 +#define IMX678_MIN_SHR0_LENGTH 3 #define IMX678_MIN_INTEGRATION_LINES 1 -#define IMX678_ANA_GAIN_MIN 0 -#define IMX678_ANA_GAIN_MAX 240 +#define IMX678_ANA_GAIN_MIN 0 +#define IMX678_ANA_GAIN_MAX 240 #define IMX678_ANA_GAIN_STEP 1 #define IMX678_ANA_GAIN_DEFAULT 0 -#define IMX678_EXP_GAIN_MIN 0 -#define IMX678_EXP_GAIN_MAX 5 -#define IMX678_EXP_GAIN_STEP 1 -#define IMX678_EXP_GAIN_DEFAULT 2 +#define IMX678_EXP_GAIN_MIN 0 +#define IMX678_EXP_GAIN_MAX 5 +#define IMX678_EXP_GAIN_STEP 1 +#define IMX678_EXP_GAIN_DEFAULT 2 #define IMX678_BLACK_LEVEL_MIN 0 #define IMX678_BLACK_LEVEL_STEP 1 @@ -75,7 +73,6 @@ enum imx678_camera_mode { IMX678_CAMERA_MODE_CLEAR_HDR, }; - static const char * const imx678_camera_mode_menu[] = { [IMX678_CAMERA_MODE_ALL_3856_2180] = "All 3856x2180", [IMX678_CAMERA_MODE_CROP_2608_1964] = "Crop 2608x1964", @@ -89,10 +86,9 @@ enum imx678_hdr_mode { IMX678_HDR_MODE_LINEAR, IMX678_HDR_MODE_CLEAR, IMX678_HDR_MODE_DOL, - IMX678_HDR_MODE_COUNT, }; -#define IMX678_NATIVE_WIDTH 3856U +#define IMX678_NATIVE_WIDTH 3856U #define IMX678_NATIVE_HEIGHT 2180U #define IMX678_PIXEL_ARRAY_LEFT 0U #define IMX678_PIXEL_ARRAY_TOP 0U @@ -118,6 +114,7 @@ struct imx678_mode { struct v4l2_rect crop; enum imx678_hdr_mode hdr_mode; struct imx678_reg_list reg_list; + bool is_binning; }; static const s64 imx678_link_freq_menu[] = { @@ -146,6 +143,7 @@ static const struct imx678_mode modes_frame[] = { .regs = mode_3856x2180, }, .hdr_mode = IMX678_HDR_MODE_LINEAR, + .is_binning = false, }, [IMX678_CAMERA_MODE_CROP_2608_1964] = { .width = IMX678_CROP_2608x1964_WIDTH, @@ -161,6 +159,7 @@ static const struct imx678_mode modes_frame[] = { .regs = mode_crop_2608x1964, }, .hdr_mode = IMX678_HDR_MODE_LINEAR, + .is_binning = false, }, [IMX678_CAMERA_MODE_CROP_1920_1080] = { .width = IMX678_CROP_1920x1080_WIDTH, @@ -176,6 +175,7 @@ static const struct imx678_mode modes_frame[] = { .regs = mode_crop_1920x1080, }, .hdr_mode = IMX678_HDR_MODE_LINEAR, + .is_binning = false, }, [IMX678_CAMERA_MODE_H2V2] = { .width = IMX678_MODE_BINNING_H2V2_WIDTH, @@ -191,6 +191,7 @@ static const struct imx678_mode modes_frame[] = { .regs = mode_h2v2_binning, }, .hdr_mode = IMX678_HDR_MODE_LINEAR, + .is_binning = true, }, [IMX678_CAMERA_MODE_DOL_HDR] = { .width = IMX678_DEFAULT_WIDTH, @@ -206,6 +207,7 @@ static const struct imx678_mode modes_frame[] = { .regs = imx678_setting_dol_hdr, }, .hdr_mode = IMX678_HDR_MODE_DOL, + .is_binning = false, }, [IMX678_CAMERA_MODE_CLEAR_HDR] = { .width = IMX678_DEFAULT_WIDTH, @@ -221,12 +223,20 @@ static const struct imx678_mode modes_frame[] = { .regs = imx678_setting_clear_hdr, }, .hdr_mode = IMX678_HDR_MODE_CLEAR, + .is_binning = false, } }; -static const u32 codes[] = { - MEDIA_BUS_FMT_SRGGB12_1X12, +static const u32 bayer_formats[] = { + MEDIA_BUS_FMT_SRGGB12_1X12, // no flip + MEDIA_BUS_FMT_SGRBG12_1X12, // H flip + MEDIA_BUS_FMT_SGBRG12_1X12, // V flip + MEDIA_BUS_FMT_SBGGR12_1X12, // H+V flip + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SBGGR10_1X10, }; struct imx678 { @@ -408,16 +418,19 @@ static int imx678_write_table(struct imx678 *imx678, static u32 imx678_get_format_code(struct imx678 *imx678, u32 code) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(codes); i++) - if (codes[i] == code) - break; - - if (i >= ARRAY_SIZE(codes)) - i = 0; + // Standard modes are 0 mod 4 + // H flip - 1 mod 4 + // V flip - 2 mod 4 + // H+V flip - 3 mod 4 + unsigned int i = (im678->hflip->val) ? 1 : 0 + + (imx678->vflip->val) ? 2 : 0; + + for (i; i < ARRAY_SIZE(bayer_formats); i += 4) { + if (bayer_formats[i] == code) + return bayer_formats[i]; + } - return codes[i]; + return bayer_formats[0]; } static int imx678_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) @@ -429,10 +442,9 @@ static int imx678_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) mutex_lock(&imx678->mutex); - fmt_img->width = modes_12bit[0].width; - fmt_img->height = modes_12bit[0].height; - fmt_img->code = imx678_get_format_code(imx678, - MEDIA_BUS_FMT_SRGGB12_1X12); + fmt_img->width = modes_frame[0].width; + fmt_img->height = modes_frame[0].height; + fmt_img->code = MEDIA_BUS_FMT_SRGGB12_1X12; fmt_img->field = V4L2_FIELD_NONE; crop = v4l2_subdev_state_get_crop(fh->state, IMAGE_PAD); @@ -446,16 +458,6 @@ static int imx678_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return 0; } -static bool imx678_is_binning_mode(struct imx678 *imx678) -{ - const struct imx678_mode *mode = imx678->mode; - - if (mode == &modes_12bit[3]) - return true; - else - return false; -} - static int imx678_set_exposure(struct imx678 *imx678, u64 val) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); @@ -547,27 +549,18 @@ static int imx678_set_data_rate(struct imx678 *imx678) switch (imx678->mode->linkfreq) { case IMX678_1440_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x03); - if (ret) { - dev_err(dev, "%s failed to write datarate reg.\n", - __func__); - return ret; - } + if (ret) + goto fail; break; case IMX678_1188_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x04); - if (ret) { - dev_err(dev, "%s failed to write datarate reg.\n", - __func__); - return ret; - } + if (ret) + goto fail; break; case IMX678_891_MBPS: ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x05); - if (ret) { - dev_err(dev, "%s failed to write datarate reg.\n", - __func__); - return ret; - } + if (ret) + goto fail; break; default: dev_err(dev, "%s datarate reg not set!\n", __func__); @@ -575,6 +568,10 @@ static int imx678_set_data_rate(struct imx678 *imx678) } return ret; + +fail: + dev_err(dev, "%s failed to set data rate\n", __func__); + return ret; } static int imx678_set_test_pattern(struct imx678 *imx678, u32 val) @@ -733,6 +730,9 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_VBLANK: imx678_adjust_exposure_range(imx678); break; + case V4L2_CID_CAMERA_MODE: + imx678->mode = modes_frame[ctrl->val]; + break; } if (pm_runtime_get_if_in_use(&client->dev) == 0) @@ -746,7 +746,7 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) ret = imx678_set_exposure(imx678, ctrl->val); break; case V4L2_CID_TEST_PATTERN: - imx678_set_test_pattern(imx678, ctrl->val); + ret = imx678_set_test_pattern(imx678, ctrl->val); break; case V4L2_CID_HFLIP: ret = imx678_write_reg(imx678, HREVERSE, 1, ctrl->val); @@ -796,11 +796,10 @@ static int imx678_enum_mbus_code(struct v4l2_subdev *sd, return -EINVAL; if (code->pad == IMAGE_PAD) { - if (code->index >= (ARRAY_SIZE(codes))) + if (code->index >= (ARRAY_SIZE(bayer_formats))) return -EINVAL; - code->code = imx678_get_format_code(imx678, - codes[code->index]); + code->code = bayer_formats[code->index]; } return 0; @@ -856,37 +855,6 @@ static void imx678_update_image_pad_format(struct imx678 *imx678, imx678_reset_colorspace(&fmt->format); } -static int imx678_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct imx678 *imx678 = to_imx678(sd); - - if (fmt->pad >= NUM_PADS) - return -EINVAL; - - mutex_lock(&imx678->mutex); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_state_get_format(sd_state, - fmt->pad); - try_fmt->code = imx678_get_format_code(imx678, try_fmt->code); - fmt->format = *try_fmt; - } else { - if (fmt->pad == IMAGE_PAD) { - imx678_update_image_pad_format(imx678, imx678->mode, - fmt); - fmt->format.code = - imx678_get_format_code(imx678, - imx678->fmt_code); - } - } - - mutex_unlock(&imx678->mutex); - return 0; -} - static void imx678_set_limits(struct imx678 *imx678) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); @@ -914,7 +882,7 @@ static void imx678_set_limits(struct imx678 *imx678) imx678->line_time = (mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); dev_dbg(dev, "%s: line time: %lld\n", __func__, imx678->line_time); - if (imx678_is_binning_mode(imx678)) + if (mode->is_binning) imx678->frame_length = mode->height * 2 + vblank; else imx678->frame_length = mode->height + vblank; @@ -938,8 +906,8 @@ static int imx678_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct v4l2_mbus_framefmt *framefmt; - const struct imx678_mode *mode; struct imx678 *imx678 = to_imx678(sd); + const struct imx678_mode *mode = imx678->mode; if (fmt->pad >= NUM_PADS) return -EINVAL; @@ -947,26 +915,14 @@ static int imx678_set_pad_format(struct v4l2_subdev *sd, mutex_lock(&imx678->mutex); if (fmt->pad == IMAGE_PAD) { - const struct imx678_mode *mode_list; - unsigned int num_modes; - fmt->format.code = imx678_get_format_code(imx678, fmt->format.code); - - get_mode_table(fmt->format.code, &mode_list, &num_modes); - - mode = v4l2_find_nearest_size(mode_list, - num_modes, - width, height, - fmt->format.width, - fmt->format.height); imx678_update_image_pad_format(imx678, mode, fmt); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); *framefmt = fmt->format; - } else if (imx678->mode != mode) { - imx678->mode = mode; + } else if (imx678->fmt_code != fmt->format.code) { imx678->fmt_code = fmt->format.code; imx678_set_limits(imx678); } @@ -1281,7 +1237,7 @@ static const struct v4l2_subdev_video_ops imx678_video_ops = { static const struct v4l2_subdev_pad_ops imx678_pad_ops = { .enum_mbus_code = imx678_enum_mbus_code, - .get_fmt = imx678_get_pad_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = imx678_set_pad_format, .get_selection = imx678_get_selection, .enum_frame_size = imx678_enum_frame_size, @@ -1578,7 +1534,7 @@ static int imx678_probe(struct i2c_client *client) return PTR_ERR(imx678->xmaster); } - imx678->mode = &modes_12bit[0]; + imx678->mode = &modes_frame[0]; imx678->fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12; pm_runtime_set_active(dev); From c1349a2803e5c61b5247e405e70c160dc50ad267 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Fri, 14 Nov 2025 16:09:22 -0800 Subject: [PATCH 05/12] progress --- drivers/media/i2c/imx678.c | 192 +++++++++++++++++++------------------ drivers/media/i2c/imx678.h | 37 +------ 2 files changed, 99 insertions(+), 130 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index eaef43e66d1972..9fb99a64c3266d 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -65,21 +65,21 @@ enum pad_types { }; enum imx678_camera_mode { - IMX678_CAMERA_MODE_ALL_3856_2180, - IMX678_CAMERA_MODE_CROP_2608_1964, - IMX678_CAMERA_MODE_CROP_1920_1080, - IMX678_CAMERA_MODE_H2V2, + IMX678_CAMERA_MODE_ALL_PIXEL, + IMX678_CAMERA_MODE_ALL_PIXEL_BINNING, IMX678_CAMERA_MODE_DOL_HDR, + IMX678_CAMERA_MODE_DOL_HDR_BINNING, IMX678_CAMERA_MODE_CLEAR_HDR, + IMX678_CAMERA_MODE_CLEAR_HDR_BINNING, }; static const char * const imx678_camera_mode_menu[] = { - [IMX678_CAMERA_MODE_ALL_3856_2180] = "All 3856x2180", - [IMX678_CAMERA_MODE_CROP_2608_1964] = "Crop 2608x1964", - [IMX678_CAMERA_MODE_CROP_1920_1080] = "Crop 1920x1080", - [IMX678_CAMERA_MODE_H2V2] = "H2V2 1928x1090", - [IMX678_CAMERA_MODE_DOL_HDR] = "DOL HDR 3856x2180", - [IMX678_CAMERA_MODE_CLEAR_HDR] = "Clear HDR 3856x2180", + [IMX678_CAMERA_MODE_ALL_PIXEL] = "All Pixel", + [IMX678_CAMERA_MODE_ALL_PIXEL_BINNING] = "All Pixel H2V2 Binning", + [IMX678_CAMERA_MODE_DOL_HDR] = "DOL HDR", + [IMX678_CAMERA_MODE_DOL_HDR_BINNING] = "DOL HDR H2V2 Binning", + [IMX678_CAMERA_MODE_CLEAR_HDR] = "Clear HDR", + [IMX678_CAMERA_MODE_CLEAR_HDR_BINNING] = "Clear HDR Binning", }; enum imx678_hdr_mode { @@ -117,6 +117,11 @@ struct imx678_mode { bool is_binning; }; +enum { + IMX678_BIT_DEPTH_10, + IMX678_BIT_DEPTH_12, +} bit_depth; + static const s64 imx678_link_freq_menu[] = { [IMX678_2376_MBPS] = IMX678_LINK_FREQ_2376, [IMX678_2079_MBPS] = IMX678_LINK_FREQ_2079, @@ -125,11 +130,90 @@ static const s64 imx678_link_freq_menu[] = { [IMX678_1188_MBPS] = IMX678_LINK_FREQ_1188, [IMX678_891_MBPS] = IMX678_LINK_FREQ_891, [IMX678_720_MBPS] = IMX678_LINK_FREQ_720, - [IMX678_594_MBPS] = IMX678_LINK_FREQ_594, +}; + +struct imx678_link_mode { + enum link_freq link_freq; + enum bit_depth bit_depth; + unsigned uint16_t hmax; + unsigned uint16_t modes; +} + +#define LINK_MODE_ALL_PIXEL (1 << 0) +#define LINK_MODE_ALL_BINNING (1 << 1) +#define LINK_MODE_DOL_HDR (1 << 2) +#define LINK_MODE_DOL_BINNING (1 << 3) +#define LINK_MODE_CLEAR_HDR (1 << 4) +#define LINK_MODE_CLEAR_BINNING (1 << 5) + +static const struct imx678_link_mode all_pixel_link_modes = { + // 25 fps, hmax 1320 + { + .link_freq = IMX678_720_MBPS, .bit_depth = 10, .hmax = 1320, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + { + .link_freq = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1320, + .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING | LINK_MODE_CLEAR_BINNING, + }, + { + .link_freq = IMX678_891_MBPS, .bit_depth = 12, .hmax = 1320, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + + // 30 fps, hmax 1100 + { + .link_freq = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1100, + .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING | LINK_MODE_CLEAR_BINNING, + }, + { + .link_freq = IMX678_891_MBPS, .bit_depth = 10, .hmax = 1100, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + { + .link_freq = IMX678_1188_MBPS, .bit_depth = 12, .hmax = 1100, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + + // 50 fps, hmax 660 + { + .link_freq = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 660, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + { + .link_freq = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 660, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | + LINK_MODE_ALL_BINNING | LINK_MODE_DOL_HDR | LINK_MODE_DOL_BINNING | + LINK_MODE_CLEAR_BINNING, + }, + + // 60 fps, hmax 550 + { + .link_freq = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 550, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + }, + { + .link_freq = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 550, + .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING, + }, + { + .link_freq = IMX678_1782_MBPS, .bit_depth = 12, .hmax = 550, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_DOL_HDR, + }, + + // 72 fps, hmax 458 + { + .link_freq = IMX678_2079_MBPS, .bit_depth = 10, .hmax = 458, + .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_DOL_HDR, + }, + { + .link_freq = IMX678_2376_MBPS, .bit_depth = 12, .hmax = 458, + .modes = LINK_MODE_ALL_BINNING, + } }; static const struct imx678_mode modes_frame[] = { - [IMX678_CAMERA_MODE_ALL_3856_2180] = { + [IMX678_CAMERA_MODE_ALL_PIXEL] = { .width = IMX678_DEFAULT_WIDTH, .height = IMX678_DEFAULT_HEIGHT, .crop = { @@ -145,54 +229,6 @@ static const struct imx678_mode modes_frame[] = { .hdr_mode = IMX678_HDR_MODE_LINEAR, .is_binning = false, }, - [IMX678_CAMERA_MODE_CROP_2608_1964] = { - .width = IMX678_CROP_2608x1964_WIDTH, - .height = IMX678_CROP_2608x1964_HEIGHT, - .crop = { - .left = 628, - .top = 108, - .width = IMX678_CROP_2608x1964_WIDTH, - .height = IMX678_CROP_2608x1964_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_crop_2608x1964), - .regs = mode_crop_2608x1964, - }, - .hdr_mode = IMX678_HDR_MODE_LINEAR, - .is_binning = false, - }, - [IMX678_CAMERA_MODE_CROP_1920_1080] = { - .width = IMX678_CROP_1920x1080_WIDTH, - .height = IMX678_CROP_1920x1080_HEIGHT, - .crop = { - .left = 972, - .top = 548, - .width = IMX678_CROP_1920x1080_WIDTH, - .height = IMX678_CROP_1920x1080_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_crop_1920x1080), - .regs = mode_crop_1920x1080, - }, - .hdr_mode = IMX678_HDR_MODE_LINEAR, - .is_binning = false, - }, - [IMX678_CAMERA_MODE_H2V2] = { - .width = IMX678_MODE_BINNING_H2V2_WIDTH, - .height = IMX678_MODE_BINNING_H2V2_HEIGHT, - .crop = { - .left = 0, - .top = 0, - .width = 2 * IMX678_MODE_BINNING_H2V2_WIDTH, - .height = 2 * IMX678_MODE_BINNING_H2V2_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_h2v2_binning), - .regs = mode_h2v2_binning, - }, - .hdr_mode = IMX678_HDR_MODE_LINEAR, - .is_binning = true, - }, [IMX678_CAMERA_MODE_DOL_HDR] = { .width = IMX678_DEFAULT_WIDTH, .height = IMX678_DEFAULT_HEIGHT, @@ -540,40 +576,6 @@ static int imx678_set_hmax_register(struct imx678 *imx678) } -static int imx678_set_data_rate(struct imx678 *imx678) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); - struct device *dev = &client->dev; - int ret; - - switch (imx678->mode->linkfreq) { - case IMX678_1440_MBPS: - ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x03); - if (ret) - goto fail; - break; - case IMX678_1188_MBPS: - ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x04); - if (ret) - goto fail; - break; - case IMX678_891_MBPS: - ret = imx678_write_reg(imx678, DATARATE_SEL, 1, 0x05); - if (ret) - goto fail; - break; - default: - dev_err(dev, "%s datarate reg not set!\n", __func__); - return 1; - } - - return ret; - -fail: - dev_err(dev, "%s failed to set data rate\n", __func__); - return ret; -} - static int imx678_set_test_pattern(struct imx678 *imx678, u32 val) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); @@ -1020,7 +1022,7 @@ static int imx678_set_mode(struct imx678 *imx678) return ret; } - ret = imx678_set_data_rate(imx678); + ret = imx678_write_reg(imx678, DATARATE_SEL, 1, imx678->linkfreq->val); if (ret) { dev_err(dev, "%s failed to set data rate\n", __func__); return ret; diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 6803e2e0fc7bd5..9c390bc2452474 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -497,41 +497,6 @@ static const struct imx678_reg mode_3856x2180[] = { {VCMODE, 0x01}, }; -static const struct imx678_reg mode_crop_2608x1964[] = { - {WINMODE, 0x04}, - {ADDMODE, 0x00}, - {WDMODE, 0x00}, - {VCMODE, 0x01}, - - {PIX_HST_HIGH, IMX678_TO_MID_BYTE(628)}, - {PIX_HST_LOW, IMX678_TO_LOW_BYTE(628)}, - {PIX_HWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_2608x1964_WIDTH)}, - {PIX_HWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_2608x1964_WIDTH)}, - - {PIX_VST_HIGH, IMX678_TO_MID_BYTE(108)}, - {PIX_VST_LOW, IMX678_TO_LOW_BYTE(108)}, - {PIX_VWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_2608x1964_HEIGHT)}, - {PIX_VWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_2608x1964_HEIGHT)}, -}; - - -static const struct imx678_reg mode_crop_1920x1080[] = { - {WINMODE, 0x04}, - {ADDMODE, 0x00}, - {WDMODE, 0x00}, - {VCMODE, 0x01}, - - {PIX_HST_HIGH, IMX678_TO_MID_BYTE(972)}, - {PIX_HST_LOW, IMX678_TO_LOW_BYTE(972)}, - {PIX_HWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_1920x1080_WIDTH)}, - {PIX_HWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_1920x1080_WIDTH)}, - - {PIX_VST_HIGH, IMX678_TO_MID_BYTE(548)}, - {PIX_VST_LOW, IMX678_TO_LOW_BYTE(548)}, - {PIX_VWIDTH_HIGH, IMX678_TO_MID_BYTE(IMX678_CROP_1920x1080_HEIGHT)}, - {PIX_VWIDTH_LOW, IMX678_TO_LOW_BYTE(IMX678_CROP_1920x1080_HEIGHT)}, -}; - static const struct imx678_reg mode_h2v2_binning[] = { {WINMODE, 0x00}, {ADDMODE, 0x01}, @@ -646,6 +611,8 @@ enum { IMX678_891_MBPS, IMX678_720_MBPS, IMX678_594_MBPS, + IMX678_525_MBPS, + IMX678_1050_MBPS, } link_freq; enum { From 94cb3665439e6363d5628c8c0b7668dd20cafe0d Mon Sep 17 00:00:00 2001 From: Brady Law Date: Sat, 15 Nov 2025 09:56:03 -0800 Subject: [PATCH 06/12] progress --- drivers/media/i2c/imx678.c | 191 ++++++++++++++++--------------------- drivers/media/i2c/imx678.h | 7 -- 2 files changed, 83 insertions(+), 115 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index 9fb99a64c3266d..8443b1f4c9d915 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -23,7 +23,6 @@ #define IMX678_K_FACTOR 1000LL #define IMX678_M_FACTOR 1000000LL #define IMX678_G_FACTOR 1000000000LL -#define IMX678_T_FACTOR 1000000000000LL #define IMX678_XCLK_FREQ 74250000 @@ -36,7 +35,7 @@ #define IMX678_LINK_FREQ_720 (720000000/2) #define IMX678_LINK_FREQ_594 (594000000/2) -#define IMX678_MODE_STANDBY 0x01 +#define IMX678_MODE_STANDBY 0x01 #define IMX678_MODE_STREAMING 0x00 #define IMX678_MIN_SHR0_LENGTH 3 @@ -64,28 +63,22 @@ enum pad_types { NUM_PADS }; -enum imx678_camera_mode { - IMX678_CAMERA_MODE_ALL_PIXEL, - IMX678_CAMERA_MODE_ALL_PIXEL_BINNING, - IMX678_CAMERA_MODE_DOL_HDR, - IMX678_CAMERA_MODE_DOL_HDR_BINNING, - IMX678_CAMERA_MODE_CLEAR_HDR, - IMX678_CAMERA_MODE_CLEAR_HDR_BINNING, +enum imx678_frame_mode { + IMX678_HDR_MODE_ALL_PIXEL, + IMX678_HDR_MODE_BINNING, + IMX678_HDR_MODE_DOL_HDR, + IMX678_HDR_MODE_DOL_HDR_BINNING, + IMX678_HDR_MODE_CLEAR_HDR, + IMX678_HDR_MODE_CLEAR_HDR_BINNING, }; -static const char * const imx678_camera_mode_menu[] = { - [IMX678_CAMERA_MODE_ALL_PIXEL] = "All Pixel", - [IMX678_CAMERA_MODE_ALL_PIXEL_BINNING] = "All Pixel H2V2 Binning", - [IMX678_CAMERA_MODE_DOL_HDR] = "DOL HDR", - [IMX678_CAMERA_MODE_DOL_HDR_BINNING] = "DOL HDR H2V2 Binning", - [IMX678_CAMERA_MODE_CLEAR_HDR] = "Clear HDR", - [IMX678_CAMERA_MODE_CLEAR_HDR_BINNING] = "Clear HDR Binning", -}; - -enum imx678_hdr_mode { - IMX678_HDR_MODE_LINEAR, - IMX678_HDR_MODE_CLEAR, - IMX678_HDR_MODE_DOL, +static const char * const imx678_frame_mode_menu[] = { + [IMX678_HDR_MODE_ALL_PIXEL] = "All pixel (HDR off)", + [IMX678_HDR_MODE_BINNING] = "H2V2 binning (HDR off)", + [IMX678_HDR_MODE_DOL_HDR] = "DOL HDR", + [IMX678_HDR_MODE_DOL_HDR_BINNING] = "DOL HDR + H2V2 binning", + [IMX678_HDR_MODE_CLEAR_HDR] = "Clear HDR", + [IMX678_HDR_MODE_CLEAR_HDR_BINNING] = "Clear HDR + H2V2 binning", }; #define IMX678_NATIVE_WIDTH 3856U @@ -95,7 +88,7 @@ enum imx678_hdr_mode { #define IMX678_PIXEL_ARRAY_WIDTH 3856U #define IMX678_PIXEL_ARRAY_HEIGHT 2180U -#define V4L2_CID_CAMERA_MODE (V4L2_CID_USER_IMX_BASE + 0) +#define V4L2_CID_FRAME_MODE (V4L2_CID_USER_IMX_BASE + 0) #define V4L2_CID_FRAME_RATE (V4L2_CID_USER_IMX_BASE + 1) #define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) #define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) @@ -108,15 +101,6 @@ struct imx678_reg_list { const struct imx678_reg *regs; }; -struct imx678_mode { - unsigned int width; - unsigned int height; - struct v4l2_rect crop; - enum imx678_hdr_mode hdr_mode; - struct imx678_reg_list reg_list; - bool is_binning; -}; - enum { IMX678_BIT_DEPTH_10, IMX678_BIT_DEPTH_12, @@ -137,7 +121,7 @@ struct imx678_link_mode { enum bit_depth bit_depth; unsigned uint16_t hmax; unsigned uint16_t modes; -} +}; #define LINK_MODE_ALL_PIXEL (1 << 0) #define LINK_MODE_ALL_BINNING (1 << 1) @@ -146,7 +130,53 @@ struct imx678_link_mode { #define LINK_MODE_CLEAR_HDR (1 << 4) #define LINK_MODE_CLEAR_BINNING (1 << 5) -static const struct imx678_link_mode all_pixel_link_modes = { +struct imx678_frame_mode { + unsigned int width; + unsigned int height; + uint8_t frame_count; + unsigned uint16_t flag; +}; + +static const struct imx678_frame_mode frame_mode_configs[] = { + [IMX678_HDR_MODE_ALL_PIXEL] = { + .width = IMX678_DEFAULT_WIDTH, + .height = IMX678_DEFAULT_HEIGHT, + .frame_count = 1, + .flag = LINK_MODE_ALL_PIXEL, + }, + [IMX678_HDR_MODE_BINNING] = { + .width = IMX678_DEFAULT_WIDTH / 2, + .height = IMX678_DEFAULT_HEIGHT / 2, + .frame_count = 1, + .flag = LINK_MODE_ALL_BINNING, + }, + [IMX678_HDR_MODE_DOL_HDR] = { + .width = IMX678_DEFAULT_WIDTH, + .height = IMX678_DEFAULT_HEIGHT, + .frame_count = 2, + .flag = LINK_MODE_DOL_HDR, + }, + [IMX678_HDR_MODE_DOL_HDR_BINNING] = { + .width = IMX678_DEFAULT_WIDTH / 2, + .height = IMX678_DEFAULT_HEIGHT / 2, + .frame_count = 2, + .flag = LINK_MODE_DOL_BINNING, + }, + [IMX678_HDR_MODE_CLEAR_HDR] = { + .width = IMX678_DEFAULT_WIDTH, + .height = IMX678_DEFAULT_HEIGHT, + .frame_count = 2, + .flag = LINK_MODE_CLEAR_HDR, + }, + [IMX678_HDR_MODE_CLEAR_HDR_BINNING] = { + .width = IMX678_DEFAULT_WIDTH / 2, + .height = IMX678_DEFAULT_HEIGHT / 2, + .frame_count = 2, + .flag = LINK_MODE_CLEAR_BINNING, + }, +}; + +static const struct imx678_link_mode all_pixel_link_modes[] = { // 25 fps, hmax 1320 { .link_freq = IMX678_720_MBPS, .bit_depth = 10, .hmax = 1320, @@ -212,57 +242,6 @@ static const struct imx678_link_mode all_pixel_link_modes = { } }; -static const struct imx678_mode modes_frame[] = { - [IMX678_CAMERA_MODE_ALL_PIXEL] = { - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - .crop = { - .left = 0, - .top = 0, - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_3856x2180), - .regs = mode_3856x2180, - }, - .hdr_mode = IMX678_HDR_MODE_LINEAR, - .is_binning = false, - }, - [IMX678_CAMERA_MODE_DOL_HDR] = { - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - .crop = { - .left = 0, - .top = 0, - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(imx678_setting_dol_hdr), - .regs = imx678_setting_dol_hdr, - }, - .hdr_mode = IMX678_HDR_MODE_DOL, - .is_binning = false, - }, - [IMX678_CAMERA_MODE_CLEAR_HDR] = { - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - .crop = { - .left = 0, - .top = 0, - .width = IMX678_DEFAULT_WIDTH, - .height = IMX678_DEFAULT_HEIGHT, - }, - .reg_list = { - .num_of_regs = ARRAY_SIZE(imx678_setting_clear_hdr), - .regs = imx678_setting_clear_hdr, - }, - .hdr_mode = IMX678_HDR_MODE_CLEAR, - .is_binning = false, - } -}; - static const u32 bayer_formats[] = { MEDIA_BUS_FMT_SRGGB12_1X12, // no flip MEDIA_BUS_FMT_SGRBG12_1X12, // H flip @@ -310,7 +289,7 @@ struct imx678 { const char *gmsl; - const struct imx678_mode *mode; + const struct imx678_frame_mode *frame_mode; struct mutex mutex; bool streaming; }; @@ -478,8 +457,8 @@ static int imx678_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) mutex_lock(&imx678->mutex); - fmt_img->width = modes_frame[0].width; - fmt_img->height = modes_frame[0].height; + fmt_img->width = frame_mode_configs[0].width; + fmt_img->height = frame_mode_configs[0].height; fmt_img->code = MEDIA_BUS_FMT_SRGGB12_1X12; fmt_img->field = V4L2_FIELD_NONE; @@ -498,7 +477,7 @@ static int imx678_set_exposure(struct imx678 *imx678, u64 val) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; u64 exposure; int ret; @@ -515,7 +494,7 @@ static int imx678_set_exposure(struct imx678 *imx678, u64 val) static void imx678_adjust_exposure_range(struct imx678 *imx678) { - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; u64 exposure_max; exposure_max = imx678->vblank->val + mode->height - IMX678_MIN_SHR0_LENGTH; @@ -543,7 +522,7 @@ static int imx678_set_frame_rate(struct imx678 *imx678, u64 val) static void imx678_update_frame_rate(struct imx678 *imx678, u64 val) { - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; u32 update_vblank; imx678->frame_length = (IMX678_M_FACTOR * IMX678_G_FACTOR) / @@ -563,7 +542,7 @@ static int imx678_set_hmax_register(struct imx678 *imx678) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; int ret; ret = imx678_write_hold_reg(imx678, HMAX_LOW, 2, mode->hmax); @@ -732,8 +711,8 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_VBLANK: imx678_adjust_exposure_range(imx678); break; - case V4L2_CID_CAMERA_MODE: - imx678->mode = modes_frame[ctrl->val]; + case V4L2_CID_FRAME_MODE: + imx678->mode = frame_mode_configs[ctrl->val]; break; } @@ -817,7 +796,7 @@ static int imx678_enum_frame_size(struct v4l2_subdev *sd, return -EINVAL; if (fse->pad == IMAGE_PAD) { - const struct imx678_mode *mode_list; + const struct imx678_frame_mode *mode_list; unsigned int num_modes; get_mode_table(fse->code, &mode_list, &num_modes); @@ -848,7 +827,7 @@ static void imx678_reset_colorspace(struct v4l2_mbus_framefmt *fmt) } static void imx678_update_image_pad_format(struct imx678 *imx678, - const struct imx678_mode *mode, + const struct imx678_frame_mode *mode, struct v4l2_subdev_format *fmt) { fmt->format.width = mode->width; @@ -861,7 +840,7 @@ static void imx678_set_limits(struct imx678 *imx678) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; u64 vblank, max_framerate; dev_dbg(dev, "%s: mode: %dx%d\n", __func__, mode->width, mode->height); @@ -884,11 +863,7 @@ static void imx678_set_limits(struct imx678 *imx678) imx678->line_time = (mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); dev_dbg(dev, "%s: line time: %lld\n", __func__, imx678->line_time); - if (mode->is_binning) - imx678->frame_length = mode->height * 2 + vblank; - else - imx678->frame_length = mode->height + vblank; - + imx678->frame_length = mode->height * mode->frame_count + vblank; dev_dbg(dev, "%s: frame length: %d\n", __func__, imx678->frame_length); max_framerate = (IMX678_G_FACTOR * IMX678_M_FACTOR) / @@ -909,7 +884,7 @@ static int imx678_set_pad_format(struct v4l2_subdev *sd, { struct v4l2_mbus_framefmt *framefmt; struct imx678 *imx678 = to_imx678(sd); - const struct imx678_mode *mode = imx678->mode; + const struct imx678_frame_mode *mode = imx678->mode; if (fmt->pad >= NUM_PADS) return -EINVAL; @@ -1310,10 +1285,10 @@ static int imx678_init_controls(struct imx678 *imx678) mutex_init(&imx678->mutex); ctrl_hdlr->lock = &imx678->mutex; - v4l2_ctrl_new_std_menu(ctrl_hdlr, &imx678_ctrl_ops, - V4L2_CID_CAMERA_MODE, - ARRAY_SIZE(modes_frame), - 0, 0, imx678_camera_mode_menu); + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_FRAME_MODE, + ARRAY_SIZE(imx678_frame_mode_menu) - 1, + 0, 0, imx678_hdr_mode_menu); imx678->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); @@ -1536,7 +1511,7 @@ static int imx678_probe(struct i2c_client *client) return PTR_ERR(imx678->xmaster); } - imx678->mode = &modes_frame[0]; + imx678->mode = &frame_mode_configs[0]; imx678->fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12; pm_runtime_set_active(dev); diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 9c390bc2452474..806d24dff9fe2c 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -93,13 +93,6 @@ #define IMX678_DEFAULT_WIDTH 3856 #define IMX678_DEFAULT_HEIGHT 2180 -#define IMX678_CROP_2608x1964_WIDTH 2608 -#define IMX678_CROP_2608x1964_HEIGHT 1964 -#define IMX678_CROP_1920x1080_WIDTH 1920 -#define IMX678_CROP_1920x1080_HEIGHT 1080 -#define IMX678_MODE_BINNING_H2V2_WIDTH 1928 -#define IMX678_MODE_BINNING_H2V2_HEIGHT 1090 - struct imx678_reg { u16 address; From 8e6ba45d8e6419aa19f276b2b5befc51014570ae Mon Sep 17 00:00:00 2001 From: Brady Law Date: Sat, 15 Nov 2025 12:57:00 -0800 Subject: [PATCH 07/12] progres --- drivers/media/i2c/imx678.c | 170 ++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 96 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index 8443b1f4c9d915..e8a201be2fec38 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -89,7 +89,6 @@ static const char * const imx678_frame_mode_menu[] = { #define IMX678_PIXEL_ARRAY_HEIGHT 2180U #define V4L2_CID_FRAME_MODE (V4L2_CID_USER_IMX_BASE + 0) -#define V4L2_CID_FRAME_RATE (V4L2_CID_USER_IMX_BASE + 1) #define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) #define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) #define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 4) @@ -117,10 +116,10 @@ static const s64 imx678_link_freq_menu[] = { }; struct imx678_link_mode { - enum link_freq link_freq; - enum bit_depth bit_depth; - unsigned uint16_t hmax; - unsigned uint16_t modes; + unsigned int link_freq; + unsigned int bit_depth; + unsigned int hmax; + unsigned int modes; }; #define LINK_MODE_ALL_PIXEL (1 << 0) @@ -130,14 +129,14 @@ struct imx678_link_mode { #define LINK_MODE_CLEAR_HDR (1 << 4) #define LINK_MODE_CLEAR_BINNING (1 << 5) -struct imx678_frame_mode { +struct imx678_frame_mode_config { unsigned int width; unsigned int height; - uint8_t frame_count; - unsigned uint16_t flag; + unsigned int frame_count; + unsigned int flag; }; -static const struct imx678_frame_mode frame_mode_configs[] = { +static const struct imx678_frame_mode_config frame_mode_configs[] = { [IMX678_HDR_MODE_ALL_PIXEL] = { .width = IMX678_DEFAULT_WIDTH, .height = IMX678_DEFAULT_HEIGHT, @@ -289,7 +288,7 @@ struct imx678 { const char *gmsl; - const struct imx678_frame_mode *frame_mode; + const struct imx678_frame_mode_config *mode; struct mutex mutex; bool streaming; }; @@ -437,10 +436,10 @@ static u32 imx678_get_format_code(struct imx678 *imx678, u32 code) // H flip - 1 mod 4 // V flip - 2 mod 4 // H+V flip - 3 mod 4 - unsigned int i = (im678->hflip->val) ? 1 : 0 + unsigned int i = (imx678->hflip->val) ? 1 : 0 + (imx678->vflip->val) ? 2 : 0; - for (i; i < ARRAY_SIZE(bayer_formats); i += 4) { + for (; i < ARRAY_SIZE(bayer_formats); i += 4) { if (bayer_formats[i] == code) return bayer_formats[i]; } @@ -477,7 +476,7 @@ static int imx678_set_exposure(struct imx678 *imx678, u64 val) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_frame_mode *mode = imx678->mode; + const struct imx678_frame_mode_config *mode = imx678->mode; u64 exposure; int ret; @@ -494,7 +493,7 @@ static int imx678_set_exposure(struct imx678 *imx678, u64 val) static void imx678_adjust_exposure_range(struct imx678 *imx678) { - const struct imx678_frame_mode *mode = imx678->mode; + const struct imx678_frame_mode_config *mode = imx678->mode; u64 exposure_max; exposure_max = imx678->vblank->val + mode->height - IMX678_MIN_SHR0_LENGTH; @@ -504,7 +503,7 @@ static void imx678_adjust_exposure_range(struct imx678 *imx678) exposure_max); } -static int imx678_set_frame_rate(struct imx678 *imx678, u64 val) +static int imx678_set_frame_interval(struct imx678 *imx678, u64 val) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; @@ -522,7 +521,7 @@ static int imx678_set_frame_rate(struct imx678 *imx678, u64 val) static void imx678_update_frame_rate(struct imx678 *imx678, u64 val) { - const struct imx678_frame_mode *mode = imx678->mode; + const struct imx678_frame_mode_config *mode = imx678->mode; u32 update_vblank; imx678->frame_length = (IMX678_M_FACTOR * IMX678_G_FACTOR) / @@ -542,7 +541,7 @@ static int imx678_set_hmax_register(struct imx678 *imx678) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_frame_mode *mode = imx678->mode; + const struct imx678_frame_mode_config *mode = imx678->mode; int ret; ret = imx678_write_hold_reg(imx678, HMAX_LOW, 2, mode->hmax); @@ -629,6 +628,54 @@ static int imx678_set_blklvl(struct imx678 *imx678, u64 val) return ret; } +static void imx678_set_limits(struct imx678 *imx678) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); + struct device *dev = &client->dev; + const struct imx678_frame_mode_config *mode = imx678->mode; + u64 vblank, max_framerate; + + dev_dbg(dev, "%s: mode: %dx%d\n", __func__, mode->width, mode->height); + + vblank = IMX678_MIN_FRAME_LENGTH_DELTA; + + __v4l2_ctrl_modify_range(imx678->vblank, vblank, + vblank, 1, vblank); + dev_dbg(dev, "%s: vblank: %lld\n", __func__, vblank); + + __v4l2_ctrl_modify_range(imx678->pixel_rate, mode->pixel_rate, + mode->pixel_rate, 1, mode->pixel_rate); + dev_dbg(dev, "%s: pixel rate: %d\n", __func__, mode->pixel_rate); + + __v4l2_ctrl_s_ctrl(imx678->link_freq, mode->linkfreq); + + dev_dbg(dev, "%s: linkfreq: %lld\n", __func__, + imx678_link_freq_menu[mode->linkfreq]); + + imx678->line_time = (mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); + dev_dbg(dev, "%s: line time: %lld\n", __func__, imx678->line_time); + + imx678->frame_length = mode->height * mode->frame_count + vblank; + dev_dbg(dev, "%s: frame length: %d\n", __func__, imx678->frame_length); + + max_framerate = (IMX678_G_FACTOR * IMX678_M_FACTOR) / + (imx678->frame_length * imx678->line_time); + + __v4l2_ctrl_modify_range(imx678->framerate, mode->min_fps, + max_framerate, 1, max_framerate); + dev_dbg(dev, "%s: max framerate: %lld\n", __func__, max_framerate); + + imx678_update_blklvl_range(imx678); + + __v4l2_ctrl_s_ctrl(imx678->framerate, max_framerate); +} + +static void imx678_set_frame_mode(struct imx678 *imx678, u64 val) +{ + imx678->mode = frame_mode_configs[ctrl->val]; + imx678_set_limits(imx678); +} + static int imx678_set_operation_mode(struct imx678 *imx678, u32 val) { gpiod_set_raw_value_cansleep(imx678->xmaster, val); @@ -705,14 +752,11 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) int ret = 0; switch (ctrl->id) { - case V4L2_CID_FRAME_RATE: - imx678_update_frame_rate(imx678, ctrl->val); - break; case V4L2_CID_VBLANK: imx678_adjust_exposure_range(imx678); break; case V4L2_CID_FRAME_MODE: - imx678->mode = frame_mode_configs[ctrl->val]; + imx678_set_frame_mode(imx678, ctrl->val); break; } @@ -735,9 +779,6 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_VFLIP: ret = imx678_write_reg(imx678, VREVERSE, 1, ctrl->val); break; - case V4L2_CID_FRAME_RATE: - ret = imx678_set_frame_rate(imx678, ctrl->val); - break; case V4L2_CID_BLACK_LEVEL: ret = imx678_set_blklvl(imx678, ctrl->val); break; @@ -771,8 +812,6 @@ static int imx678_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { - struct imx678 *imx678 = to_imx678(sd); - if (code->pad >= NUM_PADS) return -EINVAL; @@ -796,21 +835,13 @@ static int imx678_enum_frame_size(struct v4l2_subdev *sd, return -EINVAL; if (fse->pad == IMAGE_PAD) { - const struct imx678_frame_mode *mode_list; - unsigned int num_modes; - - get_mode_table(fse->code, &mode_list, &num_modes); - - if (fse->index >= num_modes) - return -EINVAL; - if (fse->code != imx678_get_format_code(imx678, fse->code)) return -EINVAL; - fse->min_width = mode_list[fse->index].width; - fse->max_width = fse->min_width; - fse->min_height = mode_list[fse->index].height; - fse->max_height = fse->min_height; + fse->min_width = imx678->mode->width; + fse->max_width = imx678->mode->width; + fse->min_height = imx678->mode->height; + fse->max_height = imx678->mode->height; } return 0; @@ -827,7 +858,7 @@ static void imx678_reset_colorspace(struct v4l2_mbus_framefmt *fmt) } static void imx678_update_image_pad_format(struct imx678 *imx678, - const struct imx678_frame_mode *mode, + const struct imx678_frame_mode_config *mode, struct v4l2_subdev_format *fmt) { fmt->format.width = mode->width; @@ -836,55 +867,13 @@ static void imx678_update_image_pad_format(struct imx678 *imx678, imx678_reset_colorspace(&fmt->format); } -static void imx678_set_limits(struct imx678 *imx678) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); - struct device *dev = &client->dev; - const struct imx678_frame_mode *mode = imx678->mode; - u64 vblank, max_framerate; - - dev_dbg(dev, "%s: mode: %dx%d\n", __func__, mode->width, mode->height); - - vblank = IMX678_MIN_FRAME_LENGTH_DELTA; - - __v4l2_ctrl_modify_range(imx678->vblank, vblank, - vblank, 1, vblank); - dev_dbg(dev, "%s: vblank: %lld\n", __func__, vblank); - - __v4l2_ctrl_modify_range(imx678->pixel_rate, mode->pixel_rate, - mode->pixel_rate, 1, mode->pixel_rate); - dev_dbg(dev, "%s: pixel rate: %d\n", __func__, mode->pixel_rate); - - __v4l2_ctrl_s_ctrl(imx678->link_freq, mode->linkfreq); - - dev_dbg(dev, "%s: linkfreq: %lld\n", __func__, - imx678_link_freq_menu[mode->linkfreq]); - - imx678->line_time = (mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); - dev_dbg(dev, "%s: line time: %lld\n", __func__, imx678->line_time); - - imx678->frame_length = mode->height * mode->frame_count + vblank; - dev_dbg(dev, "%s: frame length: %d\n", __func__, imx678->frame_length); - - max_framerate = (IMX678_G_FACTOR * IMX678_M_FACTOR) / - (imx678->frame_length * imx678->line_time); - - __v4l2_ctrl_modify_range(imx678->framerate, mode->min_fps, - max_framerate, 1, max_framerate); - dev_dbg(dev, "%s: max framerate: %lld\n", __func__, max_framerate); - - imx678_update_blklvl_range(imx678); - - __v4l2_ctrl_s_ctrl(imx678->framerate, max_framerate); -} - static int imx678_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { struct v4l2_mbus_framefmt *framefmt; struct imx678 *imx678 = to_imx678(sd); - const struct imx678_frame_mode *mode = imx678->mode; + const struct imx678_frame_mode_config *mode = imx678->mode; if (fmt->pad >= NUM_PADS) return -EINVAL; @@ -997,7 +986,7 @@ static int imx678_set_mode(struct imx678 *imx678) return ret; } - ret = imx678_write_reg(imx678, DATARATE_SEL, 1, imx678->linkfreq->val); + ret = imx678_write_reg(imx678, DATARATE_SEL, 1, imx678->link_freq->val); if (ret) { dev_err(dev, "%s failed to set data rate\n", __func__); return ret; @@ -1218,6 +1207,8 @@ static const struct v4l2_subdev_pad_ops imx678_pad_ops = { .set_fmt = imx678_set_pad_format, .get_selection = imx678_get_selection, .enum_frame_size = imx678_enum_frame_size, + .get_frame_interval = v4l2_subdev_get_frame_interval, + .set_frame_interval = imx678_set_frame_interval, }; static const struct v4l2_subdev_ops imx678_subdev_ops = { @@ -1230,19 +1221,6 @@ static const struct v4l2_subdev_internal_ops imx678_internal_ops = { .open = imx678_open, }; -static struct v4l2_ctrl_config imx678_ctrl_framerate[] = { - { - .ops = &imx678_ctrl_ops, - .id = V4L2_CID_FRAME_RATE, - .name = "Frame rate", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 1, - .max = 0xFFFF, - .def = 0xFFFF, - .step = 1, - }, -}; - static struct v4l2_ctrl_config imx678_ctrl_operation_mode[] = { { .ops = &imx678_ctrl_ops, From 25accd4124c1de82890c5fcdf28534af95fd7f64 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Sat, 15 Nov 2025 13:22:55 -0800 Subject: [PATCH 08/12] progress --- drivers/media/i2c/imx678.c | 79 +++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index e8a201be2fec38..ceb20161814c1d 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -105,7 +105,7 @@ enum { IMX678_BIT_DEPTH_12, } bit_depth; -static const s64 imx678_link_freq_menu[] = { +static const s64 imx678_link_freq_map[] = { [IMX678_2376_MBPS] = IMX678_LINK_FREQ_2376, [IMX678_2079_MBPS] = IMX678_LINK_FREQ_2079, [IMX678_1782_MBPS] = IMX678_LINK_FREQ_1782, @@ -116,10 +116,11 @@ static const s64 imx678_link_freq_menu[] = { }; struct imx678_link_mode { - unsigned int link_freq; + unsigned int freq_idx; unsigned int bit_depth; unsigned int hmax; unsigned int modes; + unsigned int lane_count; }; #define LINK_MODE_ALL_PIXEL (1 << 0) @@ -178,66 +179,79 @@ static const struct imx678_frame_mode_config frame_mode_configs[] = { static const struct imx678_link_mode all_pixel_link_modes[] = { // 25 fps, hmax 1320 { - .link_freq = IMX678_720_MBPS, .bit_depth = 10, .hmax = 1320, + .freq_idx = IMX678_720_MBPS, .bit_depth = 10, .hmax = 1320, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, { - .link_freq = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1320, + .freq_idx = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1320, .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING | LINK_MODE_CLEAR_BINNING, + .lane_count = 4, }, { - .link_freq = IMX678_891_MBPS, .bit_depth = 12, .hmax = 1320, + .freq_idx = IMX678_891_MBPS, .bit_depth = 12, .hmax = 1320, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, // 30 fps, hmax 1100 { - .link_freq = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1100, + .freq_idx = IMX678_720_MBPS, .bit_depth = 12, .hmax = 1100, .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING | LINK_MODE_CLEAR_BINNING, + .lane_count = 4, }, { - .link_freq = IMX678_891_MBPS, .bit_depth = 10, .hmax = 1100, + .freq_idx = IMX678_891_MBPS, .bit_depth = 10, .hmax = 1100, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, { - .link_freq = IMX678_1188_MBPS, .bit_depth = 12, .hmax = 1100, + .freq_idx = IMX678_1188_MBPS, .bit_depth = 12, .hmax = 1100, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, // 50 fps, hmax 660 { - .link_freq = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 660, + .freq_idx = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 660, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, { - .link_freq = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 660, + .freq_idx = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 660, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_ALL_BINNING | LINK_MODE_DOL_HDR | LINK_MODE_DOL_BINNING | LINK_MODE_CLEAR_BINNING, + .lane_count = 4, }, // 60 fps, hmax 550 { - .link_freq = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 550, + .freq_idx = IMX678_1440_MBPS, .bit_depth = 10, .hmax = 550, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_CLEAR_HDR | LINK_MODE_DOL_HDR, + .lane_count = 4, }, { - .link_freq = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 550, + .freq_idx = IMX678_1440_MBPS, .bit_depth = 12, .hmax = 550, .modes = LINK_MODE_ALL_BINNING | LINK_MODE_DOL_BINNING, + .lane_count = 4, }, { - .link_freq = IMX678_1782_MBPS, .bit_depth = 12, .hmax = 550, + .freq_idx = IMX678_1782_MBPS, .bit_depth = 12, .hmax = 550, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_DOL_HDR, + .lane_count = 4, }, // 72 fps, hmax 458 { - .link_freq = IMX678_2079_MBPS, .bit_depth = 10, .hmax = 458, + .freq_idx = IMX678_2079_MBPS, .bit_depth = 10, .hmax = 458, .modes = LINK_MODE_ALL_PIXEL | LINK_MODE_DOL_HDR, + .lane_count = 4, }, { - .link_freq = IMX678_2376_MBPS, .bit_depth = 12, .hmax = 458, + .freq_idx = IMX678_2376_MBPS, .bit_depth = 12, .hmax = 458, .modes = LINK_MODE_ALL_BINNING, + .lane_count = 4, } }; @@ -289,6 +303,7 @@ struct imx678 { const char *gmsl; const struct imx678_frame_mode_config *mode; + const struct imx678_link_mode *link_mode; struct mutex mutex; bool streaming; }; @@ -541,14 +556,13 @@ static int imx678_set_hmax_register(struct imx678 *imx678) { struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; - const struct imx678_frame_mode_config *mode = imx678->mode; int ret; - ret = imx678_write_hold_reg(imx678, HMAX_LOW, 2, mode->hmax); + ret = imx678_write_hold_reg(imx678, HMAX_LOW, 2, imx678->link_mode->hmax); if (ret) dev_err(dev, "%s failed to write HMAX register\n", __func__); - dev_dbg(dev, "%s: hmax: 0x%x\n", __func__, mode->hmax); + dev_dbg(dev, "%s: hmax: 0x%x\n", __func__, imx678->link_mode->hmax); return ret; @@ -633,6 +647,7 @@ static void imx678_set_limits(struct imx678 *imx678) struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); struct device *dev = &client->dev; const struct imx678_frame_mode_config *mode = imx678->mode; + const struct imx678_link_mode *link = imx678->link_mode; u64 vblank, max_framerate; dev_dbg(dev, "%s: mode: %dx%d\n", __func__, mode->width, mode->height); @@ -643,16 +658,20 @@ static void imx678_set_limits(struct imx678 *imx678) vblank, 1, vblank); dev_dbg(dev, "%s: vblank: %lld\n", __func__, vblank); - __v4l2_ctrl_modify_range(imx678->pixel_rate, mode->pixel_rate, - mode->pixel_rate, 1, mode->pixel_rate); - dev_dbg(dev, "%s: pixel rate: %d\n", __func__, mode->pixel_rate); + unsigned int pixel_rate = imx678_link_freq_map[link->freq_idx] * + 2 * link->lane_count / link->bit_depth; + __v4l2_ctrl_modify_range(imx678->pixel_rate, + pixel_rate, + pixel_rate, + 1, + pixel_rate); + dev_dbg(dev, "%s: pixel rate: %d\n", __func__, pixel_rate); - __v4l2_ctrl_s_ctrl(imx678->link_freq, mode->linkfreq); + __v4l2_ctrl_s_ctrl(imx678->link_freq, link->freq_idx); - dev_dbg(dev, "%s: linkfreq: %lld\n", __func__, - imx678_link_freq_menu[mode->linkfreq]); + dev_dbg(dev, "%s: linkfreq: %lld\n", __func__, imx678_link_freq_map[link->freq_idx]); - imx678->line_time = (mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); + imx678->line_time = (imx678->link_mode->hmax*IMX678_G_FACTOR) / (IMX678_XCLK_FREQ); dev_dbg(dev, "%s: line time: %lld\n", __func__, imx678->line_time); imx678->frame_length = mode->height * mode->frame_count + vblank; @@ -1276,8 +1295,8 @@ static int imx678_init_controls(struct imx678 *imx678) imx678->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(imx678_link_freq_menu) - 1, 0, - imx678_link_freq_menu); + ARRAY_SIZE(imx678_link_freq_map) - 1, 0, + imx678_link_freq_map); if (imx678->link_freq) imx678->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; @@ -1414,13 +1433,13 @@ static int imx678_check_hwcfg(struct device *dev, struct i2c_client *client) goto error_out; } - if (ep_cfg.nr_of_link_frequencies != ARRAY_SIZE(imx678_link_freq_menu)) { + if (ep_cfg.nr_of_link_frequencies != ARRAY_SIZE(imx678_link_freq_map)) { dev_err(dev, "Link frequency missing in dtree\n"); goto error_out; } - for (int i = 0; i < ARRAY_SIZE(imx678_link_freq_menu); i++) { - if (ep_cfg.link_frequencies[i] != imx678_link_freq_menu[i]) { + for (int i = 0; i < ARRAY_SIZE(imx678_link_freq_map); i++) { + if (ep_cfg.link_frequencies[i] != imx678_link_freq_map[i]) { dev_err(dev, "no supported link freq found\n"); goto error_out; } From 1ce50663f1db29cca637279df6c5354e8f193834 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Tue, 2 Dec 2025 15:46:45 -0800 Subject: [PATCH 09/12] progress --- drivers/media/i2c/imx678.c | 149 +++++++++++++++---------------------- 1 file changed, 59 insertions(+), 90 deletions(-) diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c index ceb20161814c1d..15744c6c4e07db 100644 --- a/drivers/media/i2c/imx678.c +++ b/drivers/media/i2c/imx678.c @@ -38,7 +38,7 @@ #define IMX678_MODE_STANDBY 0x01 #define IMX678_MODE_STREAMING 0x00 -#define IMX678_MIN_SHR0_LENGTH 3 +#define IMX678_MIN_SHR0_LENGTH 4 #define IMX678_MIN_INTEGRATION_LINES 1 #define IMX678_ANA_GAIN_MIN 0 @@ -84,16 +84,16 @@ static const char * const imx678_frame_mode_menu[] = { #define IMX678_NATIVE_WIDTH 3856U #define IMX678_NATIVE_HEIGHT 2180U #define IMX678_PIXEL_ARRAY_LEFT 0U -#define IMX678_PIXEL_ARRAY_TOP 0U +#define IMX678_PIXEL_ARRAY_TOP 4U #define IMX678_PIXEL_ARRAY_WIDTH 3856U -#define IMX678_PIXEL_ARRAY_HEIGHT 2180U +#define IMX678_PIXEL_ARRAY_HEIGHT 2176U #define V4L2_CID_FRAME_MODE (V4L2_CID_USER_IMX_BASE + 0) -#define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 2) -#define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 3) -#define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 4) -#define V4L2_CID_ANALOGUE_GAIN_SHORT (V4L2_CID_USER_IMX_BASE + 5) -#define V4L2_CID_EXPONENTIAL_GAIN (V4L2_CID_USER_IMX_BASE + 6) +#define V4L2_CID_OPERATION_MODE (V4L2_CID_USER_IMX_BASE + 1) +#define V4L2_CID_SYNC_MODE (V4L2_CID_USER_IMX_BASE + 2) +#define V4L2_CID_EXPOSURE_SHORT (V4L2_CID_USER_IMX_BASE + 3) +#define V4L2_CID_ANALOGUE_GAIN_SHORT (V4L2_CID_USER_IMX_BASE + 4) +#define V4L2_CID_EXPONENTIAL_GAIN (V4L2_CID_USER_IMX_BASE + 5) struct imx678_reg_list { unsigned int num_of_regs; @@ -176,7 +176,7 @@ static const struct imx678_frame_mode_config frame_mode_configs[] = { }, }; -static const struct imx678_link_mode all_pixel_link_modes[] = { +static const struct imx678_link_mode link_modes[] = { // 25 fps, hmax 1320 { .freq_idx = IMX678_720_MBPS, .bit_depth = 10, .hmax = 1320, @@ -281,13 +281,10 @@ struct imx678 { struct v4l2_ctrl *link_freq; struct v4l2_ctrl *exposure; struct v4l2_ctrl *gain; - struct v4l2_ctrl *framerate; struct v4l2_ctrl *operation_mode; struct v4l2_ctrl *sync_mode; struct v4l2_ctrl *vflip; struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vblank; - struct v4l2_ctrl *hblank; struct v4l2_ctrl *blklvl; // DOL mode @@ -462,29 +459,22 @@ static u32 imx678_get_format_code(struct imx678 *imx678, u32 code) return bayer_formats[0]; } -static int imx678_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +static int imx678_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) { - struct imx678 *imx678 = to_imx678(sd); - struct v4l2_mbus_framefmt *fmt_img = - v4l2_subdev_state_get_format(fh->state, IMAGE_PAD); - struct v4l2_rect *crop; - - mutex_lock(&imx678->mutex); - - fmt_img->width = frame_mode_configs[0].width; - fmt_img->height = frame_mode_configs[0].height; - fmt_img->code = MEDIA_BUS_FMT_SRGGB12_1X12; - fmt_img->field = V4L2_FIELD_NONE; - - crop = v4l2_subdev_state_get_crop(fh->state, IMAGE_PAD); - crop->left = IMX678_PIXEL_ARRAY_LEFT; - crop->top = IMX678_PIXEL_ARRAY_TOP; - crop->width = IMX678_PIXEL_ARRAY_WIDTH; - crop->height = IMX678_PIXEL_ARRAY_HEIGHT; - - mutex_unlock(&imx678->mutex); - - return 0; + int ret; + // FIXME: Is .which right here? + struct v4l2_subdev_format fmt = { + .which = state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE, + .pad = IMAGE_PAD, + .format = { + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .width = frame_mode_configs[0].width, + .height = frame_mode_configs[0].height, + }, + }; + ret = imx678_pad_set_fmt(sd, state, fmt); + return ret; } static int imx678_set_exposure(struct imx678 *imx678, u64 val) @@ -495,7 +485,7 @@ static int imx678_set_exposure(struct imx678 *imx678, u64 val) u64 exposure; int ret; - exposure = imx678->vblank->val + mode->height - val; + exposure = imx678->frame_length - val; ret = imx678_write_hold_reg(imx678, SHR0_LOW, 3, exposure); if (ret) { @@ -511,45 +501,51 @@ static void imx678_adjust_exposure_range(struct imx678 *imx678) const struct imx678_frame_mode_config *mode = imx678->mode; u64 exposure_max; - exposure_max = imx678->vblank->val + mode->height - IMX678_MIN_SHR0_LENGTH; + exposure_max = imx678->frame_length - IMX678_MIN_SHR0_LENGTH; __v4l2_ctrl_modify_range(imx678->exposure, IMX678_MIN_INTEGRATION_LINES, exposure_max, 1, exposure_max); } -static int imx678_set_frame_interval(struct imx678 *imx678, u64 val) +static int imx678_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval_enum *fie) { - struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); - struct device *dev = &client->dev; - int ret; + if (fie->pad >= NUM_PADS) + return -EINVAL; - ret = imx678_write_hold_reg(imx678, VMAX_LOW, 3, imx678->frame_length); + if (fie->pad == IMAGE_PAD) { + if (code->index >= ARRAY_SIZE(link_modes)) + return -EINVAL; - if (ret) { - dev_err(dev, "%s failed to set frame rate\n", __func__); - return ret; + code->code = bayer_formats[code->index]; } - return ret; + return 0; } -static void imx678_update_frame_rate(struct imx678 *imx678, u64 val) +static int imx678_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *interval) { - const struct imx678_frame_mode_config *mode = imx678->mode; - u32 update_vblank; + struct imx678 *imx678 = to_imx678(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct device *dev = &client->dev; + int ret; imx678->frame_length = (IMX678_M_FACTOR * IMX678_G_FACTOR) / (val * imx678->line_time); imx678->frame_length = (imx678->frame_length % 2) ? imx678->frame_length + 1 : imx678->frame_length; + ret = imx678_write_hold_reg(imx678, VMAX_LOW, 3, imx678->frame_length); - update_vblank = imx678->frame_length - mode->height; - - __v4l2_ctrl_modify_range(imx678->vblank, update_vblank, - update_vblank, 1, update_vblank); + if (ret) { + dev_err(dev, "%s failed to set frame rate\n", __func__); + return ret; + } - __v4l2_ctrl_s_ctrl(imx678->vblank, update_vblank); + return ret; } static int imx678_set_hmax_register(struct imx678 *imx678) @@ -648,16 +644,10 @@ static void imx678_set_limits(struct imx678 *imx678) struct device *dev = &client->dev; const struct imx678_frame_mode_config *mode = imx678->mode; const struct imx678_link_mode *link = imx678->link_mode; - u64 vblank, max_framerate; + u64 vblank; dev_dbg(dev, "%s: mode: %dx%d\n", __func__, mode->width, mode->height); - vblank = IMX678_MIN_FRAME_LENGTH_DELTA; - - __v4l2_ctrl_modify_range(imx678->vblank, vblank, - vblank, 1, vblank); - dev_dbg(dev, "%s: vblank: %lld\n", __func__, vblank); - unsigned int pixel_rate = imx678_link_freq_map[link->freq_idx] * 2 * link->lane_count / link->bit_depth; __v4l2_ctrl_modify_range(imx678->pixel_rate, @@ -677,16 +667,7 @@ static void imx678_set_limits(struct imx678 *imx678) imx678->frame_length = mode->height * mode->frame_count + vblank; dev_dbg(dev, "%s: frame length: %d\n", __func__, imx678->frame_length); - max_framerate = (IMX678_G_FACTOR * IMX678_M_FACTOR) / - (imx678->frame_length * imx678->line_time); - - __v4l2_ctrl_modify_range(imx678->framerate, mode->min_fps, - max_framerate, 1, max_framerate); - dev_dbg(dev, "%s: max framerate: %lld\n", __func__, max_framerate); - imx678_update_blklvl_range(imx678); - - __v4l2_ctrl_s_ctrl(imx678->framerate, max_framerate); } static void imx678_set_frame_mode(struct imx678 *imx678, u64 val) @@ -771,9 +752,6 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) int ret = 0; switch (ctrl->id) { - case V4L2_CID_VBLANK: - imx678_adjust_exposure_range(imx678); - break; case V4L2_CID_FRAME_MODE: imx678_set_frame_mode(imx678, ctrl->val); break; @@ -886,7 +864,7 @@ static void imx678_update_image_pad_format(struct imx678 *imx678, imx678_reset_colorspace(&fmt->format); } -static int imx678_set_pad_format(struct v4l2_subdev *sd, +static int imx678_pad_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { @@ -897,7 +875,9 @@ static int imx678_set_pad_format(struct v4l2_subdev *sd, if (fmt->pad >= NUM_PADS) return -EINVAL; - mutex_lock(&imx678->mutex); + v4l2_subdev_lock_state(sd_state); + + // FIXME: Return error code if streaming? if (fmt->pad == IMAGE_PAD) { fmt->format.code = imx678_get_format_code(imx678, fmt->format.code); @@ -913,7 +893,7 @@ static int imx678_set_pad_format(struct v4l2_subdev *sd, } } - mutex_unlock(&imx678->mutex); + v4l2_subdev_unlock_state(sd_state); return 0; } @@ -1223,9 +1203,10 @@ static const struct v4l2_subdev_video_ops imx678_video_ops = { static const struct v4l2_subdev_pad_ops imx678_pad_ops = { .enum_mbus_code = imx678_enum_mbus_code, .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = imx678_set_pad_format, + .set_fmt = imx678_pad_set_fmt, .get_selection = imx678_get_selection, .enum_frame_size = imx678_enum_frame_size, + .enum_frame_interval = imx678_enum_frame_interval, .get_frame_interval = v4l2_subdev_get_frame_interval, .set_frame_interval = imx678_set_frame_interval, }; @@ -1237,7 +1218,7 @@ static const struct v4l2_subdev_ops imx678_subdev_ops = { }; static const struct v4l2_subdev_internal_ops imx678_internal_ops = { - .open = imx678_open, + .init_state = imx678_init_state, }; static struct v4l2_ctrl_config imx678_ctrl_operation_mode[] = { @@ -1285,7 +1266,7 @@ static int imx678_init_controls(struct imx678 *imx678) v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_FRAME_MODE, ARRAY_SIZE(imx678_frame_mode_menu) - 1, - 0, 0, imx678_hdr_mode_menu); + 0, 0, imx678_frame_mode_menu); imx678->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); @@ -1300,23 +1281,11 @@ static int imx678_init_controls(struct imx678 *imx678) if (imx678->link_freq) imx678->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; - imx678->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, - V4L2_CID_VBLANK, 0, 0, 1, 0); - - imx678->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, - V4L2_CID_HBLANK, 0, 0, 1, 0); - - if (imx678->hblank) - imx678->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; - imx678->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_EXPOSURE, IMX678_MIN_INTEGRATION_LINES, 0xFF, 1, 0xFF); - imx678->framerate = v4l2_ctrl_new_custom(ctrl_hdlr, - imx678_ctrl_framerate, NULL); - imx678->operation_mode = v4l2_ctrl_new_custom(ctrl_hdlr, imx678_ctrl_operation_mode, NULL); From ad5441cc8a2f011f1c2c1c8c3334fcb05d441118 Mon Sep 17 00:00:00 2001 From: Brady Law Date: Mon, 8 Dec 2025 15:00:19 -0800 Subject: [PATCH 10/12] convert intendation to tabs --- drivers/media/i2c/imx678.h | 124 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 806d24dff9fe2c..888f3c79b69e6c 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -517,68 +517,68 @@ static struct imx678_reg imx678_setting_dol_hdr[] = { static struct imx678_reg imx678_setting_clear_hdr[] = { - {WINMODE, 0x00}, - {WDMODE, 0x08}, - {ADDMODE, 0x00}, - - {VMAX_LOW, 0x94}, - {VMAX_MID, 0x11}, - - {FDG_SEL0, 0x02}, - {SHR0_LOW, 0x06}, - {SHR0_MID, 0x00}, - - {0x306B, 0x04}, - {EXP_GAIN, 0x02}, - {0x355A, 0x00}, - {0x3A64, 0x01}, - - {0x3C37, 0x30}, - - {0x3CF2, 0x78}, - {0x3CF3, 0x00}, - - {0x3EB4, 0x7B}, - {0x3EB5, 0x00}, - {0x3EB7, 0x40}, - - {0x3F24, 0x17}, - {0x3FC4, 0x2D}, - - {0x4420, 0xFF}, - {0x4421, 0x03}, - {0x4422, 0x00}, - {0x4423, 0x08}, - - {0x44A4, 0x37}, - {0x44A6, 0x37}, - {0x44A8, 0x37}, - {0x44AA, 0x37}, - {0x44B4, 0x37}, - {0x44B6, 0x37}, - {0x44B8, 0x37}, - {0x44BA, 0x37}, - {0x44C4, 0x37}, - {0x44C6, 0x37}, - {0x44C8, 0x37}, - - {0x453D, 0x18}, - {0x453E, 0x18}, - {0x453F, 0x11}, - {0x4540, 0x11}, - {0x4541, 0x11}, - {0x4542, 0x11}, - {0x4543, 0x11}, - {0x4544, 0x11}, - {0x4549, 0x00}, - {0x454A, 0x00}, - {0x454B, 0x04}, - {0x454C, 0x04}, - {0x454D, 0x04}, - {0x454E, 0x04}, - {0x454F, 0x04}, - {0x4550, 0x04}, - {0x454A, 0x04}, + {WINMODE, 0x00}, + {WDMODE, 0x08}, + {ADDMODE, 0x00}, + + {VMAX_LOW, 0x94}, + {VMAX_MID, 0x11}, + + {FDG_SEL0, 0x02}, + {SHR0_LOW, 0x06}, + {SHR0_MID, 0x00}, + + {0x306B, 0x04}, + {EXP_GAIN, 0x02}, + {0x355A, 0x00}, + {0x3A64, 0x01}, + + {0x3C37, 0x30}, + + {0x3CF2, 0x78}, + {0x3CF3, 0x00}, + + {0x3EB4, 0x7B}, + {0x3EB5, 0x00}, + {0x3EB7, 0x40}, + + {0x3F24, 0x17}, + {0x3FC4, 0x2D}, + + {0x4420, 0xFF}, + {0x4421, 0x03}, + {0x4422, 0x00}, + {0x4423, 0x08}, + + {0x44A4, 0x37}, + {0x44A6, 0x37}, + {0x44A8, 0x37}, + {0x44AA, 0x37}, + {0x44B4, 0x37}, + {0x44B6, 0x37}, + {0x44B8, 0x37}, + {0x44BA, 0x37}, + {0x44C4, 0x37}, + {0x44C6, 0x37}, + {0x44C8, 0x37}, + + {0x453D, 0x18}, + {0x453E, 0x18}, + {0x453F, 0x11}, + {0x4540, 0x11}, + {0x4541, 0x11}, + {0x4542, 0x11}, + {0x4543, 0x11}, + {0x4544, 0x11}, + {0x4549, 0x00}, + {0x454A, 0x00}, + {0x454B, 0x04}, + {0x454C, 0x04}, + {0x454D, 0x04}, + {0x454E, 0x04}, + {0x454F, 0x04}, + {0x4550, 0x04}, + {0x454A, 0x04}, }; static const struct imx678_reg mode_enable_pattern_generator[] = { From d9748f6dea933445d3f35e8731779909be54d5ac Mon Sep 17 00:00:00 2001 From: Brady Law Date: Mon, 8 Dec 2025 15:08:04 -0800 Subject: [PATCH 11/12] register updates --- drivers/media/i2c/imx678.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 888f3c79b69e6c..723b9767419057 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -107,6 +107,7 @@ struct imx678_reg { static const struct imx678_reg mode_common_regs[] = { {LANEMODE, 0x03}, {INCK_SEL, 0x01}, + {XVS_XHS_DRV, 0x00}, {0x3460, 0x22}, {0x355A, 0x64}, @@ -465,6 +466,7 @@ static const struct imx678_reg mode_common_regs[] = { {0x47C1, 0x01}, {0x47C2, 0x3E}, {0x47C3, 0x01}, + {0x4E3C, 0x07}, }; static const struct imx678_reg raw12_framefmt_regs[] = { @@ -531,25 +533,25 @@ static struct imx678_reg imx678_setting_clear_hdr[] = { {0x306B, 0x04}, {EXP_GAIN, 0x02}, {0x355A, 0x00}, + {0x3A20, 0x34}, + {0x3A24, 0x44}, + {0x3A26, 0x4E}, + {0x3A28, 0x57}, {0x3A64, 0x01}, - {0x3C37, 0x30}, - {0x3CF2, 0x78}, {0x3CF3, 0x00}, - + {0x3CF4, 0xA5}, {0x3EB4, 0x7B}, {0x3EB5, 0x00}, + {0x3EB6, 0xA5}, {0x3EB7, 0x40}, - {0x3F24, 0x17}, - {0x3FC4, 0x2D}, - + {0x3F4C, 0x2D}, {0x4420, 0xFF}, {0x4421, 0x03}, {0x4422, 0x00}, {0x4423, 0x08}, - {0x44A4, 0x37}, {0x44A6, 0x37}, {0x44A8, 0x37}, @@ -561,7 +563,6 @@ static struct imx678_reg imx678_setting_clear_hdr[] = { {0x44C4, 0x37}, {0x44C6, 0x37}, {0x44C8, 0x37}, - {0x453D, 0x18}, {0x453E, 0x18}, {0x453F, 0x11}, @@ -578,7 +579,6 @@ static struct imx678_reg imx678_setting_clear_hdr[] = { {0x454E, 0x04}, {0x454F, 0x04}, {0x4550, 0x04}, - {0x454A, 0x04}, }; static const struct imx678_reg mode_enable_pattern_generator[] = { From fc0ac40ec62c268490e76843598f8c01020728ff Mon Sep 17 00:00:00 2001 From: Brady Law Date: Mon, 8 Dec 2025 15:10:50 -0800 Subject: [PATCH 12/12] modify indentation --- drivers/media/i2c/imx678.h | 89 +++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/drivers/media/i2c/imx678.h b/drivers/media/i2c/imx678.h index 723b9767419057..32f6d0ab857f43 100644 --- a/drivers/media/i2c/imx678.h +++ b/drivers/media/i2c/imx678.h @@ -10,11 +10,11 @@ #define XMSTA 0x3002 #define INCK_SEL 0x3014 -#define DATARATE_SEL 0x3015 +#define DATARATE_SEL 0x3015 #define WINMODE 0x3018 #define WDMODE 0x301A #define ADDMODE 0x301B -#define THIN_V_EN 0x301C +#define THIN_V_EN 0x301C #define VCMODE 0x301E @@ -28,66 +28,66 @@ #define VMAX_HIGH 0x302A #define HMAX_LOW 0x302C #define HMAX_HIGH 0x302D -#define FDG_SEL0 0x3030 +#define FDG_SEL0 0x3030 #define PIX_HST_LOW 0x303C -#define PIX_HST_HIGH 0x303D -#define PIX_HWIDTH_LOW 0x303E -#define PIX_HWIDTH_HIGH 0x303F +#define PIX_HST_HIGH 0x303D +#define PIX_HWIDTH_LOW 0x303E +#define PIX_HWIDTH_HIGH 0x303F #define LANEMODE 0x3040 #define PIX_VST_LOW 0x3044 -#define PIX_VST_HIGH 0x3045 -#define PIX_VWIDTH_LOW 0x3046 -#define PIX_VWIDTH_HIGH 0x3047 +#define PIX_VST_HIGH 0x3045 +#define PIX_VWIDTH_LOW 0x3046 +#define PIX_VWIDTH_HIGH 0x3047 // Long exposure -#define SHR0_LOW 0x3050 -#define SHR0_MID 0x3051 -#define SHR0_HIGH 0x3052 +#define SHR0_LOW 0x3050 +#define SHR0_MID 0x3051 +#define SHR0_HIGH 0x3052 // Short exposure -#define SHR1_LOW 0x3054 -#define SHR1_MID 0x3055 -#define SHR1_HIGH 0x3056 +#define SHR1_LOW 0x3054 +#define SHR1_MID 0x3055 +#define SHR1_HIGH 0x3056 // Very short exposure -#define SHR2_LOW 0x3058 -#define SHR2_MID 0x3059 -#define SHR2_HIGH 0x305A +#define SHR2_LOW 0x3058 +#define SHR2_MID 0x3059 +#define SHR2_HIGH 0x305A // Long exposure -#define GAIN_0_LOW 0x3070 -#define GAIN_0_HIGH 0x3071 +#define GAIN_0_LOW 0x3070 +#define GAIN_0_HIGH 0x3071 // Short exposure -#define GAIN_1_LOW 0x3072 -#define GAIN_1_HIGH 0x3073 +#define GAIN_1_LOW 0x3072 +#define GAIN_1_HIGH 0x3073 // Very short exposure -#define GAIN_2_LOW 0x3074 -#define GAIN_2_HIGH 0x3075 +#define GAIN_2_LOW 0x3074 +#define GAIN_2_HIGH 0x3075 -#define RHS1_LOW 0x3060 -#define RHS1_MID 0x3061 -#define RHS1_HIGH 0x3062 -#define RHS2_LOW 0x3064 -#define RHS2_MID 0x3065 -#define RHS2_HIGH 0x3066 +#define RHS1_LOW 0x3060 +#define RHS1_MID 0x3061 +#define RHS1_HIGH 0x3062 +#define RHS2_LOW 0x3064 +#define RHS2_MID 0x3065 +#define RHS2_HIGH 0x3066 -#define EXP_GAIN 0x3081 +#define EXP_GAIN 0x3081 #define XVS_XHS_DRV 0x30A6 #define BLKLEVEL_LOW 0x30DC #define BLKLEVEL_HIGH 0x30DD -#define GAIN_PGC_FIDMD 0x3400 +#define GAIN_PGC_FIDMD 0x3400 #define TPG_EN_DUOUT 0x30E0 #define TPG_PATSEL_DUOUT 0x30E2 #define TPG_COLORWIDTH 0x30E4 -#define TESTCLKEN 0x5300 +#define TESTCLKEN 0x5300 #define EXTMODE 0x30CE @@ -500,24 +500,23 @@ static const struct imx678_reg mode_h2v2_binning[] = { }; static struct imx678_reg imx678_setting_dol_hdr[] = { - {WINMODE, 0x00}, - {WDMODE, 0x01}, - {ADDMODE, 0x00}, - {THIN_V_EN, 0x01}, + {WINMODE, 0x00}, + {WDMODE, 0x01}, + {ADDMODE, 0x00}, + {THIN_V_EN, 0x01}, - {GAIN_PGC_FIDMD, 0x00}, + {GAIN_PGC_FIDMD, 0x00}, - {SHR0_LOW, 0x40}, - {SHR0_MID, 0x0b}, - {SHR1_LOW, 0x05}, + {SHR0_LOW, 0x40}, + {SHR0_MID, 0x0b}, + {SHR1_LOW, 0x05}, - {RHS1_LOW, 0x49}, - {RHS1_MID, 0x00}, + {RHS1_LOW, 0x49}, + {RHS1_MID, 0x00}, - {0x355A, 0x64}, + {0x355A, 0x64}, }; - static struct imx678_reg imx678_setting_clear_hdr[] = { {WINMODE, 0x00}, {WDMODE, 0x08},