|
74 | 74 | #define OV9282_REG_MIPI_CTRL00 0x4800 |
75 | 75 | #define OV9282_GATED_CLOCK BIT(5) |
76 | 76 |
|
| 77 | +/* Trigger mode registers */ |
| 78 | +#define OV9282_REG_POWER_CTRL 0x4F00 |
| 79 | +#define OV9282_REG_LOW_POWER_MODE_CTRL 0x3030 |
| 80 | +#define OV9282_REG_NUM_FRAME_ON_TRIG 0x303F |
| 81 | +#define OV9282_REG_SLEEP_PERIOD_CTRL0 0x302C |
| 82 | +#define OV9282_REG_SLEEP_PERIOD_CTRL3 0x302F |
| 83 | +#define OV9282_REG_TIMING_23 0x3823 |
| 84 | + |
77 | 85 | /* Input clock rate */ |
78 | 86 | #define OV9282_INCLK_RATE 24000000 |
79 | 87 |
|
@@ -196,6 +204,7 @@ struct ov9282 { |
196 | 204 | const struct ov9282_mode *cur_mode; |
197 | 205 | u32 code; |
198 | 206 | struct mutex mutex; |
| 207 | + int trigger_mode; |
199 | 208 | }; |
200 | 209 |
|
201 | 210 | static const s64 link_freq[] = { |
@@ -956,6 +965,52 @@ static int ov9282_get_selection(struct v4l2_subdev *sd, |
956 | 965 | return -EINVAL; |
957 | 966 | } |
958 | 967 |
|
| 968 | +/** |
| 969 | + * ov9282_apply_trigger_config() - Configure sensor for FSIN external trigger mode |
| 970 | + * @ov9282: pointer to ov9282 device |
| 971 | + * |
| 972 | + * Return: 0 on success, error code otherwise. |
| 973 | + */ |
| 974 | +static int ov9282_apply_trigger_config(struct ov9282 *ov9282) |
| 975 | +{ |
| 976 | + int ret; |
| 977 | + |
| 978 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 979 | + 1, OV9282_MODE_STANDBY); |
| 980 | + if (ret) |
| 981 | + return ret; |
| 982 | + |
| 983 | + /* Low power mode */ |
| 984 | + ret = ov9282_write_reg(ov9282, OV9282_REG_POWER_CTRL, 1, 0x01); |
| 985 | + if (ret) |
| 986 | + return ret; |
| 987 | + |
| 988 | + /* External trigger snapshot */ |
| 989 | + ret = ov9282_write_reg(ov9282, OV9282_REG_LOW_POWER_MODE_CTRL, 1, 0x04); |
| 990 | + if (ret) |
| 991 | + return ret; |
| 992 | + |
| 993 | + /* 1 frame per trigger */ |
| 994 | + ret = ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01); |
| 995 | + if (ret) |
| 996 | + return ret; |
| 997 | + |
| 998 | + ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00); |
| 999 | + if (ret) |
| 1000 | + return ret; |
| 1001 | + |
| 1002 | + ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F); |
| 1003 | + if (ret) |
| 1004 | + return ret; |
| 1005 | + |
| 1006 | + /* No auto wake */ |
| 1007 | + ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00); |
| 1008 | + if (ret) |
| 1009 | + return ret; |
| 1010 | + |
| 1011 | + return 0; |
| 1012 | +} |
| 1013 | + |
959 | 1014 | /** |
960 | 1015 | * ov9282_start_streaming() - Start sensor stream |
961 | 1016 | * @ov9282: pointer to ov9282 device |
@@ -1007,15 +1062,26 @@ static int ov9282_start_streaming(struct ov9282 *ov9282) |
1007 | 1062 | return ret; |
1008 | 1063 | } |
1009 | 1064 |
|
1010 | | - /* Start streaming */ |
1011 | | - ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
1012 | | - 1, OV9282_MODE_STREAMING); |
1013 | | - if (ret) { |
1014 | | - dev_err(ov9282->dev, "fail to start streaming"); |
1015 | | - return ret; |
| 1065 | + /* Configure FSIN external trigger mode */ |
| 1066 | + if (ov9282->trigger_mode > 0) { |
| 1067 | + ret = ov9282_apply_trigger_config(ov9282); |
| 1068 | + if (ret) { |
| 1069 | + dev_err(ov9282->dev, "failed to config external trigger mode"); |
| 1070 | + return ret; |
| 1071 | + } |
| 1072 | + /* stay in standby mode and wait for trigger signal */ |
| 1073 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1074 | + 1, OV9282_MODE_STANDBY); |
| 1075 | + } else { |
| 1076 | + /* Start streaming */ |
| 1077 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1078 | + 1, OV9282_MODE_STREAMING); |
1016 | 1079 | } |
1017 | 1080 |
|
1018 | | - return 0; |
| 1081 | + if (ret) |
| 1082 | + dev_err(ov9282->dev, "fail to start streaming"); |
| 1083 | + |
| 1084 | + return ret; |
1019 | 1085 | } |
1020 | 1086 |
|
1021 | 1087 | /** |
@@ -1401,6 +1467,7 @@ static int ov9282_probe(struct i2c_client *client) |
1401 | 1467 | { |
1402 | 1468 | struct ov9282 *ov9282; |
1403 | 1469 | int ret; |
| 1470 | + u32 trig_mod; |
1404 | 1471 |
|
1405 | 1472 | ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL); |
1406 | 1473 | if (!ov9282) |
@@ -1440,6 +1507,10 @@ static int ov9282_probe(struct i2c_client *client) |
1440 | 1507 | ov9282->code = MEDIA_BUS_FMT_Y10_1X10; |
1441 | 1508 | ov9282->vblank = ov9282->cur_mode->vblank; |
1442 | 1509 |
|
| 1510 | + ret = of_property_read_u32(client->dev.of_node, |
| 1511 | + "trigger-mode", &trig_mod); |
| 1512 | + ov9282->trigger_mode = (ret == 0) ? trig_mod : -1; |
| 1513 | + |
1443 | 1514 | ret = ov9282_init_controls(ov9282); |
1444 | 1515 | if (ret) { |
1445 | 1516 | dev_err(ov9282->dev, "failed to init controls: %d", ret); |
|
0 commit comments