Skip to content

Commit 55f17e6

Browse files
committed
d4xx : serdes setup fallback on invalid serializer source
Signed-off-by: florent pirou <[email protected]>
1 parent 0c2a1e5 commit 55f17e6

File tree

1 file changed

+141
-26
lines changed

1 file changed

+141
-26
lines changed

kernel/realsense/d4xx.c

Lines changed: 141 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
// SPDX-License-Identifier: GPL-2.0
32
/*
43
* ds5.c - Intel(R) RealSense(TM) D4XX camera driver
@@ -470,6 +469,14 @@ enum {
470469
struct v4l2_mbus_framefmt ds5_ffmts[NR_OF_DS5_PADS];
471470
#endif
472471

472+
#ifdef CONFIG_VIDEO_D4XX_SERDES
473+
struct serdes_state {
474+
bool isolated;
475+
int bus_nr;
476+
int addr;
477+
};
478+
#endif
479+
473480
struct ds5 {
474481
struct { struct ds5_sensor sensor; } depth;
475482
struct { struct ds5_sensor sensor; } ir;
@@ -500,6 +507,7 @@ struct ds5 {
500507
struct device *dser_dev;
501508
struct i2c_client *ser_i2c;
502509
struct i2c_client *dser_i2c;
510+
struct serdes_state dser_st;
503511
#endif
504512
#ifdef CONFIG_VIDEO_INTEL_IPU6
505513
#define NR_OF_CSI2_BE_SOC_STREAMS 16
@@ -3152,6 +3160,7 @@ static int ds5_board_setup(struct ds5 *state)
31523160
int err = 0;
31533161
int i;
31543162
char suffix = pdata->suffix;
3163+
31553164
static struct max9295_pdata max9295_pdata = {
31563165
.is_prim_ser = 1, // todo: configurable
31573166
.def_addr = 0x40, // todo: configurable
@@ -3174,16 +3183,27 @@ static int ds5_board_setup(struct ds5 *state)
31743183

31753184
i2c_info_des.addr = pdata->subdev_info[0].board_info.addr; //0x48, 0x4a, 0x68, 0x6a
31763185

3186+
state->dser_st.bus_nr = bus;
3187+
state->dser_st.addr = i2c_info_des.addr;
3188+
31773189
/* look for already registered max9296, use same context if found */
31783190
for (i = 0; i < MAX_DEV_NUM; i++) {
3179-
if (serdes_inited[i] && serdes_inited[i]->dser_i2c) {
3180-
dev_info(dev, "MAX9296 found device on %d@0x%x\n",
3181-
serdes_inited[i]->dser_i2c->adapter->nr, serdes_inited[i]->dser_i2c->addr);
3182-
if (bus == serdes_inited[i]->dser_i2c->adapter->nr
3183-
&& serdes_inited[i]->dser_i2c->addr == i2c_info_des.addr) {
3191+
if (serdes_inited[i]) {
3192+
if ( serdes_inited[i]->dser_st.isolated
3193+
&& bus == serdes_inited[i]->dser_st.bus_nr
3194+
&& serdes_inited[i]->dser_st.addr == i2c_info_des.addr ) {
3195+
3196+
dev_info(dev, "Isolate unresponsive sensor/serializer AGGREGATED on MAX9296 device 0x%x\n",
3197+
i2c_info_des.addr);
3198+
state->aggregated = 1;
3199+
break;
3200+
} else if ( serdes_inited[i]->dser_i2c
3201+
&& bus == serdes_inited[i]->dser_i2c->adapter->nr
3202+
&& serdes_inited[i]->dser_i2c->addr == i2c_info_des.addr) {
31843203
dev_info(dev, "MAX9296 AGGREGATION found device on 0x%x\n", i2c_info_des.addr);
31853204
state->dser_i2c = serdes_inited[i]->dser_i2c;
31863205
state->aggregated = 1;
3206+
break;
31873207
}
31883208
}
31893209
}
@@ -3296,6 +3316,7 @@ static int ds5_gmsl_serdes_setup(struct ds5 *state)
32963316
{
32973317
int err = 0;
32983318
int des_err = 0;
3319+
int ser_err = 0;
32993320
struct device *dev;
33003321

33013322
if (!state || !state->ser_dev || !state->dser_dev || !state->client)
@@ -3317,17 +3338,19 @@ static int ds5_gmsl_serdes_setup(struct ds5 *state)
33173338
goto error;
33183339
}
33193340
msleep(100);
3320-
err = max9295_setup_control(state->ser_dev);
33213341

3322-
/* proceed even if ser setup failed, to setup deser correctly */
3323-
if (err)
3324-
dev_err(dev, "gmsl serializer setup failed\n");
3342+
ser_err = max9295_setup_control(state->ser_dev);
3343+
/* if ser setup failed, graceful deser setup fallback */
3344+
if (ser_err) {
3345+
dev_warn(dev, "gmsl serializer invalid source\n");
3346+
err= -ENOTSUPP;
3347+
}
33253348

33263349
des_err = max9296_setup_control(state->dser_dev, &state->client->dev);
33273350
if (des_err) {
3328-
dev_err(dev, "gmsl deserializer setup failed\n");
3351+
dev_warn(dev, "gmsl deserializer setup failed\n");
33293352
/* overwrite err only if deser setup also failed */
3330-
err = des_err;
3353+
err = ( err == -ENOTSUPP) ? err : des_err;
33313354
}
33323355

33333356
error:
@@ -3372,7 +3395,7 @@ static int ds5_i2c_addr_setting(struct i2c_client *c, struct ds5 *state)
33723395
c->addr = des_addr[i];
33733396
dev_info(&c->dev, "Set max9296@%d-0x%x Link reset\n",
33743397
c_bus, c->addr);
3375-
ds5_write_8(state, 0x1000, 0x40); // reset link
3398+
ds5_write_8(state, 0x1000, 0x40); // sensor reset link
33763399
}
33773400
}
33783401
// restore original slave address
@@ -3386,23 +3409,34 @@ static int ds5_serdes_setup(struct ds5 *state)
33863409
int ret = 0;
33873410
struct i2c_client *c = state->client;
33883411
#ifdef CONFIG_VIDEO_INTEL_IPU6
3389-
int i = 0, c_bus = 0;
3412+
int i = 0, c_bus = -1;
33903413
int c_bus_new = c->adapter->nr;
33913414

33923415
for (i = 0; i < MAX_DEV_NUM; i++) {
3416+
#ifdef CONFIG_VIDEO_D4XX_SERDES
3417+
if (serdes_inited[i] && serdes_inited[i]->dser_st.isolated) {
3418+
c_bus = serdes_inited[i]->dser_st.bus_nr;
3419+
if (c_bus == c->adapter->nr) {
3420+
dev_info(&c->dev, "Already configured Isolated camera for bus %d\n", c_bus);
3421+
c_bus_new = -1;
3422+
break;
3423+
}
3424+
} else if (serdes_inited[i] && serdes_inited[i]->dser_i2c) {
3425+
#else
33933426
if (serdes_inited[i] && serdes_inited[i]->dser_i2c) {
3427+
#endif
33943428
c_bus = serdes_inited[i]->dser_i2c->adapter->nr;
33953429
if (c_bus == c->adapter->nr) {
3396-
dev_info(&c->dev, "Already configured multiple camera for bus %d\n", c_bus);
3397-
c_bus_new = 0;
3430+
dev_info(&c->dev, "Already configured Addressable camera for bus %d\n", c_bus);
3431+
c_bus_new = -1;
33983432
break;
33993433
}
34003434
} else {
34013435
break;
34023436
}
34033437
}
34043438

3405-
if (c_bus_new) {
3439+
if (c_bus_new >= 0) {
34063440
dev_info(&c->dev, "Apply multiple camera i2c addr setting for bus %d\n", c_bus_new);
34073441
ret = ds5_i2c_addr_setting(c, state);
34083442
if (ret) {
@@ -3422,7 +3456,7 @@ static int ds5_serdes_setup(struct ds5 *state)
34223456
/* Pair sensor to serializer dev */
34233457
ret = max9295_sdev_pair(state->ser_dev, &state->g_ctx);
34243458
if (ret) {
3425-
dev_err(&c->dev, "gmsl ser pairing failed\n");
3459+
dev_err(&c->dev, "gmsl serializer pairing failed\n");
34263460
return ret;
34273461
}
34283462

@@ -3435,7 +3469,16 @@ static int ds5_serdes_setup(struct ds5 *state)
34353469

34363470
ret = ds5_gmsl_serdes_setup(state);
34373471
if (ret) {
3438-
dev_err(&c->dev, "%s gmsl serdes setup failed\n", __func__);
3472+
if (ret == -ENOTSUPP) {
3473+
dev_warn(&c->dev, "graceful fallback, gmsl serdes setup\n");
3474+
if (c_bus_new >= 0)
3475+
dev_info(&c->dev, "Unresponding serializer on Newly initialized bus %d\n",
3476+
c_bus_new);
3477+
else
3478+
dev_info(&c->dev, "Unresponding serializer on Already initialized bus %d\n",
3479+
state->dser_i2c->adapter->nr);
3480+
} else
3481+
dev_err(&c->dev, "%s gmsl serdes setup failed\n", __func__);
34393482
return ret;
34403483
}
34413484

@@ -5569,6 +5612,10 @@ static int ds5_probe(struct i2c_client *c)
55695612
mutex_init(&state->lock);
55705613

55715614
state->client = c;
5615+
5616+
#ifdef CONFIG_VIDEO_D4XX_SERDES
5617+
state->dser_st.isolated = false;
5618+
#endif
55725619
dev_warn(&c->dev, "Probing driver for D45x\n");
55735620
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
55745621
state->variant = ds5_variants + id->driver_data;
@@ -5600,8 +5647,12 @@ static int ds5_probe(struct i2c_client *c)
56005647

56015648
#ifdef CONFIG_VIDEO_D4XX_SERDES
56025649
ret = ds5_serdes_setup(state);
5603-
if (ret < 0)
5650+
if (ret < 0) {
5651+
if (ret == -ENOTSUPP)
5652+
dev_warn(&c->dev, "max9295 communication failed : %d\n", ret);
56045653
goto e_regulator;
5654+
5655+
}
56055656
#endif
56065657
#ifdef CONFIG_VIDEO_INTEL_IPU6
56075658
#endif //CONFIG_VIDEO_INTEL_IPU6
@@ -5693,14 +5744,54 @@ static int ds5_probe(struct i2c_client *c)
56935744
e_chardev:
56945745
if (state->dfu_dev.ds5_class)
56955746
ds5_chrdev_remove(state);
5747+
56965748
e_regulator:
56975749
if (state->vcc)
56985750
regulator_disable(state->vcc);
56995751
#ifdef CONFIG_VIDEO_D4XX_SERDES
5700-
if (state->ser_i2c)
5752+
int i;
5753+
int c_bus = c->adapter->nr;
5754+
bool graceful_fallback = false;
5755+
for (i = 0; i < MAX_DEV_NUM; i++) {
5756+
if (serdes_inited[i]
5757+
&& serdes_inited[i] != state
5758+
&& state->dser_i2c
5759+
&& c_bus == serdes_inited[i]->dser_st.bus_nr
5760+
&& state->dser_i2c->addr == serdes_inited[i]->dser_st.addr
5761+
&& serdes_inited[i]->dser_st.isolated) {
5762+
5763+
dev_info(&c->dev, "Cleanup unresponsive sensor/serializer Isolated on bus %d\n",
5764+
c_bus);
5765+
graceful_fallback = true;
5766+
}
5767+
}
5768+
5769+
if (!state->g_ctx.serdev_found)
5770+
dev_warn(&c->dev, "graceful fallback due to unresponsive max9295, isolated SerDes %s single-link\n",
5771+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B");
5772+
else
5773+
dev_warn(&c->dev, "graceful fallback due to unresponsive d4xx, isolated SerDes %s single-link\n",
5774+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B");
5775+
5776+
mutex_lock(&serdes_lock__);
5777+
if (state->ser_i2c) {
5778+
dev_info(&c->dev, "remove unresponding serializer i2c device 0x%x\n",
5779+
state->ser_i2c->addr);
57015780
i2c_unregister_device(state->ser_i2c);
5702-
if (state->dser_i2c && !state->aggregated)
5781+
}
5782+
if (state->dser_i2c && !state->aggregated) {
5783+
dev_info(&c->dev, "remove unresponding %s single-link deserializer i2c device 0x%x\n",
5784+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B",
5785+
state->dser_i2c->addr);
57035786
i2c_unregister_device(state->dser_i2c);
5787+
state->dser_st.isolated = true;
5788+
} else if (state->dser_i2c && graceful_fallback) {
5789+
dev_info(&c->dev, "remove unresponding %s single-link deserializer i2c device 0x%x\n",
5790+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B",
5791+
state->dser_i2c->addr);
5792+
i2c_unregister_device(state->dser_i2c);
5793+
}
5794+
mutex_unlock(&serdes_lock__);
57045795
#endif
57055796
return ret;
57065797
}
@@ -5715,7 +5806,17 @@ static void ds5_remove(struct i2c_client *c)
57155806
#ifdef CONFIG_VIDEO_D4XX_SERDES
57165807
int i, ret;
57175808
int c_bus = c->adapter->nr;
5809+
bool graceful_fallback = false;
57185810
for (i = 0; i < MAX_DEV_NUM; i++) {
5811+
if (serdes_inited[i] && state->dser_i2c
5812+
&& c_bus == serdes_inited[i]->dser_st.bus_nr
5813+
&& state->dser_i2c->addr == serdes_inited[i]->dser_st.addr
5814+
&& serdes_inited[i]->dser_st.isolated) {
5815+
5816+
dev_info(&c->dev, "Cleanup unresponsive sensor/serializer Isolated on bus %d\n",
5817+
c_bus);
5818+
graceful_fallback = true;
5819+
}
57195820
if (serdes_inited[i] && serdes_inited[i] == state) {
57205821
serdes_inited[i] = NULL;
57215822
mutex_lock(&serdes_lock__);
@@ -5727,6 +5828,7 @@ static void ds5_remove(struct i2c_client *c)
57275828
if (state->dser_i2c) {
57285829
dev_info(&c->dev, "ignore 9296 reset control, already remove for bus %d\n", c_bus);
57295830
} else {
5831+
dev_info(&c->dev, "trigger 9296 reset control on bus %d\n", c_bus);
57305832
ret = max9296_reset_control(state->dser_dev,
57315833
state->g_ctx.s_dev);
57325834
if (ret)
@@ -5741,6 +5843,7 @@ static void ds5_remove(struct i2c_client *c)
57415843
if (state->dser_i2c) {
57425844
dev_info(&c->dev, "ignore 9296 unregister sdev, already remove for bus %d\n", c_bus);
57435845
} else {
5846+
dev_info(&c->dev, "unregister 9296 sdev on bus %d\n", c_bus);
57445847
ret = max9296_sdev_unregister(state->dser_dev,
57455848
state->g_ctx.s_dev);
57465849
if (ret)
@@ -5749,15 +5852,26 @@ static void ds5_remove(struct i2c_client *c)
57495852

57505853
max9296_power_off(state->dser_dev);
57515854
}
5752-
57535855
mutex_unlock(&serdes_lock__);
57545856
break;
57555857
}
57565858
}
5757-
if (state->ser_i2c)
5859+
if (state->ser_i2c && !state->dser_st.isolated) {
5860+
dev_info(&c->dev, "remove unresponding serializer i2c device 0x%x\n",
5861+
state->ser_i2c->addr);
57585862
i2c_unregister_device(state->ser_i2c);
5759-
if (state->dser_i2c && !state->aggregated)
5863+
}
5864+
if (state->dser_i2c && !state->aggregated && !state->dser_st.isolated) {
57605865
i2c_unregister_device(state->dser_i2c);
5866+
dev_info(&c->dev, "remove unresponding %s single-link deserializer i2c device 0x%x\n",
5867+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B",
5868+
state->dser_i2c->addr);
5869+
} else if (state->dser_i2c && graceful_fallback) {
5870+
dev_info(&c->dev, "remove unresponding %s single-link deserializer i2c device 0x%x\n",
5871+
state->g_ctx.serdes_csi_link == GMSL_SERDES_CSI_LINK_A ? "GMSL A": "GMSL B",
5872+
state->dser_i2c->addr);
5873+
i2c_unregister_device(state->dser_i2c);
5874+
}
57615875
#endif
57625876
#ifndef CONFIG_TEGRA_CAMERA_PLATFORM
57635877
state->is_depth = 1;
@@ -5826,7 +5940,8 @@ MODULE_AUTHOR("Guennadi Liakhovetski <[email protected]>,\n\
58265940
Xin Zhang <[email protected]>,\n\
58275941
Qingwu Zhang <[email protected]>,\n\
58285942
Evgeni Raikhel <[email protected]>,\n\
5829-
Shikun Ding <[email protected]>");
5943+
Shikun Ding <[email protected]>,\n\
5944+
Florent Pirou <[email protected]>");
58305945
MODULE_AUTHOR("Dmitry Perchanov <[email protected]>");
58315946
MODULE_LICENSE("GPL v2");
58325947
MODULE_VERSION("1.0.1.21");

0 commit comments

Comments
 (0)