Hi all,
I want to get stream from two of my cameras in single MIPI CSI. Currently I have the setup below:
I did find some useful information on the below forum post:
bring up dual Camera under single mipi csi
however, those modifications didn't work for me, but it was a good head start.
I change the device tree like below:
fragment@9 {
target = <&irqsteer_csi0>;
__overlay__ {
status = "okay";
};
};
fragment@10 {
target = <&irqsteer_csi1>;
__overlay__ {
status = "okay";
};
};
fragment@11 {
target = <&mipi_csi_0>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
/* Camera 0 MIPI CSI-2 (CSIS0) */
port@0 {
reg = <0>;
mipi_csi0_ep_0: endpoint {
remote-endpoint = <&as0149_serdes_ep_0>;
data-lanes = <1 2>;
csis-hs-settle = <10>;
};
};
port@2 {
reg = <2>;
mipi_csi0_ep_1: endpoint {
remote-endpoint = <&as0149_serdes_ep_1>;
data-lanes = <1 2>;
csis-hs-settle = <10>;
};
};
};
};
fragment@12 {
target = <&isi_0>;
__overlay__ {
status = "okay";
cap_device {
status = "okay";
};
m2m_device {
status = "okay";
};
};
};
fragment@12 {
target = <&isi_1>;
__overlay__ {
status = "okay";
cap_device {
status = "okay";
};
m2m_device {
status = "okay";
};
};
};
fragment@13 {
target = <&mipi_csi_1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
/* Camera 2 MIPI CSI-2 (CSIS2) */
port@1 {
reg = <1>;
mipi_csi1_ep_0: endpoint {
remote-endpoint = <&as0149_serdes_ep_2>;
data-lanes = <1 2>;
};
};
port@3 {
reg = <3>;
mipi_csi1_ep_1: endpoint {
remote-endpoint = <&as0149_serdes_ep_3>;
data-lanes = <1 2>;
};
};
/* Camera 3 MIPI CSI-2 (CSIS3) */
};
};
fragment@14 {
target = <&isi_4>;
__overlay__ {
status = "okay";
cap_device {
status = "okay";
};
m2m_device {
status = "okay";
};
};
};
fragment@14 {
target = <&isi_5>;
__overlay__ {
status = "okay";
cap_device {
status = "okay";
};
m2m_device {
status = "okay";
};
};
};
};
and here is the changes I made on the `imx8-mipi-csi2-sam.c` and `imx8-media-dev.c`.
diff --git a/drivers/staging/media/imx/imx8-media-dev.c b/drivers/staging/media/imx/imx8-media-dev.c
index 0d0355844eab..c18a1b15265f 100644
--- a/drivers/staging/media/imx/imx8-media-dev.c
+++ b/drivers/staging/media/imx/imx8-media-dev.c
@@ -35,8 +35,8 @@
#define ISI_OF_NODE_NAME "isi"
#define MIPI_CSI2_OF_NODE_NAME "csi"
-#define MXC_MAX_SENSORS 3
-#define MXC_MIPI_CSI2_MAX_DEVS 2
+#define MXC_MAX_SENSORS 4
+#define MXC_MIPI_CSI2_MAX_DEVS 4
#define MXC_NAME_LENS 32
@@ -516,6 +516,7 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
source->name, sink->name);
} else if (mxc_md->mipi_csi2[sensor->id].sd) {
mipi_csi2 = &mxc_md->mipi_csi2[sensor->id];
+ v4l2_info(&mxc_md->v4l2_dev, "sensor->id is (%d)\n", sensor->id);//joan
source = &sensor->sd->entity;
sink = find_entity_by_name(mxc_md, mipi_csi2->sd_name);
@@ -523,7 +524,9 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
sink_pad = source_pad;
mipi_vc = (mipi_csi2->vchannel) ? 4 : 1;
+ v4l2_info(&mxc_md->v4l2_dev, "mipi_vc is (%d)\n", mipi_vc);
for (j = 0; j < mipi_vc; j++) {
+ v4l2_info(&mxc_md->v4l2_dev, "j is (%d)\n", j);
ret = media_create_pad_link(source,
source_pad + j,
sink,
@@ -958,8 +961,8 @@ static int mxc_md_register_platform_entities(struct mxc_md *mxc_md,
static int register_sensor_entities(struct mxc_md *mxc_md)
{
struct device_node *parent = mxc_md->pdev->dev.of_node;
- struct device_node *node, *ep, *rem;
- struct v4l2_fwnode_endpoint endpoint;
+ struct device_node *node, *ep, *ep1, *rem, *rem1;
+ struct v4l2_fwnode_endpoint endpoint, endpoint1;
struct i2c_client *client;
struct v4l2_async_subdev *asd;
int index = 0;
@@ -967,9 +970,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
mxc_md->num_sensors = 0;
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", mxc_md->pdev->dev.of_node->name);//joan
+
/* Attach sensors linked to MIPI CSI2 / paralle csi / HDMI Rx */
for_each_available_child_of_node(parent, node) {
struct device_node *port;
+ struct device_node *port1;
if (!of_node_cmp(node->name, HDMI_RX_OF_NODE_NAME)) {
mxc_md->sensor[index].fwnode = of_fwnode_handle(node);
@@ -990,16 +996,25 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
continue;
/* csi2 node have only port */
- port = of_get_next_child(node, NULL);
+ //port = of_get_next_child(node, NULL);//joan
+ port1 = of_get_next_child(node, NULL);//joan
+ port = of_get_next_child(node, port1);//joan
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", port->full_name);//joan
+ v4l2_info(&mxc_md->v4l2_dev, "port name is %s\n", port->name);//joan
if (!port)
continue;
/* port can have only endpoint */
ep = of_get_next_child(port, NULL);
+ ep1 = of_get_next_child(port1, NULL);
+ v4l2_info(&mxc_md->v4l2_dev, "ep full name is %s and ep name is %s\n", ep->full_name, ep->name);//joan
+
if (!ep)
return -EINVAL;
memset(&endpoint, 0, sizeof(endpoint));
+ memset(&endpoint1, 0, sizeof(endpoint1));
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep1), &endpoint1);
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint);
if (WARN_ON(endpoint.base.port >= MXC_MAX_SENSORS || ret)) {
v4l2_err(&mxc_md->v4l2_dev,
@@ -1007,14 +1022,21 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EINVAL;
}
+ if (endpoint1.base.port ==2)//joan
+ endpoint1.base.port=0; //joan
+ if (endpoint1.base.port ==3)//joan
+ endpoint1.base.port=1; //joan
mxc_md->sensor[index].id = endpoint.base.port;
+ mxc_md->sensor[index+1].id = endpoint1.base.port;
if (!of_node_cmp(node->name, MIPI_CSI2_OF_NODE_NAME))
mxc_md->sensor[index].mipi_mode = true;
/* remote port---sensor node */
+ rem1 = of_graph_get_remote_port_parent(ep1);
rem = of_graph_get_remote_port_parent(ep);
of_node_put(ep);
+ of_node_put(ep1);
if (!rem) {
v4l2_info(&mxc_md->v4l2_dev,
"Remote device at %s not found\n",
@@ -1025,6 +1047,7 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
/*
* Need to wait sensor driver probed for the first time
*/
+ client = of_find_i2c_device_by_node(rem1);
client = of_find_i2c_device_by_node(rem);
if (!client) {
v4l2_info(&mxc_md->v4l2_dev,
@@ -1033,7 +1056,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EPROBE_DEFER;
}
+ mxc_md->sensor[index+1].fwnode = of_fwnode_handle(rem1);
mxc_md->sensor[index].fwnode = of_fwnode_handle(rem);
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &mxc_md->subdev_notifier,
+ mxc_md->sensor[index+1].fwnode,
+ struct v4l2_async_subdev);
asd = v4l2_async_notifier_add_fwnode_subdev(
&mxc_md->subdev_notifier,
mxc_md->sensor[index].fwnode,
@@ -1043,9 +1071,9 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return PTR_ERR(asd);
}
- mxc_md->num_sensors++;
+ mxc_md->num_sensors += 2;
- index++;
+ index += 2;
}
return 0;
@@ -1118,8 +1146,8 @@ static int mxc_md_probe(struct platform_device *pdev)
mxc_md_clean_unlink_channels(mxc_md);
} else {
/* no sensors connected */
- mxc_md_unregister_all(mxc_md);
- v4l2_async_notifier_unregister(&mxc_md->subdev_notifier);
+ //mxc_md_unregister_all(mxc_md);
+ //v4l2_async_notifier_unregister(&mxc_md->subdev_notifier);
}
}
}
@@ -1168,7 +1196,19 @@ static struct platform_driver mxc_md_driver = {
.remove = mxc_md_remove,
};
-module_platform_driver(mxc_md_driver);
+
+static int __init mxc_md_driver_init(void)
+{
+ return platform_driver_register(&mxc_md_driver);
+}
+
+static void __exit mxc_md_driver_exit(void)
+{
+ platform_driver_unregister(&mxc_md_driver);
+}
+
+late_initcall(mxc_md_driver_init);
+module_exit(mxc_md_driver_exit);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("MXC Media Device driver");
diff --git a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
index 1d12365520a6..c94dd8ee721d 100644
--- a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
+++ b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
@@ -46,7 +46,7 @@
#define CSIS_DRIVER_NAME "mxc-mipi-csi2-sam"
#define CSIS_SUBDEV_NAME "mxc-mipi-csi2"
-#define CSIS_MAX_ENTITIES 2
+#define CSIS_MAX_ENTITIES 4
#define CSIS0_MAX_LANES 4
#define CSIS1_MAX_LANES 2
@@ -1486,6 +1486,7 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
struct csi_state *state)
{
struct device_node *node = pdev->dev.of_node;
+ struct device_node *node1;
state->index = of_alias_get_id(node, "csi");
@@ -1495,7 +1496,9 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
if (of_property_read_u32(node, "bus-width", &state->max_num_lanes))
return -EINVAL;
- node = of_graph_get_next_endpoint(node, NULL);
+ //node = of_graph_get_next_endpoint(node, NULL);
+ node1 = of_graph_get_next_endpoint(node, NULL);
+ node = of_graph_get_next_endpoint(node, node1);
if (!node) {
dev_err(&pdev->dev, "No port node\n");
return -EINVAL;
@@ -1505,10 +1508,14 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
of_property_read_u32(node, "csis-hs-settle", &state->hs_settle);
of_property_read_u32(node, "csis-clk-settle", &state->clk_settle);
of_property_read_u32(node, "data-lanes", &state->num_lanes);
+ of_property_read_u32(node1, "csis-hs-settle", &state->hs_settle);
+ of_property_read_u32(node1, "csis-clk-settle", &state->clk_settle);
+ of_property_read_u32(node1, "data-lanes", &state->num_lanes);
state->wclk_ext = of_property_read_bool(node, "csis-wclk");
of_node_put(node);
+ of_node_put(node1);
return 0;
}
with the above changes I manage to get this log from the dmesg:
[ 13.882103] mxc-mipi-csi2 58227000.csi: lanes: 2, name: mxc-mipi-csi2.0
[ 13.910417] mxc-mipi-csi2 58247000.csi: lanes: 2, name: mxc-mipi-csi2.1
[ 13.925936] mxc-isi 58110000.isi: mxc_isi.1 registered successfully
[ 13.933616] mxc-isi 58150000.isi: mxc_isi.5 registered successfully
[ 13.945677] mx8-img-md: Registered mxc_isi.1.capture as /dev/video2
[ 13.952694] mx8-img-md: Registered mxc_isi.5.capture as /dev/video3
[ 13.959160] mx8-img-md: port full name is camera
[ 13.963813] mx8-img-md: port full name is port@0
[ 13.968440] mx8-img-md: port name is port
[ 13.972455] mx8-img-md: ep full name is endpoint and ep name is endpoint
[ 13.979270] mx8-img-md: port full name is port@1
[ 13.983896] mx8-img-md: port name is port
[ 13.987913] mx8-img-md: ep full name is endpoint and ep name is endpoint
[ 13.994738] mx8-img-md: Registered sensor subdevice: as0149 3-005f (1)
[ 14.002070] mx8-img-md: Registered sensor subdevice: as0149 3-005e (2)
[ 14.009413] mx8-img-md: created link [mxc_isi.1] => [mxc_isi.1.capture]
[ 14.016050] mx8-img-md: created link [mxc-mipi-csi2.0] => [mxc_isi.1]
[ 14.022527] mx8-img-md: created link [mxc_isi.5] => [mxc_isi.5.capture]
[ 14.029150] mx8-img-md: created link [mxc-mipi-csi2.1] => [mxc_isi.5]
[ 14.035616] mx8-img-md: sensor->id is (1)
[ 14.039634] mx8-img-md: mipi_vc is (1)
[ 14.043386] mx8-img-md: j is (0)
[ 14.046632] mx8-img-md: created link [as0149 3-005f] => [mxc-mipi-csi2.1]
[ 14.054212] mx8-img-md: sensor->id is (1)
[ 14.058238] mx8-img-md: mipi_vc is (1)
[ 14.061997] mx8-img-md: j is (0)
[ 14.065228] mx8-img-md: created link [as0149 3-005e] => [mxc-mipi-csi2.1]
[ 14.072817] mxc-md bus@58000000:camera: mxc_md_create_links
[ 14.078833] mxc-md bus@58000000:camera: mxc_md_do_clean get remote pad fail
[ 14.085829] mxc_md_clean_unlink_channels: clean channel fail(0)
however as you can see I have a remote pad fail error, and also below error:
[ 18.034390] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
I can see that it links on the media-ctl:
root@sm2s-imx8:~/test-suite/camera# media-ctl -p -d 1
Media controller API version 5.15.71
Media device information
------------------------
driver mxc-md
model FSL Capture Media Device
serial
bus info
hw revision 0x0
driver version 5.15.71
Device topology
- entity 1: mxc_isi.1 (16 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
pad0: Sink
pad1: Sink
<- "mxc-mipi-csi2.0":5 [ENABLED]
pad2: Sink
pad3: Sink
pad4: Sink
pad5: Sink
pad6: Sink
pad7: Sink
pad8: Sink
pad9: Sink
pad10: Sink
pad11: Sink
pad12: Source
-> "mxc_isi.1.capture":0 [ENABLED]
pad13: Source
pad14: Source
pad15: Sink
- entity 18: mxc_isi.1.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video2
pad0: Sink
<- "mxc_isi.1":12 [ENABLED]
- entity 22: mxc_isi.5 (16 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
pad0: Sink
pad1: Sink
pad2: Sink
pad3: Sink
pad4: Sink
pad5: Sink
<- "mxc-mipi-csi2.1":5 [ENABLED]
pad6: Sink
pad7: Sink
pad8: Sink
pad9: Sink
pad10: Sink
pad11: Sink
pad12: Source
-> "mxc_isi.5.capture":0 [ENABLED]
pad13: Source
pad14: Source
pad15: Sink
- entity 39: mxc_isi.5.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video3
pad0: Sink
<- "mxc_isi.5":12 [ENABLED]
- entity 43: mxc-mipi-csi2.0 (8 pads, 1 link)
type Node subtype V4L flags 0
device node name /dev/v4l-subdev0
pad0: Sink
pad1: Sink
pad2: Sink
pad3: Sink
pad4: Source
pad5: Source
-> "mxc_isi.1":1 [ENABLED]
pad6: Source
pad7: Source
- entity 52: mxc-mipi-csi2.1 (8 pads, 3 links)
type Node subtype V4L flags 0
device node name /dev/v4l-subdev1
pad0: Sink
<- "as0149 3-005f":0 [ENABLED,IMMUTABLE]
<- "as0149 3-005e":0 [ENABLED,IMMUTABLE]
pad1: Sink
pad2: Sink
pad3: Sink
pad4: Source
pad5: Source
-> "mxc_isi.5":5 [ENABLED]
pad6: Source
pad7: Source
- entity 61: as0149 3-005f (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
pad0: Source
-> "mxc-mipi-csi2.1":0 [ENABLED,IMMUTABLE]
- entity 63: as0149 3-005e (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
pad0: Source
-> "mxc-mipi-csi2.1":0 [ENABLED,IMMUTABLE]
however when I try to stream I get the following error:
[ 1271.639925] subdev->entity.num_pads = 16
[ 1271.639952] subdev->entity.num_pads = 8
[ 1271.644613] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
[ 1271.655623] subdev->entity.num_pads = 16
[ 1271.655638] subdev->entity.num_pads = 8
[ 1271.659931] subdev->entity.num_pads = 16
[ 1271.685547] subdev->entity.num_pads = 16
[ 1271.689520] subdev->entity.num_pads = 8
[ 1271.693488] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
[ 1271.706157] subdev->entity.num_pads = 16
[ 1271.706178] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.717394] subdev->entity.num_pads = 16
[ 1271.717408] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.728498] subdev->entity.num_pads = 16
[ 1271.728509] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.739767] subdev->entity.num_pads = 16
[ 1271.739788] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.754653] subdev->entity.num_pads = 16
[ 1271.754669] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.768329] subdev->entity.num_pads = 16
[ 1271.768344] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.779549] subdev->entity.num_pads = 16
[ 1271.779561] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.790708] subdev->entity.num_pads = 16
[ 1271.790727] mxc-mipi-csi2.0: mipi_csi2_enum_framesizes, No remote pad found!
[ 1271.803980] subdev->entity.num_pads = 16
[ 1271.803996] mxc-mipi-csi2.0: mipi_csi2_g_frame_interval, No remote pad found!
[ 1271.837543] subdev->entity.num_pads = 16
[ 1271.837568] mxc-mipi-csi2.0: mipi_csi2_s_power, No remote pad found!
[ 1271.847946] mxc_isi.1: Call subdev s_power fail!
maybe if I solve the padding error I might able to get a stream ? hopefully :). Can you help me on this ? I kind of stuck at this.
Thanks!
Solved! Go to Solution.
Hi all,
Below you can find how you can create virtual channels in i.mx8 board. I manage to create 4 virtual channels and get a stream from all 4 of them:
diff --git a/drivers/staging/media/imx/imx8-media-dev.c b/drivers/staging/media/imx/imx8-media-dev.c
index 0d0355844..4d86eadc0 100644
--- a/drivers/staging/media/imx/imx8-media-dev.c
+++ b/drivers/staging/media/imx/imx8-media-dev.c
@@ -35,8 +35,8 @@
#define ISI_OF_NODE_NAME "isi"
#define MIPI_CSI2_OF_NODE_NAME "csi"
-#define MXC_MAX_SENSORS 3
-#define MXC_MIPI_CSI2_MAX_DEVS 2
+#define MXC_MAX_SENSORS 4
+#define MXC_MIPI_CSI2_MAX_DEVS 4
#define MXC_NAME_LENS 32
@@ -515,7 +517,11 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
"created link [%s] => [%s]\n",
source->name, sink->name);
} else if (mxc_md->mipi_csi2[sensor->id].sd) {
- mipi_csi2 = &mxc_md->mipi_csi2[sensor->id];
+ if(mxc_md->mipi_csi2[i].sd == 0)
+ mipi_csi2 = &mxc_md->mipi_csi2[1];
+ else
+ mipi_csi2 = &mxc_md->mipi_csi2[0];
+ v4l2_info(&mxc_md->v4l2_dev, "sensor->id is (%d)\n", sensor->id);
source = &sensor->sd->entity;
sink = find_entity_by_name(mxc_md, mipi_csi2->sd_name);
@@ -523,7 +529,12 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
sink_pad = source_pad;
mipi_vc = (mipi_csi2->vchannel) ? 4 : 1;
+ v4l2_info(&mxc_md->v4l2_dev, "mipi_vc is (%d)\n", mipi_vc);
for (j = 0; j < mipi_vc; j++) {
+ v4l2_info(&mxc_md->v4l2_dev, "j is (%d), sink pad is (%d), source_pad is (%d)\n", j, sink_pad, source_pad);
+ if(sensor->id == 1)
+ sink_pad++;
+
ret = media_create_pad_link(source,
source_pad + j,
sink,
@@ -958,8 +969,8 @@ static int mxc_md_register_platform_entities(struct mxc_md *mxc_md,
static int register_sensor_entities(struct mxc_md *mxc_md)
{
struct device_node *parent = mxc_md->pdev->dev.of_node;
- struct device_node *node, *ep, *rem;
- struct v4l2_fwnode_endpoint endpoint;
+ struct device_node *node, *ep, *ep1, *rem, *rem1;
+ struct v4l2_fwnode_endpoint endpoint, endpoint1;
struct i2c_client *client;
struct v4l2_async_subdev *asd;
int index = 0;
@@ -967,9 +978,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
mxc_md->num_sensors = 0;
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", mxc_md->pdev->dev.of_node->name);
+
/* Attach sensors linked to MIPI CSI2 / paralle csi / HDMI Rx */
for_each_available_child_of_node(parent, node) {
struct device_node *port;
+ struct device_node *port1;
if (!of_node_cmp(node->name, HDMI_RX_OF_NODE_NAME)) {
mxc_md->sensor[index].fwnode = of_fwnode_handle(node);
@@ -990,16 +1004,25 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
continue;
/* csi2 node have only port */
- port = of_get_next_child(node, NULL);
+ //port = of_get_next_child(node, NULL);
+ port1 = of_get_next_child(node, NULL);
+ port = of_get_next_child(node, port1);
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", port->full_name);
+ v4l2_info(&mxc_md->v4l2_dev, "port name is %s\n", port->name);
if (!port)
continue;
/* port can have only endpoint */
ep = of_get_next_child(port, NULL);
+ ep1 = of_get_next_child(port1, NULL);
+ v4l2_info(&mxc_md->v4l2_dev, "ep full name is %s and ep name is %s\n", ep->full_name, ep->name);
+
if (!ep)
return -EINVAL;
memset(&endpoint, 0, sizeof(endpoint));
+ memset(&endpoint1, 0, sizeof(endpoint1));
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep1), &endpoint1);
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint);
if (WARN_ON(endpoint.base.port >= MXC_MAX_SENSORS || ret)) {
v4l2_err(&mxc_md->v4l2_dev,
@@ -1007,14 +1030,21 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EINVAL;
}
+ if (endpoint1.base.port ==2)
+ endpoint1.base.port=1;
mxc_md->sensor[index].id = endpoint.base.port;
+ mxc_md->sensor[index+1].id = endpoint1.base.port;
if (!of_node_cmp(node->name, MIPI_CSI2_OF_NODE_NAME))
mxc_md->sensor[index].mipi_mode = true;
/* remote port---sensor node */
+ rem1 = of_graph_get_remote_port_parent(ep1);
rem = of_graph_get_remote_port_parent(ep);
of_node_put(ep);
+ of_node_put(ep1);
if (!rem) {
v4l2_info(&mxc_md->v4l2_dev,
"Remote device at %s not found\n",
@@ -1025,6 +1055,7 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
/*
* Need to wait sensor driver probed for the first time
*/
+ client = of_find_i2c_device_by_node(rem1);
client = of_find_i2c_device_by_node(rem);
if (!client) {
v4l2_info(&mxc_md->v4l2_dev,
@@ -1033,7 +1064,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EPROBE_DEFER;
}
+ mxc_md->sensor[index+1].fwnode = of_fwnode_handle(rem1);
mxc_md->sensor[index].fwnode = of_fwnode_handle(rem);
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &mxc_md->subdev_notifier,
+ mxc_md->sensor[index+1].fwnode,
+ struct v4l2_async_subdev);
asd = v4l2_async_notifier_add_fwnode_subdev(
&mxc_md->subdev_notifier,
mxc_md->sensor[index].fwnode,
@@ -1043,9 +1079,9 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return PTR_ERR(asd);
}
- mxc_md->num_sensors++;
+ mxc_md->num_sensors += 2;
- index++;
+ index += 2;
}
return 0;
diff --git a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
index 1d1236552..d2ba5c890 100644
--- a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
+++ b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
@@ -46,7 +46,7 @@
#define CSIS_DRIVER_NAME "mxc-mipi-csi2-sam"
#define CSIS_SUBDEV_NAME "mxc-mipi-csi2"
-#define CSIS_MAX_ENTITIES 2
+#define CSIS_MAX_ENTITIES 4
#define CSIS0_MAX_LANES 4
#define CSIS1_MAX_LANES 2
@@ -1486,6 +1486,7 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
struct csi_state *state)
{
struct device_node *node = pdev->dev.of_node;
+ struct device_node *node1;
state->index = of_alias_get_id(node, "csi");
@@ -1495,7 +1496,9 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
if (of_property_read_u32(node, "bus-width", &state->max_num_lanes))
return -EINVAL;
- node = of_graph_get_next_endpoint(node, NULL);
+ //node = of_graph_get_next_endpoint(node, NULL);
+ node1 = of_graph_get_next_endpoint(node, NULL);
+ node = of_graph_get_next_endpoint(node, node1);
if (!node) {
dev_err(&pdev->dev, "No port node\n");
return -EINVAL;
its very messy way to do such thing but for now, it works without an issue.
The above code basically parses device tree and connects two cameras into csi2.0 and other two to csi2.1. And since we have isi subdevices you can get a stream from all 4 of them.
Hopefully this will help someone in future.
Hello,
Have you connected the MIPI port? since it looks like you are not attached nothing on it, please try the latest BSP it include support for dual camera, but check your hardware camera firts.
Regards
Hello Bio_TICFSL,
Yes I connect my camera into mipi_csi_1. Where can I find the `latest BSP` ?
thanks
Hello @Bio_TICFSL,
I check out the latest BSP, if I understood it correctly, the approach is basically didn't changed.
I can get some output from video3 and video4, which is both connected to csi2.0.
[ 14.313983] mx8-img-md: num_sensors is (4)
[ 14.318097] mx8-img-md: sensor is (as0149 2-005f), sd (69904512)
[ 14.324920] mx8-img-md: sensor->id is (0)
[ 14.328947] mx8-img-md: mipi_vc is (1)
[ 14.332708] mx8-img-md: j is (0)
[ 14.335973] mx8-img-md: created link [as0149 2-005f] => [mxc-mipi-csi2.0]
[ 14.343561] mx8-img-md: sensor is (as0149 2-005e), sd (70127744)
[ 14.350392] mx8-img-md: sensor->id is (1)
[ 14.354419] mx8-img-md: mipi_vc is (1)
[ 14.358179] mx8-img-md: j is (0)
[ 14.361413] mx8-img-md: created link [as0149 2-005e] => [mxc-mipi-csi2.0]
[ 14.369019] mx8-img-md: sensor is ((efault)), sd (0)
[ 14.374009] mx8-img-md: sensor is ((efault)), sd (0)
[ 14.378987] mxc-md bus@58000000:camera: mxc_md_create_links
but the output is green, and at the top of the screen there are statics. Like below:
How can I possibly solve this ? Also from media-ctl -p -d 1:
- entity 85: mxc-mipi-csi2.0 (8 pads, 4 links)
type Node subtype V4L flags 0
device node name /dev/v4l-subdev0
pad0: Sink
<- "as0149 2-005f":0 [ENABLED,IMMUTABLE]
<- "as0149 2-005e":0 [ENABLED,IMMUTABLE]
pad1: Sink
pad2: Sink
pad3: Sink
pad4: Source
-> "mxc_isi.0":0 [ENABLED]
pad5: Source
-> "mxc_isi.1":1 [ENABLED]
pad6: Source
pad7: Source
I see both of my cameras connected to port0, which basically means when I try to stream from video3 or video4 both of my cameras tries to go into stream. May be this is the problem why I'm getting the green screen output from the MIPI CSI ?
I appreciate any help I can get on this.
Thanks.
Hi,
My kernel version is 5.15.71_2.2.0, the one you linked is Linux 6.6.36_2.1.0. Is it possible to compare the changes and apply it on my own and work it that way ?
Thanks.
Hi all,
Below you can find how you can create virtual channels in i.mx8 board. I manage to create 4 virtual channels and get a stream from all 4 of them:
diff --git a/drivers/staging/media/imx/imx8-media-dev.c b/drivers/staging/media/imx/imx8-media-dev.c
index 0d0355844..4d86eadc0 100644
--- a/drivers/staging/media/imx/imx8-media-dev.c
+++ b/drivers/staging/media/imx/imx8-media-dev.c
@@ -35,8 +35,8 @@
#define ISI_OF_NODE_NAME "isi"
#define MIPI_CSI2_OF_NODE_NAME "csi"
-#define MXC_MAX_SENSORS 3
-#define MXC_MIPI_CSI2_MAX_DEVS 2
+#define MXC_MAX_SENSORS 4
+#define MXC_MIPI_CSI2_MAX_DEVS 4
#define MXC_NAME_LENS 32
@@ -515,7 +517,11 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
"created link [%s] => [%s]\n",
source->name, sink->name);
} else if (mxc_md->mipi_csi2[sensor->id].sd) {
- mipi_csi2 = &mxc_md->mipi_csi2[sensor->id];
+ if(mxc_md->mipi_csi2[i].sd == 0)
+ mipi_csi2 = &mxc_md->mipi_csi2[1];
+ else
+ mipi_csi2 = &mxc_md->mipi_csi2[0];
+ v4l2_info(&mxc_md->v4l2_dev, "sensor->id is (%d)\n", sensor->id);
source = &sensor->sd->entity;
sink = find_entity_by_name(mxc_md, mipi_csi2->sd_name);
@@ -523,7 +529,12 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
sink_pad = source_pad;
mipi_vc = (mipi_csi2->vchannel) ? 4 : 1;
+ v4l2_info(&mxc_md->v4l2_dev, "mipi_vc is (%d)\n", mipi_vc);
for (j = 0; j < mipi_vc; j++) {
+ v4l2_info(&mxc_md->v4l2_dev, "j is (%d), sink pad is (%d), source_pad is (%d)\n", j, sink_pad, source_pad);
+ if(sensor->id == 1)
+ sink_pad++;
+
ret = media_create_pad_link(source,
source_pad + j,
sink,
@@ -958,8 +969,8 @@ static int mxc_md_register_platform_entities(struct mxc_md *mxc_md,
static int register_sensor_entities(struct mxc_md *mxc_md)
{
struct device_node *parent = mxc_md->pdev->dev.of_node;
- struct device_node *node, *ep, *rem;
- struct v4l2_fwnode_endpoint endpoint;
+ struct device_node *node, *ep, *ep1, *rem, *rem1;
+ struct v4l2_fwnode_endpoint endpoint, endpoint1;
struct i2c_client *client;
struct v4l2_async_subdev *asd;
int index = 0;
@@ -967,9 +978,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
mxc_md->num_sensors = 0;
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", mxc_md->pdev->dev.of_node->name);
+
/* Attach sensors linked to MIPI CSI2 / paralle csi / HDMI Rx */
for_each_available_child_of_node(parent, node) {
struct device_node *port;
+ struct device_node *port1;
if (!of_node_cmp(node->name, HDMI_RX_OF_NODE_NAME)) {
mxc_md->sensor[index].fwnode = of_fwnode_handle(node);
@@ -990,16 +1004,25 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
continue;
/* csi2 node have only port */
- port = of_get_next_child(node, NULL);
+ //port = of_get_next_child(node, NULL);
+ port1 = of_get_next_child(node, NULL);
+ port = of_get_next_child(node, port1);
+ v4l2_info(&mxc_md->v4l2_dev, "port full name is %s\n", port->full_name);
+ v4l2_info(&mxc_md->v4l2_dev, "port name is %s\n", port->name);
if (!port)
continue;
/* port can have only endpoint */
ep = of_get_next_child(port, NULL);
+ ep1 = of_get_next_child(port1, NULL);
+ v4l2_info(&mxc_md->v4l2_dev, "ep full name is %s and ep name is %s\n", ep->full_name, ep->name);
+
if (!ep)
return -EINVAL;
memset(&endpoint, 0, sizeof(endpoint));
+ memset(&endpoint1, 0, sizeof(endpoint1));
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep1), &endpoint1);
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint);
if (WARN_ON(endpoint.base.port >= MXC_MAX_SENSORS || ret)) {
v4l2_err(&mxc_md->v4l2_dev,
@@ -1007,14 +1030,21 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EINVAL;
}
+ if (endpoint1.base.port ==2)
+ endpoint1.base.port=1;
mxc_md->sensor[index].id = endpoint.base.port;
+ mxc_md->sensor[index+1].id = endpoint1.base.port;
if (!of_node_cmp(node->name, MIPI_CSI2_OF_NODE_NAME))
mxc_md->sensor[index].mipi_mode = true;
/* remote port---sensor node */
+ rem1 = of_graph_get_remote_port_parent(ep1);
rem = of_graph_get_remote_port_parent(ep);
of_node_put(ep);
+ of_node_put(ep1);
if (!rem) {
v4l2_info(&mxc_md->v4l2_dev,
"Remote device at %s not found\n",
@@ -1025,6 +1055,7 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
/*
* Need to wait sensor driver probed for the first time
*/
+ client = of_find_i2c_device_by_node(rem1);
client = of_find_i2c_device_by_node(rem);
if (!client) {
v4l2_info(&mxc_md->v4l2_dev,
@@ -1033,7 +1064,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return -EPROBE_DEFER;
}
+ mxc_md->sensor[index+1].fwnode = of_fwnode_handle(rem1);
mxc_md->sensor[index].fwnode = of_fwnode_handle(rem);
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ &mxc_md->subdev_notifier,
+ mxc_md->sensor[index+1].fwnode,
+ struct v4l2_async_subdev);
asd = v4l2_async_notifier_add_fwnode_subdev(
&mxc_md->subdev_notifier,
mxc_md->sensor[index].fwnode,
@@ -1043,9 +1079,9 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
return PTR_ERR(asd);
}
- mxc_md->num_sensors++;
+ mxc_md->num_sensors += 2;
- index++;
+ index += 2;
}
return 0;
diff --git a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
index 1d1236552..d2ba5c890 100644
--- a/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
+++ b/drivers/staging/media/imx/imx8-mipi-csi2-sam.c
@@ -46,7 +46,7 @@
#define CSIS_DRIVER_NAME "mxc-mipi-csi2-sam"
#define CSIS_SUBDEV_NAME "mxc-mipi-csi2"
-#define CSIS_MAX_ENTITIES 2
+#define CSIS_MAX_ENTITIES 4
#define CSIS0_MAX_LANES 4
#define CSIS1_MAX_LANES 2
@@ -1486,6 +1486,7 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
struct csi_state *state)
{
struct device_node *node = pdev->dev.of_node;
+ struct device_node *node1;
state->index = of_alias_get_id(node, "csi");
@@ -1495,7 +1496,9 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
if (of_property_read_u32(node, "bus-width", &state->max_num_lanes))
return -EINVAL;
- node = of_graph_get_next_endpoint(node, NULL);
+ //node = of_graph_get_next_endpoint(node, NULL);
+ node1 = of_graph_get_next_endpoint(node, NULL);
+ node = of_graph_get_next_endpoint(node, node1);
if (!node) {
dev_err(&pdev->dev, "No port node\n");
return -EINVAL;
its very messy way to do such thing but for now, it works without an issue.
The above code basically parses device tree and connects two cameras into csi2.0 and other two to csi2.1. And since we have isi subdevices you can get a stream from all 4 of them.
Hopefully this will help someone in future.