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.
This commit is contained in:
SPRESENSE 2021-11-29 09:31:43 +09:00 committed by Petro Karashchenko
parent a25ac08774
commit b45489753a
3 changed files with 118 additions and 27 deletions

View File

@ -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 */

View File

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

View File

@ -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 (*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 (*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