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