]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/misc/ivsc/intel_vsc.c
UBUNTU: [Config] ivsc: enable Intel VSC drivers
[mirror_ubuntu-jammy-kernel.git] / drivers / misc / ivsc / intel_vsc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2021 Intel Corporation */
3
4 #include <linux/module.h>
5 #include <linux/mutex.h>
6 #include <linux/sched.h>
7 #include <linux/vsc.h>
8 #include <linux/wait.h>
9
10 #include "intel_vsc.h"
11
12 #define ACE_PRIVACY_ON 2
13
14 struct intel_vsc {
15 struct mutex mutex;
16
17 void *csi;
18 struct vsc_csi_ops *csi_ops;
19 uint16_t csi_registerred;
20 wait_queue_head_t csi_waitq;
21
22 void *ace;
23 struct vsc_ace_ops *ace_ops;
24 uint16_t ace_registerred;
25 wait_queue_head_t ace_waitq;
26 };
27
28 static struct intel_vsc vsc;
29
30 static int wait_component_ready(void)
31 {
32 int ret;
33
34 ret = wait_event_interruptible(vsc.ace_waitq,
35 vsc.ace_registerred);
36 if (ret < 0) {
37 pr_err("wait ace register failed\n");
38 return ret;
39 }
40
41 ret = wait_event_interruptible(vsc.csi_waitq,
42 vsc.csi_registerred);
43 if (ret < 0) {
44 pr_err("wait csi register failed\n");
45 return ret;
46 }
47
48 return 0;
49 }
50
51 static void update_camera_status(struct vsc_camera_status *status,
52 struct camera_status *s)
53 {
54 if (status && s) {
55 status->owner = s->camera_owner;
56 status->exposure_level = s->exposure_level;
57 status->status = VSC_PRIVACY_OFF;
58
59 if (s->privacy_stat == ACE_PRIVACY_ON)
60 status->status = VSC_PRIVACY_ON;
61 }
62 }
63
64 int vsc_register_ace(void *ace, struct vsc_ace_ops *ops)
65 {
66 if (ace && ops)
67 if (ops->ipu_own_camera && ops->ace_own_camera) {
68 mutex_lock(&vsc.mutex);
69 vsc.ace = ace;
70 vsc.ace_ops = ops;
71 vsc.ace_registerred = true;
72 mutex_unlock(&vsc.mutex);
73
74 wake_up_interruptible_all(&vsc.ace_waitq);
75 return 0;
76 }
77
78 pr_err("register ace failed\n");
79 return -1;
80 }
81 EXPORT_SYMBOL_GPL(vsc_register_ace);
82
83 void vsc_unregister_ace(void)
84 {
85 mutex_lock(&vsc.mutex);
86 vsc.ace_registerred = false;
87 mutex_unlock(&vsc.mutex);
88 }
89 EXPORT_SYMBOL_GPL(vsc_unregister_ace);
90
91 int vsc_register_csi(void *csi, struct vsc_csi_ops *ops)
92 {
93 if (csi && ops)
94 if (ops->set_privacy_callback &&
95 ops->set_owner && ops->set_mipi_conf) {
96 mutex_lock(&vsc.mutex);
97 vsc.csi = csi;
98 vsc.csi_ops = ops;
99 vsc.csi_registerred = true;
100 mutex_unlock(&vsc.mutex);
101
102 wake_up_interruptible_all(&vsc.csi_waitq);
103 return 0;
104 }
105
106 pr_err("register csi failed\n");
107 return -1;
108 }
109 EXPORT_SYMBOL_GPL(vsc_register_csi);
110
111 void vsc_unregister_csi(void)
112 {
113 mutex_lock(&vsc.mutex);
114 vsc.csi_registerred = false;
115 mutex_unlock(&vsc.mutex);
116 }
117 EXPORT_SYMBOL_GPL(vsc_unregister_csi);
118
119 int vsc_acquire_camera_sensor(struct vsc_mipi_config *config,
120 vsc_privacy_callback_t callback,
121 void *handle,
122 struct vsc_camera_status *status)
123 {
124 int ret;
125 struct camera_status s;
126 struct mipi_conf conf = { 0 };
127
128 struct vsc_csi_ops *csi_ops;
129 struct vsc_ace_ops *ace_ops;
130
131 if (!config)
132 return -EINVAL;
133
134 ret = wait_component_ready();
135 if (ret)
136 return ret;
137
138 mutex_lock(&vsc.mutex);
139 if (!vsc.csi_registerred || !vsc.ace_registerred) {
140 ret = -1;
141 goto err;
142 }
143
144 csi_ops = vsc.csi_ops;
145 ace_ops = vsc.ace_ops;
146
147 csi_ops->set_privacy_callback(vsc.csi, callback, handle);
148
149 ret = ace_ops->ipu_own_camera(vsc.ace, &s);
150 if (ret) {
151 pr_err("ipu own camera failed\n");
152 goto err;
153 }
154 update_camera_status(status, &s);
155
156 ret = csi_ops->set_owner(vsc.csi, CSI_IPU);
157 if (ret) {
158 pr_err("ipu own csi failed\n");
159 goto err;
160 }
161
162 conf.lane_num = config->lane_num;
163 conf.freq = config->freq;
164 ret = csi_ops->set_mipi_conf(vsc.csi, &conf);
165 if (ret) {
166 pr_err("config mipi failed\n");
167 goto err;
168 }
169
170 err:
171 mutex_unlock(&vsc.mutex);
172 return ret;
173 }
174 EXPORT_SYMBOL_GPL(vsc_acquire_camera_sensor);
175
176 int vsc_release_camera_sensor(struct vsc_camera_status *status)
177 {
178 int ret;
179 struct camera_status s;
180
181 struct vsc_csi_ops *csi_ops;
182 struct vsc_ace_ops *ace_ops;
183
184 ret = wait_component_ready();
185 if (ret)
186 return ret;
187
188 mutex_lock(&vsc.mutex);
189 if (!vsc.csi_registerred || !vsc.ace_registerred) {
190 ret = -1;
191 goto err;
192 }
193
194 csi_ops = vsc.csi_ops;
195 ace_ops = vsc.ace_ops;
196
197 csi_ops->set_privacy_callback(vsc.csi, NULL, NULL);
198
199 ret = csi_ops->set_owner(vsc.csi, CSI_FW);
200 if (ret) {
201 pr_err("vsc own csi failed\n");
202 goto err;
203 }
204
205 ret = ace_ops->ace_own_camera(vsc.ace, &s);
206 if (ret) {
207 pr_err("vsc own camera failed\n");
208 goto err;
209 }
210 update_camera_status(status, &s);
211
212 err:
213 mutex_unlock(&vsc.mutex);
214 return ret;
215 }
216 EXPORT_SYMBOL_GPL(vsc_release_camera_sensor);
217
218 static int __init intel_vsc_init(void)
219 {
220 memset(&vsc, 0, sizeof(struct intel_vsc));
221
222 mutex_init(&vsc.mutex);
223
224 vsc.csi_registerred = false;
225 vsc.ace_registerred = false;
226
227 init_waitqueue_head(&vsc.ace_waitq);
228 init_waitqueue_head(&vsc.csi_waitq);
229
230 return 0;
231 }
232
233 static void __exit intel_vsc_exit(void)
234 {
235 if (wq_has_sleeper(&vsc.ace_waitq))
236 wake_up_all(&vsc.ace_waitq);
237
238 if (wq_has_sleeper(&vsc.csi_waitq))
239 wake_up_all(&vsc.csi_waitq);
240 }
241
242 module_init(intel_vsc_init);
243 module_exit(intel_vsc_exit);
244
245 MODULE_AUTHOR("Intel Corporation");
246 MODULE_LICENSE("GPL v2");
247 MODULE_DESCRIPTION("Device driver for Intel VSC");