* [PATCH v3 0/5] fix and improve for Hi846
@ 2026-05-11 9:09 Pengyu Luo
2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab,
Hans Verkuil, Sebastian Krzyszkowiak
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media,
Pengyu Luo
This series fixes errors blocking Hi846 driver function, fixes
link frequency and supports 6MP and 8MP modes on Hi846.
Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
---
Changes in v3:
- fix modes handling for different lane cases (Sebastian)
- fix header missing (the Media CI robot)
- Link to v2: https://lore.kernel.org/linux-media/20260501095433.1609309-1-mitltlatltl@gmail.com
Changes in v2:
- remove uncessary `else` (Sakari)
- fix link frequency (Sakari)
- correct link frequency for DT
- Link to v1: https://lore.kernel.org/linux-media/20260429070351.1307204-1-mitltlatltl@gmail.com
Pengyu Luo (5):
media: hi846: fix hi846_write_reg_16 handling
media: hi846: fix link frequency handling
media: hi846: fix modes handling for different lane cases
media: hi846: Add 6MP and 8MP modes support
arm64: dts: imx8mq-librem5: Correct link frequency list
.../boot/dts/freescale/imx8mq-librem5.dtsi | 2 +-
drivers/media/i2c/hi846.c | 251 +++++++++++++++---
2 files changed, 210 insertions(+), 43 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo @ 2026-05-11 9:09 ` Pengyu Luo 2026-05-11 9:36 ` Markus Elfring 2026-05-12 1:24 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo ` (3 subsequent siblings) 4 siblings, 2 replies; 13+ messages in thread From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Hans Verkuil, Sebastian Krzyszkowiak Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media, Pengyu Luo hi846_write_reg_16() does not clear a positive *err value on success. pm_runtime_get_if_in_use() returns a positive value when the device is already in use. When hi846_set_ctrl() passes &ret holding this positive value) to hi846_write_reg_16(), the function returns with ret as is, the positive value propagates back as a return code, which callers interpret as an error. Fix this by resetting *err to 0 only when it is positive. Fixes: 04fc06f6dc15 ("media: hi846: fix usage of pm_runtime_get_if_in_use()") Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com> --- drivers/media/i2c/hi846.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index a3f77b8434ca..7f069aca0fce 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1271,6 +1271,8 @@ static void hi846_write_reg_16(struct hi846 *hi846, u16 reg, u16 val, int *err) if (*err < 0) return; + *err = 0; + put_unaligned_be16(reg, buf); put_unaligned_be16(val, buf + 2); ret = i2c_master_send(client, buf, sizeof(buf)); -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling 2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo @ 2026-05-11 9:36 ` Markus Elfring 2026-05-12 1:24 ` sashiko-bot 1 sibling, 0 replies; 13+ messages in thread From: Markus Elfring @ 2026-05-11 9:36 UTC (permalink / raw) To: Pengyu Luo, linux-media, devicetree, linux-arm-kernel, imx, kernel, Conor Dooley, Fabio Estevam, Frank Li, Hans Verkuil, Krzysztof Kozlowski, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Rob Herring, Sakari Ailus, Sascha Hauer, Sebastian Krzyszkowiak Cc: LKML … > Fix this by resetting *err to 0 only when it is positive. How do you think about to handle return values by an adjusted interface? https://elixir.bootlin.com/linux/v7.1-rc2/source/drivers/media/i2c/hi846.c#L1265-L1282 Would a function signature (like the following) be nicer? static int hi846_write_reg_16(struct hi846 *hi846, u16 reg, u16 val); Regards, Markus ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling 2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo 2026-05-11 9:36 ` Markus Elfring @ 2026-05-12 1:24 ` sashiko-bot 1 sibling, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-05-12 1:24 UTC (permalink / raw) To: Pengyu Luo; +Cc: imx, robh, Frank.Li, conor+dt, krzk+dt, devicetree Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Unhandled negative error code from pm_runtime_get_if_in_use() causes silent failure of exposure/vblank controls and PM usage count underflow. -- commit 4a36c43ca7959e04a86201166380c7cb4acf35d4 Author: Pengyu Luo <mitltlatltl@gmail.com> media: hi846: fix hi846_write_reg_16 handling This commit fixes an issue where a positive return value from pm_runtime_get_if_in_use() propagates back to callers as an error. It resets the error pointer to 0 inside hi846_write_reg_16() before performing I2C operations. > diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c > index a3f77b8434ca7..7f069aca0fce5 100644 > --- a/drivers/media/i2c/hi846.c > +++ b/drivers/media/i2c/hi846.c > @@ -1271,6 +1271,8 @@ static void hi846_write_reg_16(struct hi846 *hi846, u16 reg, u16 val, int *err) > if (*err < 0) > return; While this patch handles the positive return code, does it miss the case where pm_runtime_get_if_in_use() returns a negative error code like -EINVAL? If runtime PM is disabled, pm_runtime_get_if_in_use() returns -EINVAL. In hi846_set_ctrl(), the error check misses this negative value: drivers/media/i2c/hi846.c:hi846_set_ctrl() { ... ret = pm_runtime_get_if_in_use(&client->dev); if (!ret || ret == -EAGAIN) return 0; ... } This allows the negative ret to propagate to hi846_write_reg_16(). Since *err is less than zero, the function returns immediately, silently skipping all hardware writes for V4L2_CID_EXPOSURE and V4L2_CID_VBLANK. Additionally, does this cause a PM usage count underflow? At the end of hi846_set_ctrl(), pm_runtime_put() is called unconditionally: drivers/media/i2c/hi846.c:hi846_set_ctrl() { ... pm_runtime_put(&client->dev); return ret; } Since the usage count was never incremented when pm_runtime_get_if_in_use() returned -EINVAL, this might trigger a usage count underflow warning. Could hi846_set_ctrl() explicitly isolate the PM status, set ret to 0 before making hardware writes, and only call pm_runtime_put() if the get function returned a value greater than 0? > + *err = 0; > + > put_unaligned_be16(reg, buf); > put_unaligned_be16(val, buf + 2); > ret = i2c_master_send(client, buf, sizeof(buf)); -- Sashiko AI review · https://sashiko.dev/#/patchset/20260511090924.269106-1-mitltlatltl@gmail.com?part=1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 2/5] media: hi846: fix link frequency handling 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo 2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo @ 2026-05-11 9:09 ` Pengyu Luo 2026-05-11 10:42 ` Markus Elfring 2026-05-12 1:56 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases Pengyu Luo ` (2 subsequent siblings) 4 siblings, 2 replies; 13+ messages in thread From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Hans Verkuil, Sebastian Krzyszkowiak Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media, Pengyu Luo link frequency is tied to PLL configuration, lane count, and external clock rate, so use runtime here instead of hardcoding for specific configuration. To implement this, this commit did 1. dropped exposed link freqs as a v4l2_ctrl, since we are runtime now, it is inconvenient and unnecessary to expose it, and hi846_set_ctrl has nothing to do with it. 2. attached pll_cfg_2lane to current mode, and use it with clock, lane count to calculate link frequency, we use 2-lane config as default, but we can halve it easily for 4-lane case. 3. dropped mclk clock rate check. Fixes: e8c0882685f9 ("media: i2c: add driver for the SK Hynix Hi-846 8M pixel camera") Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com> --- drivers/media/i2c/hi846.c | 75 ++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 7f069aca0fce..befd54553df2 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2021 Purism SPC -#include <linux/unaligned.h> +#include <linux/bitops.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> @@ -11,6 +11,7 @@ #include <linux/pm.h> #include <linux/property.h> #include <linux/regulator/consumer.h> +#include <linux/unaligned.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> @@ -219,8 +220,8 @@ struct hi846_mode { /* Horizontal timing size */ u32 llp; - /* Link frequency needed for this resolution */ - u8 link_freq_index; + /* PLL configuration for 4-lane link at this resolution */ + u16 pll_cfg_4lane; u16 fps; @@ -1040,13 +1041,6 @@ static const char * const hi846_test_pattern_menu[] = { "Resolution Pattern", }; -#define FREQ_INDEX_640 0 -#define FREQ_INDEX_1280 1 -static const s64 hi846_link_freqs[] = { - [FREQ_INDEX_640] = 80000000, - [FREQ_INDEX_1280] = 200000000, -}; - static const struct hi846_reg_list hi846_init_regs_list_2lane = { .num_of_regs = ARRAY_SIZE(hi846_init_2lane), .regs = hi846_init_2lane, @@ -1061,7 +1055,7 @@ static const struct hi846_mode supported_modes[] = { { .width = 640, .height = 480, - .link_freq_index = FREQ_INDEX_640, + .pll_cfg_4lane = 0x4924, /* HI846_REG_PLL_CFG_MIPI2_H */ .fps = 120, .frame_len = 631, .llp = HI846_LINE_LENGTH, @@ -1086,7 +1080,7 @@ static const struct hi846_mode supported_modes[] = { { .width = 1280, .height = 720, - .link_freq_index = FREQ_INDEX_1280, + .pll_cfg_4lane = 0x4924, /* HI846_REG_PLL_CFG_MIPI2_H */ .fps = 90, .frame_len = 842, .llp = HI846_LINE_LENGTH, @@ -1112,7 +1106,7 @@ static const struct hi846_mode supported_modes[] = { { .width = 1632, .height = 1224, - .link_freq_index = FREQ_INDEX_1280, + .pll_cfg_4lane = 0x4924, /* HI846_REG_PLL_CFG_MIPI2_H */ .fps = 30, .frame_len = 2526, .llp = HI846_LINE_LENGTH, @@ -1161,7 +1155,6 @@ struct hi846 { struct v4l2_ctrl_handler ctrl_handler; u8 nr_lanes; - struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *vblank; struct v4l2_ctrl *hblank; @@ -1192,21 +1185,37 @@ static const struct hi846_datafmt *hi846_find_datafmt(u32 code) return NULL; } -static inline u8 hi846_get_link_freq_index(struct hi846 *hi846) +static u64 +hi846_get_link_freq(struct hi846 *hi846, const struct hi846_mode *cur_mode) { - return hi846->cur_mode->link_freq_index; -} + u16 cfg = cur_mode->pll_cfg_4lane; + u64 mclk = clk_get_rate(hi846->clock); -static u64 hi846_get_link_freq(struct hi846 *hi846) -{ - u8 index = hi846_get_link_freq_index(hi846); + /* NOTE: 6, 7 actually map to 8, 10, but this won't be that big */ + u8 post_div1 = 1 + FIELD_GET(GENMASK(10, 8), cfg); + u8 post_div2 = 1 << FIELD_GET(GENMASK(12, 11), cfg); - return hi846_link_freqs[index]; + /* + * HI846_REG_PLL_CFG_MIPI1_H = 0x025a, it is fixed in listed modes + * [11:8]: 0x02 => pre_div = 3 + * [7:0]: 0x5a => multiplier = 90 + */ + u64 link_freq = mclk / 3 * 90 / post_div1 / post_div2; + /* + * for shared modes, since lane count is halved for 2-lane, then getting + * link_freq doubled to match the same data rate. Since 720x480 is + * 2-lane only(reg_list_4lane.num_of_regs == 0), no pll cfg for 4-lane, + * the pll cfg is for 2-lane, so use the cfg as is. + */ + if (2 == hi846->nr_lanes && cur_mode->reg_list_4lane.num_of_regs) + link_freq *= 2; + + return link_freq; } static u64 hi846_calc_pixel_rate(struct hi846 *hi846) { - u64 link_freq = hi846_get_link_freq(hi846); + u64 link_freq = hi846_get_link_freq(hi846, hi846->cur_mode); u64 pixel_rate = link_freq * 2 * hi846->nr_lanes; do_div(pixel_rate, HI846_RGB_DEPTH); @@ -1426,14 +1435,6 @@ static int hi846_init_controls(struct hi846 *hi846) ctrl_hdlr->lock = &hi846->mutex; - hi846->link_freq = - v4l2_ctrl_new_int_menu(ctrl_hdlr, &hi846_ctrl_ops, - V4L2_CID_LINK_FREQ, - ARRAY_SIZE(hi846_link_freqs) - 1, - 0, hi846_link_freqs); - if (hi846->link_freq) - hi846->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; - hi846->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops, V4L2_CID_PIXEL_RATE, 0, @@ -1503,10 +1504,10 @@ static int hi846_set_video_mode(struct hi846 *hi846, int fps) u64 frame_length; int ret = 0; int dummy_lines; - u64 link_freq = hi846_get_link_freq(hi846); + u64 link_freq = hi846_get_link_freq(hi846, hi846->cur_mode); dev_dbg(&client->dev, "%s: link freq: %llu\n", __func__, - hi846_get_link_freq(hi846)); + link_freq); do_div(link_freq, fps); frame_length = link_freq; @@ -1749,7 +1750,6 @@ static int hi846_set_format(struct v4l2_subdev *sd, mf->code = HI846_MEDIA_BUS_FORMAT; mf->field = V4L2_FIELD_NONE; - __v4l2_ctrl_s_ctrl(hi846->link_freq, hi846_get_link_freq_index(hi846)); __v4l2_ctrl_s_ctrl_int64(hi846->pixel_rate, hi846_calc_pixel_rate(hi846)); @@ -1950,16 +1950,17 @@ static int hi846_identify_module(struct hi846 *hi846) static s64 hi846_check_link_freqs(struct hi846 *hi846, struct v4l2_fwnode_endpoint *ep) { - const s64 *freqs = hi846_link_freqs; - int freqs_count = ARRAY_SIZE(hi846_link_freqs); + int freqs_count = ARRAY_SIZE(supported_modes); + u64 link_freq; int i, j; for (i = 0; i < freqs_count; i++) { + link_freq = hi846_get_link_freq(hi846, &supported_modes[i]); for (j = 0; j < ep->nr_of_link_frequencies; j++) - if (freqs[i] == ep->link_frequencies[j]) + if (link_freq == ep->link_frequencies[j]) break; if (j == ep->nr_of_link_frequencies) - return freqs[i]; + return link_freq; } return 0; -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/5] media: hi846: fix link frequency handling 2026-05-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo @ 2026-05-11 10:42 ` Markus Elfring 2026-05-12 1:56 ` sashiko-bot 1 sibling, 0 replies; 13+ messages in thread From: Markus Elfring @ 2026-05-11 10:42 UTC (permalink / raw) To: Pengyu Luo, linux-media, devicetree, linux-arm-kernel, imx, kernel, Conor Dooley, Fabio Estevam, Frank Li, Hans Verkuil, Krzysztof Kozlowski, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Rob Herring, Sakari Ailus, Sascha Hauer, Sebastian Krzyszkowiak Cc: LKML … > configuration. To implement this, this commit did … See also once more: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v7.1-rc3#n94 Regards, Markus ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/5] media: hi846: fix link frequency handling 2026-05-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo 2026-05-11 10:42 ` Markus Elfring @ 2026-05-12 1:56 ` sashiko-bot 1 sibling, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-05-12 1:56 UTC (permalink / raw) To: Pengyu Luo; +Cc: devicetree, imx, Frank.Li, robh, krzk+dt, conor+dt Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider: - [High] Uninitialized clock usage completely bypasses Device Tree link frequency validation. - [High] Precision loss in link frequency calculation falsely rejects valid Device Tree configurations. - [High] Native 64-bit integer division breaks compilation on 32-bit platforms. - [High] Dynamic doubling of `link_freq` for 2-lane modes introduces a severe framerate regression. - [Medium] Removal of `V4L2_CID_LINK_FREQ` control without a replacement violates V4L2 subsystem APIs. - [Low] Commit message falsely claims to have dropped the `mclk` clock rate check. -- commit 42a7ca82b9bb88db227afdc90d80e44ac458930b Author: Pengyu Luo <mitltlatltl@gmail.com> media: hi846: fix link frequency handling This commit modifies the link frequency handling in the hi846 driver to calculate it at runtime based on the PLL configuration, lane count, and external clock rate instead of using hardcoded values. It also removes the exposed link frequency control and attaches the configuration to the current mode. > 3. dropped mclk clock rate check. This isn't a bug, but the commit message states the mclk clock rate check was dropped. Looking at hi846_probe(), the code block checking if mclk_freq != 25000000 appears to have been left untouched by this patch. Is this description accurate? > diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c > index 7f069aca0fce5..befd54553df2e 100644 > --- a/drivers/media/i2c/hi846.c > +++ b/drivers/media/i2c/hi846.c [ ... ] > @@ -1192,21 +1185,37 @@ static const struct hi846_datafmt *hi846_find_datafmt(u32 code) > return NULL; > } > > -static inline u8 hi846_get_link_freq_index(struct hi846 *hi846) > +static u64 > +hi846_get_link_freq(struct hi846 *hi846, const struct hi846_mode *cur_mode) > { > - return hi846->cur_mode->link_freq_index; > -} > + u16 cfg = cur_mode->pll_cfg_4lane; > + u64 mclk = clk_get_rate(hi846->clock); Can mclk be zero here during probe? Looking at hi846_probe(), hi846_parse_dt() is called before hi846->clock is requested via devm_v4l2_sensor_clk_get(). When hi846_parse_dt() calls hi846_check_link_freqs(), hi846->clock will be NULL, causing clk_get_rate() to return 0. Will this result in a computed frequency of 0, which fails to match the DT endpoints and completely bypasses the device tree link frequency validation? > -static u64 hi846_get_link_freq(struct hi846 *hi846) > -{ > - u8 index = hi846_get_link_freq_index(hi846); > + /* NOTE: 6, 7 actually map to 8, 10, but this won't be that big */ > + u8 post_div1 = 1 + FIELD_GET(GENMASK(10, 8), cfg); > + u8 post_div2 = 1 << FIELD_GET(GENMASK(12, 11), cfg); > > - return hi846_link_freqs[index]; > + /* > + * HI846_REG_PLL_CFG_MIPI1_H = 0x025a, it is fixed in listed modes > + * [11:8]: 0x02 => pre_div = 3 > + * [7:0]: 0x5a => multiplier = 90 > + */ > + u64 link_freq = mclk / 3 * 90 / post_div1 / post_div2; Does this native 64-bit division break compilation on 32-bit platforms? Since mclk is a u64, using the native division operator / with 32-bit values will emit a call to __udivdi3, which is intentionally absent from the kernel libgcc. Should this use div_u64() or do_div() instead? Also, does the order of operations cause a precision loss that falsely rejects valid device tree configurations? For the expected 25MHz external clock, dividing by 3 first evaluates to 8333333, truncating the fractional part early. The final calculated frequency becomes 187499992 instead of 187500000. Since hi846_check_link_freqs() strictly checks for equality against the DT values, will this cause validation to fail and abort the probe? > + /* > + * for shared modes, since lane count is halved for 2-lane, then getting > + * link_freq doubled to match the same data rate. Since 720x480 is > + * 2-lane only(reg_list_4lane.num_of_regs == 0), no pll cfg for 4-lane, > + * the pll cfg is for 2-lane, so use the cfg as is. > + */ > + if (2 == hi846->nr_lanes && cur_mode->reg_list_4lane.num_of_regs) > + link_freq *= 2; > + > + return link_freq; > } [ ... ] > @@ -1426,14 +1435,6 @@ static int hi846_init_controls(struct hi846 *hi846) > > ctrl_hdlr->lock = &hi846->mutex; > > - hi846->link_freq = > - v4l2_ctrl_new_int_menu(ctrl_hdlr, &hi846_ctrl_ops, > - V4L2_CID_LINK_FREQ, > - ARRAY_SIZE(hi846_link_freqs) - 1, > - 0, hi846_link_freqs); > - if (hi846->link_freq) > - hi846->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; > - Does the removal of the V4L2_CID_LINK_FREQ control violate the V4L2 subsystem APIs? The V4L2 MIPI CSI-2 specification mandates that transmitter drivers report their link frequency so receiver PHYs can dynamically configure their timings. Since the .get_mbus_config pad operation isn't implemented as an alternative, does this force the V4L2 core to fall back to an inaccurate estimation based on pixel rate, potentially misconfiguring receiver hardware? [ ... ] > @@ -1503,10 +1504,10 @@ static int hi846_set_video_mode(struct hi846 *hi846, int fps) > u64 frame_length; > int ret = 0; > int dummy_lines; > - u64 link_freq = hi846_get_link_freq(hi846); > + u64 link_freq = hi846_get_link_freq(hi846, hi846->cur_mode); > > dev_dbg(&client->dev, "%s: link freq: %llu\n", __func__, > - hi846_get_link_freq(hi846)); > + link_freq); > > do_div(link_freq, fps); > frame_length = link_freq; Does this calculation introduce a framerate regression for 2-lane modes? Earlier in hi846_get_link_freq(), the link_freq is dynamically doubled for 2-lane modes to match the data rate. Because frame_length relies directly on link_freq here, the resulting frame_length programmed into the HI846_REG_FLL register will also be doubled. Since FLL dictates the duration of a frame, will doubling it halve the actual physical output framerate? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260511090924.269106-1-mitltlatltl@gmail.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo 2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo 2026-05-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo @ 2026-05-11 9:09 ` Pengyu Luo 2026-05-12 2:35 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support Pengyu Luo 2026-05-11 9:09 ` [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list Pengyu Luo 4 siblings, 1 reply; 13+ messages in thread From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Hans Verkuil, Sebastian Krzyszkowiak Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media, Pengyu Luo When using 4-lane, v4l2_find_nearest_size may return an unsupported mode, 640x480 mode, and it is set to the default mode. To fix it, specifying the supported modes for different lane cases, once the lane count is determined. Reported-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm> Closes: https://lore.kernel.org/linux-media/OmTXoHZJTSGePymL9I-1Cw@puri.sm/ Fixes: e8c0882685f9 ("media: i2c: add driver for the SK Hynix Hi-846 8M pixel camera") Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com> --- drivers/media/i2c/hi846.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index befd54553df2..9decfda74787 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1130,6 +1130,8 @@ static const struct hi846_mode supported_modes[] = { }, } }; +#define NUM_MODES_2LANE ARRAY_SIZE(supported_modes) +#define NUM_MODES_4LANE (ARRAY_SIZE(supported_modes) - 1) struct hi846_datafmt { u32 code; @@ -1162,6 +1164,8 @@ struct hi846 { struct mutex mutex; /* protect cur_mode, streaming and chip access */ const struct hi846_mode *cur_mode; + const struct hi846_mode *supported_modes; + int num_modes; bool streaming; }; @@ -1736,8 +1740,8 @@ static int hi846_set_format(struct v4l2_subdev *sd, hi846->fmt = fmt; hi846->cur_mode = - v4l2_find_nearest_size(supported_modes, - ARRAY_SIZE(supported_modes), + v4l2_find_nearest_size(hi846->supported_modes, + hi846->num_modes, width, height, mf->width, mf->height); dev_dbg(&client->dev, "%s: found mode: %dx%d\n", __func__, hi846->cur_mode->width, hi846->cur_mode->height); @@ -1821,8 +1825,11 @@ static int hi846_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_frame_size_enum *fse) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct hi846 *hi846 = to_hi846(sd); + const struct hi846_mode *supported_modes = hi846->supported_modes; + - if (fse->pad || fse->index >= ARRAY_SIZE(supported_modes)) + if (fse->pad || fse->index >= hi846->num_modes) return -EINVAL; if (fse->code != HI846_MEDIA_BUS_FORMAT) { @@ -1950,12 +1957,12 @@ static int hi846_identify_module(struct hi846 *hi846) static s64 hi846_check_link_freqs(struct hi846 *hi846, struct v4l2_fwnode_endpoint *ep) { - int freqs_count = ARRAY_SIZE(supported_modes); + int freqs_count = hi846->num_modes; u64 link_freq; int i, j; for (i = 0; i < freqs_count; i++) { - link_freq = hi846_get_link_freq(hi846, &supported_modes[i]); + link_freq = hi846_get_link_freq(hi846, &hi846->supported_modes[i]); for (j = 0; j < ep->nr_of_link_frequencies; j++) if (link_freq == ep->link_frequencies[j]) break; @@ -1999,6 +2006,13 @@ static int hi846_parse_dt(struct hi846 *hi846, struct device *dev) hi846->nr_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + hi846->supported_modes = supported_modes; + hi846->num_modes = NUM_MODES_2LANE; + if (hi846->nr_lanes == 4) { + hi846->supported_modes = supported_modes + 1; + hi846->num_modes = NUM_MODES_4LANE; + } + if (!bus_cfg.nr_of_link_frequencies) { dev_err(dev, "link-frequency property not found in DT\n"); ret = -EINVAL; @@ -2088,7 +2102,7 @@ static int hi846_probe(struct i2c_client *client) if (ret) goto err_power_off; - hi846->cur_mode = &supported_modes[0]; + hi846->cur_mode = &hi846->supported_modes[0]; ret = hi846_init_controls(hi846); if (ret) { -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases 2026-05-11 9:09 ` [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases Pengyu Luo @ 2026-05-12 2:35 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-05-12 2:35 UTC (permalink / raw) To: Pengyu Luo; +Cc: devicetree, conor+dt, krzk+dt, Frank.Li, robh, imx Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Low] The mode filtering logic for 4-lane setups relies on brittle array pointer arithmetic and implicitly assumes a specific global array ordering. - [Low] A local variable shadows a global variable in `hi846_enum_frame_size`. -- commit 809f6817858f4d273d756eeec1b017198bbcfa3a Author: Pengyu Luo <mitltlatltl@gmail.com> media: hi846: fix modes handling for different lane cases When using 4-lane, a 640x480 mode may be incorrectly set. This patch fixes the issue by specifying the supported modes and mode count dynamically based on the number of lanes. Closes: https://lore.kernel.org/linux-media/OmTXoHZJTSGePymL9I-1Cw@puri.sm/ Fixes: e8c0882685f9 ("media: i2c: add driver for the SK Hynix Hi-846 8M pixel camera") > diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c > index befd54553df2e..9decfda747876 100644 > --- a/drivers/media/i2c/hi846.c > +++ b/drivers/media/i2c/hi846.c [ ... ] > @@ -1821,8 +1825,11 @@ static int hi846_enum_frame_size(struct v4l2_subdev *sd, > struct v4l2_subdev_frame_size_enum *fse) > { > struct i2c_client *client = v4l2_get_subdevdata(sd); > + struct hi846 *hi846 = to_hi846(sd); > + const struct hi846_mode *supported_modes = hi846->supported_modes; This isn't a bug, but does declaring supported_modes here shadow the global static array supported_modes[] defined earlier in the file? [ ... ] > @@ -1999,6 +2006,13 @@ static int hi846_parse_dt(struct hi846 *hi846, struct device *dev) > > hi846->nr_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; > > + hi846->supported_modes = supported_modes; > + hi846->num_modes = NUM_MODES_2LANE; > + if (hi846->nr_lanes == 4) { > + hi846->supported_modes = supported_modes + 1; > + hi846->num_modes = NUM_MODES_4LANE; > + } Does this mode filtering logic rely on the exact ordering of the global supported_modes array? By advancing the array pointer by 1 and using a hardcoded mode count for the 4-lane setup, this implicitly assumes the only mode incompatible with 4-lane operation is located exactly at the first index. If another 2-lane-only mode is added or the modes are reordered in the future, could this silently corrupt the subdevice's mode list by misaligning the array bounds? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260511090924.269106-1-mitltlatltl@gmail.com?part=3 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo ` (2 preceding siblings ...) 2026-05-11 9:09 ` [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases Pengyu Luo @ 2026-05-11 9:09 ` Pengyu Luo 2026-05-12 3:22 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list Pengyu Luo 4 siblings, 1 reply; 13+ messages in thread From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Hans Verkuil, Sebastian Krzyszkowiak Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media, Pengyu Luo Hi846 is an 8MP sensor, but the upstream driver has only supported 2MP mode for years. This patch adds 6MP and 8MP modes to maximize sensor utilization. Note that these modes require 4-lane MIPI CSI-2, as the downstream driver only exposes 2MP, 6MP, and 8MP configurations in 4-lane operation on the target device. The register sequences are extracted from the downstream Windows driver. Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com> --- drivers/media/i2c/hi846.c | 154 +++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 9decfda74787..68302d0b7ca5 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1028,6 +1028,106 @@ static const struct hi846_reg mode_1632x1224_mipi_4lane[] = { {HI846_REG_TG_ENABLE, 0x0100}, }; +static const struct hi846_reg mode_3264x1836_config[] = { + {HI846_REG_MODE_SELECT, 0x0000}, + {HI846_REG_Y_ODD_INC_FOBP, 0x1111}, + {HI846_REG_Y_ODD_INC_VACT, 0x1111}, + {HI846_REG_Y_ADDR_START_VACT_H, 0x0172}, + {HI846_REG_Y_ADDR_END_VACT_H, 0x089d}, + {HI846_REG_UNKNOWN_005C, 0x2101}, + {HI846_REG_FLL, 0x09de}, + {HI846_REG_LLP, 0x0ed8}, + {HI846_REG_BINNING_MODE, 0x0022}, + {HI846_REG_HBIN_MODE, 0x0000}, + {HI846_REG_UNKNOWN_0A24, 0x0000}, + {HI846_REG_X_START_H, 0x0000}, + {HI846_REG_X_OUTPUT_SIZE_H, 0x0cc0}, + {HI846_REG_Y_OUTPUT_SIZE_H, 0x072c}, + {HI846_REG_EXPOSURE, 0x09d8}, + + /* For OTP */ + {HI846_REG_UNKNOWN_021C, 0x0001}, + {HI846_REG_UNKNOWN_021E, 0x0235}, + + {HI846_REG_ISP_EN_H, 0x014a}, + {HI846_REG_UNKNOWN_0418, 0x023e}, + {HI846_REG_UNKNOWN_0B02, 0xe04d}, + {HI846_REG_UNKNOWN_0B10, 0x6821}, + {HI846_REG_UNKNOWN_0B12, 0x0120}, + {HI846_REG_UNKNOWN_0B14, 0x0001}, + {HI846_REG_UNKNOWN_2008, 0x38fd}, + {HI846_REG_UNKNOWN_326E, 0x0000}, +}; + +static const struct hi846_reg mode_3264x1836_mipi_4lane[] = { + {HI846_REG_UNKNOWN_0900, 0x0300}, + {HI846_REG_MIPI_TX_OP_MODE, 0xc319}, + {HI846_REG_UNKNOWN_0914, 0xc109}, + {HI846_REG_TCLK_PREPARE, 0x061a}, + {HI846_REG_UNKNOWN_0918, 0x0407}, + {HI846_REG_THS_ZERO, 0x0a0b}, + {HI846_REG_TCLK_POST, 0x0e08}, + {HI846_REG_UNKNOWN_091E, 0x0a00}, + {HI846_REG_UNKNOWN_090C, 0x0427}, + {HI846_REG_UNKNOWN_090E, 0x0059}, + {HI846_REG_UNKNOWN_0954, 0x0089}, + {HI846_REG_UNKNOWN_0956, 0x0000}, + {HI846_REG_UNKNOWN_0958, 0xca80}, + {HI846_REG_UNKNOWN_095A, 0x9240}, + {HI846_REG_PLL_CFG_MIPI2_H, 0x4124}, + {HI846_REG_TG_ENABLE, 0x0100}, +}; + +static const struct hi846_reg mode_3264x2448_config[] = { + {HI846_REG_MODE_SELECT, 0x0000}, + {HI846_REG_Y_ODD_INC_FOBP, 0x1111}, + {HI846_REG_Y_ODD_INC_VACT, 0x1111}, + {HI846_REG_Y_ADDR_START_VACT_H, 0x0040}, + {HI846_REG_Y_ADDR_END_VACT_H, 0x09cf}, + {HI846_REG_UNKNOWN_005C, 0x2101}, + {HI846_REG_FLL, 0x09de}, + {HI846_REG_LLP, 0x0ed8}, + {HI846_REG_BINNING_MODE, 0x0022}, + {HI846_REG_HBIN_MODE, 0x0000}, + {HI846_REG_UNKNOWN_0A24, 0x0000}, + {HI846_REG_X_START_H, 0x0000}, + {HI846_REG_X_OUTPUT_SIZE_H, 0x0cc0}, + {HI846_REG_Y_OUTPUT_SIZE_H, 0x0990}, + {HI846_REG_EXPOSURE, 0x09d8}, + + /* For OTP */ + {HI846_REG_UNKNOWN_021C, 0x0001}, + {HI846_REG_UNKNOWN_021E, 0x0235}, + + {HI846_REG_ISP_EN_H, 0x014a}, + {HI846_REG_UNKNOWN_0418, 0x0000}, + {HI846_REG_UNKNOWN_0B02, 0xe04d}, + {HI846_REG_UNKNOWN_0B10, 0x6821}, + {HI846_REG_UNKNOWN_0B12, 0x0120}, + {HI846_REG_UNKNOWN_0B14, 0x0001}, + {HI846_REG_UNKNOWN_2008, 0x38fd}, + {HI846_REG_UNKNOWN_326E, 0x0000}, +}; + +static const struct hi846_reg mode_3264x2448_mipi_4lane[] = { + {HI846_REG_UNKNOWN_0900, 0x0300}, + {HI846_REG_MIPI_TX_OP_MODE, 0xc319}, + {HI846_REG_UNKNOWN_0914, 0xc109}, + {HI846_REG_TCLK_PREPARE, 0x061a}, + {HI846_REG_UNKNOWN_0918, 0x0407}, + {HI846_REG_THS_ZERO, 0x0a0b}, + {HI846_REG_TCLK_POST, 0x0e08}, + {HI846_REG_UNKNOWN_091E, 0x0a00}, + {HI846_REG_UNKNOWN_090C, 0x0427}, + {HI846_REG_UNKNOWN_090E, 0x0059}, + {HI846_REG_UNKNOWN_0954, 0x0089}, + {HI846_REG_UNKNOWN_0956, 0x0000}, + {HI846_REG_UNKNOWN_0958, 0xca80}, + {HI846_REG_UNKNOWN_095A, 0x9240}, + {HI846_REG_PLL_CFG_MIPI2_H, 0x4124}, + {HI846_REG_TG_ENABLE, 0x0100}, +}; + static const char * const hi846_test_pattern_menu[] = { "Disabled", "Solid Colour", @@ -1128,9 +1228,59 @@ static const struct hi846_mode supported_modes[] = { .width = 1632 * 2, .height = 1224 * 2, }, - } + }, + { + .width = 3264, + .height = 1836, + .pll_cfg_4lane = 0x4124, /* HI846_REG_PLL_CFG_MIPI2_H */ + .fps = 30, + .frame_len = 2526, + .llp = HI846_LINE_LENGTH, + .reg_list_config = { + .num_of_regs = ARRAY_SIZE(mode_3264x1836_config), + .regs = mode_3264x1836_config, + }, + .reg_list_2lane = { + .num_of_regs = 0, + }, + .reg_list_4lane = { + .num_of_regs = ARRAY_SIZE(mode_3264x1836_mipi_4lane), + .regs = mode_3264x1836_mipi_4lane, + }, + .crop = { + .left = 0x46, + .top = 0x172, + .width = 3264, + .height = 1836, + }, + }, + { + .width = 3264, + .height = 2448, + .pll_cfg_4lane = 0x4124, /* HI846_REG_PLL_CFG_MIPI2_H */ + .fps = 30, + .frame_len = 2526, + .llp = HI846_LINE_LENGTH, + .reg_list_config = { + .num_of_regs = ARRAY_SIZE(mode_3264x2448_config), + .regs = mode_3264x2448_config, + }, + .reg_list_2lane = { + .num_of_regs = 0, + }, + .reg_list_4lane = { + .num_of_regs = ARRAY_SIZE(mode_3264x2448_mipi_4lane), + .regs = mode_3264x2448_mipi_4lane, + }, + .crop = { + .left = 0x46, + .top = 0x40, + .width = 3264, + .height = 2448, + }, + }, }; -#define NUM_MODES_2LANE ARRAY_SIZE(supported_modes) +#define NUM_MODES_2LANE (ARRAY_SIZE(supported_modes) - 2) #define NUM_MODES_4LANE (ARRAY_SIZE(supported_modes) - 1) struct hi846_datafmt { -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support 2026-05-11 9:09 ` [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support Pengyu Luo @ 2026-05-12 3:22 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-05-12 3:22 UTC (permalink / raw) To: Pengyu Luo; +Cc: krzk+dt, robh, Frank.Li, conor+dt, devicetree, imx Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Mismatch between hardware registers and V4L2 Selection API bounds for new 6MP/8MP modes. - [Low] Brittle array size math for mode iteration depending on hardcoded array layout. -- commit 6d3bd49fa87b78bd49f2c7ba2cecba16a37a6a83 Author: Pengyu Luo <mitltlatltl@gmail.com> media: hi846: Add 6MP and 8MP modes support This patch adds 6MP and 8MP modes for the hi846 sensor using 4-lane MIPI CSI-2. It extracts register sequences from a downstream driver to maximize sensor utilization. > diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c > index 9decfda747876..68302d0b7ca5f 100644 > --- a/drivers/media/i2c/hi846.c > +++ b/drivers/media/i2c/hi846.c [ ... ] > @@ -1028,6 +1028,106 @@ static const struct hi846_reg mode_1632x1224_mipi_4lane[] = { > {HI846_REG_TG_ENABLE, 0x0100}, > }; > > +static const struct hi846_reg mode_3264x1836_config[] = { > + {HI846_REG_MODE_SELECT, 0x0000}, > + {HI846_REG_Y_ODD_INC_FOBP, 0x1111}, > + {HI846_REG_Y_ODD_INC_VACT, 0x1111}, > + {HI846_REG_Y_ADDR_START_VACT_H, 0x0172}, > + {HI846_REG_Y_ADDR_END_VACT_H, 0x089d}, > + {HI846_REG_UNKNOWN_005C, 0x2101}, > + {HI846_REG_FLL, 0x09de}, > + {HI846_REG_LLP, 0x0ed8}, > + {HI846_REG_BINNING_MODE, 0x0022}, > + {HI846_REG_HBIN_MODE, 0x0000}, > + {HI846_REG_UNKNOWN_0A24, 0x0000}, > + {HI846_REG_X_START_H, 0x0000}, [ ... ] > @@ -1128,9 +1228,59 @@ static const struct hi846_mode supported_modes[] = { > .width = 1632 * 2, > .height = 1224 * 2, > }, > - } > + }, > + { > + .width = 3264, > + .height = 1836, [ ... ] > + .crop = { > + .left = 0x46, > + .top = 0x172, > + .width = 3264, > + .height = 1836, > + }, Does this crop configuration exceed the V4L2 Selection API bounds? In hi846_get_selection(), V4L2_SEL_TGT_CROP_BOUNDS and V4L2_SEL_TGT_NATIVE_SIZE are hardcoded to width 3264 and height 2448 with left and top set to 0. Here, crop.left is 0x46 and crop.width is 3264, resulting in a right bound of 3334, which exceeds the native size. Also, there appears to be a contradiction in the hardware registers. The crop.left is set to 0x46 here, but HI846_REG_X_START_H is explicitly set to 0x0000 in the mode_3264x1836_config array. Should crop.left be 0x00, or do the V4L2 hardware bounds and X_START_H need to be updated to match the physical pixel array? > + }, > + { > + .width = 3264, > + .height = 2448, [ ... ] > + .crop = { > + .left = 0x46, > + .top = 0x40, > + .width = 3264, > + .height = 2448, > + }, > + }, > }; > -#define NUM_MODES_2LANE ARRAY_SIZE(supported_modes) > +#define NUM_MODES_2LANE (ARRAY_SIZE(supported_modes) - 2) Is it safe to rely on this array index arithmetic for mode support? This implicitly assumes the supported_modes array is strictly ordered so that the last two modes lack 2-lane support. If modes are added, removed, or reordered in the future, these macros could silently produce incorrect array boundaries. Would it be safer to dynamically filter modes based on reg_list_2lane.num_of_regs instead? > #define NUM_MODES_4LANE (ARRAY_SIZE(supported_modes) - 1) -- Sashiko AI review · https://sashiko.dev/#/patchset/20260511090924.269106-1-mitltlatltl@gmail.com?part=4 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo ` (3 preceding siblings ...) 2026-05-11 9:09 ` [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support Pengyu Luo @ 2026-05-11 9:09 ` Pengyu Luo 2026-05-12 3:48 ` sashiko-bot 4 siblings, 1 reply; 13+ messages in thread From: Pengyu Luo @ 2026-05-11 9:09 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Sakari Ailus, Martin Kepplinger-Novakovic, Mauro Carvalho Chehab, Hans Verkuil, Sebastian Krzyszkowiak Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux-media, Pengyu Luo According to the hi846 datasheet and the register lists, they are mclk / prediv * multiplier / post_div1 / post_div2 = 25Mhz / 3 * 90 / 1 / {1,2} = 187.5Mhz, 375Mhz Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com> --- arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi index f5d529c5baf3..cc5604172192 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi @@ -1122,7 +1122,7 @@ port { camera1_ep: endpoint { data-lanes = <1 2>; link-frequencies = /bits/ 64 - <80000000 200000000 300000000>; + <187500000 375000000>; remote-endpoint = <&mipi1_sensor_ep>; }; }; -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list 2026-05-11 9:09 ` [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list Pengyu Luo @ 2026-05-12 3:48 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-05-12 3:48 UTC (permalink / raw) To: Pengyu Luo; +Cc: robh, Frank.Li, krzk+dt, devicetree, conor+dt, imx Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] Strict equality check failure due to integer truncation precision loss - [Medium] Device Tree ABI / Backward Compatibility break - [Low] Mathematical error in commit message derivation -- commit e44214657fa2d9bae2190f57c8fa133a21051c14 Author: Pengyu Luo <mitltlatltl@gmail.com> arm64: dts: imx8mq-librem5: Correct link frequency list This commit updates the device tree binding for the imx8mq-librem5 board to correct the supported link frequencies for the hi846 camera sensor. > According to the hi846 datasheet and the register lists, they are > > mclk / prediv * multiplier / post_div1 / post_div2 = > 25Mhz / 3 * 90 / 1 / {1,2} = 187.5Mhz, 375Mhz Is this calculation completely accurate? Mathematically, 25 / 3 * 90 / 1 / 1 equals 750 MHz, not 375 MHz. To achieve 187.5 MHz and 375 MHz, does the post_div1 divisor need to be 2 instead of 1? > diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi > index eee390c272105..959a5c8dcd0d3 100644 > --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi > +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi [ ... ] > @@ -1122,7 +1122,7 @@ port { > camera1_ep: endpoint { > data-lanes = <1 2>; > link-frequencies = /bits/ 64 > - <80000000 200000000 300000000>; > + <187500000 375000000>; Could this exact value specification cause the driver probe to fail due to integer truncation? The hi846 driver calculates the expected link frequency using the formula mclk / 3 * 90 / post_div1 / post_div2. Because mclk is exactly 25,000,000, the C integer division 25000000 / 3 evaluates to 8,333,333. After the subsequent multiplications and divisions, the evaluated link frequencies are 187,499,992 Hz and 374,999,984 Hz. Since hi846_check_link_freqs() performs a strict equality check against the device tree values, this mismatch could cause it to reject the frequencies and fail probing. Additionally, does completely removing the old values break backward compatibility for older kernels? Prior to the driver update that dynamically calculates link frequencies, the hi846 driver strictly required the hardcoded frequencies 80000000 and 200000000 to be present in the device tree. Appending the new values while keeping the old ones might preserve backward compatibility. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260511090924.269106-1-mitltlatltl@gmail.com?part=5 ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-12 3:48 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-11 9:09 [PATCH v3 0/5] fix and improve for Hi846 Pengyu Luo 2026-05-11 9:09 ` [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling Pengyu Luo 2026-05-11 9:36 ` Markus Elfring 2026-05-12 1:24 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo 2026-05-11 10:42 ` Markus Elfring 2026-05-12 1:56 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases Pengyu Luo 2026-05-12 2:35 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 4/5] media: hi846: Add 6MP and 8MP modes support Pengyu Luo 2026-05-12 3:22 ` sashiko-bot 2026-05-11 9:09 ` [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list Pengyu Luo 2026-05-12 3:48 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox