]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/misc/ivsc/intel_vsc.c
Revert "UBUNTU: SAUCE: ivsc: return error when device not ready"
[mirror_ubuntu-jammy-kernel.git] / drivers / misc / ivsc / intel_vsc.c
CommitLineData
986aaa71
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>
7#include <linux/vsc.h>
315c38fe 8#include <linux/wait.h>
986aaa71
WW
9
10#include "intel_vsc.h"
11
12#define ACE_PRIVACY_ON 2
13
14struct intel_vsc {
15 struct mutex mutex;
16
17 void *csi;
18 struct vsc_csi_ops *csi_ops;
19 uint16_t csi_registerred;
315c38fe 20 wait_queue_head_t csi_waitq;
986aaa71
WW
21
22 void *ace;
23 struct vsc_ace_ops *ace_ops;
24 uint16_t ace_registerred;
315c38fe 25 wait_queue_head_t ace_waitq;
986aaa71
WW
26};
27
28static struct intel_vsc vsc;
29
315c38fe 30static int wait_component_ready(void)
986aaa71 31{
315c38fe 32 int ret;
986aaa71 33
315c38fe
SB
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 }
986aaa71 40
315c38fe
SB
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 }
9a356830 47
315c38fe 48 return 0;
986aaa71
WW
49}
50
51static 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
64int vsc_register_ace(void *ace, struct vsc_ace_ops *ops)
65{
315c38fe 66 if (ace && ops)
986aaa71 67 if (ops->ipu_own_camera && ops->ace_own_camera) {
315c38fe 68 mutex_lock(&vsc.mutex);
986aaa71
WW
69 vsc.ace = ace;
70 vsc.ace_ops = ops;
71 vsc.ace_registerred = true;
315c38fe 72 mutex_unlock(&vsc.mutex);
986aaa71 73
315c38fe 74 wake_up_interruptible_all(&vsc.ace_waitq);
986aaa71
WW
75 return 0;
76 }
77
78 pr_err("register ace failed\n");
79 return -1;
80}
81EXPORT_SYMBOL_GPL(vsc_register_ace);
82
83void vsc_unregister_ace(void)
84{
315c38fe 85 mutex_lock(&vsc.mutex);
986aaa71 86 vsc.ace_registerred = false;
315c38fe 87 mutex_unlock(&vsc.mutex);
986aaa71
WW
88}
89EXPORT_SYMBOL_GPL(vsc_unregister_ace);
90
91int vsc_register_csi(void *csi, struct vsc_csi_ops *ops)
92{
315c38fe 93 if (csi && ops)
986aaa71
WW
94 if (ops->set_privacy_callback &&
95 ops->set_owner && ops->set_mipi_conf) {
315c38fe 96 mutex_lock(&vsc.mutex);
986aaa71
WW
97 vsc.csi = csi;
98 vsc.csi_ops = ops;
99 vsc.csi_registerred = true;
315c38fe 100 mutex_unlock(&vsc.mutex);
986aaa71 101
315c38fe 102 wake_up_interruptible_all(&vsc.csi_waitq);
986aaa71
WW
103 return 0;
104 }
105
106 pr_err("register csi failed\n");
107 return -1;
108}
109EXPORT_SYMBOL_GPL(vsc_register_csi);
110
111void vsc_unregister_csi(void)
112{
315c38fe 113 mutex_lock(&vsc.mutex);
986aaa71 114 vsc.csi_registerred = false;
315c38fe 115 mutex_unlock(&vsc.mutex);
986aaa71
WW
116}
117EXPORT_SYMBOL_GPL(vsc_unregister_csi);
118
119int 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
315c38fe
SB
134 ret = wait_component_ready();
135 if (ret)
136 return ret;
986aaa71
WW
137
138 mutex_lock(&vsc.mutex);
315c38fe
SB
139 if (!vsc.csi_registerred || !vsc.ace_registerred) {
140 ret = -1;
141 goto err;
142 }
986aaa71
WW
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
170err:
171 mutex_unlock(&vsc.mutex);
172 return ret;
173}
174EXPORT_SYMBOL_GPL(vsc_acquire_camera_sensor);
175
176int 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
315c38fe
SB
184 ret = wait_component_ready();
185 if (ret)
186 return ret;
986aaa71
WW
187
188 mutex_lock(&vsc.mutex);
315c38fe
SB
189 if (!vsc.csi_registerred || !vsc.ace_registerred) {
190 ret = -1;
191 goto err;
192 }
986aaa71
WW
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
212err:
213 mutex_unlock(&vsc.mutex);
214 return ret;
215}
216EXPORT_SYMBOL_GPL(vsc_release_camera_sensor);
217
218static 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
315c38fe
SB
227 init_waitqueue_head(&vsc.ace_waitq);
228 init_waitqueue_head(&vsc.csi_waitq);
229
986aaa71
WW
230 return 0;
231}
232
233static void __exit intel_vsc_exit(void)
234{
315c38fe
SB
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);
986aaa71
WW
240}
241
242module_init(intel_vsc_init);
243module_exit(intel_vsc_exit);
244
245MODULE_AUTHOR("Intel Corporation");
246MODULE_LICENSE("GPL v2");
247MODULE_DESCRIPTION("Device driver for Intel VSC");