Skip to content

Commit 425a1df

Browse files
trunghieulenxpngphibang
authored andcommitted
drivers: video: mcux_mipi_csi2rx: Set clocks according to pixel rate
Instead of fixing csi2rx clock frequencies, set them according to the pixel rate got from the camera sensor. Signed-off-by: Trung Hieu Le <trunghieu.le@nxp.com> Signed-off-by: Phi Bang Nguyen <phibang.nguyen@nxp.com>
1 parent 9b58769 commit 425a1df

File tree

3 files changed

+106
-91
lines changed

3 files changed

+106
-91
lines changed

drivers/video/video_mcux_mipi_csi2rx.c

Lines changed: 73 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
#include <zephyr/drivers/video.h>
1010
#include <zephyr/kernel.h>
1111
#include <zephyr/logging/log.h>
12+
#include <soc.h>
1213

1314
#include <fsl_mipi_csi2rx.h>
1415

1516
LOG_MODULE_REGISTER(video_mipi_csi2rx, CONFIG_VIDEO_LOG_LEVEL);
1617

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)
1821

1922
struct mipi_csi2rx_config {
2023
const MIPI_CSI2RX_Type *base;
@@ -25,98 +28,82 @@ struct mipi_csi2rx_data {
2528
csi2rx_config_t csi2rxConfig;
2629
};
2730

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)
3044
{
3145
const struct mipi_csi2rx_config *config = dev->config;
3246
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+
}
3558

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;
10663
}
10764

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");
11070
return -ENOTSUP;
11171
}
11272

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;
114101

115102
if (video_set_format(config->sensor_dev, ep, fmt)) {
116103
return -EIO;
117104
}
118105

119-
return 0;
106+
return mipi_csi2rx_update_settings(dev, ep);
120107
}
121108

122109
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)
204191
return -ENODEV;
205192
}
206193

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);
208201
}
209202

210203
#define MIPI_CSI2RX_INIT(n) \

soc/nxp/imxrt/imxrt11xx/soc.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -474,17 +474,6 @@ static ALWAYS_INLINE void clock_init(void)
474474
CLOCK_EnableClock(kCLOCK_Video_Mux);
475475
VIDEO_MUX->VID_MUX_CTRL.SET = VIDEO_MUX_VID_MUX_CTRL_CSI_SEL_MASK;
476476

477-
/* Configure MIPI CSI-2 Rx clocks */
478-
rootCfg.div = 8;
479-
rootCfg.mux = kCLOCK_CSI2_ClockRoot_MuxSysPll3Out;
480-
CLOCK_SetRootClock(kCLOCK_Root_Csi2, &rootCfg);
481-
482-
rootCfg.mux = kCLOCK_CSI2_ESC_ClockRoot_MuxSysPll3Out;
483-
CLOCK_SetRootClock(kCLOCK_Root_Csi2_Esc, &rootCfg);
484-
485-
rootCfg.mux = kCLOCK_CSI2_UI_ClockRoot_MuxSysPll3Out;
486-
CLOCK_SetRootClock(kCLOCK_Root_Csi2_Ui, &rootCfg);
487-
488477
/* Enable power domain for MIPI CSI-2 */
489478
PGMC_BPC4->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK |
490479
PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK);
@@ -682,6 +671,35 @@ void imxrt_post_init_display_interface(void)
682671

683672
#endif
684673

674+
#if CONFIG_VIDEO_MCUX_MIPI_CSI2RX
675+
void mipi_csi2rx_clock_set_freq(clock_root_t clock_root, uint32_t rate)
676+
{
677+
clock_root_config_t rootCfg = {0};
678+
uint32_t freq;
679+
clock_name_t clk_source;
680+
681+
switch (clock_root) {
682+
case kCLOCK_Root_Csi2:
683+
rootCfg.mux = kCLOCK_CSI2_ClockRoot_MuxSysPll3Out;
684+
break;
685+
case kCLOCK_Root_Csi2_Esc:
686+
rootCfg.mux = kCLOCK_CSI2_ESC_ClockRoot_MuxSysPll3Out;
687+
break;
688+
case kCLOCK_Root_Csi2_Ui:
689+
rootCfg.mux = kCLOCK_CSI2_UI_ClockRoot_MuxSysPll3Out;
690+
break;
691+
default:
692+
return;
693+
}
694+
695+
clk_source = CLOCK_GetRootClockSource(clock_root, rootCfg.mux);
696+
freq = CLOCK_GetFreq(clk_source);
697+
__ASSERT(rate < freq, "Requested rate is higher than the maximum clock frequency");
698+
rootCfg.div = (uint32_t)freq / rate;
699+
CLOCK_SetRootClock(clock_root, &rootCfg);
700+
}
701+
#endif
702+
685703
/**
686704
*
687705
* @brief Perform basic hardware initialization

soc/nxp/imxrt/imxrt11xx/soc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ void imxrt_pre_init_display_interface(void);
3232
void imxrt_post_init_display_interface(void);
3333
#endif
3434

35+
#if CONFIG_VIDEO_MCUX_MIPI_CSI2RX
36+
void mipi_csi2rx_clock_set_freq(clock_root_t clock_root, uint32_t rate);
37+
#endif
38+
3539
void flexspi_clock_set_div(uint32_t value);
3640
uint32_t flexspi_clock_get_freq(void);
3741

0 commit comments

Comments
 (0)