* [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; 8+ 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] 8+ 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-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ 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] 8+ 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-11 9:09 ` [PATCH v3 3/5] media: hi846: fix modes handling for different lane cases Pengyu Luo
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ 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] 8+ 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-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, 0 replies; 8+ 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] 8+ 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-11 9:09 ` [PATCH v3 5/5] arm64: dts: imx8mq-librem5: Correct link frequency list Pengyu Luo
4 siblings, 0 replies; 8+ 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] 8+ 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
4 siblings, 0 replies; 8+ 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] 8+ 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
0 siblings, 0 replies; 8+ 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] 8+ 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
0 siblings, 0 replies; 8+ 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] 8+ messages in thread
end of thread, other threads:[~2026-05-11 10:42 UTC | newest]
Thread overview: 8+ 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-11 9:09 ` [PATCH v3 2/5] media: hi846: fix link frequency handling Pengyu Luo
2026-05-11 10:42 ` Markus Elfring
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 ` [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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox