1- From 29c0552aaf01373b5177e3d7be4fcf3aad217d94 Mon Sep 17 00:00:00 2001
1+ From 63bf100fd5dab0e5b2fca23463bb9ac901159fe2 Mon Sep 17 00:00:00 2001
22From: ejgoldik <ehud.joseph.goldik@realsenseai.com>
33Date: Wed, 11 Feb 2026 01:29:44 +0200
44Subject: [PATCH] Adding max96712 support for D4xx
55
66Signed-off-by: ejgoldik <ehud.joseph.goldik@realsenseai.com>
77---
8- drivers/media/i2c/max96712.c | 328 ++++++++++++++++++++++++++++++++++-
9- 1 file changed, 325 insertions(+), 3 deletions(-)
8+ drivers/media/i2c/max96712.c | 337 ++++++++++++++++++++++++++++++++++-
9+ 1 file changed, 334 insertions(+), 3 deletions(-)
1010
1111diff --git a/drivers/media/i2c/max96712.c b/drivers/media/i2c/max96712.c
12- index 8081385f0..6d451c034 100644
12+ index 8081385f0..0caedb1ae 100644
1313--- a/drivers/media/i2c/max96712.c
1414+++ b/drivers/media/i2c/max96712.c
15- @@ -21,17 +21,63 @@
15+ @@ -21,17 +21,64 @@
1616 #include <linux/debugfs.h>
1717 #include <media/camera_common.h>
1818 #include <linux/module.h>
@@ -28,6 +28,7 @@ index 8081385f0..6d451c034 100644
2828+ #define MAX96712_CTRL1_ADDR 0x18
2929+
3030+ #define MAX96712_BACKTOP24_ADDR 0x417
31+ + #define MAX96712_BACKTOP22_ADDR 0x415
3132+ #define MAX96712_BACKTOP25_ADDR 0x418
3233+
3334+ #define MAX96712_MIPI_PHY0_ADDR 0x8A0
@@ -78,7 +79,7 @@ index 8081385f0..6d451c034 100644
7879 u16 addr, u8 val)
7980 {
8081 struct i2c_client *i2c_client = NULL;
81- @@ -99,6 +145,19 @@ static int max96712_read_reg(struct max96712 *priv,
82+ @@ -99,6 +146,18 @@ static int max96712_read_reg(struct max96712 *priv,
8283 return err;
8384 }
8485
@@ -87,7 +88,6 @@ index 8081385f0..6d451c034 100644
8788+ {
8889+ struct i2c_client *i2c_client = priv->i2c_client;
8990+ int err;
90- +
9191+ err = regmap_write(priv->regmap, addr, val);
9292+ if (err)
9393+ dev_err(&i2c_client->dev, "%s:i2c write failed, 0x%x = %x\n",
@@ -154,7 +154,7 @@ index 8081385f0..6d451c034 100644
154154 i2c_unregister_device(client);
155155 client = NULL;
156156 }
157- @@ -252,13 +332,254 @@ max96712_remove(struct i2c_client *client)
157+ @@ -252,13 +332,263 @@ max96712_remove(struct i2c_client *client)
158158 return 0;
159159 }
160160
@@ -197,8 +197,6 @@ index 8081385f0..6d451c034 100644
197197+ {
198198+ struct max96712 *priv = dev_get_drvdata(dev);
199199+ max96712_write_reg(priv, MAX96712_CTRL1_ADDR, 0x0F);
200- + msleep(1);
201- + max96712_write_reg(priv, MAX96712_CTRL1_ADDR, 0x00);
202200+ msleep(100);
203201+ }
204202+ EXPORT_SYMBOL(max96712_reset_oneshot);
@@ -211,18 +209,6 @@ index 8081385f0..6d451c034 100644
211209+
212210+ int i = 0;
213211+
214- + struct reg_pair map_pipe_select[] = {
215- + {MAX96712_REG5_ADDR, 0x80}, // Enable lock
216- + {MAX96712_REG6_ADDR, 0xF1}, // Enable lock
217- + {MAX96712_MIPI_PHY0_ADDR, 0x01},
218- + {MAX96712_MIPI_PHY2_ADDR, 0xF4},
219- + {MAX96712_MIPI_PHY3_ADDR, 0x44},
220- + {MAX96712_MIPI_PHY5_ADDR, 0x00},
221- + {MAX96712_VIDEO_PIPE_SEL_0_ADDR, 0x10},
222- + {MAX96712_VIDEO_PIPE_SEL_1_ADDR, 0x32},
223- + {MAX96712_VIDEO_PIPE_EN_ADDR, 0x0F},
224- + };
225- +
226212+ struct reg_pair map_pipe_control[] = {
227213+ // Enable 4 mappings for Pipe X
228214+ {MAX96712_MIPI_TX11_ADDR, 0x0F},
@@ -240,21 +226,10 @@ index 8081385f0..6d451c034 100644
240226+ {MAX96712_MIPI_TX20_DST_3_MAP_ADDR, 0x12},
241227+ // All mappings to PHY1 (master for port A)
242228+ {MAX96712_MIPI_TX45_MAP_DPHY_DEST_ADDR, 0x00},
243- + {MAX96712_MIPI_TX10_ADDR, 0x40},
244- + {MAX96712_MIPI_TX51_ADDR, 0x10},
245229+ // SEQ_MISS_EN: Disabled / DIS_PKT_DET: Disabled
246230+ {MAX96712_VIDEO_RX0_ADDR, 0x23}, // pipe X
247231+ };
248232+
249- + struct reg_pair map_pipe_opt[] = {
250- + {MAX96712_RLMS_A_RLMS58_ADDR, 0x28}, // PHY A Optimization
251- + {MAX96712_RLMS_A_RLMS59_ADDR, 0x68}, // PHY A Optimization
252- + {MAX96712_RLMS_B_RLMS58_ADDR, 0x28}, // PHY B Optimization
253- + {MAX96712_RLMS_B_RLMS59_ADDR, 0x68}, // PHY B Optimization
254- + {MAX96712_BACKTOP24_ADDR, 0xf0},
255- + {MAX96712_BACKTOP25_ADDR, 0x2f},
256- + };
257- +
258233+ for (i = 0; i < (ARRAY_SIZE(map_pipe_control) - 1); i++) {
259234+ map_pipe_control[i].addr += 0x40 * pipe_id;
260235+ }
@@ -264,7 +239,7 @@ index 8081385f0..6d451c034 100644
264239+ /* For IMU (which has no metadata) we override mapping
265240+ * to enable only 3
266241+ */
267- + map_pipe_control[1 ].val = 0x07;
242+ + map_pipe_control[0 ].val = 0x07;
268243+ }
269244+ map_pipe_control[1].val = (vc_id << 6) | data_type1;
270245+ map_pipe_control[2].val = (vc_id << 6) | data_type1;
@@ -275,39 +250,73 @@ index 8081385f0..6d451c034 100644
275250+ map_pipe_control[7].val = (vc_id << 6) | data_type2;
276251+ map_pipe_control[8].val = (vc_id << 6) | data_type2;
277252+
278- + max96712_write_reg(priv, MAX96712_BACKTOP12_CSI_OUT_EN_ADDR, 0x0);
279- +
280- + err |= max96712_set_registers(priv, map_pipe_select,
281- + ARRAY_SIZE(map_pipe_select));
282- +
283253+ err |= max96712_set_registers(priv, map_pipe_control,
284254+ ARRAY_SIZE(map_pipe_control));
285255+
286- + err |= max96712_set_registers(priv, map_pipe_opt,
287- + ARRAY_SIZE(map_pipe_opt));
288- +
289- + max96712_write_reg(priv, MAX96712_BACKTOP12_CSI_OUT_EN_ADDR, 0x2);
290- +
291256+ max96712_reset_oneshot(dev);
257+ + max96712_write_reg(priv, MAX96712_VIDEO_PIPE_EN_ADDR, 0xF);
292258+
293259+ return err;
294260+ }
295261+
296262+ int max96712_init_settings(struct device *dev)
297263+ {
298264+ int err = 0;
299- + int i;
300265+ struct max96712 *priv = dev_get_drvdata(dev);
266+ + struct reg_pair map_pipe_opt[] =
267+ + {
268+ + /* ----------Video pipes configure ----------------------*/
269+ + {MAX96712_REG6_ADDR, 0xF1}, // Enable link - Why is this needed?
270+ + {MAX96712_VIDEO_PIPE_SEL_0_ADDR, 0x10}, //0xF0, Link A ID 0 to pipe 0 , Link A ID 1 to pipe 1
271+ + {MAX96712_VIDEO_PIPE_SEL_1_ADDR, 0x32}, //0xF1, Link A ID 2 to pipe 2 , Link A ID 3 to pipe 3
272+ + {MAX96712_VIDEO_PIPE_EN_ADDR, 0x00}, //0xF4, Enable pipe 0-3, 0xFF
273+ + };
301274+
302- + mutex_lock(&priv->lock);
275+ + struct reg_pair map_phy_opt_4x2[] =
276+ + {
277+ + /* MIPI D-PHY Config */
278+ + {MAX96712_MIPI_PHY0_ADDR, 0x1}, //0x8A0
279+ + {MAX96712_MIPI_PHY3_ADDR, 0x44}, //0x8A3, Default 4x2 lane mapping
280+ + //{MAX96712_MIPI_PHY4_ADDR, 0x44}, //0x8A4, Default 4x2 lane mapping
281+ +
282+ + /* 4 lanes on port A, 0x40 -> 2 lanes, 0xC0 -> 4 lanes */
283+ + {MAX96712_MIPI_TX10_ADDR + (0x40 * 0), 0x40}, //0x90A, MIPI PHY0
284+ + {MAX96712_MIPI_TX10_ADDR + (0x40 * 1), 0x40}, //0x94A, MIPI PHY1
285+ + {MAX96712_MIPI_TX10_ADDR + (0x40 * 2), 0x40}, //0x98A, MIPI PHY2
286+ + {MAX96712_MIPI_TX10_ADDR + (0x40 * 3), 0x40}, //0x9CA, MIPI PHY3
287+ +
288+ + /* Put DPLL for ctrl 1 and 2 in reset (config_soft_rst_n = 0) before changing MIPI lane rates */
289+ + //{0x1C00, 0xF4}, //PHY0
290+ + {0x1D00, 0xF4}, //PHY1
291+ + //{0x1E00, 0xF4}, //PHY2
292+ + //{0x1F00, 0xF4}, //PHY3
293+ +
294+ + /* 1500Mbps/lane on port A */
295+ + //{MAX96712_BACKTOP22_ADDR + (0x3 * 0), 0x2F}, //0x415
296+ + {MAX96712_BACKTOP22_ADDR + (0x3 * 1), 0x2F}, //0x418
297+ + //{MAX96712_BACKTOP22_ADDR + (0x3 * 2), 0x2F}, //0x41B
298+ + //{MAX96712_BACKTOP22_ADDR + (0x3 * 3), 0x2F}, //0x41E
299+ +
300+ + /* Release DPLL reset (config_soft_rst_n = 1) */
301+ + //{0x1C00, 0xF5}, //PHY0
302+ + {0x1D00, 0xF5}, //PHY1
303+ + //{0x1E00, 0xF5}, //PHY2
304+ + //{0x1F00, 0xF5}, //PHY3
305+ +
306+ + /* 0x02: ALT_MEM_MAP8, 0x10: ALT2_MEM_MAP8 */
307+ + {MAX96712_MIPI_TX51_ADDR + (0x40 * 0), 0x10}, //MIPI TX0
308+ + {MAX96712_MIPI_TX51_ADDR + (0x40 * 1), 0x10}, //0x10, MIPI TX1
309+ + {MAX96712_MIPI_TX51_ADDR + (0x40 * 2), 0x10}, //0x10, MIPI TX2
310+ + {MAX96712_MIPI_TX51_ADDR + (0x40 * 3), 0x10}, //MIPI TX3
311+ +
312+ + {MAX96712_MIPI_PHY2_ADDR, 0xF4}, //0x8A2 TODO: EHUD - 0xF0?
313+ + {MAX96712_BACKTOP12_CSI_OUT_EN_ADDR, 0x02}, // (CSI_OUT_EN): CSI output enabled
314+ + };
303315+
304- + max96712_write_reg(priv, MAX96712_CTRL0_ADDR, 0x14);
305- + max96712_write_reg(priv, MAX96712_CTRL1_ADDR, 0xF0);
306- + max96712_write_reg(priv, MAX96712_CTRL1_ADDR, 0x00);
316+ + mutex_lock(&priv->lock);
307317+
308- + for (i = 0; i < MAX96712_MAX_PIPES; i++)
309- + err |= __max96712_set_pipe(dev, i, GMSL_CSI_DT_YUV422_8,
310- + GMSL_CSI_DT_EMBED, i);
318+ + err |= max96712_set_registers(priv, map_pipe_opt, ARRAY_SIZE(map_pipe_opt));
319+ + err |= max96712_set_registers(priv, map_phy_opt_4x2, ARRAY_SIZE(map_phy_opt_4x2));
311320+
312321+ mutex_unlock(&priv->lock);
313322+
@@ -410,7 +419,7 @@ index 8081385f0..6d451c034 100644
410419 { },
411420 };
412421
413- @@ -268,6 +589 ,7 @@ static struct i2c_driver max96712_i2c_driver = {
422+ @@ -268,6 +598 ,7 @@ static struct i2c_driver max96712_i2c_driver = {
414423 .driver = {
415424 .name = "max96712",
416425 .owner = THIS_MODULE,
0 commit comments