diff --git a/boards/arduino/nicla_vision/arduino_nicla_vision_stm32h747xx_m7.dts b/boards/arduino/nicla_vision/arduino_nicla_vision_stm32h747xx_m7.dts index 0028128f8e231..6627ec5441e73 100644 --- a/boards/arduino/nicla_vision/arduino_nicla_vision_stm32h747xx_m7.dts +++ b/boards/arduino/nicla_vision/arduino_nicla_vision_stm32h747xx_m7.dts @@ -22,7 +22,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; - zephyr,camera = &dcmi; }; aliases { diff --git a/boards/espressif/esp32s3_eye/esp32s3_eye_procpu.dts b/boards/espressif/esp32s3_eye/esp32s3_eye_procpu.dts index 7391ad2357e42..fe498e4bee167 100644 --- a/boards/espressif/esp32s3_eye/esp32s3_eye_procpu.dts +++ b/boards/espressif/esp32s3_eye/esp32s3_eye_procpu.dts @@ -31,7 +31,6 @@ zephyr,code-partition = &slot0_partition; zephyr,bt-hci = &esp32_bt_hci; zephyr,display = &st7789v; - zephyr,camera = &lcd_cam; }; buttons { diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu_sense.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu_sense.dts index f8f7ed4a31675..f4ced1f0e3b05 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu_sense.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu_sense.dts @@ -11,10 +11,6 @@ / { model = "Seeed Xiao ESP32S3 PROCPU Sense"; compatible = "seeed,xiao-esp32s3"; - - chosen { - zephyr,camera = &lcd_cam; - }; }; &i2c1 { diff --git a/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay b/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay index 49bc018779a8f..4c0798597c8de 100644 --- a/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay +++ b/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/{ - chosen { - zephyr,camera = &dvp_fpc24_interface; - }; -}; - &dvp_fpc24_i2c { mt9m114: mt9m114@48 { compatible = "aptina,mt9m114"; diff --git a/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay b/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay index 9eca70c27cdeb..8ad00caff867c 100644 --- a/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay +++ b/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay @@ -6,12 +6,6 @@ #include -/{ - chosen { - zephyr,camera = &nxp_csi; - }; -}; - &nxp_cam_i2c { status = "okay"; diff --git a/boards/shields/st_b_cams_omv_mb1683/st_b_cams_omv_mb1683.overlay b/boards/shields/st_b_cams_omv_mb1683/st_b_cams_omv_mb1683.overlay index 0ffb5669dadfe..87a30533e0243 100644 --- a/boards/shields/st_b_cams_omv_mb1683/st_b_cams_omv_mb1683.overlay +++ b/boards/shields/st_b_cams_omv_mb1683/st_b_cams_omv_mb1683.overlay @@ -7,12 +7,6 @@ #include -/ { - chosen { - zephyr,camera = &st_cam_dvp; - }; -}; - &st_cam_i2c { ov5640: ov5640@3c { diff --git a/boards/shields/weact_ov2640_cam_module/weact_ov2640_cam_module.overlay b/boards/shields/weact_ov2640_cam_module/weact_ov2640_cam_module.overlay index bc8c6ebddb288..1ccd36121f2c1 100644 --- a/boards/shields/weact_ov2640_cam_module/weact_ov2640_cam_module.overlay +++ b/boards/shields/weact_ov2640_cam_module/weact_ov2640_cam_module.overlay @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - chosen { - zephyr,camera = &zephyr_camera_dvp; - }; -}; - &zephyr_camera_i2c { status = "okay"; clock-frequency = ; diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index d46376edd03fb..8a9db048c0f98 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -127,6 +127,7 @@ endif() if(CONFIG_VIDEO) zephyr_iterable_section(NAME video_device GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN}) + zephyr_iterable_section(NAME video_mdev GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN}) endif() if(CONFIG_LOG) diff --git a/drivers/video/Kconfig.sw_generator b/drivers/video/Kconfig.sw_generator index 7675908b4bc19..f258a00e1a2f5 100644 --- a/drivers/video/Kconfig.sw_generator +++ b/drivers/video/Kconfig.sw_generator @@ -3,10 +3,7 @@ # Copyright (c) 2016 Linaro Limited # SPDX-License-Identifier: Apache-2.0 -DT_CHOSEN_ZEPHYR_CAMERA := zephyr,camera - config VIDEO_SW_GENERATOR bool "Video Software Generator" - depends on !$(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CAMERA)) help Enable video pattern generator (for testing purposes). diff --git a/drivers/video/video.ld b/drivers/video/video.ld index 935ee1ed302b3..23ffbc5b3537e 100644 --- a/drivers/video/video.ld +++ b/drivers/video/video.ld @@ -1,3 +1,4 @@ #include ITERABLE_SECTION_RAM(video_device, Z_LINK_ITERABLE_SUBALIGN) +ITERABLE_SECTION_RAM(video_mdev, Z_LINK_ITERABLE_SUBALIGN) diff --git a/drivers/video/video_device.c b/drivers/video/video_device.c index a895fed42f144..c299f9fe921db 100644 --- a/drivers/video/video_device.c +++ b/drivers/video/video_device.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "video_device.h" struct video_device *video_find_vdev(const struct device *dev) @@ -20,3 +22,21 @@ struct video_device *video_find_vdev(const struct device *dev) return NULL; } + +const struct device *video_get_dev(uint8_t i) +{ + const struct video_mdev *vmd = NULL; + + STRUCT_SECTION_GET(video_mdev, i, &vmd); + + return vmd->dev; +} + +uint8_t video_get_devs_num(void) +{ + uint8_t count = 0; + + STRUCT_SECTION_COUNT(video_mdev, &count); + + return count; +} diff --git a/drivers/video/video_device.h b/drivers/video/video_device.h index 3ba2ee3486cda..70a0283aad7fb 100644 --- a/drivers/video/video_device.h +++ b/drivers/video/video_device.h @@ -16,6 +16,10 @@ struct video_device { sys_dlist_t ctrls; }; +struct video_mdev { + const struct device *dev; +}; + #define VIDEO_DEVICE_DEFINE(name, device, source) \ static STRUCT_SECTION_ITERABLE(video_device, name) = { \ .dev = device, \ @@ -23,6 +27,11 @@ struct video_device { .ctrls = SYS_DLIST_STATIC_INIT(&name.ctrls), \ } +#define VIDEO_MDEV_DEFINE(name, device) \ + static STRUCT_SECTION_ITERABLE(video_mdev, name_##mdev) = { \ + .dev = device, \ + } + struct video_device *video_find_vdev(const struct device *dev); #endif /* ZEPHYR_INCLUDE_DRIVERS_VIDEO_VIDEO_DEVICE_H_ */ diff --git a/drivers/video/video_emul_rx.c b/drivers/video/video_emul_rx.c index ba44a2c59ed66..8070b6680bccf 100644 --- a/drivers/video/video_emul_rx.c +++ b/drivers/video/video_emul_rx.c @@ -282,6 +282,8 @@ int emul_rx_init(const struct device *dev) DEVICE_DT_INST_DEFINE(n, &emul_rx_init, NULL, &emul_rx_data_##n, &emul_rx_cfg_##n, \ POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &emul_rx_driver_api); \ \ - VIDEO_DEVICE_DEFINE(emul_rx_##n, DEVICE_DT_INST_GET(n), emul_rx_cfg_##n.source_dev); + VIDEO_DEVICE_DEFINE(emul_rx_##n, DEVICE_DT_INST_GET(n), emul_rx_cfg_##n.source_dev); \ + \ + VIDEO_MDEV_DEFINE(emul_rx_##n, DEVICE_DT_INST_GET(n)); DT_INST_FOREACH_STATUS_OKAY(EMUL_RX_DEFINE) diff --git a/drivers/video/video_esp32_dvp.c b/drivers/video/video_esp32_dvp.c index 5d1ec69f24218..921718368195a 100644 --- a/drivers/video/video_esp32_dvp.c +++ b/drivers/video/video_esp32_dvp.c @@ -452,6 +452,8 @@ DEVICE_DT_INST_DEFINE(0, video_esp32_init, NULL, &esp32_data, &esp32_config, POS VIDEO_DEVICE_DEFINE(esp32, DEVICE_DT_INST_GET(0), esp32_config.source_dev); +VIDEO_MDEV_DEFINE(esp32, DEVICE_DT_INST_GET(0)); + static int video_esp32_cam_init_master_clock(void) { int ret = 0; diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 4b4a46dc2cbd3..58e3382c63c9b 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -483,4 +483,6 @@ DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, NULL, &video_mcux_csi_data_0, VIDEO_DEVICE_DEFINE(csi, DEVICE_DT_INST_GET(0), video_mcux_csi_config_0.source_dev); +VIDEO_MDEV_DEFINE(csi, DEVICE_DT_INST_GET(0)); + #endif diff --git a/drivers/video/video_mcux_smartdma.c b/drivers/video/video_mcux_smartdma.c index 9081bcb596741..0b3b9d02b734d 100644 --- a/drivers/video/video_mcux_smartdma.c +++ b/drivers/video/video_mcux_smartdma.c @@ -383,6 +383,8 @@ static DEVICE_API(video, nxp_video_sdma_api) = { &sdma_config_##inst, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &nxp_video_sdma_api); \ \ - VIDEO_DEVICE_DEFINE(sdma_##inst, DEVICE_DT_INST_GET(inst), sdma_config_##inst.sensor_dev); + VIDEO_DEVICE_DEFINE(sdma_##inst, DEVICE_DT_INST_GET(inst), sdma_config_##inst.sensor_dev); \ + \ + VIDEO_MDEV_DEFINE(sdma_##inst, DEVICE_DT_INST_GET(inst)); DT_INST_FOREACH_STATUS_OKAY(NXP_VIDEO_SDMA_INIT) diff --git a/drivers/video/video_stm32_dcmi.c b/drivers/video/video_stm32_dcmi.c index 35c55449a5580..9e43683de2634 100644 --- a/drivers/video/video_stm32_dcmi.c +++ b/drivers/video/video_stm32_dcmi.c @@ -501,3 +501,5 @@ DEVICE_DT_INST_DEFINE(0, &video_stm32_dcmi_init, &video_stm32_dcmi_driver_api); VIDEO_DEVICE_DEFINE(dcmi, DEVICE_DT_INST_GET(0), video_stm32_dcmi_config_0.sensor_dev); + +VIDEO_MDEV_DEFINE(dcmi, DEVICE_DT_INST_GET(0)); diff --git a/drivers/video/video_sw_generator.c b/drivers/video/video_sw_generator.c index ed8ade5270ca5..939d03a2124a7 100644 --- a/drivers/video/video_sw_generator.c +++ b/drivers/video/video_sw_generator.c @@ -371,3 +371,5 @@ DEVICE_DEFINE(video_sw_generator, "VIDEO_SW_GENERATOR", &video_sw_generator_init &video_sw_generator_driver_api); VIDEO_DEVICE_DEFINE(video_sw_generator, DEVICE_GET(video_sw_generator), NULL); + +VIDEO_MDEV_DEFINE(video_sw_generator, DEVICE_GET(video_sw_generator)); diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index c0b814932f74c..60808bd9afc40 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -819,6 +819,26 @@ void video_closest_frmival_stepwise(const struct video_frmival_stepwise *stepwis void video_closest_frmival(const struct device *dev, enum video_endpoint_id ep, struct video_frmival_enum *match); +/** + * @brief Get a video device by index + * + * The video subsystem keeps a list of registered video devices that application + * can use for streaming. This function is to get a video device in this list by + * specifying an index. + * + * @param i Index of the video device to get + */ +const struct device *video_get_dev(uint8_t i); + +/** + * @brief Get the number of registered video devices + * + * The video subsystem keeps a list of registered video devices that application + * can use for streaming. This function is to retrieve the size of this list. + * + */ +uint8_t video_get_devs_num(void); + /** * @defgroup video_pixel_formats Video pixel formats * The '|' characters separate the pixels or logical blocks, and spaces separate the bytes. diff --git a/samples/drivers/video/capture/boards/frdm_mcxn947_cpu0.overlay b/samples/drivers/video/capture/boards/frdm_mcxn947_cpu0.overlay deleted file mode 100644 index db18ee736c4ff..0000000000000 --- a/samples/drivers/video/capture/boards/frdm_mcxn947_cpu0.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2024 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/{ - chosen { - zephyr,camera = &video_sdma; - }; -}; diff --git a/samples/drivers/video/capture/src/main.c b/samples/drivers/video/capture/src/main.c index 501ebd8794ab5..8c8356e4f04bf 100644 --- a/samples/drivers/video/capture/src/main.c +++ b/samples/drivers/video/capture/src/main.c @@ -92,22 +92,24 @@ int main(void) size_t bsize; int i = 0; int err; - -#if DT_HAS_CHOSEN(zephyr_camera) - const struct device *const video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); - - if (!device_is_ready(video_dev)) { - LOG_ERR("%s: video device is not ready", video_dev->name); - return 0; + const struct device *video_dev = NULL; + const struct device *const vsg = device_get_binding(VIDEO_DEV_SW); + uint8_t vdevs_num = video_get_devs_num(); + bool found_vdev = false; + + /* Get the 1st video HW available, otherwise fallbacks to video sw generator */ + for (int j = 0; j < vdevs_num; j++) { + video_dev = video_get_dev(j); + if (device_is_ready(video_dev) && (vdevs_num == 1 || video_dev != vsg)) { + found_vdev = true; + break; + } } -#else - const struct device *const video_dev = device_get_binding(VIDEO_DEV_SW); - if (video_dev == NULL) { - LOG_ERR("%s: video device not found or failed to initialized", VIDEO_DEV_SW); + if (!found_vdev) { + LOG_ERR("No video device ready!"); return 0; } -#endif LOG_INF("Video device: %s", video_dev->name); diff --git a/samples/drivers/video/capture_to_lvgl/src/main.c b/samples/drivers/video/capture_to_lvgl/src/main.c index 201e0a8bed904..819d500c2ae1c 100644 --- a/samples/drivers/video/capture_to_lvgl/src/main.c +++ b/samples/drivers/video/capture_to_lvgl/src/main.c @@ -26,6 +26,9 @@ int main(void) const struct device *video_dev; size_t bsize; int i = 0; + const struct device *const vsg = device_get_binding(VIDEO_DEV_SW); + uint8_t vdevs_num = video_get_devs_num(); + bool found_vdev = false; display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); if (!device_is_ready(display_dev)) { @@ -33,19 +36,19 @@ int main(void) return 0; } -#if DT_HAS_CHOSEN(zephyr_camera) - video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); - if (!device_is_ready(video_dev)) { - LOG_ERR("%s device is not ready", video_dev->name); - return 0; + /* Get the 1st video HW available, otherwise fallbacks to video sw generator */ + for (int j = 0; j < vdevs_num; j++) { + video_dev = video_get_dev(j); + if (device_is_ready(video_dev) && (vdevs_num == 1 || video_dev != vsg)) { + found_vdev = true; + break; + } } -#else - video_dev = device_get_binding(VIDEO_DEV_SW); - if (video_dev == NULL) { - LOG_ERR("%s device not found", VIDEO_DEV_SW); + + if (!found_vdev) { + LOG_ERR("No video device ready!"); return 0; } -#endif LOG_INF("- Device name: %s", video_dev->name); diff --git a/samples/drivers/video/tcpserversink/src/main.c b/samples/drivers/video/tcpserversink/src/main.c index da3f9e4a8319e..49445c6dab1fc 100644 --- a/samples/drivers/video/tcpserversink/src/main.c +++ b/samples/drivers/video/tcpserversink/src/main.c @@ -42,21 +42,24 @@ int main(void) int i, ret, sock, client; struct video_format fmt; struct video_caps caps; -#if DT_HAS_CHOSEN(zephyr_camera) - const struct device *const video = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); - - if (!device_is_ready(video)) { - LOG_ERR("%s: video device not ready.", video->name); - return 0; + const struct device *video = NULL; + const struct device *const vsg = device_get_binding(VIDEO_DEV_SW); + uint8_t vdevs_num = video_get_devs_num(); + bool found_vdev = false; + + /* Get the 1st video HW available, otherwise fallbacks to video sw generator */ + for (int j = 0; j < vdevs_num; j++) { + video = video_get_dev(j); + if (device_is_ready(video) && (vdevs_num == 1 || video != vsg)) { + found_vdev = true; + break; + } } -#else - const struct device *const video = device_get_binding(VIDEO_DEV_SW); - if (video == NULL) { - LOG_ERR("%s: video device not found or failed to initialized.", VIDEO_DEV_SW); + if (!found_vdev) { + LOG_ERR("No video device ready!"); return 0; } -#endif /* Prepare Network */ (void)memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET;