* [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver.
@ 2026-08-05 16:09 Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 1/4] media: i2c: imx678: Always program the sensor in window mode Dave Stevenson
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Dave Stevenson @ 2026-08-05 16:09 UTC (permalink / raw)
To: Sakari Ailus, Jai Luthra, Mauro Carvalho Chehab
Cc: Laurent Pinchart, Alexander Shiyan, linux-media, linux-kernel,
Dave Stevenson
The IMX678 (8MPix) driver has been accepted.
Whilst preparing a patchset for IMX662 (1080p), I observed such
commonality between the two that it seemed sensible to attempt
a common driver rather than submitting a separate IMX662 series
again.
On checking my box of sensors, I found I had an IMX675 (5MPix) as
well, so that has been incorporated.
This set proposes a common driver that is working with all 3 of
those sensors.
It's sent as an RFC to gather confirmation that the resulting driver
structure is acceptable as implied by [1].
If it is viewed as acceptable then there is still a modest amount
of tidying up required:
- DT binding updates for the extra compatibles.
- Rename the common functions so that the model references are
only on the model specific parts.
- Add the Sony init sequence for IMX662.
- Check the init sequence for IMX675 (I'm waiting on a datasheet).
- Update the 2 lane mode handling of HMAX. IMX662 can achieve the
same maximum framerate in 2 lane mode with a link freq of 594MHz
or greater, and I suspect others can do so too.
- Hopefully add IMX585 (8MPix) to the supported list, and Jai has
mentioned IMX676 (12MPix) as well.
I wanted to confirm that there aren't any major objections before
doing those cleanups though.
For anyone testing on a Pi, I've thrown a branch at [2] which includes
overlays for each. I've tested with modules from Soho Enterprises,
but there seem to be a few different vendors around.
[1] https://lore.kernel.org/linux-media/20260312150437.1091195-1-eagle.alexander923@gmail.com/T/#md6a186b4abd05fb035d020ce0bc562455ef5bed1
[2] https://github.com/6by9/linux/tree/rpi-7.2.y-starvis
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
Dave Stevenson (4):
media: i2c: imx678: Always program the sensor in window mode
media: i2c: imx678: Parameterise the configuration to allow for other models
media: i2c: imx678: Add imx662 support to the driver
media: i2c: imx678: Add imx675 support to the driver
drivers/media/i2c/imx678.c | 451 +++++++++++++++++++++++++++++++++++++++------
1 file changed, 393 insertions(+), 58 deletions(-)
---
base-commit: 31152f5b0f8719f92063b8c6196cd5e34106c73d
change-id: 20260804-media-starvis2-65a5bc405b74
Best regards,
--
Dave Stevenson <dave.stevenson@raspberrypi.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH RFC 1/4] media: i2c: imx678: Always program the sensor in window mode
2026-08-05 16:09 [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
@ 2026-08-05 16:09 ` Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 2/4] media: i2c: imx678: Parameterise the configuration to allow for other models Dave Stevenson
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Dave Stevenson @ 2026-08-05 16:09 UTC (permalink / raw)
To: Sakari Ailus, Jai Luthra, Mauro Carvalho Chehab
Cc: Laurent Pinchart, Alexander Shiyan, linux-media, linux-kernel,
Dave Stevenson
If the requested region matched the defined active area then
the driver switched to all-pixel mode. This left the possibilty
that the activeare was incorrect and not reading out the area
expected.
Switch to always requesting window mode.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx678.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c
index 0efbf43d2fe6..f7b988dca2ac 100644
--- a/drivers/media/i2c/imx678.c
+++ b/drivers/media/i2c/imx678.c
@@ -917,9 +917,7 @@ static int imx678_program_window(struct imx678 *imx678,
int ret = 0;
cci_write(imx678->cci, IMX678_REG_ADDMODE, 0x00, &ret);
- cci_write(imx678->cci, IMX678_REG_WINMODE,
- v4l2_rect_equal(crop, &imx678_active_area) ? 0x00 : 0x04,
- &ret);
+ cci_write(imx678->cci, IMX678_REG_WINMODE, 0x04, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_HST,
crop->left - imx678_active_area.left, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_HWIDTH, crop->width, &ret);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH RFC 2/4] media: i2c: imx678: Parameterise the configuration to allow for other models
2026-08-05 16:09 [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 1/4] media: i2c: imx678: Always program the sensor in window mode Dave Stevenson
@ 2026-08-05 16:09 ` Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 3/4] media: i2c: imx678: Add imx662 support to the driver Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 4/4] media: i2c: imx678: Add imx675 " Dave Stevenson
3 siblings, 0 replies; 5+ messages in thread
From: Dave Stevenson @ 2026-08-05 16:09 UTC (permalink / raw)
To: Sakari Ailus, Jai Luthra, Mauro Carvalho Chehab
Cc: Laurent Pinchart, Alexander Shiyan, linux-media, linux-kernel,
Dave Stevenson
Several of the Sony Starvis 2 sensors are identical in the
majority of their programming, but differ largely only in the
size of pixel array and some timing parameters.
Parameterise those parameters in preparation for supporting other
variants.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx678.c | 161 +++++++++++++++++++++++++++++----------------
1 file changed, 106 insertions(+), 55 deletions(-)
diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c
index f7b988dca2ac..40ba6661b366 100644
--- a/drivers/media/i2c/imx678.c
+++ b/drivers/media/i2c/imx678.c
@@ -148,32 +148,11 @@
/* Subdev pads */
#define IMX678_SOURCE_PAD 0
-/* IMX678 native and active pixel array size. */
-static const struct v4l2_rect imx678_native_area = {
- .top = 0,
- .left = 0,
- .width = 3857,
- .height = 2201,
-};
-
-static const struct v4l2_rect imx678_active_area = {
- .top = 20,
- .left = 0,
- .width = 3856,
- .height = 2180,
-};
-
enum imx678_type {
IMX678_COLOR = 0,
IMX678_MONOCHROME = 1,
};
-struct imx678_model_info {
- enum imx678_type type;
- const u32 *codes;
- unsigned int num_codes;
-};
-
enum imx678_lanemode {
IMX678_LANEMODE_2L = 1,
IMX678_LANEMODE_4L = 3,
@@ -213,7 +192,7 @@ static const u64 link_freqs[] = {
[IMX678_LINK_FREQ_1188MHZ] = 1188000000,
};
-static const u16 min_hmax_4lane[] = {
+static const u16 imx678_min_hmax_4lane[] = {
[IMX678_LINK_FREQ_297MHZ] = 1584,
[IMX678_LINK_FREQ_360MHZ] = 1320,
[IMX678_LINK_FREQ_445MHZ] = 1100,
@@ -273,7 +252,7 @@ static const int imx678_tpg_val[] = {
};
/* Common configuration */
-static const struct cci_reg_sequence common_regs[] = {
+static const struct cci_reg_sequence imx678_common_regs[] = {
{ IMX678_REG_THIN_V_EN, 0x00 },
{ IMX678_REG_VCMODE, 0x01 },
{ CCI_REG8(0x306b), 0x00 },
@@ -656,16 +635,72 @@ static const u32 codes_monochrome[] = {
MEDIA_BUS_FMT_Y12_1X12,
};
+struct imx678_variant {
+ const char *name;
+ u32 id_reg;
+ u32 id_value;
+ struct v4l2_rect native_area;
+ struct v4l2_rect active_area;
+ u64 pixel_rate;
+ unsigned int pix_per_clk;
+ const struct cci_reg_sequence *common_regs;
+ unsigned int num_common_regs;
+ unsigned int vmax_default;
+ const u16 *hmax_min;
+};
+
+const struct imx678_variant imx678_variant_def = {
+ .name = "imx678",
+ .id_reg = IMX678_REG_MODULE_ID,
+ .id_value = IMX678_ID,
+ .native_area = {
+ .top = 0,
+ .left = 0,
+ .width = 3857,
+ .height = 2201,
+ },
+ .active_area = {
+ .top = 20,
+ .left = 0,
+ .width = 3856,
+ .height = 2180,
+ },
+ .pixel_rate = IMX678_PIXEL_RATE,
+ .pix_per_clk = IMX678_PIX_PER_CLK,
+ .common_regs = imx678_common_regs,
+ .num_common_regs = ARRAY_SIZE(imx678_common_regs),
+ .vmax_default = IMX678_VMAX_DEFAULT,
+ .hmax_min = imx678_min_hmax_4lane,
+};
+
+struct imx678_model_info {
+ enum imx678_type type;
+ const u32 *codes;
+ unsigned int num_codes;
+ const struct imx678_variant *variant;
+
+ const struct imx678_model_info *auto_detect_colour;
+ const struct imx678_model_info *auto_detect_mono;
+};
+
static const struct imx678_model_info imx678_aaqr_info = {
.type = IMX678_COLOR,
.codes = codes_bayer,
.num_codes = ARRAY_SIZE(codes_bayer),
+ .variant = &imx678_variant_def,
};
static const struct imx678_model_info imx678_aamr_info = {
.type = IMX678_MONOCHROME,
.codes = codes_monochrome,
.num_codes = ARRAY_SIZE(codes_monochrome),
+ .variant = &imx678_variant_def,
+};
+
+static const struct imx678_model_info imx678_autodetect_info = {
+ .variant = &imx678_variant_def,
+ .auto_detect_colour = &imx678_aaqr_info,
+ .auto_detect_mono = &imx678_aamr_info,
};
static const char * const imx678_supply_name[] = {
@@ -680,6 +715,7 @@ struct imx678 {
struct regmap *cci;
const struct imx678_model_info *info;
+ const struct imx678_variant *variant;
struct clk *xclk;
u32 xclk_freq;
@@ -774,7 +810,7 @@ static int imx678_set_ctrl(struct v4l2_ctrl *ctrl)
cci_write(imx678->cci, IMX678_REG_GAIN, ctrl->val, &ret);
break;
case V4L2_CID_HBLANK: {
- u32 hmax = (format->width + ctrl->val) / IMX678_PIX_PER_CLK;
+ u32 hmax = (format->width + ctrl->val) / imx678->variant->pix_per_clk;
cci_write(imx678->cci, IMX678_REG_HMAX, hmax, &ret);
break;
@@ -852,18 +888,20 @@ static int imx678_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
+ struct imx678 *imx678 = to_imx678(sd);
+
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
return 0;
case V4L2_SEL_TGT_NATIVE_SIZE:
- sel->r = imx678_native_area;
+ sel->r = imx678->variant->native_area;
return 0;
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP_BOUNDS:
- sel->r = imx678_active_area;
+ sel->r = imx678->variant->active_area;
return 0;
}
@@ -878,12 +916,12 @@ static int imx678_init_state(struct v4l2_subdev *sd,
struct v4l2_rect *crop;
crop = v4l2_subdev_state_get_crop(state, IMX678_SOURCE_PAD);
- *crop = imx678_active_area;
+ *crop = imx678->variant->active_area;
format = v4l2_subdev_state_get_format(state, IMX678_SOURCE_PAD);
format->code = imx678_default_mbus_code(imx678);
- format->width = imx678_active_area.width;
- format->height = imx678_active_area.height;
+ format->width = imx678->variant->active_area.width;
+ format->height = imx678->variant->active_area.height;
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_RAW;
format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
@@ -897,8 +935,8 @@ static int imx678_write_common(struct imx678 *imx678)
{
int ret = 0;
- cci_multi_reg_write(imx678->cci, common_regs, ARRAY_SIZE(common_regs),
- &ret);
+ cci_multi_reg_write(imx678->cci, imx678->variant->common_regs,
+ imx678->variant->num_common_regs, &ret);
cci_write(imx678->cci, IMX678_REG_INCK_SEL, imx678->inck_sel_val, &ret);
cci_write(imx678->cci, IMX678_REG_DATARATE_SEL,
@@ -919,10 +957,10 @@ static int imx678_program_window(struct imx678 *imx678,
cci_write(imx678->cci, IMX678_REG_ADDMODE, 0x00, &ret);
cci_write(imx678->cci, IMX678_REG_WINMODE, 0x04, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_HST,
- crop->left - imx678_active_area.left, &ret);
+ crop->left - imx678->variant->active_area.left, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_HWIDTH, crop->width, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_VST,
- crop->top - imx678_active_area.top, &ret);
+ crop->top - imx678->variant->active_area.top, &ret);
cci_write(imx678->cci, IMX678_REG_PIX_VWIDTH, crop->height, &ret);
cci_write(imx678->cci, IMX678_REG_ADBIT, 0x01, &ret);
@@ -1027,11 +1065,13 @@ static int imx678_power_on(struct device *dev)
fsleep(20); /* T4 > 20us */
- ret = imx678_write_common(imx678);
- if (ret) {
- dev_err(&client->dev, "%s failed to write registers\n",
- __func__);
- goto clk_off;
+ if (imx678->variant) {
+ ret = imx678_write_common(imx678);
+ if (ret) {
+ dev_err(&client->dev, "%s failed to write registers\n",
+ __func__);
+ goto clk_off;
+ }
}
return 0;
@@ -1065,11 +1105,16 @@ static int imx678_identify_model(struct imx678 *imx678)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd);
const struct imx678_model_info *info;
+ const struct imx678_variant *variant;
enum imx678_type detected;
int ret = 0;
u64 val = 0;
info = device_get_match_data(&client->dev);
+ if (!info)
+ return -EINVAL;
+
+ variant = info->variant;
/*
* This sensor's ID registers become accessible 80ms after coming out
@@ -1078,7 +1123,7 @@ static int imx678_identify_model(struct imx678 *imx678)
cci_write(imx678->cci, IMX678_REG_MODE_SELECT, 0, &ret);
fsleep(IMX678_MODULE_ID_DELAY);
- cci_read(imx678->cci, IMX678_REG_MODULE_ID, &val, &ret);
+ cci_read(imx678->cci, variant->id_reg, &val, &ret);
if (ret) {
dev_err(&client->dev,
@@ -1086,9 +1131,9 @@ static int imx678_identify_model(struct imx678 *imx678)
return ret;
}
- if (val != IMX678_ID) {
- dev_err(&client->dev,
- "Chip ID mismatch: %x!=%llx\n", IMX678_ID, val);
+ if (val != variant->id_value) {
+ dev_err(&client->dev, "Chip ID mismatch: %x!=%llx\n",
+ variant->id_value, val);
return -ENXIO;
}
@@ -1103,7 +1148,7 @@ static int imx678_identify_model(struct imx678 *imx678)
detected = val & IMX678_TYPE;
/* Prefer to use sensor type specified in device tree */
- if (info) {
+ if (info->codes) {
imx678->info = info;
if (detected != info->type)
dev_err(&client->dev,
@@ -1112,12 +1157,14 @@ static int imx678_identify_model(struct imx678 *imx678)
info->type == IMX678_COLOR ? "color" : "mono");
} else {
imx678->info = detected == IMX678_MONOCHROME ?
- &imx678_aamr_info : &imx678_aaqr_info;
+ info->auto_detect_mono : info->auto_detect_colour;
dev_info(&client->dev,
"sensor type missing in DT; detected %s sensor\n",
detected == IMX678_MONOCHROME ? "mono" : "color");
}
+ imx678->variant = imx678->info->variant;
+
return 0;
}
@@ -1147,7 +1194,7 @@ static const struct v4l2_subdev_internal_ops imx678_internal_ops = {
static int imx678_init_controls(struct imx678 *imx678)
{
struct v4l2_ctrl_handler *ctrl_hdlr;
- const u32 hmax_4lane = min_hmax_4lane[__ffs(imx678->link_freq_bitmap)];
+ const u32 hmax_4lane = imx678->variant->hmax_min[__ffs(imx678->link_freq_bitmap)];
const u32 lane_scale = imx678->lane_mode == IMX678_LANEMODE_2L ? 2 : 1;
struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd);
struct v4l2_fwnode_device_properties props;
@@ -1165,13 +1212,14 @@ static int imx678_init_controls(struct imx678 *imx678)
if (ret)
return ret;
- imx678->vmax = IMX678_VMAX_DEFAULT;
+ imx678->vmax = imx678->variant->vmax_default;
hmax = hmax_4lane * lane_scale;
/* PIXEL_RATE is fixed and read-only */
v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_PIXEL_RATE,
- IMX678_PIXEL_RATE, IMX678_PIXEL_RATE, 1,
- IMX678_PIXEL_RATE);
+ imx678->variant->pixel_rate,
+ imx678->variant->pixel_rate, 1,
+ imx678->variant->pixel_rate);
/* LINK_FREQ is also read only */
link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx678_ctrl_ops,
@@ -1183,15 +1231,16 @@ static int imx678_init_controls(struct imx678 *imx678)
if (link_freq)
link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- vblank = imx678->vmax - imx678_active_area.height;
- max_vblank = IMX678_VMAX_MAX - imx678_active_area.height;
+ vblank = imx678->vmax - imx678->variant->active_area.height;
+ max_vblank = IMX678_VMAX_MAX - imx678->variant->active_area.height;
imx678->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops,
V4L2_CID_VBLANK, vblank, max_vblank,
2, vblank);
- hblank = hmax * IMX678_PIX_PER_CLK - imx678_active_area.width;
- max_hblank = IMX678_HMAX_MAX * IMX678_PIX_PER_CLK -
- imx678_active_area.width;
+ hblank = hmax * imx678->variant->pix_per_clk -
+ imx678->variant->active_area.width;
+ max_hblank = IMX678_HMAX_MAX * imx678->variant->pix_per_clk -
+ imx678->variant->active_area.width;
imx678->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops,
V4L2_CID_HBLANK, hblank, max_hblank,
IMX678_PIX_PER_CLK, hblank);
@@ -1335,11 +1384,13 @@ static int imx678_probe(struct i2c_client *client)
ret = imx678_power_on(dev);
if (ret)
return ret;
-
ret = imx678_identify_model(imx678);
if (ret)
goto error_power_off;
+ v4l2_i2c_subdev_set_name(&imx678->sd, client,
+ imx678->variant->name, NULL);
+
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -1420,7 +1471,7 @@ static const struct of_device_id imx678_of_match[] = {
{ .compatible = "sony,imx678-aamr", .data = &imx678_aamr_info },
{ .compatible = "sony,imx678-aaqr", .data = &imx678_aaqr_info },
/* for non-conforming DTs that rely on runtime check */
- { .compatible = "sony,imx678" },
+ { .compatible = "sony,imx678", .data = &imx678_autodetect_info },
{ /* sentinel */ }
};
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH RFC 3/4] media: i2c: imx678: Add imx662 support to the driver
2026-08-05 16:09 [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 1/4] media: i2c: imx678: Always program the sensor in window mode Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 2/4] media: i2c: imx678: Parameterise the configuration to allow for other models Dave Stevenson
@ 2026-08-05 16:09 ` Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 4/4] media: i2c: imx678: Add imx675 " Dave Stevenson
3 siblings, 0 replies; 5+ messages in thread
From: Dave Stevenson @ 2026-08-05 16:09 UTC (permalink / raw)
To: Sakari Ailus, Jai Luthra, Mauro Carvalho Chehab
Cc: Laurent Pinchart, Alexander Shiyan, linux-media, linux-kernel,
Dave Stevenson
IMX662 is a 1080p Starvis 2 sensor that follows the same programming
pattern as IMX678, so add it to the newly parameterised driver.
FIXME: Update the common registers based on the Sony spreadsheet.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx678.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c
index 40ba6661b366..9083f2744510 100644
--- a/drivers/media/i2c/imx678.c
+++ b/drivers/media/i2c/imx678.c
@@ -673,6 +673,47 @@ const struct imx678_variant imx678_variant_def = {
.hmax_min = imx678_min_hmax_4lane,
};
+static const struct cci_reg_sequence imx662_common_regs[] = {
+ { IMX678_REG_WDMODE, 0x00 },
+ { IMX678_REG_MDBIT, 0x01 },
+ { IMX678_REG_XXS_DRV, 0x00 },
+};
+
+static const u16 imx662_min_hmax_4lane[] = {
+ [IMX678_LINK_FREQ_297MHZ] = 990,
+ [IMX678_LINK_FREQ_360MHZ] = 990,
+ [IMX678_LINK_FREQ_445MHZ] = 990,
+ [IMX678_LINK_FREQ_594MHZ] = 990,
+ [IMX678_LINK_FREQ_720MHZ] = 990,
+ [IMX678_LINK_FREQ_891MHZ] = 990,
+ [IMX678_LINK_FREQ_1039MHZ] = 990,
+ [IMX678_LINK_FREQ_1188MHZ] = 990,
+};
+
+const struct imx678_variant imx662_variant_def = {
+ .name = "imx662",
+ .id_reg = IMX678_REG_MODULE_ID,
+ .id_value = 0x296,
+ .native_area = {
+ .top = 0,
+ .left = 0,
+ .width = 1937,
+ .height = 1101,
+ },
+ .active_area = {
+ .top = 0,
+ .left = 0,
+ .width = 1936,
+ .height = 1096,
+ },
+ .pixel_rate = 222750000,
+ .pix_per_clk = 3,
+ .common_regs = imx662_common_regs,
+ .num_common_regs = ARRAY_SIZE(imx662_common_regs),
+ .vmax_default = 1096 + 40,
+ .hmax_min = imx662_min_hmax_4lane,
+};
+
struct imx678_model_info {
enum imx678_type type;
const u32 *codes;
@@ -703,6 +744,26 @@ static const struct imx678_model_info imx678_autodetect_info = {
.auto_detect_mono = &imx678_aamr_info,
};
+static const struct imx678_model_info imx662_aaqr_info = {
+ .type = IMX678_COLOR,
+ .codes = codes_bayer,
+ .num_codes = ARRAY_SIZE(codes_bayer),
+ .variant = &imx662_variant_def,
+};
+
+static const struct imx678_model_info imx662_aamr_info = {
+ .type = IMX678_MONOCHROME,
+ .codes = codes_monochrome,
+ .num_codes = ARRAY_SIZE(codes_monochrome),
+ .variant = &imx662_variant_def,
+};
+
+static const struct imx678_model_info imx662_autodetect_info = {
+ .variant = &imx662_variant_def,
+ .auto_detect_colour = &imx662_aaqr_info,
+ .auto_detect_mono = &imx662_aamr_info,
+};
+
static const char * const imx678_supply_name[] = {
"avdd", /* Analog (3.3V) supply */
"dvdd", /* Digital Core (1.1V) supply */
@@ -1470,8 +1531,11 @@ static const struct dev_pm_ops imx678_pm_ops = {
static const struct of_device_id imx678_of_match[] = {
{ .compatible = "sony,imx678-aamr", .data = &imx678_aamr_info },
{ .compatible = "sony,imx678-aaqr", .data = &imx678_aaqr_info },
+ { .compatible = "sony,imx662-aamr", .data = &imx662_aamr_info },
+ { .compatible = "sony,imx662-aaqr", .data = &imx662_aaqr_info },
/* for non-conforming DTs that rely on runtime check */
{ .compatible = "sony,imx678", .data = &imx678_autodetect_info },
+ { .compatible = "sony,imx662", .data = &imx662_autodetect_info },
{ /* sentinel */ }
};
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH RFC 4/4] media: i2c: imx678: Add imx675 support to the driver
2026-08-05 16:09 [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
` (2 preceding siblings ...)
2026-08-05 16:09 ` [PATCH RFC 3/4] media: i2c: imx678: Add imx662 support to the driver Dave Stevenson
@ 2026-08-05 16:09 ` Dave Stevenson
3 siblings, 0 replies; 5+ messages in thread
From: Dave Stevenson @ 2026-08-05 16:09 UTC (permalink / raw)
To: Sakari Ailus, Jai Luthra, Mauro Carvalho Chehab
Cc: Laurent Pinchart, Alexander Shiyan, linux-media, linux-kernel,
Dave Stevenson
The IMX675 is a 5MPix Starvis2 sensor that follows the same
programming pattern as IMX678 and IMX662, so add it into the
driver.
FIXME: Validate common_regs against Sony documentation.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx678.c | 222 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 222 insertions(+)
diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c
index 9083f2744510..4b82823c260e 100644
--- a/drivers/media/i2c/imx678.c
+++ b/drivers/media/i2c/imx678.c
@@ -714,6 +714,205 @@ const struct imx678_variant imx662_variant_def = {
.hmax_min = imx662_min_hmax_4lane,
};
+static const struct cci_reg_sequence imx675_common_regs[] = {
+ { CCI_REG8(0x301B), 0x00 },
+ { CCI_REG8(0x301C), 0x00 },
+ { CCI_REG8(0x301E), 0x01 },
+
+ { CCI_REG8(0x3060), 0x95 },
+ { CCI_REG8(0x3061), 0x00 },
+ { CCI_REG8(0x3062), 0x00 },
+ { CCI_REG8(0x3064), 0x56 },
+ { CCI_REG8(0x3065), 0x00 },
+ { CCI_REG8(0x3066), 0x00 },
+
+ { CCI_REG8(0x3072), 0x00 },
+ { CCI_REG8(0x3073), 0x00 },
+ { CCI_REG8(0x3074), 0x00 },
+ { CCI_REG8(0x3075), 0x00 },
+ { CCI_REG8(0x3081), 0x00 },
+ { CCI_REG8(0x30A4), 0xAA },
+ { CCI_REG8(0x30A6), 0x0F },
+ { CCI_REG8(0x30CC), 0x00 },
+ { CCI_REG8(0x30CD), 0x00 },
+ { CCI_REG8(0x30CE), 0x02 },
+ { CCI_REG8(0x3400), 0x01 },
+
+ { CCI_REG8(0x3400), 0x01 },
+ { CCI_REG8(0x3460), 0x22 },
+ { CCI_REG8(0x3492), 0x08 },
+ { CCI_REG8(0x3B1D), 0x17 },
+ { CCI_REG8(0x3B44), 0x3F },
+ { CCI_REG8(0x3B60), 0x03 },
+ { CCI_REG8(0x3C03), 0x04 },
+ { CCI_REG8(0x3C04), 0x04 },
+ { CCI_REG8(0x3C0A), 0x00 },
+ { CCI_REG8(0x3C0B), 0x00 },
+ { CCI_REG8(0x3C0C), 0x00 },
+ { CCI_REG8(0x3C0D), 0x00 },
+ { CCI_REG8(0x3C0E), 0x00 },
+ { CCI_REG8(0x3C0F), 0x00 },
+ { CCI_REG8(0x3C30), 0x73 },
+ { CCI_REG8(0x3C3C), 0x20 },
+ { CCI_REG8(0x3C7C), 0xB9 },
+ { CCI_REG8(0x3C7D), 0x01 },
+ { CCI_REG8(0x3C7E), 0xB7 },
+ { CCI_REG8(0x3C7F), 0x01 },
+ { CCI_REG8(0x3CB0), 0x00 },
+ { CCI_REG8(0x3CB2), 0xFF },
+ { CCI_REG8(0x3CB3), 0x03 },
+ { CCI_REG8(0x3CB4), 0xFF },
+ { CCI_REG8(0x3CB5), 0x03 },
+ { CCI_REG8(0x3CBA), 0xFF },
+ { CCI_REG8(0x3CBB), 0x03 },
+ { CCI_REG8(0x3CC0), 0xFF },
+ { CCI_REG8(0x3CC1), 0x03 },
+ { CCI_REG8(0x3CC2), 0x00 },
+ { CCI_REG8(0x3CC6), 0xFF },
+ { CCI_REG8(0x3CC7), 0x03 },
+ { CCI_REG8(0x3CC8), 0xFF },
+ { CCI_REG8(0x3CC9), 0x03 },
+ { CCI_REG8(0x3E00), 0x1E },
+ { CCI_REG8(0x3E02), 0x04 },
+ { CCI_REG8(0x3E03), 0x00 },
+ { CCI_REG8(0x3E20), 0x04 },
+ { CCI_REG8(0x3E21), 0x00 },
+ { CCI_REG8(0x3E22), 0x1E },
+ { CCI_REG8(0x3E24), 0xBA },
+ { CCI_REG8(0x3E72), 0x85 },
+ { CCI_REG8(0x3E76), 0x0C },
+
+ { CCI_REG8(0x3E77), 0x01 },
+ { CCI_REG8(0x3E7A), 0x85 },
+ { CCI_REG8(0x3E7E), 0x1F },
+ { CCI_REG8(0x3E82), 0xA6 },
+ { CCI_REG8(0x3E86), 0x2D },
+ { CCI_REG8(0x3EE2), 0x33 },
+ { CCI_REG8(0x3EE3), 0x03 },
+ { CCI_REG8(0x4490), 0x07 },
+ { CCI_REG8(0x4494), 0x19 },
+ { CCI_REG8(0x4495), 0x00 },
+ { CCI_REG8(0x4496), 0xBB },
+ { CCI_REG8(0x4497), 0x00 },
+ { CCI_REG8(0x4498), 0x55 },
+ { CCI_REG8(0x449A), 0x50 },
+ { CCI_REG8(0x449C), 0x50 },
+ { CCI_REG8(0x449E), 0x50 },
+ { CCI_REG8(0x44A0), 0x3C },
+ { CCI_REG8(0x44A2), 0x19 },
+ { CCI_REG8(0x44A4), 0x19 },
+ { CCI_REG8(0x44A6), 0x19 },
+ { CCI_REG8(0x44A8), 0x4B },
+ { CCI_REG8(0x44AA), 0x4B },
+ { CCI_REG8(0x44AC), 0x4B },
+ { CCI_REG8(0x44AE), 0x4B },
+ { CCI_REG8(0x44B0), 0x3C },
+ { CCI_REG8(0x44B2), 0x19 },
+ { CCI_REG8(0x44B4), 0x19 },
+ { CCI_REG8(0x44B6), 0x19 },
+ { CCI_REG8(0x44B8), 0x4B },
+ { CCI_REG8(0x44BA), 0x4B },
+ { CCI_REG8(0x44BC), 0x4B },
+ { CCI_REG8(0x44BE), 0x4B },
+ { CCI_REG8(0x44C0), 0x3C },
+ { CCI_REG8(0x44C2), 0x19 },
+ { CCI_REG8(0x44C4), 0x19 },
+ { CCI_REG8(0x44C6), 0x19 },
+ { CCI_REG8(0x44C8), 0xF0 },
+ { CCI_REG8(0x44CA), 0xEB },
+ { CCI_REG8(0x44CC), 0xEB },
+ { CCI_REG8(0x44CE), 0xE6 },
+ { CCI_REG8(0x44D0), 0xE6 },
+ { CCI_REG8(0x44D2), 0xBB },
+
+ { CCI_REG8(0x44D4), 0xBB },
+ { CCI_REG8(0x44D6), 0xBB },
+ { CCI_REG8(0x44D8), 0xE6 },
+ { CCI_REG8(0x44DA), 0xE6 },
+ { CCI_REG8(0x44DC), 0xE6 },
+ { CCI_REG8(0x44DE), 0xE6 },
+ { CCI_REG8(0x44E0), 0xE6 },
+ { CCI_REG8(0x44E2), 0xBB },
+ { CCI_REG8(0x44E4), 0xBB },
+ { CCI_REG8(0x44E6), 0xBB },
+ { CCI_REG8(0x44E8), 0xE6 },
+ { CCI_REG8(0x44EA), 0xE6 },
+ { CCI_REG8(0x44EC), 0xE6 },
+ { CCI_REG8(0x44EE), 0xE6 },
+ { CCI_REG8(0x44F0), 0xE6 },
+ { CCI_REG8(0x44F2), 0xBB },
+ { CCI_REG8(0x44F4), 0xBB },
+ { CCI_REG8(0x44F6), 0xBB },
+ { CCI_REG8(0x4538), 0x15 },
+ { CCI_REG8(0x4539), 0x15 },
+ { CCI_REG8(0x453A), 0x15 },
+ { CCI_REG8(0x4544), 0x15 },
+ { CCI_REG8(0x4545), 0x15 },
+ { CCI_REG8(0x4546), 0x15 },
+ { CCI_REG8(0x4550), 0x11 },
+ { CCI_REG8(0x4551), 0x11 },
+ { CCI_REG8(0x4552), 0x11 },
+ { CCI_REG8(0x4553), 0x11 },
+ { CCI_REG8(0x4554), 0x11 },
+ { CCI_REG8(0x4555), 0x11 },
+ { CCI_REG8(0x4556), 0x11 },
+ { CCI_REG8(0x4557), 0x11 },
+ { CCI_REG8(0x4558), 0x11 },
+ { CCI_REG8(0x455C), 0x11 },
+ { CCI_REG8(0x455D), 0x11 },
+ { CCI_REG8(0x455E), 0x11 },
+ { CCI_REG8(0x455F), 0x11 },
+ { CCI_REG8(0x4560), 0x11 },
+ { CCI_REG8(0x4561), 0x11 },
+ { CCI_REG8(0x4562), 0x11 },
+ { CCI_REG8(0x4563), 0x11 },
+ { CCI_REG8(0x4564), 0x11 },
+
+ { CCI_REG8(0x4569), 0x01 },
+ { CCI_REG8(0x456A), 0x01 },
+ { CCI_REG8(0x456B), 0x06 },
+ { CCI_REG8(0x456C), 0x06 },
+ { CCI_REG8(0x456D), 0x06 },
+ { CCI_REG8(0x456E), 0x06 },
+ { CCI_REG8(0x456F), 0x06 },
+ { CCI_REG8(0x4570), 0x06 },
+};
+
+static const u16 imx675_min_hmax_4lane[] = {
+ [IMX678_LINK_FREQ_297MHZ] = 1125,
+ [IMX678_LINK_FREQ_360MHZ] = 1125,
+ [IMX678_LINK_FREQ_445MHZ] = 1125,
+ [IMX678_LINK_FREQ_594MHZ] = 1125 / 2,
+ [IMX678_LINK_FREQ_720MHZ] = 1125 / 2,
+ [IMX678_LINK_FREQ_891MHZ] = 1125 / 2,
+ [IMX678_LINK_FREQ_1039MHZ] = 1125 / 2,
+ [IMX678_LINK_FREQ_1188MHZ] = 1125 / 2,
+};
+
+const struct imx678_variant imx675_variant_def = {
+ .name = "imx675",
+ .id_reg = IMX678_REG_MODULE_ID,
+ .id_value = 0x296,
+ .native_area = {
+ .top = 0,
+ .left = 0,
+ .width = 2609,
+ .height = 1984,
+ },
+ .active_area = {
+ .top = 0,
+ .left = 0,
+ .width = 2608,
+ .height = 1984,
+ },
+ .pixel_rate = 594000000,
+ .pix_per_clk = 8,
+ .common_regs = imx675_common_regs,
+ .num_common_regs = ARRAY_SIZE(imx675_common_regs),
+ .vmax_default = 1984 + 40,
+ .hmax_min = imx675_min_hmax_4lane,
+};
+
struct imx678_model_info {
enum imx678_type type;
const u32 *codes;
@@ -764,6 +963,26 @@ static const struct imx678_model_info imx662_autodetect_info = {
.auto_detect_mono = &imx662_aamr_info,
};
+static const struct imx678_model_info imx675_aaqr_info = {
+ .type = IMX678_COLOR,
+ .codes = codes_bayer,
+ .num_codes = ARRAY_SIZE(codes_bayer),
+ .variant = &imx675_variant_def,
+};
+
+static const struct imx678_model_info imx675_aamr_info = {
+ .type = IMX678_MONOCHROME,
+ .codes = codes_monochrome,
+ .num_codes = ARRAY_SIZE(codes_monochrome),
+ .variant = &imx675_variant_def,
+};
+
+static const struct imx678_model_info imx675_autodetect_info = {
+ .variant = &imx675_variant_def,
+ .auto_detect_colour = &imx675_aaqr_info,
+ .auto_detect_mono = &imx675_aamr_info,
+};
+
static const char * const imx678_supply_name[] = {
"avdd", /* Analog (3.3V) supply */
"dvdd", /* Digital Core (1.1V) supply */
@@ -1533,9 +1752,12 @@ static const struct of_device_id imx678_of_match[] = {
{ .compatible = "sony,imx678-aaqr", .data = &imx678_aaqr_info },
{ .compatible = "sony,imx662-aamr", .data = &imx662_aamr_info },
{ .compatible = "sony,imx662-aaqr", .data = &imx662_aaqr_info },
+ { .compatible = "sony,imx675-aamr", .data = &imx675_aamr_info },
+ { .compatible = "sony,imx675-aaqr", .data = &imx675_aaqr_info },
/* for non-conforming DTs that rely on runtime check */
{ .compatible = "sony,imx678", .data = &imx678_autodetect_info },
{ .compatible = "sony,imx662", .data = &imx662_autodetect_info },
+ { .compatible = "sony,imx675", .data = &imx675_autodetect_info },
{ /* sentinel */ }
};
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-05 16:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-05 16:09 [PATCH RFC 0/4] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 1/4] media: i2c: imx678: Always program the sensor in window mode Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 2/4] media: i2c: imx678: Parameterise the configuration to allow for other models Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 3/4] media: i2c: imx678: Add imx662 support to the driver Dave Stevenson
2026-08-05 16:09 ` [PATCH RFC 4/4] media: i2c: imx678: Add imx675 " Dave Stevenson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox