This is an automated email from the ASF dual-hosted git repository. pkarashchenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit b45489753aaf914669b5f130915ee9d739e82e7f Author: SPRESENSE <[email protected]> AuthorDate: Mon Nov 29 09:31:43 2021 +0900 drivers/video: Enable to select connected image sensor driver at runtime Enable to select connected image sensor driver at runtime by adding is_available() to image sensor I/F. --- drivers/video/isx012.c | 52 ++++++++++++++++++++++++++++++++++++++++- drivers/video/video.c | 52 ++++++++++++++++++++++++++++++++++++----- include/nuttx/video/imgsensor.h | 43 +++++++++++++++++----------------- 3 files changed, 119 insertions(+), 28 deletions(-) diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c index ea4658e8f1..83f06d77e5 100644 --- a/drivers/video/isx012.c +++ b/drivers/video/isx012.c @@ -140,6 +140,9 @@ (((val - min) % step) == 0) ? \ OK : -EINVAL)) +#define ISX012_CHIPID_L (0x0000c460) +#define ISX012_CHIPID_H (0x00005516) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -215,6 +218,7 @@ static bool is_movie_needed(uint8_t fmt, uint8_t fps); /* image sensor device operations interface */ +static bool isx012_is_available(void); static int isx012_init(void); static int isx012_uninit(void); static const char *isx012_get_driver_name(void); @@ -615,6 +619,7 @@ static uint8_t g_isx012_iso_regval[] = static struct imgsensor_ops_s g_isx012_ops = { + isx012_is_available, /* is HW available */ isx012_init, /* init */ isx012_uninit, /* uninit */ isx012_get_driver_name, /* get driver name */ @@ -1236,6 +1241,45 @@ int init_isx012(FAR struct isx012_dev_s *priv) return ret; } +static void get_chipid(uint32_t *l, uint32_t *h) +{ + uint16_t l1; + uint16_t l2; + uint16_t h1; + uint16_t h2; + + ASSERT(l && h); + + l1 = isx012_getreg(&g_isx012_private, OTP_CHIPID_L, 2); + l2 = isx012_getreg(&g_isx012_private, OTP_CHIPID_L + 2, 2); + + h1 = isx012_getreg(&g_isx012_private, OTP_CHIPID_H, 2); + h2 = isx012_getreg(&g_isx012_private, OTP_CHIPID_H + 2, 2); + + *l = (l2 << 16) | l1; + *h = (h2 << 16) | h1; +} + +static bool isx012_is_available(void) +{ + bool ret = false; + uint32_t l; + uint32_t h; + + isx012_init(); + + get_chipid(&l, &h); + + if ((l == ISX012_CHIPID_L) && (h == ISX012_CHIPID_H)) + { + ret = true; + } + + isx012_uninit(); + + return ret; +} + static int isx012_init(void) { FAR struct isx012_dev_s *priv = &g_isx012_private; @@ -2885,11 +2929,17 @@ static int isx012_set_shd(FAR isx012_dev_t *priv) int isx012_initialize(void) { + int ret; FAR struct isx012_dev_s *priv = &g_isx012_private; /* Regiser image sensor operations variable */ - imgsensor_register(&g_isx012_ops); + ret = imgsensor_register(&g_isx012_ops); + if (ret != OK) + { + verr("Failed to register ops to video driver.\n"); + return ret; + } /* Initialize other information */ diff --git a/drivers/video/video.c b/drivers/video/video.c index 79b4c6f3ba..c8e4980cd1 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -398,6 +398,8 @@ static video_parameter_name_t g_video_parameter_name[] = }; static FAR void *video_handler; +static FAR const struct imgsensor_ops_s **g_video_registered_sensor; +static int g_video_registered_sensor_num; static FAR const struct imgsensor_ops_s *g_video_sensor_ops; static FAR const struct imgdata_ops_s *g_video_data_ops; @@ -930,6 +932,24 @@ static bool is_sem_waited(FAR sem_t *sem) } } +static FAR const struct imgsensor_ops_s *get_connected_imgsensor(void) +{ + int i; + FAR const struct imgsensor_ops_s *ops = NULL; + + for (i = 0; i < g_video_registered_sensor_num; i++) + { + if (g_video_registered_sensor[i] && + g_video_registered_sensor[i]->is_available()) + { + ops = g_video_registered_sensor[i]; + break; + } + } + + return ops; +} + static int video_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; @@ -941,15 +961,23 @@ static int video_open(FAR struct file *filep) { /* Only in first execution, open device */ - ret = g_video_sensor_ops->init(); - if (ret == OK) + g_video_sensor_ops = get_connected_imgsensor(); + if (g_video_sensor_ops) { - ret = g_video_data_ops->init(); + ret = g_video_sensor_ops->init(); if (ret == OK) { - initialize_resources(priv); + ret = g_video_data_ops->init(); + if (ret == OK) + { + initialize_resources(priv); + } } } + else + { + ret = -ENODEV; + } } /* In second or later execution, ret is initial value(=OK) */ @@ -3018,9 +3046,21 @@ int video_uninitialize(void) return OK; } -void imgsensor_register(FAR const struct imgsensor_ops_s *ops) +int imgsensor_register(FAR const struct imgsensor_ops_s *ops) { - g_video_sensor_ops = ops; + int ret = -ENOMEM; + FAR const struct imgsensor_ops_s **new_addr; + + new_addr = realloc(g_video_registered_sensor, + sizeof(ops) * (g_video_registered_sensor_num + 1)); + if (new_addr) + { + new_addr[g_video_registered_sensor_num++] = ops; + g_video_registered_sensor = new_addr; + ret = OK; + } + + return ret; } void imgdata_register(FAR const struct imgdata_ops_s *ops) diff --git a/include/nuttx/video/imgsensor.h b/include/nuttx/video/imgsensor.h index 0254250cf7..8d1f60109b 100644 --- a/include/nuttx/video/imgsensor.h +++ b/include/nuttx/video/imgsensor.h @@ -303,27 +303,28 @@ typedef union imgsensor_value_u struct imgsensor_ops_s { - CODE int (*init)(void); - CODE int (*uninit)(void); + CODE bool (*is_available)(void); + CODE int (*init)(void); + CODE int (*uninit)(void); CODE const char * (*get_driver_name)(void); - CODE int (*validate_frame_setting)(imgsensor_stream_type_t type, - uint8_t nr_datafmts, - FAR imgsensor_format_t *datafmts, - FAR imgsensor_interval_t *interval); - CODE int (*start_capture)(imgsensor_stream_type_t type, - uint8_t nr_datafmts, - FAR imgsensor_format_t *datafmts, - FAR imgsensor_interval_t *interval); - CODE int (*stop_capture)(imgsensor_stream_type_t type); - - CODE int (*get_supported_value)(uint32_t id, - FAR imgsensor_supported_value_t *value); - CODE int (*get_value)(uint32_t id, - uint32_t size, - FAR imgsensor_value_t *value); - CODE int (*set_value)(uint32_t id, - uint32_t size, - imgsensor_value_t value); + CODE int (*validate_frame_setting)(imgsensor_stream_type_t type, + uint8_t nr_datafmts, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); + CODE int (*start_capture)(imgsensor_stream_type_t type, + uint8_t nr_datafmts, + FAR imgsensor_format_t *datafmts, + FAR imgsensor_interval_t *interval); + CODE int (*stop_capture)(imgsensor_stream_type_t type); + + CODE int (*get_supported_value)(uint32_t id, + FAR imgsensor_supported_value_t *value); + CODE int (*get_value)(uint32_t id, + uint32_t size, + FAR imgsensor_value_t *value); + CODE int (*set_value)(uint32_t id, + uint32_t size, + imgsensor_value_t value); }; #ifdef __cplusplus @@ -340,7 +341,7 @@ extern "C" /* Register image sensor operations. */ -void imgsensor_register(FAR const struct imgsensor_ops_s *ops); +int imgsensor_register(FAR const struct imgsensor_ops_s *ops); #undef EXTERN #ifdef __cplusplus
