diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/media/test-drivers/vimc/vimc-lens.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/media/test-drivers/vimc/vimc-lens.c b/drivers/media/test-drivers/vimc/vimc-lens.c new file mode 100644 index 0000000000..3ce7f4b4d2 --- /dev/null +++ b/drivers/media/test-drivers/vimc/vimc-lens.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * vimc-lens.c Virtual Media Controller Driver + * Copyright (C) 2022 Google, Inc + * Author: yunkec@google.com (Yunke Cao) + */ + +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> +#include <media/v4l2-subdev.h> + +#include "vimc-common.h" + +#define VIMC_LENS_MAX_FOCUS_POS 1023 +#define VIMC_LENS_MAX_FOCUS_STEP 1 + +struct vimc_lens_device { + struct vimc_ent_device ved; + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + u32 focus_absolute; +}; + +static const struct v4l2_subdev_core_ops vimc_lens_core_ops = { + .log_status = v4l2_ctrl_subdev_log_status, + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_ops vimc_lens_ops = { + .core = &vimc_lens_core_ops +}; + +static int vimc_lens_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vimc_lens_device *vlens = + container_of(ctrl->handler, struct vimc_lens_device, hdl); + if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { + vlens->focus_absolute = ctrl->val; + return 0; + } + return -EINVAL; +} + +static const struct v4l2_ctrl_ops vimc_lens_ctrl_ops = { + .s_ctrl = vimc_lens_s_ctrl, +}; + +static struct vimc_ent_device *vimc_lens_add(struct vimc_device *vimc, + const char *vcfg_name) +{ + struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; + struct vimc_lens_device *vlens; + int ret; + + /* Allocate the vlens struct */ + vlens = kzalloc(sizeof(*vlens), GFP_KERNEL); + if (!vlens) + return ERR_PTR(-ENOMEM); + + v4l2_ctrl_handler_init(&vlens->hdl, 1); + + v4l2_ctrl_new_std(&vlens->hdl, &vimc_lens_ctrl_ops, + V4L2_CID_FOCUS_ABSOLUTE, 0, + VIMC_LENS_MAX_FOCUS_POS, VIMC_LENS_MAX_FOCUS_STEP, 0); + vlens->sd.ctrl_handler = &vlens->hdl; + if (vlens->hdl.error) { + ret = vlens->hdl.error; + goto err_free_vlens; + } + vlens->ved.dev = vimc->mdev.dev; + + ret = vimc_ent_sd_register(&vlens->ved, &vlens->sd, v4l2_dev, + vcfg_name, MEDIA_ENT_F_LENS, 0, + NULL, &vimc_lens_ops); + if (ret) + goto err_free_hdl; + + return &vlens->ved; + +err_free_hdl: + v4l2_ctrl_handler_free(&vlens->hdl); +err_free_vlens: + kfree(vlens); + + return ERR_PTR(ret); +} + +static void vimc_lens_release(struct vimc_ent_device *ved) +{ + struct vimc_lens_device *vlens = + container_of(ved, struct vimc_lens_device, ved); + + v4l2_ctrl_handler_free(&vlens->hdl); + media_entity_cleanup(vlens->ved.ent); + kfree(vlens); +} + +struct vimc_ent_type vimc_lens_type = { + .add = vimc_lens_add, + .release = vimc_lens_release +}; |