]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/misc/ivsc/intel_vsc.c
UBUNTU: SAUCE: ivsc: add soft dependencies for intel_vsc module
[mirror_ubuntu-jammy-kernel.git] / drivers / misc / ivsc / intel_vsc.c
CommitLineData
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
14struct 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
27static struct intel_vsc vsc;
28
7111970c 29static 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
44static 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
57int 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}
78EXPORT_SYMBOL_GPL(vsc_register_ace);
79
80void 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}
90EXPORT_SYMBOL_GPL(vsc_unregister_ace);
91
92int 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}
114EXPORT_SYMBOL_GPL(vsc_register_csi);
115
116void 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}
126EXPORT_SYMBOL_GPL(vsc_unregister_csi);
127
128int 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
178err:
179 mutex_unlock(&vsc.mutex);
180 return ret;
181}
182EXPORT_SYMBOL_GPL(vsc_acquire_camera_sensor);
183
184int 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
219err:
220 mutex_unlock(&vsc.mutex);
221 return ret;
222}
223EXPORT_SYMBOL_GPL(vsc_release_camera_sensor);
224
225static 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
238static void __exit intel_vsc_exit(void)
239{
8745013f
WW
240}
241
242module_init(intel_vsc_init);
243module_exit(intel_vsc_exit);
244
245MODULE_AUTHOR("Intel Corporation");
246MODULE_LICENSE("GPL v2");
2642a2a3 247MODULE_SOFTDEP("post: mei_csi mei_ace");
8745013f 248MODULE_DESCRIPTION("Device driver for Intel VSC");