1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * vimc-lens.c Virtual Media Controller Driver
4 * Copyright (C) 2022 Google, Inc
5 * Author: yunkec@google.com (Yunke Cao)
6 */
7
8#include <media/v4l2-ctrls.h>
9#include <media/v4l2-event.h>
10#include <media/v4l2-subdev.h>
11
12#include "vimc-common.h"
13
14#define VIMC_LENS_MAX_FOCUS_POS 1023
15#define VIMC_LENS_MAX_FOCUS_STEP 1
16
17struct vimc_lens_device {
18 struct vimc_ent_device ved;
19 struct v4l2_subdev sd;
20 struct v4l2_ctrl_handler hdl;
21 u32 focus_absolute;
22};
23
24static const struct v4l2_subdev_core_ops vimc_lens_core_ops = {
25 .log_status = v4l2_ctrl_subdev_log_status,
26 .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
27 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
28};
29
30static const struct v4l2_subdev_ops vimc_lens_ops = {
31 .core = &vimc_lens_core_ops
32};
33
34static int vimc_lens_s_ctrl(struct v4l2_ctrl *ctrl)
35{
36 struct vimc_lens_device *vlens =
37 container_of(ctrl->handler, struct vimc_lens_device, hdl);
38 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) {
39 vlens->focus_absolute = ctrl->val;
40 return 0;
41 }
42 return -EINVAL;
43}
44
45static const struct v4l2_ctrl_ops vimc_lens_ctrl_ops = {
46 .s_ctrl = vimc_lens_s_ctrl,
47};
48
49static struct vimc_ent_device *vimc_lens_add(struct vimc_device *vimc,
50 const char *vcfg_name)
51{
52 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
53 struct vimc_lens_device *vlens;
54 int ret;
55
56 /* Allocate the vlens struct */
57 vlens = kzalloc(size: sizeof(*vlens), GFP_KERNEL);
58 if (!vlens)
59 return ERR_PTR(error: -ENOMEM);
60
61 v4l2_ctrl_handler_init(&vlens->hdl, 1);
62
63 v4l2_ctrl_new_std(hdl: &vlens->hdl, ops: &vimc_lens_ctrl_ops,
64 V4L2_CID_FOCUS_ABSOLUTE, min: 0,
65 VIMC_LENS_MAX_FOCUS_POS, VIMC_LENS_MAX_FOCUS_STEP, def: 0);
66 vlens->sd.ctrl_handler = &vlens->hdl;
67 if (vlens->hdl.error) {
68 ret = vlens->hdl.error;
69 goto err_free_vlens;
70 }
71 vlens->ved.dev = vimc->mdev.dev;
72
73 ret = vimc_ent_sd_register(ved: &vlens->ved, sd: &vlens->sd, v4l2_dev,
74 name: vcfg_name, MEDIA_ENT_F_LENS, num_pads: 0,
75 NULL, sd_ops: &vimc_lens_ops);
76 if (ret)
77 goto err_free_hdl;
78
79 return &vlens->ved;
80
81err_free_hdl:
82 v4l2_ctrl_handler_free(hdl: &vlens->hdl);
83err_free_vlens:
84 kfree(objp: vlens);
85
86 return ERR_PTR(error: ret);
87}
88
89static void vimc_lens_release(struct vimc_ent_device *ved)
90{
91 struct vimc_lens_device *vlens =
92 container_of(ved, struct vimc_lens_device, ved);
93
94 v4l2_ctrl_handler_free(hdl: &vlens->hdl);
95 media_entity_cleanup(entity: vlens->ved.ent);
96 kfree(objp: vlens);
97}
98
99struct vimc_ent_type vimc_lens_type = {
100 .add = vimc_lens_add,
101 .release = vimc_lens_release
102};
103

source code of linux/drivers/media/test-drivers/vimc/vimc-lens.c