66
77#define DT_DRV_COMPAT nxp_mipi_csi2rx
88
9+ #include <zephyr/drivers/clock_control.h>
910#include <zephyr/drivers/video.h>
1011#include <zephyr/kernel.h>
1112#include <zephyr/logging/log.h>
13+ #include <soc.h>
1214
1315#include <fsl_mipi_csi2rx.h>
1416
1517LOG_MODULE_REGISTER (video_mipi_csi2rx , CONFIG_VIDEO_LOG_LEVEL );
1618
17- #define DEFAULT_CAMERA_FRAME_RATE 30
19+ #define MAX_SUPPORTED_PIXEL_RATE MHZ(96)
20+
21+ #define ABS (a , b ) (a > b ? a - b : b - a)
1822
1923#define DEVICE_DT_INST_GET_SENSOR_DEV (n ) \
2024 DEVICE_DT_GET(DT_GPARENT(DT_NODELABEL( \
@@ -28,100 +32,106 @@ struct mipi_csi2rx_config {
2832
2933struct mipi_csi2rx_data {
3034 csi2rx_config_t csi2rxConfig ;
35+ const struct device * clock_dev ;
36+ clock_control_subsys_t clock_root ;
37+ clock_control_subsys_t clock_ui ;
38+ clock_control_subsys_t clock_esc ;
3139};
3240
33- static int mipi_csi2rx_set_fmt (const struct device * dev , enum video_endpoint_id ep ,
34- struct video_format * fmt )
41+ struct mipi_csi2rx_tHsSettleEscClk_config {
42+ uint64_t pixel_rate ;
43+ uint8_t tHsSettle_EscClk ;
44+ };
45+
46+ /* Must be in pixel rate ascending order */
47+ const struct mipi_csi2rx_tHsSettleEscClk_config tHsSettleEscClk_configs [] = {
48+ {MHZ (24 ), 0x24 },
49+ {MHZ (48 ), 0x12 },
50+ {MHZ (96 ), 0x09 },
51+ };
52+
53+ static int mipi_csi2rx_update_settings (const struct device * dev , enum video_endpoint_id ep )
3554{
3655 const struct mipi_csi2rx_config * config = dev -> config ;
3756 struct mipi_csi2rx_data * drv_data = dev -> data ;
38- csi2rx_config_t csi2rxConfig = {0 };
39- uint8_t i = 0 ;
57+ uint8_t bpp ;
58+ uint64_t sensor_pixel_rate ;
59+ uint32_t root_clk_rate , ui_clk_rate , sensor_byte_clk , best_match ;
60+ int ret , ind = 0 ;
61+ struct video_format fmt ;
62+
63+ ret = video_get_format (config -> sensor_dev , ep , & fmt );
64+ if (ret ) {
65+ LOG_ERR ("Cannot get sensor_dev pixel format" );
66+ return ret ;
67+ }
4068
41- /*
42- * Initialize the MIPI CSI2
43- *
44- * From D-PHY specification, the T-HSSETTLE should in the range of 85ns+6*UI to 145ns+10*UI
45- * UI is Unit Interval, equal to the duration of any HS state on the Clock Lane
46- *
47- * T-HSSETTLE = csi2rxConfig.tHsSettle_EscClk * (Tperiod of RxClkInEsc)
48- *
49- * csi2rxConfig.tHsSettle_EscClk setting for camera:
50- *
51- * Resolution | frame rate | T_HS_SETTLE
52- * =============================================
53- * 720P | 30 | 0x12
54- * ---------------------------------------------
55- * 720P | 15 | 0x17
56- * ---------------------------------------------
57- * VGA | 30 | 0x1F
58- * ---------------------------------------------
59- * VGA | 15 | 0x24
60- * ---------------------------------------------
61- * QVGA | 30 | 0x1F
62- * ---------------------------------------------
63- * QVGA | 15 | 0x24
64- * ---------------------------------------------
65- */
66- static const uint32_t csi2rxHsSettle [][4 ] = {
67- {
68- 1280 ,
69- 720 ,
70- 30 ,
71- 0x12 ,
72- },
73- {
74- 1280 ,
75- 720 ,
76- 15 ,
77- 0x17 ,
78- },
79- {
80- 640 ,
81- 480 ,
82- 30 ,
83- 0x1F ,
84- },
85- {
86- 640 ,
87- 480 ,
88- 15 ,
89- 0x24 ,
90- },
91- {
92- 320 ,
93- 240 ,
94- 30 ,
95- 0x1F ,
96- },
97- {
98- 320 ,
99- 240 ,
100- 15 ,
101- 0x24 ,
102- },
103- };
104-
105- for (i = 0 ; i < ARRAY_SIZE (csi2rxHsSettle ); i ++ ) {
106- if ((fmt -> width == csi2rxHsSettle [i ][0 ]) && (fmt -> height == csi2rxHsSettle [i ][1 ]) &&
107- (DEFAULT_CAMERA_FRAME_RATE == csi2rxHsSettle [i ][2 ])) {
108- csi2rxConfig .tHsSettle_EscClk = csi2rxHsSettle [i ][3 ];
109- break ;
110- }
69+ ret = video_get_ctrl (config -> sensor_dev , VIDEO_CID_PIXEL_RATE , & sensor_pixel_rate );
70+ if (ret ) {
71+ LOG_ERR ("Can not get sensor_dev pixel rate" );
72+ return ret ;
11173 }
11274
113- if (i == ARRAY_SIZE ( csi2rxHsSettle ) ) {
114- LOG_ERR ("Unsupported resolution " );
75+ if (sensor_pixel_rate > MAX_SUPPORTED_PIXEL_RATE ) {
76+ LOG_ERR ("Sensor pixel rate is not supported " );
11577 return - ENOTSUP ;
11678 }
11779
118- drv_data -> csi2rxConfig = csi2rxConfig ;
80+ bpp = video_pix_fmt_bpp (fmt .pixelformat ) * 8 ;
81+ sensor_byte_clk = sensor_pixel_rate * bpp / drv_data -> csi2rxConfig .laneNum / 8 ;
82+
83+ ret = clock_control_get_rate (drv_data -> clock_dev , drv_data -> clock_root , & root_clk_rate );
84+ if (ret ) {
85+ return ret ;
86+ }
87+
88+ if (sensor_byte_clk > root_clk_rate ) {
89+ ret = clock_control_set_rate (drv_data -> clock_dev , drv_data -> clock_root ,
90+ (clock_control_subsys_rate_t )sensor_byte_clk );
91+ if (ret ) {
92+ return ret ;
93+ }
94+ }
95+
96+ ret = clock_control_get_rate (drv_data -> clock_dev , drv_data -> clock_ui , & ui_clk_rate );
97+ if (ret ) {
98+ return ret ;
99+ }
100+
101+ if (sensor_pixel_rate > ui_clk_rate ) {
102+ ret = clock_control_set_rate (
103+ drv_data -> clock_dev , drv_data -> clock_ui ,
104+ (clock_control_subsys_rate_t )(uint32_t )sensor_pixel_rate );
105+ if (ret ) {
106+ return ret ;
107+ }
108+ }
109+
110+ /* Find the supported sensor_pixel_rate closest to the desired one */
111+ best_match = tHsSettleEscClk_configs [ind ].pixel_rate ;
112+ for (uint8_t i = 0 ; i < ARRAY_SIZE (tHsSettleEscClk_configs ); i ++ ) {
113+ if (ABS (tHsSettleEscClk_configs [i ].pixel_rate , sensor_pixel_rate ) <
114+ ABS (tHsSettleEscClk_configs [i ].pixel_rate , best_match )) {
115+ best_match = tHsSettleEscClk_configs [i ].pixel_rate ;
116+ ind = i ;
117+ }
118+ }
119+
120+ drv_data -> csi2rxConfig .tHsSettle_EscClk = tHsSettleEscClk_configs [ind ].tHsSettle_EscClk ;
121+
122+ return ret ;
123+ }
124+
125+ static int mipi_csi2rx_set_fmt (const struct device * dev , enum video_endpoint_id ep ,
126+ struct video_format * fmt )
127+ {
128+ const struct mipi_csi2rx_config * config = dev -> config ;
119129
120130 if (video_set_format (config -> sensor_dev , ep , fmt )) {
121131 return - EIO ;
122132 }
123133
124- return 0 ;
134+ return mipi_csi2rx_update_settings ( dev , ep ) ;
125135}
126136
127137static int mipi_csi2rx_get_fmt (const struct device * dev , enum video_endpoint_id ep ,
@@ -203,20 +213,36 @@ static const struct video_driver_api mipi_csi2rx_driver_api = {
203213static int mipi_csi2rx_init (const struct device * dev )
204214{
205215 const struct mipi_csi2rx_config * config = dev -> config ;
216+ struct mipi_csi2rx_data * drv_data = dev -> data ;
217+ int ret ;
206218
207219 /* Check if there is any sensor device */
208220 if (!device_is_ready (config -> sensor_dev )) {
209221 return - ENODEV ;
210222 }
211223
212- return 0 ;
224+ /*
225+ * CSI2 escape clock should be in the range [60, 80] Mhz. We set it
226+ * to 60 Mhz.
227+ */
228+ ret = clock_control_set_rate (drv_data -> clock_dev , drv_data -> clock_esc ,
229+ (clock_control_subsys_rate_t )MHZ (60 ));
230+ if (ret ) {
231+ return ret ;
232+ }
233+
234+ return mipi_csi2rx_update_settings (dev , VIDEO_EP_ALL );
213235}
214236
215237#define MIPI_CSI2RX_INIT (n ) \
216238 static struct mipi_csi2rx_data mipi_csi2rx_data_##n = { \
217239 .csi2rxConfig.laneNum = \
218240 DT_PROP_LEN(DT_CHILD(DT_CHILD(DT_INST_CHILD(n, ports), port_1), endpoint), \
219241 data_lanes), \
242+ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
243+ .clock_root = (clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_IDX(n, 0, name), \
244+ .clock_ui = (clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_IDX(n, 1, name), \
245+ .clock_esc = (clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_IDX(n, 2, name), \
220246 }; \
221247 \
222248 static const struct mipi_csi2rx_config mipi_csi2rx_config_##n = { \
0 commit comments