103 lines
2.4 KiB
C
103 lines
2.4 KiB
C
|
// 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
|
||
|
};
|