]>
Commit | Line | Data |
---|---|---|
8745013f WW |
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> | |
7111970c | 7 | #include <linux/spinlock.h> |
8745013f | 8 | #include <linux/vsc.h> |
8745013f WW |
9 | |
10 | #include "intel_vsc.h" | |
11 | ||
12 | #define ACE_PRIVACY_ON 2 | |
13 | ||
14 | struct intel_vsc { | |
7111970c | 15 | spinlock_t lock; |
8745013f WW |
16 | struct mutex mutex; |
17 | ||
18 | void *csi; | |
19 | struct vsc_csi_ops *csi_ops; | |
20 | uint16_t csi_registerred; | |
8745013f WW |
21 | |
22 | void *ace; | |
23 | struct vsc_ace_ops *ace_ops; | |
24 | uint16_t ace_registerred; | |
8745013f WW |
25 | }; |
26 | ||
27 | static struct intel_vsc vsc; | |
28 | ||
7111970c | 29 | static int check_component_ready(void) |
8745013f | 30 | { |
7111970c WW |
31 | int ret = -1; |
32 | unsigned long flags; | |
8745013f | 33 | |
7111970c | 34 | spin_lock_irqsave(&vsc.lock, flags); |
8745013f | 35 | |
7111970c WW |
36 | if (vsc.ace_registerred && vsc.csi_registerred) |
37 | ret = 0; | |
8745013f | 38 | |
7111970c WW |
39 | spin_unlock_irqrestore(&vsc.lock, flags); |
40 | ||
41 | return ret; | |
8745013f WW |
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 | { | |
7111970c WW |
59 | unsigned long flags; |
60 | ||
61 | if (ace && ops) { | |
8745013f | 62 | if (ops->ipu_own_camera && ops->ace_own_camera) { |
7111970c WW |
63 | spin_lock_irqsave(&vsc.lock, flags); |
64 | ||
8745013f WW |
65 | vsc.ace = ace; |
66 | vsc.ace_ops = ops; | |
67 | vsc.ace_registerred = true; | |
8745013f | 68 | |
7111970c WW |
69 | spin_unlock_irqrestore(&vsc.lock, flags); |
70 | ||
8745013f WW |
71 | return 0; |
72 | } | |
7111970c | 73 | } |
8745013f WW |
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 | { | |
7111970c WW |
82 | unsigned long flags; |
83 | ||
84 | spin_lock_irqsave(&vsc.lock, flags); | |
85 | ||
8745013f | 86 | vsc.ace_registerred = false; |
7111970c WW |
87 | |
88 | spin_unlock_irqrestore(&vsc.lock, flags); | |
8745013f WW |
89 | } |
90 | EXPORT_SYMBOL_GPL(vsc_unregister_ace); | |
91 | ||
92 | int vsc_register_csi(void *csi, struct vsc_csi_ops *ops) | |
93 | { | |
7111970c WW |
94 | unsigned long flags; |
95 | ||
96 | if (csi && ops) { | |
8745013f WW |
97 | if (ops->set_privacy_callback && |
98 | ops->set_owner && ops->set_mipi_conf) { | |
7111970c WW |
99 | spin_lock_irqsave(&vsc.lock, flags); |
100 | ||
8745013f WW |
101 | vsc.csi = csi; |
102 | vsc.csi_ops = ops; | |
103 | vsc.csi_registerred = true; | |
8745013f | 104 | |
7111970c WW |
105 | spin_unlock_irqrestore(&vsc.lock, flags); |
106 | ||
8745013f WW |
107 | return 0; |
108 | } | |
7111970c | 109 | } |
8745013f WW |
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 | { | |
7111970c WW |
118 | unsigned long flags; |
119 | ||
120 | spin_lock_irqsave(&vsc.lock, flags); | |
121 | ||
8745013f | 122 | vsc.csi_registerred = false; |
7111970c WW |
123 | |
124 | spin_unlock_irqrestore(&vsc.lock, flags); | |
8745013f WW |
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 | ||
7111970c WW |
143 | ret = check_component_ready(); |
144 | if (ret < 0) { | |
145 | pr_info("intel vsc not ready\n"); | |
146 | return -EAGAIN; | |
147 | } | |
8745013f WW |
148 | |
149 | mutex_lock(&vsc.mutex); | |
7111970c | 150 | /* no need check component again here */ |
8745013f WW |
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 | ||
7111970c WW |
192 | ret = check_component_ready(); |
193 | if (ret < 0) { | |
194 | pr_info("intel vsc not ready\n"); | |
195 | return -EAGAIN; | |
196 | } | |
8745013f WW |
197 | |
198 | mutex_lock(&vsc.mutex); | |
7111970c | 199 | /* no need check component again here */ |
8745013f WW |
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 | ||
7111970c | 229 | spin_lock_init(&vsc.lock); |
8745013f WW |
230 | mutex_init(&vsc.mutex); |
231 | ||
232 | vsc.csi_registerred = false; | |
233 | vsc.ace_registerred = false; | |
234 | ||
8745013f WW |
235 | return 0; |
236 | } | |
237 | ||
238 | static void __exit intel_vsc_exit(void) | |
239 | { | |
8745013f WW |
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"); | |
2642a2a3 | 247 | MODULE_SOFTDEP("post: mei_csi mei_ace"); |
8745013f | 248 | MODULE_DESCRIPTION("Device driver for Intel VSC"); |