Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: vimc: add ancillary lens

Add lens to vimc driver and link them with sensors using ancillary links.
Provides an example of ancillary link usage.The lens supports
FOCUS_ABSOLUTE control.

Test example: With default vimc topology
> media-ctl -p
Media controller API version 5.18.0
...
- entity 28: Lens A (0 pad, 0 link)
type V4L2 subdev subtype Lens flags 0
device node name /dev/v4l-subdev6
- entity 29: Lens B (0 pad, 0 link)
type V4L2 subdev subtype Lens flags 0
device node name /dev/v4l-subdev7
> v4l2-ctl -d /dev/v4l-subdev7 -C focus_absolute
focus_absolute: 0

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Yunke Cao <yunkec@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Yunke Cao and committed by
Mauro Carvalho Chehab
d534b952 46347e3e

+170 -21
+1 -1
drivers/media/test-drivers/vimc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 vimc-y := vimc-core.o vimc-common.o vimc-streamer.o vimc-capture.o \ 3 - vimc-debayer.o vimc-scaler.o vimc-sensor.o 3 + vimc-debayer.o vimc-scaler.o vimc-sensor.o vimc-lens.o 4 4 5 5 obj-$(CONFIG_VIDEO_VIMC) += vimc.o 6 6
+1
drivers/media/test-drivers/vimc/vimc-common.h
··· 171 171 extern struct vimc_ent_type vimc_deb_type; 172 172 extern struct vimc_ent_type vimc_sca_type; 173 173 extern struct vimc_ent_type vimc_cap_type; 174 + extern struct vimc_ent_type vimc_len_type; 174 175 175 176 /** 176 177 * vimc_pix_map_by_index - get vimc_pix_map struct by its index
+66 -20
drivers/media/test-drivers/vimc/vimc-core.c
··· 24 24 25 25 #define VIMC_MDEV_MODEL_NAME "VIMC MDEV" 26 26 27 - #define VIMC_ENT_LINK(src, srcpad, sink, sinkpad, link_flags) { \ 27 + #define VIMC_DATA_LINK(src, srcpad, sink, sinkpad, link_flags) { \ 28 28 .src_ent = src, \ 29 29 .src_pad = srcpad, \ 30 30 .sink_ent = sink, \ ··· 32 32 .flags = link_flags, \ 33 33 } 34 34 35 - /* Structure which describes links between entities */ 36 - struct vimc_ent_link { 35 + #define VIMC_ANCILLARY_LINK(primary, ancillary) { \ 36 + .primary_ent = primary, \ 37 + .ancillary_ent = ancillary \ 38 + } 39 + 40 + /* Structure which describes data links between entities */ 41 + struct vimc_data_link { 37 42 unsigned int src_ent; 38 43 u16 src_pad; 39 44 unsigned int sink_ent; ··· 46 41 u32 flags; 47 42 }; 48 43 44 + /* Structure which describes ancillary links between entities */ 45 + struct vimc_ancillary_link { 46 + unsigned int primary_ent; 47 + unsigned int ancillary_ent; 48 + }; 49 + 49 50 /* Structure which describes the whole topology */ 50 51 struct vimc_pipeline_config { 51 52 const struct vimc_ent_config *ents; 52 53 size_t num_ents; 53 - const struct vimc_ent_link *links; 54 - size_t num_links; 54 + const struct vimc_data_link *data_links; 55 + size_t num_data_links; 56 + const struct vimc_ancillary_link *ancillary_links; 57 + size_t num_ancillary_links; 55 58 }; 56 59 57 60 /* -------------------------------------------------------------------------- ··· 104 91 .name = "RGB/YUV Capture", 105 92 .type = &vimc_cap_type 106 93 }, 94 + { 95 + .name = "Lens A", 96 + .type = &vimc_len_type 97 + }, 98 + { 99 + .name = "Lens B", 100 + .type = &vimc_len_type 101 + }, 107 102 }; 108 103 109 - static const struct vimc_ent_link ent_links[] = { 104 + static const struct vimc_data_link data_links[] = { 110 105 /* Link: Sensor A (Pad 0)->(Pad 0) Debayer A */ 111 - VIMC_ENT_LINK(0, 0, 2, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 106 + VIMC_DATA_LINK(0, 0, 2, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 112 107 /* Link: Sensor A (Pad 0)->(Pad 0) Raw Capture 0 */ 113 - VIMC_ENT_LINK(0, 0, 4, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 108 + VIMC_DATA_LINK(0, 0, 4, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 114 109 /* Link: Sensor B (Pad 0)->(Pad 0) Debayer B */ 115 - VIMC_ENT_LINK(1, 0, 3, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 110 + VIMC_DATA_LINK(1, 0, 3, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 116 111 /* Link: Sensor B (Pad 0)->(Pad 0) Raw Capture 1 */ 117 - VIMC_ENT_LINK(1, 0, 5, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 112 + VIMC_DATA_LINK(1, 0, 5, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 118 113 /* Link: Debayer A (Pad 1)->(Pad 0) Scaler */ 119 - VIMC_ENT_LINK(2, 1, 7, 0, MEDIA_LNK_FL_ENABLED), 114 + VIMC_DATA_LINK(2, 1, 7, 0, MEDIA_LNK_FL_ENABLED), 120 115 /* Link: Debayer B (Pad 1)->(Pad 0) Scaler */ 121 - VIMC_ENT_LINK(3, 1, 7, 0, 0), 116 + VIMC_DATA_LINK(3, 1, 7, 0, 0), 122 117 /* Link: RGB/YUV Input (Pad 0)->(Pad 0) Scaler */ 123 - VIMC_ENT_LINK(6, 0, 7, 0, 0), 118 + VIMC_DATA_LINK(6, 0, 7, 0, 0), 124 119 /* Link: Scaler (Pad 1)->(Pad 0) RGB/YUV Capture */ 125 - VIMC_ENT_LINK(7, 1, 8, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 120 + VIMC_DATA_LINK(7, 1, 8, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE), 121 + }; 122 + 123 + static const struct vimc_ancillary_link ancillary_links[] = { 124 + /* Link: Sensor A -> Lens A */ 125 + VIMC_ANCILLARY_LINK(0, 9), 126 + /* Link: Sensor B -> Lens B */ 127 + VIMC_ANCILLARY_LINK(1, 10), 126 128 }; 127 129 128 130 static struct vimc_pipeline_config pipe_cfg = { 129 - .ents = ent_config, 130 - .num_ents = ARRAY_SIZE(ent_config), 131 - .links = ent_links, 132 - .num_links = ARRAY_SIZE(ent_links) 131 + .ents = ent_config, 132 + .num_ents = ARRAY_SIZE(ent_config), 133 + .data_links = data_links, 134 + .num_data_links = ARRAY_SIZE(data_links), 135 + .ancillary_links = ancillary_links, 136 + .num_ancillary_links = ARRAY_SIZE(ancillary_links), 133 137 }; 134 138 135 139 /* -------------------------------------------------------------------------- */ ··· 165 135 int ret; 166 136 167 137 /* Initialize the links between entities */ 168 - for (i = 0; i < vimc->pipe_cfg->num_links; i++) { 169 - const struct vimc_ent_link *link = &vimc->pipe_cfg->links[i]; 138 + for (i = 0; i < vimc->pipe_cfg->num_data_links; i++) { 139 + const struct vimc_data_link *link = &vimc->pipe_cfg->data_links[i]; 170 140 171 141 struct vimc_ent_device *ved_src = 172 142 vimc->ent_devs[link->src_ent]; ··· 178 148 link->flags); 179 149 if (ret) 180 150 goto err_rm_links; 151 + } 152 + 153 + for (i = 0; i < vimc->pipe_cfg->num_ancillary_links; i++) { 154 + const struct vimc_ancillary_link *link = &vimc->pipe_cfg->ancillary_links[i]; 155 + 156 + struct vimc_ent_device *ved_primary = 157 + vimc->ent_devs[link->primary_ent]; 158 + struct vimc_ent_device *ved_ancillary = 159 + vimc->ent_devs[link->ancillary_ent]; 160 + struct media_link *ret_link = 161 + media_create_ancillary_link(ved_primary->ent, ved_ancillary->ent); 162 + 163 + if (IS_ERR(ret_link)) { 164 + ret = PTR_ERR(link); 165 + goto err_rm_links; 166 + } 181 167 } 182 168 183 169 return 0;
+102
drivers/media/test-drivers/vimc/vimc-lens.c
··· 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_LEN_MAX_FOCUS_POS 1023 15 + #define VIMC_LEN_MAX_FOCUS_STEP 1 16 + 17 + struct vimc_len_device { 18 + struct vimc_ent_device ved; 19 + struct v4l2_subdev sd; 20 + struct v4l2_ctrl_handler hdl; 21 + u32 focus_absolute; 22 + }; 23 + 24 + static const struct v4l2_subdev_core_ops vimc_len_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 + 30 + static const struct v4l2_subdev_ops vimc_len_ops = { 31 + .core = &vimc_len_core_ops 32 + }; 33 + 34 + static int vimc_len_s_ctrl(struct v4l2_ctrl *ctrl) 35 + { 36 + struct vimc_len_device *vlen = 37 + container_of(ctrl->handler, struct vimc_len_device, hdl); 38 + if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { 39 + vlen->focus_absolute = ctrl->val; 40 + return 0; 41 + } 42 + return -EINVAL; 43 + } 44 + 45 + static const struct v4l2_ctrl_ops vimc_len_ctrl_ops = { 46 + .s_ctrl = vimc_len_s_ctrl, 47 + }; 48 + 49 + static struct vimc_ent_device *vimc_len_add(struct vimc_device *vimc, 50 + const char *vcfg_name) 51 + { 52 + struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; 53 + struct vimc_len_device *vlen; 54 + int ret; 55 + 56 + /* Allocate the vlen struct */ 57 + vlen = kzalloc(sizeof(*vlen), GFP_KERNEL); 58 + if (!vlen) 59 + return ERR_PTR(-ENOMEM); 60 + 61 + v4l2_ctrl_handler_init(&vlen->hdl, 1); 62 + 63 + v4l2_ctrl_new_std(&vlen->hdl, &vimc_len_ctrl_ops, 64 + V4L2_CID_FOCUS_ABSOLUTE, 0, 65 + VIMC_LEN_MAX_FOCUS_POS, VIMC_LEN_MAX_FOCUS_STEP, 0); 66 + vlen->sd.ctrl_handler = &vlen->hdl; 67 + if (vlen->hdl.error) { 68 + ret = vlen->hdl.error; 69 + goto err_free_vlen; 70 + } 71 + vlen->ved.dev = vimc->mdev.dev; 72 + 73 + ret = vimc_ent_sd_register(&vlen->ved, &vlen->sd, v4l2_dev, 74 + vcfg_name, MEDIA_ENT_F_LENS, 0, 75 + NULL, &vimc_len_ops); 76 + if (ret) 77 + goto err_free_hdl; 78 + 79 + return &vlen->ved; 80 + 81 + err_free_hdl: 82 + v4l2_ctrl_handler_free(&vlen->hdl); 83 + err_free_vlen: 84 + kfree(vlen); 85 + 86 + return ERR_PTR(ret); 87 + } 88 + 89 + static void vimc_len_release(struct vimc_ent_device *ved) 90 + { 91 + struct vimc_len_device *vlen = 92 + container_of(ved, struct vimc_len_device, ved); 93 + 94 + v4l2_ctrl_handler_free(&vlen->hdl); 95 + media_entity_cleanup(vlen->ved.ent); 96 + kfree(vlen); 97 + } 98 + 99 + struct vimc_ent_type vimc_len_type = { 100 + .add = vimc_len_add, 101 + .release = vimc_len_release 102 + };