From: Sakari Ailus <sakari.ailus@linux.intel.com>
To: Dave Stevenson <dave.stevenson@raspberrypi.com>
Cc: Jai Luthra <jai.luthra@ideasonboard.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Alexander Shiyan <eagle.alexander923@gmail.com>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH v4 04/16] media: sony-starvis2: Parameterise the configuration to allow for other models
Date: Tue, 20 Oct 2026 12:34:50 +0300 [thread overview]
Message-ID: <atc1us1fj6MN6UfF@kekkonen.localdomain> (raw)
In-Reply-To: <20261015-media-starvis2-v4-4-75fcdb4163f3@raspberrypi.com>
Hi Dave,
On Thu, Oct 15, 2026 at 04:57:30PM +0100, Dave Stevenson wrote:
> 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/sony-starvis2.c | 170 ++++++++++++++++++++++++--------------
> 1 file changed, 109 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/media/i2c/sony-starvis2.c b/drivers/media/i2c/sony-starvis2.c
> index c4f590c489d9..189caac78066 100644
> --- a/drivers/media/i2c/sony-starvis2.c
> +++ b/drivers/media/i2c/sony-starvis2.c
> @@ -51,17 +51,9 @@
> /* Lane Count */
> #define STARVIS2_REG_LANEMODE CCI_REG8(0x3040)
>
> -/*
> - * The internal readout clock runs at 74.25 MHz. In one cycle the AD reads 8
> - * pixels, thus giving us a rate of 74.25 * 8 = 594 MPix/s
> - */
> -#define IMX678_PIXEL_RATE 594000000
> -#define IMX678_PIX_PER_CLK 8
> -
> /* VMAX - Frame Length in Lines */
> #define STARVIS2_REG_VMAX CCI_REG24_LE(0x3028)
> #define STARVIS2_VMAX_MAX 0xfffff
> -#define IMX678_VMAX_DEFAULT 2250
>
> /* HMAX - Line Length in Cycles (8 Pixels) */
> #define STARVIS2_REG_HMAX CCI_REG16_LE(0x302c)
> @@ -102,8 +94,6 @@
> /* Sensor Identification */
> #define STARVIS2_REG_MONOCHROME CCI_REG8(0x4d18)
> #define STARVIS2_TYPE BIT(0)
> -#define IMX678_REG_MODULE_ID CCI_REG16_LE(0x4d1c)
> -#define IMX678_ID 0x02a6
> #define STARVIS2_MODULE_ID_DELAY 80000
>
> /* Common configuration registers */
> @@ -153,32 +143,11 @@
> /* Subdev pads */
> #define STARVIS2_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 starvis2_type {
> STARVIS2_COLOR = 0,
> STARVIS2_MONOCHROME = 1,
> };
>
> -struct starvis2_model_info {
> - enum starvis2_type type;
> - const u32 *codes;
> - unsigned int num_codes;
> -};
> -
> enum starvis2_lanemode {
> STARVIS2_LANEMODE_2L = 1,
> STARVIS2_LANEMODE_4L = 3,
> @@ -207,7 +176,7 @@ static const u64 link_freqs[] = {
> [STARVIS2_LINK_FREQ_1188MHZ] = 1188000000,
> };
>
> -static const u16 min_hmax_4lane[] = {
> +static const u16 imx678_min_hmax_4lane[] = {
> [STARVIS2_LINK_FREQ_297MHZ] = 1584,
> [STARVIS2_LINK_FREQ_360MHZ] = 1320,
> [STARVIS2_LINK_FREQ_445MHZ] = 1100,
> @@ -267,7 +236,7 @@ static const int starvis2_tpg_val[] = {
> };
>
> /* Common configuration */
> -static const struct cci_reg_sequence common_regs[] = {
> +static const struct cci_reg_sequence imx678_common_regs[] = {
> { STARVIS2_REG_THIN_V_EN, 0x00 },
> { STARVIS2_REG_VCMODE, 0x01 },
> { CCI_REG8(0x306b), 0x00 },
> @@ -650,16 +619,74 @@ static const u32 codes_monochrome[] = {
> MEDIA_BUS_FMT_Y12_1X12,
> };
>
> +struct starvis2_variant {
> + const char *name;
> + u32 id_reg;
> + u32 id_mask;
> + 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;
> +};
> +
> +static const struct starvis2_variant imx678_variant_def = {
> + .name = "imx678",
> + .id_reg = CCI_REG16_LE(0x4d1c),
> + .id_mask = 0x3ff,
> + .id_value = 0x2a6,
> + .native_area = {
> + .top = 0,
> + .left = 0,
> + .width = 3857,
> + .height = 2201,
> + },
> + .active_area = {
> + .top = 20,
> + .left = 0,
> + .width = 3856,
> + .height = 2180,
> + },
> + .pixel_rate = 594000000,
> + .pix_per_clk = 8,
> + .common_regs = imx678_common_regs,
> + .num_common_regs = ARRAY_SIZE(imx678_common_regs),
> + .vmax_default = 2250,
> + .hmax_min = imx678_min_hmax_4lane,
> +};
> +
> +struct starvis2_model_info {
> + enum starvis2_type type;
> + const u32 *codes;
> + unsigned int num_codes;
> + const struct starvis2_variant *variant;
> +
> + const struct starvis2_model_info *auto_detect_colour;
> + const struct starvis2_model_info *auto_detect_mono;
> +};
> +
> static const struct starvis2_model_info imx678_aaqr_info = {
> .type = STARVIS2_COLOR,
> .codes = codes_bayer,
> .num_codes = ARRAY_SIZE(codes_bayer),
> + .variant = &imx678_variant_def,
> };
>
> static const struct starvis2_model_info imx678_aamr_info = {
> .type = STARVIS2_MONOCHROME,
> .codes = codes_monochrome,
> .num_codes = ARRAY_SIZE(codes_monochrome),
> + .variant = &imx678_variant_def,
> +};
> +
> +static const struct starvis2_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 starvis2_supply_name[] = {
> @@ -674,6 +701,7 @@ struct starvis2 {
> struct regmap *cci;
>
> const struct starvis2_model_info *info;
> + const struct starvis2_variant *variant;
>
> struct clk *xclk;
> u32 xclk_freq;
> @@ -770,7 +798,8 @@ static int starvis2_set_ctrl(struct v4l2_ctrl *ctrl)
> cci_write(starvis2->cci, STARVIS2_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) /
> + starvis2->variant->pix_per_clk;
This seems to be a pre-existing bug but it'd be nice to fix (and backport)
this before this set -- the control value is divided here by 8 but the
control's step is still 1. The step should reflect the granularity here.
>
> cci_write(starvis2->cci, STARVIS2_REG_HMAX, hmax, &ret);
> break;
> @@ -851,18 +880,20 @@ static int starvis2_get_selection(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *sd_state,
> struct v4l2_subdev_selection *sel)
> {
> + struct starvis2 *starvis2 = to_starvis2(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 = starvis2->variant->native_area;
> return 0;
>
> case V4L2_SEL_TGT_CROP_DEFAULT:
> case V4L2_SEL_TGT_CROP_BOUNDS:
> - sel->r = imx678_active_area;
> + sel->r = starvis2->variant->active_area;
> return 0;
> }
>
> @@ -877,12 +908,12 @@ static int starvis2_init_state(struct v4l2_subdev *sd,
> struct v4l2_rect *crop;
>
> crop = v4l2_subdev_state_get_crop(state, STARVIS2_SOURCE_PAD);
> - *crop = imx678_active_area;
> + *crop = starvis2->variant->active_area;
>
> format = v4l2_subdev_state_get_format(state, STARVIS2_SOURCE_PAD);
> format->code = starvis2_default_mbus_code(starvis2);
> - format->width = imx678_active_area.width;
> - format->height = imx678_active_area.height;
> + format->width = starvis2->variant->active_area.width;
> + format->height = starvis2->variant->active_area.height;
> format->field = V4L2_FIELD_NONE;
> format->colorspace = V4L2_COLORSPACE_RAW;
> format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> @@ -896,8 +927,12 @@ static int starvis2_write_common(struct starvis2 *starvis2)
> {
> int ret = 0;
>
> - cci_multi_reg_write(starvis2->cci, common_regs, ARRAY_SIZE(common_regs),
> - &ret);
> + if (!starvis2->variant)
> + /* Powered on during probe to do detection. Variant unknown. */
> + return 0;
> +
> + cci_multi_reg_write(starvis2->cci, starvis2->variant->common_regs,
> + starvis2->variant->num_common_regs, &ret);
>
> cci_write(starvis2->cci, STARVIS2_REG_INCK_SEL, starvis2->inck_sel_val,
> &ret);
> @@ -923,10 +958,10 @@ static int starvis2_program_window(struct starvis2 *starvis2,
> cci_write(starvis2->cci, STARVIS2_REG_ADDMODE, 0x00, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_WINMODE, 0x04, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_PIX_HST,
> - crop->left - imx678_active_area.left, &ret);
> + crop->left - starvis2->variant->active_area.left, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_PIX_HWIDTH, crop->width, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_PIX_VST,
> - crop->top - imx678_active_area.top, &ret);
> + crop->top - starvis2->variant->active_area.top, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_PIX_VWIDTH, crop->height, &ret);
> cci_write(starvis2->cci, STARVIS2_REG_ADBIT, 0x01, &ret);
>
> @@ -1080,11 +1115,16 @@ static int starvis2_identify_model(struct starvis2 *starvis2)
> {
> struct i2c_client *client = v4l2_get_subdevdata(&starvis2->sd);
> const struct starvis2_model_info *info;
> + const struct starvis2_variant *variant;
> enum starvis2_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
> @@ -1093,7 +1133,7 @@ static int starvis2_identify_model(struct starvis2 *starvis2)
> cci_write(starvis2->cci, STARVIS2_REG_MODE_SELECT, 0, &ret);
> fsleep(STARVIS2_MODULE_ID_DELAY);
>
> - cci_read(starvis2->cci, IMX678_REG_MODULE_ID, &val, &ret);
> + cci_read(starvis2->cci, variant->id_reg, &val, &ret);
>
> if (ret) {
> dev_err(&client->dev,
> @@ -1101,9 +1141,10 @@ static int starvis2_identify_model(struct starvis2 *starvis2)
> return ret;
> }
>
> - if (val != IMX678_ID) {
> - dev_err(&client->dev,
> - "Chip ID mismatch: %x!=%llx\n", IMX678_ID, val);
> + val &= variant->id_mask;
> + if (val != variant->id_value) {
> + dev_err(&client->dev, "Chip ID mismatch: %x!=%llx\n",
> + variant->id_value, val);
> return -ENXIO;
> }
>
> @@ -1118,7 +1159,7 @@ static int starvis2_identify_model(struct starvis2 *starvis2)
> detected = val & STARVIS2_TYPE;
>
> /* Prefer to use sensor type specified in device tree */
> - if (info) {
> + if (info->codes) {
> starvis2->info = info;
> if (detected != info->type)
> dev_err(&client->dev,
> @@ -1127,11 +1168,12 @@ static int starvis2_identify_model(struct starvis2 *starvis2)
> info->type == STARVIS2_COLOR ? "color" : "mono");
> } else {
> starvis2->info = detected == STARVIS2_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 == STARVIS2_MONOCHROME ? "mono" : "color");
> }
> + starvis2->variant = starvis2->info->variant;
>
> return 0;
> }
> @@ -1162,7 +1204,7 @@ static int starvis2_init_controls(struct starvis2 *starvis2)
> {
> struct v4l2_ctrl_handler *ctrl_hdlr;
> const u32 hmax_4lane =
> - min_hmax_4lane[__fls(starvis2->link_freq_bitmap)];
> + starvis2->variant->hmax_min[__fls(starvis2->link_freq_bitmap)];
> const u32 lane_scale =
> starvis2->lane_mode == STARVIS2_LANEMODE_2L ? 2 : 1;
> struct i2c_client *client = v4l2_get_subdevdata(&starvis2->sd);
> @@ -1181,13 +1223,14 @@ static int starvis2_init_controls(struct starvis2 *starvis2)
> if (ret)
> return ret;
>
> - starvis2->vmax = IMX678_VMAX_DEFAULT;
> + starvis2->vmax = starvis2->variant->vmax_default;
> hmax = hmax_4lane * lane_scale;
>
> /* PIXEL_RATE is fixed and read-only */
> v4l2_ctrl_new_std(ctrl_hdlr, &starvis2_ctrl_ops, V4L2_CID_PIXEL_RATE,
> - IMX678_PIXEL_RATE, IMX678_PIXEL_RATE, 1,
> - IMX678_PIXEL_RATE);
> + starvis2->variant->pixel_rate,
> + starvis2->variant->pixel_rate, 1,
> + starvis2->variant->pixel_rate);
>
> /* LINK_FREQ is also read only */
> link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &starvis2_ctrl_ops,
> @@ -1199,23 +1242,25 @@ static int starvis2_init_controls(struct starvis2 *starvis2)
> if (link_freq)
> link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
>
> - vblank = starvis2->vmax - imx678_active_area.height;
> - max_vblank = STARVIS2_VMAX_MAX - imx678_active_area.height;
> + vblank = starvis2->vmax - starvis2->variant->active_area.height;
> + max_vblank = STARVIS2_VMAX_MAX - starvis2->variant->active_area.height;
> starvis2->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &starvis2_ctrl_ops,
> V4L2_CID_VBLANK, vblank, max_vblank,
> 2, vblank);
>
> - hblank = hmax * IMX678_PIX_PER_CLK - imx678_active_area.width;
> - max_hblank = STARVIS2_HMAX_MAX * IMX678_PIX_PER_CLK -
> - imx678_active_area.width;
> + hblank = hmax * starvis2->variant->pix_per_clk -
> + starvis2->variant->active_area.width;
> + max_hblank = STARVIS2_HMAX_MAX * starvis2->variant->pix_per_clk -
> + starvis2->variant->active_area.width;
> starvis2->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &starvis2_ctrl_ops,
> V4L2_CID_HBLANK, hblank, max_hblank,
> - IMX678_PIX_PER_CLK, hblank);
> + starvis2->variant->pix_per_clk,
> + hblank);
>
> starvis2->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &starvis2_ctrl_ops,
> V4L2_CID_EXPOSURE,
> STARVIS2_EXPOSURE_MIN,
> - IMX678_VMAX_DEFAULT -
> + starvis2->variant->vmax_default -
> STARVIS2_SHR_MIN,
> STARVIS2_EXPOSURE_STEP,
> STARVIS2_EXPOSURE_DEFAULT);
> @@ -1356,6 +1401,9 @@ static int starvis2_probe(struct i2c_client *client)
> if (ret)
> goto error_power_off;
>
> + v4l2_i2c_subdev_set_name(&starvis2->sd, client, starvis2->variant->name,
> + NULL);
> +
> pm_runtime_set_active(dev);
> pm_runtime_enable(dev);
>
> @@ -1436,7 +1484,7 @@ static const struct of_device_id starvis2_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 */ }
> };
>
>
--
Kind regards,
Sakari Ailus
next prev parent reply other threads:[~2026-10-20 9:34 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 15:57 [PATCH v4 00/16] Update imx678 to act as a common Sony Starvis 2 driver Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 01/16] media: imx678: Rework into generic Starvis 2 sensor driver Dave Stevenson
2026-10-20 9:12 ` Sakari Ailus
2026-10-15 15:57 ` [PATCH v4 02/16] media: sony-starvis2: Reorder link frequencies to remove lookup Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 03/16] media: sony-starvis2: Always program the sensor in window mode Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 04/16] media: sony-starvis2: Parameterise the configuration to allow for other models Dave Stevenson
2026-10-20 9:34 ` Sakari Ailus [this message]
2026-10-15 15:57 ` [PATCH v4 05/16] media: sony-starvis2: Rework 2 lane support for higher link freqs Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 06/16] media: sony-starvis2: Allow runtime control of link frequency Dave Stevenson
2026-10-20 9:59 ` Sakari Ailus
2026-10-15 15:57 ` [PATCH v4 07/16] media: sony-starvis2: Correct the exposure range Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 08/16] media: sony-starvis2: Put module into standby after identify Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 09/16] media: sony-starvis2: Use pm_runtime_autosuspend Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 10/16] media: dt-bindings: sony,imx678: Add other Starvis 2 family members Dave Stevenson
2026-10-15 20:17 ` Rob Herring
2026-10-20 10:07 ` Sakari Ailus
2026-10-20 14:39 ` Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 11/16] media: sony-starvis2: Add support for IMX662 Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 12/16] media: sony-starvis2: Add support for IMX675 Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 13/16] media: sony-starvis2: Add support for IMX832 Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 14/16] media: sony-starvis2: Only update bits for window mode Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 15/16] media: sony-starvis2: Parameterise exposure min and step Dave Stevenson
2026-10-15 15:57 ` [PATCH v4 16/16] media: sony-starvis2: Add support for IMX585 Dave Stevenson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=atc1us1fj6MN6UfF@kekkonen.localdomain \
--to=sakari.ailus@linux.intel.com \
--cc=conor+dt@kernel.org \
--cc=dave.stevenson@raspberrypi.com \
--cc=devicetree@vger.kernel.org \
--cc=eagle.alexander923@gmail.com \
--cc=jai.luthra@ideasonboard.com \
--cc=krzk+dt@kernel.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®