12
12
#include <zephyr/drivers/video-controls.h>
13
13
#include <zephyr/drivers/i2c.h>
14
14
#include <zephyr/drivers/gpio.h>
15
-
15
+ #include <zephyr/dt-bindings/video/video-interfaces.h>
16
16
#include <zephyr/logging/log.h>
17
17
18
18
#include "video_ctrls.h"
@@ -42,6 +42,54 @@ LOG_MODULE_REGISTER(video_gc2145, CONFIG_VIDEO_LOG_LEVEL);
42
42
#define GC2145_REG_SUBSAMPLE_MODE 0x9A
43
43
#define GC2145_SUBSAMPLE_MODE_SMOOTH 0x0E
44
44
45
+ /* MIPI-CSI registers - on page 3 */
46
+ #define GC2145_REG_DPHY_MODE1 0x01
47
+ #define GC2145_DPHY_MODE1_CLK_EN BIT(0)
48
+ #define GC2145_DPHY_MODE1_LANE0_EN BIT(1)
49
+ #define GC2145_DPHY_MODE1_LANE1_EN BIT(2)
50
+ #define GC2145_DPHY_MODE1_CLK_LANE_P2S_SEL BIT(7)
51
+
52
+ #define GC2145_REG_DPHY_MODE2 0x02
53
+ #define GC2145_DPHY_MODE2_CLK_DIFF (a ) ((a) & 0x07)
54
+ #define GC2145_DPHY_MODE2_LANE0_DIFF (a ) (((a) & 0x07) << 4)
55
+
56
+ #define GC2145_REG_DPHY_MODE3 0x03
57
+ #define GC2145_DPHY_MODE3_LANE1_DIFF (a ) ((a) & 0x07)
58
+ #define GC2145_DPHY_MODE3_CLK_DELAY BIT(4)
59
+ #define GC2145_DPHY_MODE3_LANE0_DELAY BIT(5)
60
+ #define GC2145_DPHY_MODE3_LANE1_DELAY BIT(6)
61
+
62
+ #define GC2145_REG_FIFO_FULL_LVL_LOW 0x04
63
+ #define GC2145_REG_FIFO_FULL_LVL_HIGH 0x05
64
+ #define GC2145_REG_FIFO_MODE 0x06
65
+ #define GC2145_FIFO_MODE_READ_GATE BIT(3)
66
+ #define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)
67
+
68
+ #define GC2145_REG_BUF_CSI2_MODE 0x10
69
+ #define GC2145_CSI2_MODE_DOUBLE BIT(0)
70
+ #define GC2145_CSI2_MODE_RAW8 BIT(2)
71
+ #define GC2145_CSI2_MODE_MIPI_EN BIT(4)
72
+ #define GC2145_CSI2_MODE_EN BIT(7)
73
+
74
+ #define GC2145_REG_MIPI_DT 0x11
75
+ #define GC2145_REG_LWC_LOW 0x12
76
+ #define GC2145_REG_LWC_HIGH 0x13
77
+ #define GC2145_REG_DPHY_MODE 0x15
78
+ #define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)
79
+
80
+ #define GC2145_REG_FIFO_GATE_MODE 0x17
81
+ #define GC2145_REG_T_LPX 0x21
82
+ #define GC2145_REG_T_CLK_HS_PREPARE 0x22
83
+ #define GC2145_REG_T_CLK_ZERO 0x23
84
+ #define GC2145_REG_T_CLK_PRE 0x24
85
+ #define GC2145_REG_T_CLK_POST 0x25
86
+ #define GC2145_REG_T_CLK_TRAIL 0x26
87
+ #define GC2145_REG_T_HS_EXIT 0x27
88
+ #define GC2145_REG_T_WAKEUP 0x28
89
+ #define GC2145_REG_T_HS_PREPARE 0x29
90
+ #define GC2145_REG_T_HS_ZERO 0x2a
91
+ #define GC2145_REG_T_HS_TRAIL 0x2b
92
+
45
93
#define UXGA_HSIZE 1600
46
94
#define UXGA_VSIZE 1200
47
95
@@ -681,6 +729,32 @@ static const struct gc2145_reg default_regs[] = {
681
729
{0x00 , 0x00 },
682
730
};
683
731
732
+ static const struct gc2145_reg default_mipi_csi_regs [] = {
733
+ /* Switch to page 3 */
734
+ {0xfe , 0x03 },
735
+ {GC2145_REG_DPHY_MODE1 , GC2145_DPHY_MODE1_CLK_EN |
736
+ GC2145_DPHY_MODE1_LANE0_EN | GC2145_DPHY_MODE1_LANE1_EN |
737
+ GC2145_DPHY_MODE1_CLK_LANE_P2S_SEL },
738
+ {GC2145_REG_DPHY_MODE2 , GC2145_DPHY_MODE2_CLK_DIFF (2 ) |
739
+ GC2145_DPHY_MODE2_LANE0_DIFF (2 )},
740
+ {GC2145_REG_DPHY_MODE3 , GC2145_DPHY_MODE3_LANE1_DIFF (0 ) |
741
+ GC2145_DPHY_MODE3_CLK_DELAY },
742
+ {GC2145_REG_FIFO_MODE , GC2145_FIFO_MODE_READ_GATE |
743
+ GC2145_FIFO_MODE_MIPI_CLK_MODULE },
744
+ {GC2145_REG_DPHY_MODE , GC2145_DPHY_MODE_TRIGGER_PROG },
745
+
746
+ /* Clock & Data lanes timing */
747
+ {GC2145_REG_T_LPX , 0x10 },
748
+ {GC2145_REG_T_CLK_HS_PREPARE , 0x04 },
749
+ {GC2145_REG_T_CLK_ZERO , 0x10 },
750
+ {GC2145_REG_T_CLK_PRE , 0x10 },
751
+ {GC2145_REG_T_CLK_POST , 0x10 },
752
+ {GC2145_REG_T_CLK_TRAIL , 0x05 },
753
+ {GC2145_REG_T_HS_PREPARE , 0x03 },
754
+ {GC2145_REG_T_HS_ZERO , 0x0a },
755
+ {GC2145_REG_T_HS_TRAIL , 0x06 },
756
+ };
757
+
684
758
struct gc2145_config {
685
759
struct i2c_dt_spec i2c ;
686
760
#if DT_INST_NODE_HAS_PROP (0 , pwdn_gpios )
@@ -689,11 +763,13 @@ struct gc2145_config {
689
763
#if DT_INST_NODE_HAS_PROP (0 , reset_gpios )
690
764
struct gpio_dt_spec reset_gpio ;
691
765
#endif
766
+ int bus_type ;
692
767
};
693
768
694
769
struct gc2145_ctrls {
695
770
struct video_ctrl hflip ;
696
771
struct video_ctrl vflip ;
772
+ struct video_ctrl pixelrate ;
697
773
};
698
774
699
775
struct gc2145_data {
@@ -1038,10 +1114,85 @@ static uint8_t gc2145_check_connection(const struct device *dev)
1038
1114
return 0 ;
1039
1115
}
1040
1116
1117
+ #define GC2145_640_480_PIXEL_RATE 30000000
1118
+ #define GC2145_1600_1200_PIXEL_RATE 60000000
1119
+ static int gc2145_config_csi (const struct device * dev , uint32_t pixelformat ,
1120
+ uint32_t width , uint32_t height )
1121
+ {
1122
+ const struct gc2145_config * cfg = dev -> config ;
1123
+ struct gc2145_data * drv_data = dev -> data ;
1124
+ struct gc2145_ctrls * ctrls = & drv_data -> ctrls ;
1125
+ uint16_t fifo_full_level = width == 1600 ? 0x0001 : 0x0190 ;
1126
+ uint16_t lwc = width * 2 ;
1127
+ uint8_t csi_dt ;
1128
+ int ret ;
1129
+
1130
+ switch (pixelformat ) {
1131
+ case VIDEO_PIX_FMT_RGB565 :
1132
+ csi_dt = VIDEO_MIPI_CSI2_DT_RGB565 ;
1133
+ break ;
1134
+ case VIDEO_PIX_FMT_YUYV :
1135
+ csi_dt = VIDEO_MIPI_CSI2_DT_YUV422_8 ;
1136
+ break ;
1137
+ default :
1138
+ LOG_ERR ("Unsupported pixelformat for CSI" );
1139
+ return - EINVAL ;
1140
+ }
1141
+
1142
+ /* Only VGA & UXGA work (currently) in CSI */
1143
+ if (width == RESOLUTION_VGA_W && height == RESOLUTION_VGA_H ) {
1144
+ ctrls -> pixelrate .val64 = GC2145_640_480_PIXEL_RATE ;
1145
+ } else if (width == RESOLUTION_UXGA_W && height == RESOLUTION_UXGA_H ) {
1146
+ ctrls -> pixelrate .val64 = GC2145_1600_1200_PIXEL_RATE ;
1147
+ } else {
1148
+ LOG_ERR ("Unsupported resolution 320x240 for CSI" );
1149
+ return - EINVAL ;
1150
+ }
1151
+
1152
+ /* Apply fixed settings for MIPI-CSI. After that active page is 3 */
1153
+ ret = gc2145_write_all (dev , default_mipi_csi_regs , ARRAY_SIZE (default_mipi_csi_regs ));
1154
+ if (ret ) {
1155
+ return ret ;
1156
+ }
1157
+
1158
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_LWC_LOW , lwc & 0xff );
1159
+ if (ret ) {
1160
+ return ret ;
1161
+ }
1162
+
1163
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_LWC_HIGH , lwc >> 8 );
1164
+ if (ret ) {
1165
+ return ret ;
1166
+ }
1167
+
1168
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_FIFO_FULL_LVL_LOW , fifo_full_level & 0xff );
1169
+ if (ret ) {
1170
+ return ret ;
1171
+ }
1172
+
1173
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_FIFO_FULL_LVL_HIGH , fifo_full_level >> 8 );
1174
+ if (ret ) {
1175
+ return ret ;
1176
+ }
1177
+
1178
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_FIFO_GATE_MODE , 0xf0 );
1179
+ if (ret ) {
1180
+ return ret ;
1181
+ }
1182
+
1183
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_MIPI_DT , csi_dt );
1184
+ if (ret ) {
1185
+ return ret ;
1186
+ }
1187
+
1188
+ return gc2145_write_reg (& cfg -> i2c , 0xfe , 0x0 );
1189
+ }
1190
+
1041
1191
static int gc2145_set_fmt (const struct device * dev , enum video_endpoint_id ep ,
1042
1192
struct video_format * fmt )
1043
1193
{
1044
1194
struct gc2145_data * drv_data = dev -> data ;
1195
+ const struct gc2145_config * cfg = dev -> config ;
1045
1196
size_t res = ARRAY_SIZE (fmts );
1046
1197
int ret ;
1047
1198
@@ -1080,6 +1231,14 @@ static int gc2145_set_fmt(const struct device *dev, enum video_endpoint_id ep,
1080
1231
return ret ;
1081
1232
}
1082
1233
1234
+ if (cfg -> bus_type == VIDEO_BUS_TYPE_CSI2_DPHY ) {
1235
+ ret = gc2145_config_csi (dev , fmt -> pixelformat , fmt -> width , fmt -> height );
1236
+ if (ret < 0 ) {
1237
+ LOG_ERR ("Failed to configure MIPI-CSI" );
1238
+ return ret ;
1239
+ }
1240
+ }
1241
+
1083
1242
return 0 ;
1084
1243
}
1085
1244
@@ -1093,14 +1252,44 @@ static int gc2145_get_fmt(const struct device *dev, enum video_endpoint_id ep,
1093
1252
return 0 ;
1094
1253
}
1095
1254
1096
- static int gc2145_set_stream (const struct device * dev , bool enable )
1255
+ static int gc2145_set_stream_dvp (const struct device * dev , bool enable )
1097
1256
{
1098
1257
const struct gc2145_config * cfg = dev -> config ;
1099
1258
1100
1259
return enable ? gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x0f )
1101
1260
: gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x00 );
1102
1261
}
1103
1262
1263
+ static int gc2145_set_stream_csi (const struct device * dev , bool enable )
1264
+ {
1265
+ const struct gc2145_config * cfg = dev -> config ;
1266
+ int ret ;
1267
+
1268
+ ret = gc2145_write_reg (& cfg -> i2c , 0xfe , 0x03 );
1269
+ if (ret ) {
1270
+ return ret ;
1271
+ }
1272
+
1273
+ ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_BUF_CSI2_MODE ,
1274
+ enable ? GC2145_CSI2_MODE_RAW8 | GC2145_CSI2_MODE_DOUBLE |
1275
+ GC2145_CSI2_MODE_EN | GC2145_CSI2_MODE_MIPI_EN
1276
+ : 0 );
1277
+ if (ret ) {
1278
+ return ret ;
1279
+ }
1280
+
1281
+ return gc2145_write_reg (& cfg -> i2c , 0xfe , 0x0 );
1282
+ }
1283
+
1284
+ static int gc2145_set_stream (const struct device * dev , bool enable )
1285
+ {
1286
+ const struct gc2145_config * cfg = dev -> config ;
1287
+
1288
+ return cfg -> bus_type == VIDEO_BUS_TYPE_PARALLEL ?
1289
+ gc2145_set_stream_dvp (dev , enable ) :
1290
+ gc2145_set_stream_csi (dev , enable );
1291
+ }
1292
+
1104
1293
static int gc2145_get_caps (const struct device * dev , enum video_endpoint_id ep ,
1105
1294
struct video_caps * caps )
1106
1295
{
@@ -1142,8 +1331,17 @@ static int gc2145_init_controls(const struct device *dev)
1142
1331
return ret ;
1143
1332
}
1144
1333
1145
- return video_init_ctrl (& ctrls -> vflip , dev , VIDEO_CID_VFLIP ,
1146
- (struct video_ctrl_range ){.min = 0 , .max = 1 , .step = 1 , .def = 0 });
1334
+ ret = video_init_ctrl (& ctrls -> vflip , dev , VIDEO_CID_VFLIP ,
1335
+ (struct video_ctrl_range ){.min = 0 , .max = 1 , .step = 1 , .def = 0 });
1336
+ if (ret ) {
1337
+ return ret ;
1338
+ }
1339
+
1340
+ return video_init_ctrl (& ctrls -> pixelrate , dev , VIDEO_CID_PIXEL_RATE ,
1341
+ (struct video_ctrl_range ){.min64 = GC2145_640_480_PIXEL_RATE ,
1342
+ .max64 = GC2145_1600_1200_PIXEL_RATE ,
1343
+ .step64 = 1 ,
1344
+ .def64 = GC2145_640_480_PIXEL_RATE });
1147
1345
}
1148
1346
1149
1347
static int gc2145_init (const struct device * dev )
@@ -1205,6 +1403,8 @@ static const struct gc2145_config gc2145_cfg_0 = {
1205
1403
#if DT_INST_NODE_HAS_PROP (0 , reset_gpios )
1206
1404
.reset_gpio = GPIO_DT_SPEC_INST_GET (0 , reset_gpios ),
1207
1405
#endif
1406
+ .bus_type = DT_PROP_OR (DT_CHILD (DT_INST_CHILD (0 , port ), endpoint ), bus_type ,
1407
+ VIDEO_BUS_TYPE_PARALLEL ),
1208
1408
};
1209
1409
static struct gc2145_data gc2145_data_0 ;
1210
1410
0 commit comments