|
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,65 @@ 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, 1, OV9282_MODE_STANDBY); |
| 970 | + if (ret) { |
| 971 | + return ret; |
| 972 | + } |
| 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 | + |
| 980 | + /* External trigger snapshot */ |
| 981 | + ret = ov9282_write_reg(ov9282, OV9282_REG_LOW_POWER_MODE_CTRL, 1, 0x04); |
| 982 | + if (ret) { |
| 983 | + return ret; |
| 984 | + } |
| 985 | + |
| 986 | + /* 1 frame per trigger */ |
| 987 | + ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01); |
| 988 | + if (ret) { |
| 989 | + return ret; |
| 990 | + } |
| 991 | + |
| 992 | + ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00); |
| 993 | + if (ret) { |
| 994 | + return ret; |
| 995 | + } |
| 996 | + |
| 997 | + ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F); |
| 998 | + if (ret) { |
| 999 | + return ret; |
| 1000 | + } |
| 1001 | + |
| 1002 | + /* No auto wake */ |
| 1003 | + ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00); |
| 1004 | + if (ret) { |
| 1005 | + return ret; |
| 1006 | + } |
| 1007 | + |
| 1008 | + /* stay standby mode and wait for trigger signal */ |
| 1009 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1010 | + 1, OV9282_MODE_STANDBY); |
| 1011 | + if (ret) { |
| 1012 | + return ret; |
| 1013 | + } |
| 1014 | + |
| 1015 | + return 0; |
| 1016 | +} |
| 1017 | + |
950 | 1018 | /**
|
951 | 1019 | * ov9282_start_streaming() - Start sensor stream
|
952 | 1020 | * @ov9282: pointer to ov9282 device
|
@@ -998,12 +1066,21 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
|
998 | 1066 | return ret;
|
999 | 1067 | }
|
1000 | 1068 |
|
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; |
| 1069 | + if (ov9282->trigger_mode > 0) { |
| 1070 | + /* Configure FSIN external trigger mode */ |
| 1071 | + ret = ov9282_apply_trigger_config(ov9282); |
| 1072 | + if (ret) { |
| 1073 | + dev_err(ov9282->dev, "failed to config external trigger mode"); |
| 1074 | + } |
| 1075 | + } |
| 1076 | + else { |
| 1077 | + /* Start streaming */ |
| 1078 | + ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, |
| 1079 | + 1, OV9282_MODE_STREAMING); |
| 1080 | + if (ret) { |
| 1081 | + dev_err(ov9282->dev, "fail to start streaming"); |
| 1082 | + return ret; |
| 1083 | + } |
1007 | 1084 | }
|
1008 | 1085 |
|
1009 | 1086 | return 0;
|
@@ -1392,6 +1469,7 @@ static int ov9282_probe(struct i2c_client *client)
|
1392 | 1469 | {
|
1393 | 1470 | struct ov9282 *ov9282;
|
1394 | 1471 | int ret;
|
| 1472 | + u32 trig_mod; |
1395 | 1473 |
|
1396 | 1474 | ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
|
1397 | 1475 | if (!ov9282)
|
@@ -1431,6 +1509,9 @@ static int ov9282_probe(struct i2c_client *client)
|
1431 | 1509 | ov9282->code = MEDIA_BUS_FMT_Y10_1X10;
|
1432 | 1510 | ov9282->vblank = ov9282->cur_mode->vblank;
|
1433 | 1511 |
|
| 1512 | + ret = of_property_read_u32(client->dev.of_node, "trigger-mode", &trig_mod); |
| 1513 | + ov9282->trigger_mode = (ret == 0) ? trig_mod : -1; |
| 1514 | + |
1434 | 1515 | ret = ov9282_init_controls(ov9282);
|
1435 | 1516 | if (ret) {
|
1436 | 1517 | dev_err(ov9282->dev, "failed to init controls: %d", ret);
|
|
0 commit comments