|
65 | 65 | #define OV9282_REG_MIPI_CTRL00 0x4800 |
66 | 66 | #define OV9282_GATED_CLOCK BIT(5) |
67 | 67 |
|
| 68 | +/* Trigger mode registers */ |
| 69 | +#define OV9282_REG_POWER_CTRL 0x4F00 |
| 70 | +#define OV9282_REG_LOW_POWER_MODE_CTRL 0x3030 |
| 71 | +#define OV9282_REG_NUM_FRAME_ON_TRIG 0x303F |
| 72 | +#define OV9282_REG_SLEEP_PERIOD_CTRL0 0x302C |
| 73 | +#define OV9282_REG_SLEEP_PERIOD_CTRL3 0x302F |
| 74 | +#define OV9282_REG_TIMING_23 0x3823 |
| 75 | + |
68 | 76 | /* Input clock rate */ |
69 | 77 | #define OV9282_INCLK_RATE 24000000 |
70 | 78 |
|
@@ -187,6 +195,7 @@ struct ov9282 { |
187 | 195 | const struct ov9282_mode *cur_mode; |
188 | 196 | u32 code; |
189 | 197 | struct mutex mutex; |
| 198 | + int trigger_mode; |
190 | 199 | }; |
191 | 200 |
|
192 | 201 | static const s64 link_freq[] = { |
@@ -947,6 +956,52 @@ static int ov9282_get_selection(struct v4l2_subdev *sd, |
947 | 956 | return -EINVAL; |
948 | 957 | } |
949 | 958 |
|
| 959 | +/** |
| 960 | + * ov9282_apply_trigger_config() - Configure sensor for FSIN external trigger mode |
| 961 | + * @ov9282: pointer to ov9282 device |
| 962 | + * |
| 963 | + * Return: 0 on success, error code otherwise. |
| 964 | + */ |
| 965 | +static int ov9282_apply_trigger_config(struct ov9282 *ov9282) |
| 966 | +{ |
| 967 | + int ret; |
| 968 | + |
| 969 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 970 | + 1, OV9282_MODE_STANDBY); |
| 971 | + if (ret) |
| 972 | + return ret; |
| 973 | + |
| 974 | + /* Low power mode */ |
| 975 | + ret = ov9282_write_reg(ov9282, OV9282_REG_POWER_CTRL, 1, 0x01); |
| 976 | + if (ret) |
| 977 | + return ret; |
| 978 | + |
| 979 | + /* External trigger snapshot */ |
| 980 | + ret = ov9282_write_reg(ov9282, OV9282_REG_LOW_POWER_MODE_CTRL, 1, 0x04); |
| 981 | + if (ret) |
| 982 | + return ret; |
| 983 | + |
| 984 | + /* 1 frame per trigger */ |
| 985 | + ret = ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01); |
| 986 | + if (ret) |
| 987 | + return ret; |
| 988 | + |
| 989 | + ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00); |
| 990 | + if (ret) |
| 991 | + return ret; |
| 992 | + |
| 993 | + ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F); |
| 994 | + if (ret) |
| 995 | + return ret; |
| 996 | + |
| 997 | + /* No auto wake */ |
| 998 | + ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00); |
| 999 | + if (ret) |
| 1000 | + return ret; |
| 1001 | + |
| 1002 | + return 0; |
| 1003 | +} |
| 1004 | + |
950 | 1005 | /** |
951 | 1006 | * ov9282_start_streaming() - Start sensor stream |
952 | 1007 | * @ov9282: pointer to ov9282 device |
@@ -998,15 +1053,26 @@ static int ov9282_start_streaming(struct ov9282 *ov9282) |
998 | 1053 | return ret; |
999 | 1054 | } |
1000 | 1055 |
|
1001 | | - /* Start streaming */ |
1002 | | - ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
1003 | | - 1, OV9282_MODE_STREAMING); |
1004 | | - if (ret) { |
1005 | | - dev_err(ov9282->dev, "fail to start streaming"); |
1006 | | - return ret; |
| 1056 | + /* Configure FSIN external trigger mode */ |
| 1057 | + if (ov9282->trigger_mode > 0) { |
| 1058 | + ret = ov9282_apply_trigger_config(ov9282); |
| 1059 | + if (ret) { |
| 1060 | + dev_err(ov9282->dev, "failed to config external trigger mode"); |
| 1061 | + return ret; |
| 1062 | + } |
| 1063 | + /* stay in standby mode and wait for trigger signal */ |
| 1064 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1065 | + 1, OV9282_MODE_STANDBY); |
| 1066 | + } else { |
| 1067 | + /* Start streaming */ |
| 1068 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1069 | + 1, OV9282_MODE_STREAMING); |
1007 | 1070 | } |
1008 | 1071 |
|
1009 | | - return 0; |
| 1072 | + if (ret) |
| 1073 | + dev_err(ov9282->dev, "fail to start streaming"); |
| 1074 | + |
| 1075 | + return ret; |
1010 | 1076 | } |
1011 | 1077 |
|
1012 | 1078 | /** |
@@ -1392,6 +1458,7 @@ static int ov9282_probe(struct i2c_client *client) |
1392 | 1458 | { |
1393 | 1459 | struct ov9282 *ov9282; |
1394 | 1460 | int ret; |
| 1461 | + u32 trig_mod; |
1395 | 1462 |
|
1396 | 1463 | ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL); |
1397 | 1464 | if (!ov9282) |
@@ -1431,6 +1498,10 @@ static int ov9282_probe(struct i2c_client *client) |
1431 | 1498 | ov9282->code = MEDIA_BUS_FMT_Y10_1X10; |
1432 | 1499 | ov9282->vblank = ov9282->cur_mode->vblank; |
1433 | 1500 |
|
| 1501 | + ret = of_property_read_u32(client->dev.of_node, |
| 1502 | + "trigger-mode", &trig_mod); |
| 1503 | + ov9282->trigger_mode = (ret == 0) ? trig_mod : -1; |
| 1504 | + |
1434 | 1505 | ret = ov9282_init_controls(ov9282); |
1435 | 1506 | if (ret) { |
1436 | 1507 | dev_err(ov9282->dev, "failed to init controls: %d", ret); |
|
0 commit comments