Skip to content

Commit d8b162e

Browse files
committed
Enhance DS5 sensor configuration with retry logic for I2C operations and caching of parameters
1 parent bbb0814 commit d8b162e

1 file changed

Lines changed: 167 additions & 39 deletions

File tree

kernel/realsense/d4xx.c

Lines changed: 167 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,17 @@ struct ds5_sensor {
419419
const struct ds5_format *formats;
420420
unsigned int n_formats;
421421
int pipe_id;
422+
int last_pipe_id;
423+
u16 pipe_data_type1;
424+
u16 pipe_data_type2;
425+
u32 pipe_vc_id;
426+
bool pipe_configured;
427+
u16 cached_dt_value;
428+
u16 cached_md_value;
429+
u16 cached_override_value;
430+
u16 cached_fps_value;
431+
u16 cached_width_value;
432+
u16 cached_height_value;
422433
};
423434

424435
#ifdef CONFIG_TEGRA_CAMERA_PLATFORM
@@ -536,6 +547,8 @@ static int ds5_write(struct ds5 *state, u16 reg, u16 val)
536547
{
537548
int ret;
538549
u8 value[2];
550+
int retry;
551+
int delay_ms = 10;
539552

540553
value[1] = val >> 8;
541554
value[0] = val & 0x00FF;
@@ -544,7 +557,28 @@ static int ds5_write(struct ds5 *state, u16 reg, u16 val)
544557
"%s(): writing to register: 0x%04x, value1: 0x%x, value2:0x%x\n",
545558
__func__, reg, value[1], value[0]);
546559

547-
ret = regmap_raw_write(state->regmap, reg, value, sizeof(value));
560+
for (retry = 0; retry < 3; retry++) {
561+
ret = regmap_raw_write(state->regmap, reg, value, sizeof(value));
562+
if (ret == 0)
563+
break;
564+
565+
/* Retry only on timeout/remote IO errors */
566+
if (ret != -ETIMEDOUT && ret != -EREMOTEIO) {
567+
dev_err(&state->client->dev,
568+
"%s(): i2c write failed %d, 0x%04x = 0x%x\n",
569+
__func__, ret, reg, val);
570+
return ret;
571+
}
572+
573+
if (retry < 2) {
574+
dev_dbg(&state->client->dev,
575+
"%s(): retry %d after %dms delay, 0x%04x\n",
576+
__func__, retry + 1, delay_ms, reg);
577+
msleep(delay_ms);
578+
delay_ms *= 2;
579+
}
580+
}
581+
548582
if (ret < 0)
549583
dev_err(&state->client->dev,
550584
"%s(): i2c write failed %d, 0x%04x = 0x%x\n",
@@ -560,7 +594,32 @@ static int ds5_write(struct ds5 *state, u16 reg, u16 val)
560594
static int ds5_raw_write(struct ds5 *state, u16 reg,
561595
const void *val, size_t val_len)
562596
{
563-
int ret = regmap_raw_write(state->regmap, reg, val, val_len);
597+
int ret;
598+
int retry;
599+
int delay_ms = 10;
600+
601+
for (retry = 0; retry < 3; retry++) {
602+
ret = regmap_raw_write(state->regmap, reg, val, val_len);
603+
if (ret == 0)
604+
break;
605+
606+
/* Retry only on timeout/remote IO errors */
607+
if (ret != -ETIMEDOUT && ret != -EREMOTEIO) {
608+
dev_err(&state->client->dev,
609+
"%s(): i2c raw write failed %d, %04x size(%d) bytes\n",
610+
__func__, ret, reg, (int)val_len);
611+
return ret;
612+
}
613+
614+
if (retry < 2) {
615+
dev_dbg(&state->client->dev,
616+
"%s(): retry %d after %dms delay, 0x%04x\n",
617+
__func__, retry + 1, delay_ms, reg);
618+
msleep(delay_ms);
619+
delay_ms *= 2;
620+
}
621+
}
622+
564623
if (ret < 0)
565624
dev_err(&state->client->dev,
566625
"%s(): i2c raw write failed %d, %04x size(%d) bytes\n",
@@ -576,7 +635,31 @@ static int ds5_raw_write(struct ds5 *state, u16 reg,
576635

577636
static int ds5_read(struct ds5 *state, u16 reg, u16 *val)
578637
{
579-
int ret = regmap_raw_read(state->regmap, reg, val, 2);
638+
int ret;
639+
int retry;
640+
int delay_ms = 10;
641+
642+
for (retry = 0; retry < 3; retry++) {
643+
ret = regmap_raw_read(state->regmap, reg, val, 2);
644+
if (ret == 0)
645+
break;
646+
647+
/* Retry only on timeout/remote IO errors */
648+
if (ret != -ETIMEDOUT && ret != -EREMOTEIO) {
649+
dev_err(&state->client->dev, "%s(): i2c read failed %d, 0x%04x\n",
650+
__func__, ret, reg);
651+
return ret;
652+
}
653+
654+
if (retry < 2) {
655+
dev_dbg(&state->client->dev,
656+
"%s(): retry %d after %dms delay, 0x%04x\n",
657+
__func__, retry + 1, delay_ms, reg);
658+
msleep(delay_ms);
659+
delay_ms *= 2;
660+
}
661+
}
662+
580663
if (ret < 0)
581664
dev_err(&state->client->dev, "%s(): i2c read failed %d, 0x%04x\n",
582665
__func__, ret, reg);
@@ -1827,6 +1910,11 @@ static int ds5_configure(struct ds5 *state)
18271910
u16 data_type1, data_type2;
18281911
#endif
18291912
u16 dt_addr, md_addr, override_addr, fps_addr, width_addr, height_addr;
1913+
u16 dt_value = 0;
1914+
u16 md_value = 0;
1915+
u16 fps_value = 0;
1916+
u16 width_value = 0;
1917+
u16 height_value = 0;
18301918
int ret;
18311919

18321920
if (state->is_depth) {
@@ -1878,14 +1966,31 @@ static int ds5_configure(struct ds5 *state)
18781966
data_type2 = state->is_imu ? 0x00 : md_fmt;
18791967

18801968
vc_id = state->g_ctx.dst_vc;
1881-
1882-
ret = ds5_setup_pipeline(state, data_type1, data_type2, sensor->pipe_id,
1883-
vc_id);
1884-
// reset data path when switching to Y12I
1885-
if (state->is_y8 && data_type1 == GMSL_CSI_DT_RGB_888)
1886-
max9296_reset_oneshot(state->dser_dev);
1887-
if (ret < 0)
1888-
return ret;
1969+
if (!sensor->pipe_configured ||
1970+
sensor->pipe_id != sensor->last_pipe_id ||
1971+
sensor->pipe_data_type1 != data_type1 ||
1972+
sensor->pipe_data_type2 != data_type2 ||
1973+
sensor->pipe_vc_id != vc_id) {
1974+
ret = ds5_setup_pipeline(state, data_type1, data_type2,
1975+
sensor->pipe_id, vc_id);
1976+
// reset data path when switching to Y12I
1977+
if (state->is_y8 && data_type1 == GMSL_CSI_DT_RGB_888)
1978+
max9296_reset_oneshot(state->dser_dev);
1979+
if (ret < 0)
1980+
return ret;
1981+
sensor->pipe_configured = true;
1982+
sensor->last_pipe_id = sensor->pipe_id;
1983+
sensor->pipe_data_type1 = data_type1;
1984+
sensor->pipe_data_type2 = data_type2;
1985+
sensor->pipe_vc_id = vc_id;
1986+
dev_warn(&state->client->dev,
1987+
"pipe %d configured (dt1=0x%x dt2=0x%x vc=%u)\n",
1988+
sensor->pipe_id, data_type1, data_type2, vc_id);
1989+
} else {
1990+
dev_warn(&state->client->dev,
1991+
"pipe %d already configured (dt1=0x%x dt2=0x%x vc=%u)\n",
1992+
sensor->pipe_id, data_type1, data_type2, vc_id);
1993+
}
18891994
#endif
18901995

18911996
fmt = sensor->streaming ? sensor->config.format->data_type : 0;
@@ -1895,55 +2000,72 @@ static int ds5_configure(struct ds5 *state)
18952000
* Set IR stream Y8I data type as 0x32
18962001
*/
18972002
if (state->is_depth && fmt != 0)
1898-
ret = ds5_write(state, dt_addr, 0x31);
2003+
dt_value = 0x31;
18992004
else if (state->is_y8 && fmt != 0 &&
19002005
sensor->config.format->data_type == GMSL_CSI_DT_YUV422_8) {
1901-
if (sensor->config.format->mbus_code == MEDIA_BUS_FMT_VYUY8_1X16)
1902-
{
1903-
/* This is the custom Y8I format -
1904-
* telling FW to enable "etMipiDataType_UserDefined3_R8L8"
1905-
*/
1906-
ret = ds5_write(state, dt_addr, GMSL_CSI_DT_CUSTOM_Y8I_16);
2006+
if (sensor->config.format->mbus_code == MEDIA_BUS_FMT_VYUY8_1X16) {
2007+
dt_value = GMSL_CSI_DT_CUSTOM_Y8I_16;
19072008
} else if (sensor->config.format->mbus_code == MEDIA_BUS_FMT_YUYV8_1X16) {
1908-
/* This is the custom RGB through IR format -
1909-
* telling FW to enable "etMipiDataType_UserDefined0_IR_RGB"
1910-
*/
1911-
ret = ds5_write(state, dt_addr, GMSL_CSI_DT_CUSTOM_IR_RGB_16);
2009+
dt_value = GMSL_CSI_DT_CUSTOM_IR_RGB_16;
19122010
} else {
19132011
dev_err(sensor->sd.dev, "%s(): Illegal mbus_code %u for IR sensor\n",
19142012
__func__, sensor->config.format->mbus_code);
19152013
return -EINVAL;
19162014
}
19172015
} else {
1918-
ret = ds5_write(state, dt_addr, fmt);
2016+
dt_value = fmt;
19192017
}
1920-
if (ret < 0)
1921-
return ret;
19222018

1923-
ret = ds5_write(state, md_addr, (vc_id << 8) | md_fmt);
1924-
if (ret < 0)
1925-
return ret;
2019+
if (sensor->cached_dt_value != dt_value) {
2020+
ret = ds5_write(state, dt_addr, dt_value);
2021+
if (ret < 0)
2022+
return ret;
2023+
sensor->cached_dt_value = dt_value;
2024+
}
2025+
2026+
md_value = (vc_id << 8) | md_fmt;
2027+
if (sensor->cached_md_value != md_value) {
2028+
ret = ds5_write(state, md_addr, md_value);
2029+
if (ret < 0)
2030+
return ret;
2031+
sensor->cached_md_value = md_value;
2032+
}
19262033

19272034
if (!sensor->streaming)
19282035
return ret;
19292036

19302037
if (override_addr != 0) {
1931-
ret = ds5_write(state, override_addr, fmt);
2038+
if (sensor->cached_override_value != fmt) {
2039+
ret = ds5_write(state, override_addr, fmt);
2040+
if (ret < 0)
2041+
return ret;
2042+
sensor->cached_override_value = fmt;
2043+
}
2044+
}
2045+
2046+
fps_value = sensor->config.framerate;
2047+
if (sensor->cached_fps_value != fps_value) {
2048+
ret = ds5_write(state, fps_addr, fps_value);
19322049
if (ret < 0)
19332050
return ret;
2051+
sensor->cached_fps_value = fps_value;
19342052
}
19352053

1936-
ret = ds5_write(state, fps_addr, sensor->config.framerate);
1937-
if (ret < 0)
1938-
return ret;
1939-
1940-
ret = ds5_write(state, width_addr, sensor->config.resolution->width);
1941-
if (ret < 0)
1942-
return ret;
2054+
width_value = sensor->config.resolution->width;
2055+
if (sensor->cached_width_value != width_value) {
2056+
ret = ds5_write(state, width_addr, width_value);
2057+
if (ret < 0)
2058+
return ret;
2059+
sensor->cached_width_value = width_value;
2060+
}
19432061

1944-
ret = ds5_write(state, height_addr, sensor->config.resolution->height);
1945-
if (ret < 0)
1946-
return ret;
2062+
height_value = sensor->config.resolution->height;
2063+
if (sensor->cached_height_value != height_value) {
2064+
ret = ds5_write(state, height_addr, height_value);
2065+
if (ret < 0)
2066+
return ret;
2067+
sensor->cached_height_value = height_value;
2068+
}
19472069

19482070
return 0;
19492071
}
@@ -4751,6 +4873,8 @@ static int ds5_mux_s_stream(struct v4l2_subdev *sd, int on)
47514873
ret = -(ENOSR);
47524874
goto restore_s_state;
47534875
}
4876+
sensor->pipe_configured = false;
4877+
sensor->last_pipe_id = sensor->pipe_id;
47544878
#endif
47554879

47564880
ret = ds5_configure(state);
@@ -4815,6 +4939,8 @@ static int ds5_mux_s_stream(struct v4l2_subdev *sd, int on)
48154939
if (max9296_release_pipe(state->dser_dev, sensor->pipe_id) < 0)
48164940
dev_warn(&state->client->dev, "release pipe failed\n");
48174941
sensor->pipe_id = -1;
4942+
sensor->last_pipe_id = -1;
4943+
sensor->pipe_configured = false;
48184944
#else
48194945
#ifdef CONFIG_VIDEO_INTEL_IPU6
48204946
d4xx_reset_oneshot(state);
@@ -4839,6 +4965,8 @@ static int ds5_mux_s_stream(struct v4l2_subdev *sd, int on)
48394965
if (max9296_release_pipe(state->dser_dev, sensor->pipe_id) < 0)
48404966
dev_warn(&state->client->dev, "release pipe failed\n");
48414967
sensor->pipe_id = -1;
4968+
sensor->last_pipe_id = -1;
4969+
sensor->pipe_configured = false;
48424970
}
48434971
#endif
48444972

0 commit comments

Comments
 (0)