Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/video/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zephyr_library()
zephyr_library_sources(video_common.c)

zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_CSI video_mcux_csi.c)
zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_MIPI_CSI2RX video_mcux_mipi_csi2rx.c)
zephyr_library_sources_ifdef(CONFIG_VIDEO_SW_GENERATOR video_sw_generator.c)
zephyr_library_sources_ifdef(CONFIG_VIDEO_MT9M114 mt9m114.c)
zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c)
Expand Down
2 changes: 2 additions & 0 deletions drivers/video/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ config VIDEO_BUFFER_POOL_ALIGN

source "drivers/video/Kconfig.mcux_csi"

source "drivers/video/Kconfig.mcux_mipi_csi2rx"

source "drivers/video/Kconfig.sw_generator"

source "drivers/video/Kconfig.mt9m114"
Expand Down
10 changes: 10 additions & 0 deletions drivers/video/Kconfig.mcux_mipi_csi2rx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# NXP MIPI CSI-2 Rx driver configuration option

# Copyright 2024 NXP
# SPDX-License-Identifier: Apache-2.0

config VIDEO_MCUX_MIPI_CSI2RX
bool "NXP MIPI CSI-2 Rx driver"
default y
depends on DT_HAS_NXP_MIPI_CSI2RX_ENABLED
select VIDEO_MCUX_CSI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VIDEO_MCUX_CSI currently depends on HAS_MCUX_CSI, which we don't select for the RT11xx. Perhaps the best choice is to remove the dependency on HAS_MCUX_CSI in #72420?

Copy link
Contributor Author

@ngphibang ngphibang May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is already done in #71860 as a "misc fix".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, this does not relate to this PR, right ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed that PR- it does relate, because the select VIDEO_MCUX_CSI statement here will trigger a Kconfig error on the RT11xx series when building the CSI2X driver, because VIDEO_MCUX_CSI currently has a dependency on HAS_MCUX_CSI. All this means is that this PR is dependent on #71860, as far as I can tell

Copy link
Contributor Author

@ngphibang ngphibang May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this CSI2Rx driver doesn't build. Both CSI and CSI2Rx will build only when there is a camera sensor connected to them and the build is triggered in the camera sensor overlay (another PR). By default, CSI2Rx and CSI nodes are disabled.

BTW, this PR is dependent on #72420 because of the change from "sensor" to "sdev".

So, there is a mutual dependency here ...

Copy link
Contributor Author

@ngphibang ngphibang May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danieldegrasse : So, is it better to move the commit b226ded to #71860 or make it a standalone PR ? I think the first option is better

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine to move b226dedfbc2c4cbcf37dd1c86e85895a4660afa3 into #71860.

But this CSI2Rx driver doesn't build. Both CSI and CSI2Rx will build only when there is a camera sensor connected to them and the build is triggered in the camera sensor overlay (another PR). By default, CSI2Rx and CSI nodes are disabled.

Maybe I'm not following here- are you saying that since the CSI2Rx driver does not build as part of this PR, there is no dependency on #71860? Generally, we want to be able to build code that is introduced with a PR as part of that PR. Finding out there is a build error later on means we have to fix something in the tree, which is less clean than getting it right the first time around

Copy link
Contributor Author

@ngphibang ngphibang May 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay ...

This PR is now dependent on #72623 and #71854 as #71860 is merged.

Is it ok for you now ?

Copy link
Contributor

@danieldegrasse danieldegrasse May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this is ok. To make sure I understand the dependency chain here:

#72623: no dependencies
#71854: no dependencies
#71859: dependent on #72623 and #71854
#72420: dependent on #71859 (and its dependencies)
#72434: dependent on #72420 (and its dependencies)
#72632: dependent on #72434 (and its dependencies)

Is this all accurate? I'm not clear why this PR depends on #71854, but you know this code best

Copy link
Contributor Author

@ngphibang ngphibang May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danieldegrasse It's nearly correct. The dependency chain are:
#72435: no dependencies
#71854: no dependencies
#72623: no dependencies (merged)
#72631: no dependencies (merged)
#71859: dependent on #72623 (merged) and #71854
#72420: dependent on #71859 (and its dependencies)
#72434: dependent on #71859 (and its dependencies)
#72633: dependent on #72434 (and its dependencies)

218 changes: 218 additions & 0 deletions drivers/video/video_mcux_mipi_csi2rx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nxp_mipi_csi2rx

#include <fsl_mipi_csi2rx.h>

#include <zephyr/drivers/video.h>
#include <zephyr/kernel.h>

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mipi_csi);

/*
* Two data lanes are set by default as 2-lanes camera sensors are
* more common and more performant but single lane is also supported.
*/
#define DEFAULT_MIPI_CSI_NUM_LANES 2
#define DEFAULT_CAMERA_FRAME_RATE 30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a value to making this a Kconfig. Write now the user has to edit this driver file to change the default frame rate.

Copy link
Contributor Author

@ngphibang ngphibang May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmahadevan108 : This has been explained to Daniel. Similar to format, framerate setting needs a runtime accordance and depends on capacity of multiple elements along the camera pipeline. That means which framerate can be supported depends on not only the mipi csi2rx but also other elements (e.g. the camera sensor). It also depends on which format is chosen at runtime.

That's why simply putting this setting in devicetree or Kconfig will not work. I made this PR to add framerate APIs. The ov5640 camera sensor driver will need to be changed as well to support framerate changing. When these things are done and merged, we will be able improve this driver to add support for framerate changing.


struct mipi_csi2rx_config {
const MIPI_CSI2RX_Type *base;
const struct device *sensor_dev;
};

struct mipi_csi2rx_data {
csi2rx_config_t csi2rxConfig;
};

static int mipi_csi2rx_set_fmt(const struct device *dev, enum video_endpoint_id ep,
struct video_format *fmt)
{
const struct mipi_csi2rx_config *config = dev->config;
struct mipi_csi2rx_data *drv_data = dev->data;
csi2rx_config_t csi2rxConfig = {0};
uint8_t i = 0;

/*
* Initialize the MIPI CSI2
*
* From D-PHY specification, the T-HSSETTLE should in the range of 85ns+6*UI to 145ns+10*UI
* UI is Unit Interval, equal to the duration of any HS state on the Clock Lane
*
* T-HSSETTLE = csi2rxConfig.tHsSettle_EscClk * (Tperiod of RxClkInEsc)
*
* csi2rxConfig.tHsSettle_EscClk setting for camera:
*
* Resolution | frame rate | T_HS_SETTLE
* =============================================
* 720P | 30 | 0x12
* ---------------------------------------------
* 720P | 15 | 0x17
* ---------------------------------------------
* VGA | 30 | 0x1F
* ---------------------------------------------
* VGA | 15 | 0x24
* ---------------------------------------------
* QVGA | 30 | 0x1F
* ---------------------------------------------
* QVGA | 15 | 0x24
* ---------------------------------------------
*/
static const uint32_t csi2rxHsSettle[][4] = {
{
1280,
720,
30,
0x12,
},
{
1280,
720,
15,
0x17,
},
{
640,
480,
30,
0x1F,
},
{
640,
480,
15,
0x24,
},
{
320,
240,
30,
0x1F,
},
{
320,
240,
15,
0x24,
},
};

csi2rxConfig.laneNum = DEFAULT_MIPI_CSI_NUM_LANES;

for (i = 0; i < ARRAY_SIZE(csi2rxHsSettle); i++) {
if ((fmt->width == csi2rxHsSettle[i][0]) && (fmt->height == csi2rxHsSettle[i][1]) &&
(DEFAULT_CAMERA_FRAME_RATE == csi2rxHsSettle[i][2])) {
csi2rxConfig.tHsSettle_EscClk = csi2rxHsSettle[i][3];
break;
}
}

if (i == ARRAY_SIZE(csi2rxHsSettle)) {
LOG_ERR("Unsupported resolution");
return -ENOTSUP;
}

drv_data->csi2rxConfig = csi2rxConfig;

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

return 0;
}

static int mipi_csi2rx_get_fmt(const struct device *dev, enum video_endpoint_id ep,
struct video_format *fmt)
{
const struct mipi_csi2rx_config *config = dev->config;

if (fmt == NULL || ep != VIDEO_EP_OUT) {
return -EINVAL;
}

if (video_get_format(config->sensor_dev, ep, fmt)) {
return -EIO;
}

return 0;
}

static int mipi_csi2rx_stream_start(const struct device *dev)
{
const struct mipi_csi2rx_config *config = dev->config;
struct mipi_csi2rx_data *drv_data = dev->data;

CSI2RX_Init((MIPI_CSI2RX_Type *)config->base, &drv_data->csi2rxConfig);

if (video_stream_start(config->sensor_dev)) {
return -EIO;
}

return 0;
}

static int mipi_csi2rx_stream_stop(const struct device *dev)
{
const struct mipi_csi2rx_config *config = dev->config;

if (video_stream_stop(config->sensor_dev)) {
return -EIO;
}

CSI2RX_Deinit((MIPI_CSI2RX_Type *)config->base);

return 0;
}

static int mipi_csi2rx_get_caps(const struct device *dev, enum video_endpoint_id ep,
struct video_caps *caps)
{
const struct mipi_csi2rx_config *config = dev->config;

if (ep != VIDEO_EP_OUT) {
return -EINVAL;
}

/* Just forward to sensor dev for now */
return video_get_caps(config->sensor_dev, ep, caps);
}

static const struct video_driver_api mipi_csi2rx_driver_api = {
.get_caps = mipi_csi2rx_get_caps,
.get_format = mipi_csi2rx_get_fmt,
.set_format = mipi_csi2rx_set_fmt,
.stream_start = mipi_csi2rx_stream_start,
.stream_stop = mipi_csi2rx_stream_stop,
};

static int mipi_csi2rx_init(const struct device *dev)
{
const struct mipi_csi2rx_config *config = dev->config;

/* Check if there is any sensor device */
if (!device_is_ready(config->sensor_dev)) {
return -ENODEV;
}

return 0;
}

#define MIPI_CSI2RX_INIT(n) \
static struct mipi_csi2rx_data mipi_csi2rx_data_##n; \
\
static const struct mipi_csi2rx_config mipi_csi2rx_config_##n = { \
.base = (MIPI_CSI2RX_Type *)DT_INST_REG_ADDR(n), \
.sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, sensor)), \
}; \
\
DEVICE_DT_INST_DEFINE(n, &mipi_csi2rx_init, NULL, &mipi_csi2rx_data_##n, \
&mipi_csi2rx_config_##n, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
&mipi_csi2rx_driver_api);

DT_INST_FOREACH_STATUS_OKAY(MIPI_CSI2RX_INIT)
29 changes: 29 additions & 0 deletions dts/arm/nxp/nxp_rt11xx.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,35 @@
reg = <0x40800000 0x4000>;
interrupts = <56 1>;
status = "disabled";
source = <&mipi_csi2rx>;

port {
csi_ep_in: endpoint {
remote-endpoint = <&mipi_csi2rx_ep_out>;
};
};
};

mipi_csi2rx: mipi_csi2rx@40810000 {
compatible = "nxp,mipi-csi2rx";
reg = <0x40810000 0x200>;
status = "disabled";

ports {
#address-cells = <1>;
#size-cells = <0>;

port@0 {
reg = <0>;
mipi_csi2rx_ep_out: endpoint {
remote-endpoint = <&csi_ep_in>;
};
};

port@1 {
reg = <1>;
};
};
};

flexcan1: can@400c4000 {
Expand Down
17 changes: 17 additions & 0 deletions dts/bindings/video/nxp,mipi-csi2rx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
#

description: NXP MIPI CSI-2 Rx interface

compatible: "nxp,mipi-csi2rx"

include: [base.yaml]

properties:
sensor:
required: true
type: phandle
description: the connected camera sensor
21 changes: 21 additions & 0 deletions soc/nxp/imxrt/imxrt11xx/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,27 @@ static ALWAYS_INLINE void clock_init(void)
CLOCK_SetRootClock(kCLOCK_Root_Lpspi1, &rootCfg);
#endif

#ifdef CONFIG_VIDEO_MCUX_MIPI_CSI2RX
/* MIPI CSI-2 Rx connects to CSI via Video Mux */
CLOCK_EnableClock(kCLOCK_Video_Mux);
VIDEO_MUX->VID_MUX_CTRL.SET = VIDEO_MUX_VID_MUX_CTRL_CSI_SEL_MASK;

/* Configure MIPI CSI-2 Rx clocks */
rootCfg.div = 8;
rootCfg.mux = kCLOCK_CSI2_ClockRoot_MuxSysPll3Out;
CLOCK_SetRootClock(kCLOCK_Root_Csi2, &rootCfg);

rootCfg.mux = kCLOCK_CSI2_ESC_ClockRoot_MuxSysPll3Out;
CLOCK_SetRootClock(kCLOCK_Root_Csi2_Esc, &rootCfg);

rootCfg.mux = kCLOCK_CSI2_UI_ClockRoot_MuxSysPll3Out;
CLOCK_SetRootClock(kCLOCK_Root_Csi2_Ui, &rootCfg);

/* Enable power domain for MIPI CSI-2 */
PGMC_BPC4->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK |
PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK);
#endif

#ifdef CONFIG_CAN_MCUX_FLEXCAN
#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan1), okay)
/* Configure CAN1 using Osc48MDiv2 */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*
* Names in this file should be chosen in a way that won't conflict
* with real-world devicetree nodes, to allow these tests to run on
* (and be extended to test) real hardware.
*/

/ {
test {
#address-cells = <1>;
#size-cells = <1>;

test_gpio: gpio@deadbeef {
compatible = "vnd,gpio";
gpio-controller;
reg = <0xdeadbeef 0x1000>;
#gpio-cells = <0x2>;
status = "okay";
};

test_i2c: i2c@11112222 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "vnd,i2c";
reg = <0x11112222 0x1000>;
status = "okay";
clock-frequency = <100000>;

test_i2c_ov5640: ov5640@1 {
compatible = "ovti,ov5640";
reg = <0x1>;
reset-gpios = <&test_gpio 0 0>;
powerdown-gpios = <&test_gpio 1 0>;
};
};

test_csi: csi@22223333 {
compatible = "nxp,imx-csi";
reg = <0x22223333 0x4000>;
status = "okay";
interrupt-parent = <&nvic>;
interrupts = <56 1>;
source = <&test_mipi_csi2rx>;
};

test_mipi_csi2rx: mipi_csi2rx@33334444 {
compatible = "nxp,mipi-csi2rx";
reg = <0x33334444 0x200>;
status = "okay";
sensor = <&test_i2c_ov5640>;
};
};
};
4 changes: 4 additions & 0 deletions tests/drivers/build_all/video/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ tests:
platform_allow:
- mimxrt1064_evk
- mimxrt1170_evk/mimxrt1176/cm7
drivers.video.mcux_mipi_csi2rx.build:
platform_allow:
- mimxrt1170_evk/mimxrt1176/cm7
- mimxrt1170_evk@B/mimxrt1176/cm7