9
9
#include <zephyr/drivers/video.h>
10
10
#include <zephyr/kernel.h>
11
11
#include <zephyr/logging/log.h>
12
+ #include <soc.h>
12
13
13
14
#include <fsl_mipi_csi2rx.h>
14
15
15
16
LOG_MODULE_REGISTER (video_mipi_csi2rx , CONFIG_VIDEO_LOG_LEVEL );
16
17
17
- #define DEFAULT_CAMERA_FRAME_RATE 30
18
+ #define MAX_SUPPORTED_PIXEL_RATE MHZ(96)
19
+
20
+ #define ABS (a , b ) (a > b ? a - b : b - a)
18
21
19
22
struct mipi_csi2rx_config {
20
23
const MIPI_CSI2RX_Type * base ;
@@ -25,98 +28,82 @@ struct mipi_csi2rx_data {
25
28
csi2rx_config_t csi2rxConfig ;
26
29
};
27
30
28
- static int mipi_csi2rx_set_fmt (const struct device * dev , enum video_endpoint_id ep ,
29
- struct video_format * fmt )
31
+ struct mipi_csi2rx_tHsSettleEscClk_config {
32
+ uint64_t pixel_rate ;
33
+ uint8_t tHsSettle_EscClk ;
34
+ };
35
+
36
+ /* Must be in pixel rate ascending order */
37
+ const struct mipi_csi2rx_tHsSettleEscClk_config tHsSettleEscClk_configs [] = {
38
+ {MHZ (24 ), 0x24 },
39
+ {MHZ (48 ), 0x12 },
40
+ {MHZ (96 ), 0x09 },
41
+ };
42
+
43
+ static int mipi_csi2rx_update_settings (const struct device * dev , enum video_endpoint_id ep )
30
44
{
31
45
const struct mipi_csi2rx_config * config = dev -> config ;
32
46
struct mipi_csi2rx_data * drv_data = dev -> data ;
33
- csi2rx_config_t csi2rxConfig = {0 };
34
- uint8_t i = 0 ;
47
+ uint8_t bpp ;
48
+ uint64_t sensor_pixel_rate , sensor_lane_rate , sensor_byte_clk ;
49
+ uint32_t best_match ;
50
+ int ret , ind = 0 ;
51
+ struct video_format fmt ;
52
+
53
+ ret = video_get_format (config -> sensor_dev , ep , & fmt );
54
+ if (ret ) {
55
+ LOG_ERR ("Cannot get sensor_dev pixel format" );
56
+ return ret ;
57
+ }
35
58
36
- /*
37
- * Initialize the MIPI CSI2
38
- *
39
- * From D-PHY specification, the T-HSSETTLE should in the range of 85ns+6*UI to 145ns+10*UI
40
- * UI is Unit Interval, equal to the duration of any HS state on the Clock Lane
41
- *
42
- * T-HSSETTLE = csi2rxConfig.tHsSettle_EscClk * (Tperiod of RxClkInEsc)
43
- *
44
- * csi2rxConfig.tHsSettle_EscClk setting for camera:
45
- *
46
- * Resolution | frame rate | T_HS_SETTLE
47
- * =============================================
48
- * 720P | 30 | 0x12
49
- * ---------------------------------------------
50
- * 720P | 15 | 0x17
51
- * ---------------------------------------------
52
- * VGA | 30 | 0x1F
53
- * ---------------------------------------------
54
- * VGA | 15 | 0x24
55
- * ---------------------------------------------
56
- * QVGA | 30 | 0x1F
57
- * ---------------------------------------------
58
- * QVGA | 15 | 0x24
59
- * ---------------------------------------------
60
- */
61
- static const uint32_t csi2rxHsSettle [][4 ] = {
62
- {
63
- 1280 ,
64
- 720 ,
65
- 30 ,
66
- 0x12 ,
67
- },
68
- {
69
- 1280 ,
70
- 720 ,
71
- 15 ,
72
- 0x17 ,
73
- },
74
- {
75
- 640 ,
76
- 480 ,
77
- 30 ,
78
- 0x1F ,
79
- },
80
- {
81
- 640 ,
82
- 480 ,
83
- 15 ,
84
- 0x24 ,
85
- },
86
- {
87
- 320 ,
88
- 240 ,
89
- 30 ,
90
- 0x1F ,
91
- },
92
- {
93
- 320 ,
94
- 240 ,
95
- 15 ,
96
- 0x24 ,
97
- },
98
- };
99
-
100
- for (i = 0 ; i < ARRAY_SIZE (csi2rxHsSettle ); i ++ ) {
101
- if ((fmt -> width == csi2rxHsSettle [i ][0 ]) && (fmt -> height == csi2rxHsSettle [i ][1 ]) &&
102
- (DEFAULT_CAMERA_FRAME_RATE == csi2rxHsSettle [i ][2 ])) {
103
- csi2rxConfig .tHsSettle_EscClk = csi2rxHsSettle [i ][3 ];
104
- break ;
105
- }
59
+ ret = video_get_ctrl (config -> sensor_dev , VIDEO_CID_PIXEL_RATE , & sensor_pixel_rate );
60
+ if (ret ) {
61
+ LOG_ERR ("Can not get sensor_dev pixel rate" );
62
+ return ret ;
106
63
}
107
64
108
- if (i == ARRAY_SIZE (csi2rxHsSettle )) {
109
- LOG_ERR ("Unsupported resolution" );
65
+ bpp = video_pix_fmt_bpp (fmt .pixelformat ) * 8 ;
66
+ sensor_lane_rate = sensor_pixel_rate * bpp / drv_data -> csi2rxConfig .laneNum ;
67
+
68
+ if (sensor_pixel_rate > MAX_SUPPORTED_PIXEL_RATE ) {
69
+ LOG_ERR ("Sensor pixel rate is not supported" );
110
70
return - ENOTSUP ;
111
71
}
112
72
113
- drv_data -> csi2rxConfig = csi2rxConfig ;
73
+ sensor_byte_clk = sensor_pixel_rate * bpp / drv_data -> csi2rxConfig .laneNum / 8 ;
74
+ if (sensor_byte_clk > CLOCK_GetRootClockFreq (kCLOCK_Root_Csi2 )) {
75
+ mipi_csi2rx_clock_set_freq (kCLOCK_Root_Csi2 , sensor_byte_clk );
76
+ }
77
+
78
+ if (sensor_pixel_rate > CLOCK_GetRootClockFreq (kCLOCK_Root_Csi2_Ui )) {
79
+ mipi_csi2rx_clock_set_freq (kCLOCK_Root_Csi2_Ui , sensor_pixel_rate );
80
+ }
81
+
82
+ /* Find the supported sensor_pixel_rate closest to the desired one */
83
+ best_match = tHsSettleEscClk_configs [ind ].pixel_rate ;
84
+ for (uint8_t i = 0 ; i < ARRAY_SIZE (tHsSettleEscClk_configs ); i ++ ) {
85
+ if (ABS (tHsSettleEscClk_configs [i ].pixel_rate , sensor_pixel_rate ) <
86
+ ABS (tHsSettleEscClk_configs [i ].pixel_rate , best_match )) {
87
+ best_match = tHsSettleEscClk_configs [i ].pixel_rate ;
88
+ ind = i ;
89
+ }
90
+ }
91
+
92
+ drv_data -> csi2rxConfig .tHsSettle_EscClk = tHsSettleEscClk_configs [ind ].tHsSettle_EscClk ;
93
+
94
+ return ret ;
95
+ }
96
+
97
+ static int mipi_csi2rx_set_fmt (const struct device * dev , enum video_endpoint_id ep ,
98
+ struct video_format * fmt )
99
+ {
100
+ const struct mipi_csi2rx_config * config = dev -> config ;
114
101
115
102
if (video_set_format (config -> sensor_dev , ep , fmt )) {
116
103
return - EIO ;
117
104
}
118
105
119
- return 0 ;
106
+ return mipi_csi2rx_update_settings ( dev , ep ) ;
120
107
}
121
108
122
109
static int mipi_csi2rx_get_fmt (const struct device * dev , enum video_endpoint_id ep ,
@@ -204,7 +191,13 @@ static int mipi_csi2rx_init(const struct device *dev)
204
191
return - ENODEV ;
205
192
}
206
193
207
- return 0 ;
194
+ /*
195
+ * CSI2 escape clock should be in the range [60, 80] Mhz. We set it
196
+ * to 60 Mhz.
197
+ */
198
+ mipi_csi2rx_clock_set_freq (kCLOCK_Root_Csi2_Esc , MHZ (60 ));
199
+
200
+ return mipi_csi2rx_update_settings (dev , VIDEO_EP_ALL );
208
201
}
209
202
210
203
#define MIPI_CSI2RX_INIT (n ) \
0 commit comments