blob: 6e48c6aeccebfc3af4b3d38c8a726e0918638d1f [file] [log] [blame]
Jing Zhou076a3092017-02-27 02:43:03 -08001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/debugfs.h>
14#include <linux/videodev2.h>
15#include <linux/uaccess.h>
16
17#include "cam_node.h"
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -060018#include "cam_trace.h"
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070019#include "cam_debug_util.h"
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070020static void __cam_node_handle_shutdown(struct cam_node *node)
21{
22 if (node->hw_mgr_intf.hw_close)
23 node->hw_mgr_intf.hw_close(node->hw_mgr_intf.hw_mgr_priv,
24 NULL);
25}
26
Jing Zhou076a3092017-02-27 02:43:03 -080027static int __cam_node_handle_query_cap(struct cam_node *node,
28 struct cam_query_cap_cmd *query)
29{
30 int rc = -EFAULT;
31
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070032 if (!query) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070033 CAM_ERR(CAM_CORE, "Invalid params");
Jing Zhou076a3092017-02-27 02:43:03 -080034 return -EINVAL;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070035 }
Jing Zhou076a3092017-02-27 02:43:03 -080036
37 if (node->hw_mgr_intf.hw_get_caps) {
38 rc = node->hw_mgr_intf.hw_get_caps(
39 node->hw_mgr_intf.hw_mgr_priv, query);
40 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070041
Jing Zhou076a3092017-02-27 02:43:03 -080042 return rc;
43}
44
45static int __cam_node_handle_acquire_dev(struct cam_node *node,
46 struct cam_acquire_dev_cmd *acquire)
47{
48 int rc = 0;
49 struct cam_context *ctx = NULL;
50
51 if (!acquire)
52 return -EINVAL;
53
54 mutex_lock(&node->list_mutex);
55 if (!list_empty(&node->free_ctx_list)) {
56 ctx = list_first_entry(&node->free_ctx_list,
57 struct cam_context, list);
58 list_del_init(&ctx->list);
59 }
60 mutex_unlock(&node->list_mutex);
Jing Zhou076a3092017-02-27 02:43:03 -080061 if (!ctx) {
62 rc = -ENOMEM;
63 goto err;
64 }
65
66 rc = cam_context_handle_acquire_dev(ctx, acquire);
67 if (rc) {
Harsh Shah2abfe542017-09-29 17:09:22 -070068 CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
69 node->name);
Jing Zhou076a3092017-02-27 02:43:03 -080070 goto free_ctx;
71 }
72
73 return 0;
74free_ctx:
75 mutex_lock(&node->list_mutex);
76 list_add_tail(&ctx->list, &node->free_ctx_list);
77 mutex_unlock(&node->list_mutex);
78err:
79 return rc;
80}
81
82static int __cam_node_handle_start_dev(struct cam_node *node,
83 struct cam_start_stop_dev_cmd *start)
84{
85 struct cam_context *ctx = NULL;
Harsh Shah2abfe542017-09-29 17:09:22 -070086 int rc;
Jing Zhou076a3092017-02-27 02:43:03 -080087
88 if (!start)
89 return -EINVAL;
90
91 if (start->dev_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070092 CAM_ERR(CAM_CORE, "Invalid device handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -080093 return -EINVAL;
94 }
95
96 if (start->session_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070097 CAM_ERR(CAM_CORE, "Invalid session handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -080098 return -EINVAL;
99 }
100
101 ctx = (struct cam_context *)cam_get_device_priv(start->dev_handle);
102 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700103 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
104 start->dev_handle);
Jing Zhou076a3092017-02-27 02:43:03 -0800105 return -EINVAL;
106 }
107
Harsh Shah2abfe542017-09-29 17:09:22 -0700108 rc = cam_context_handle_start_dev(ctx, start);
109 if (rc)
110 CAM_ERR(CAM_CORE, "Start failure for node %s", node->name);
111
112 return rc;
Jing Zhou076a3092017-02-27 02:43:03 -0800113}
114
115static int __cam_node_handle_stop_dev(struct cam_node *node,
116 struct cam_start_stop_dev_cmd *stop)
117{
118 struct cam_context *ctx = NULL;
Harsh Shah2abfe542017-09-29 17:09:22 -0700119 int rc;
Jing Zhou076a3092017-02-27 02:43:03 -0800120
121 if (!stop)
122 return -EINVAL;
123
124 if (stop->dev_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700125 CAM_ERR(CAM_CORE, "Invalid device handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800126 return -EINVAL;
127 }
128
129 if (stop->session_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700130 CAM_ERR(CAM_CORE, "Invalid session handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800131 return -EINVAL;
132 }
133
134 ctx = (struct cam_context *)cam_get_device_priv(stop->dev_handle);
135 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700136 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
137 stop->dev_handle);
Jing Zhou076a3092017-02-27 02:43:03 -0800138 return -EINVAL;
139 }
140
Harsh Shah2abfe542017-09-29 17:09:22 -0700141 rc = cam_context_handle_stop_dev(ctx, stop);
142 if (rc)
143 CAM_ERR(CAM_CORE, "Stop failure for node %s", node->name);
144
145 return rc;
Jing Zhou076a3092017-02-27 02:43:03 -0800146}
147
148static int __cam_node_handle_config_dev(struct cam_node *node,
149 struct cam_config_dev_cmd *config)
150{
151 struct cam_context *ctx = NULL;
Harsh Shah2abfe542017-09-29 17:09:22 -0700152 int rc;
Jing Zhou076a3092017-02-27 02:43:03 -0800153
154 if (!config)
155 return -EINVAL;
156
157 if (config->dev_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700158 CAM_ERR(CAM_CORE, "Invalid device handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800159 return -EINVAL;
160 }
161
162 if (config->session_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700163 CAM_ERR(CAM_CORE, "Invalid session handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800164 return -EINVAL;
165 }
166
167 ctx = (struct cam_context *)cam_get_device_priv(config->dev_handle);
168 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700169 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
170 config->dev_handle);
Jing Zhou076a3092017-02-27 02:43:03 -0800171 return -EINVAL;
172 }
173
Harsh Shah2abfe542017-09-29 17:09:22 -0700174 rc = cam_context_handle_config_dev(ctx, config);
175 if (rc)
176 CAM_ERR(CAM_CORE, "Config failure for node %s", node->name);
177
178 return rc;
Jing Zhou076a3092017-02-27 02:43:03 -0800179}
180
181static int __cam_node_handle_release_dev(struct cam_node *node,
182 struct cam_release_dev_cmd *release)
183{
184 int rc = 0;
185 struct cam_context *ctx = NULL;
186
187 if (!release)
188 return -EINVAL;
189
190 if (release->dev_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700191 CAM_ERR(CAM_CORE, "Invalid device handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800192 return -EINVAL;
193 }
194
195 if (release->session_handle <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700196 CAM_ERR(CAM_CORE, "Invalid session handle for context");
Jing Zhou076a3092017-02-27 02:43:03 -0800197 return -EINVAL;
198 }
199
200 ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle);
201 if (!ctx) {
Harsh Shah2abfe542017-09-29 17:09:22 -0700202 CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s",
203 release->dev_handle, node->name);
Jing Zhou076a3092017-02-27 02:43:03 -0800204 return -EINVAL;
205 }
206
207 rc = cam_context_handle_release_dev(ctx, release);
208 if (rc)
Harsh Shah2abfe542017-09-29 17:09:22 -0700209 CAM_ERR(CAM_CORE, "context release failed node %s", node->name);
Jing Zhou076a3092017-02-27 02:43:03 -0800210
211 rc = cam_destroy_device_hdl(release->dev_handle);
212 if (rc)
Harsh Shah2abfe542017-09-29 17:09:22 -0700213 CAM_ERR(CAM_CORE, "destroy device handle is failed node %s",
214 node->name);
Jing Zhou076a3092017-02-27 02:43:03 -0800215
216 mutex_lock(&node->list_mutex);
217 list_add_tail(&ctx->list, &node->free_ctx_list);
218 mutex_unlock(&node->list_mutex);
219 return rc;
220}
221
Jing Zhoub524a852017-05-16 15:47:30 +0530222static int __cam_node_crm_get_dev_info(struct cam_req_mgr_device_info *info)
Jing Zhou076a3092017-02-27 02:43:03 -0800223{
224 struct cam_context *ctx = NULL;
225
226 if (!info)
227 return -EINVAL;
228
229 ctx = (struct cam_context *) cam_get_device_priv(info->dev_hdl);
230 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700231 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
232 info->dev_hdl);
Jing Zhou076a3092017-02-27 02:43:03 -0800233 return -EINVAL;
234 }
Jing Zhoub524a852017-05-16 15:47:30 +0530235 return cam_context_handle_crm_get_dev_info(ctx, info);
Jing Zhou076a3092017-02-27 02:43:03 -0800236}
237
Jing Zhoub524a852017-05-16 15:47:30 +0530238static int __cam_node_crm_link_setup(
239 struct cam_req_mgr_core_dev_link_setup *setup)
Jing Zhou076a3092017-02-27 02:43:03 -0800240{
241 int rc;
242 struct cam_context *ctx = NULL;
243
244 if (!setup)
245 return -EINVAL;
246
247 ctx = (struct cam_context *) cam_get_device_priv(setup->dev_hdl);
248 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700249 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
250 setup->dev_hdl);
Jing Zhou076a3092017-02-27 02:43:03 -0800251 return -EINVAL;
252 }
253
254 if (setup->link_enable)
Jing Zhoub524a852017-05-16 15:47:30 +0530255 rc = cam_context_handle_crm_link(ctx, setup);
Jing Zhou076a3092017-02-27 02:43:03 -0800256 else
Jing Zhoub524a852017-05-16 15:47:30 +0530257 rc = cam_context_handle_crm_unlink(ctx, setup);
Jing Zhou076a3092017-02-27 02:43:03 -0800258
259 return rc;
260}
261
Jing Zhoub524a852017-05-16 15:47:30 +0530262static int __cam_node_crm_apply_req(struct cam_req_mgr_apply_request *apply)
Jing Zhou076a3092017-02-27 02:43:03 -0800263{
264 struct cam_context *ctx = NULL;
265
266 if (!apply)
267 return -EINVAL;
268
269 ctx = (struct cam_context *) cam_get_device_priv(apply->dev_hdl);
270 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700271 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
272 apply->dev_hdl);
Jing Zhou076a3092017-02-27 02:43:03 -0800273 return -EINVAL;
274 }
275
Junzhe Zou5fa08b12017-08-15 10:08:12 -0700276 trace_cam_apply_req("Node", apply->request_id);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -0600277
Jing Zhoub524a852017-05-16 15:47:30 +0530278 return cam_context_handle_crm_apply_req(ctx, apply);
279}
280
281static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush)
282{
283 struct cam_context *ctx = NULL;
284
285 if (!flush) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700286 CAM_ERR(CAM_CORE, "Invalid flush request payload");
Jing Zhoub524a852017-05-16 15:47:30 +0530287 return -EINVAL;
288 }
289
290 ctx = (struct cam_context *) cam_get_device_priv(flush->dev_hdl);
291 if (!ctx) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700292 CAM_ERR(CAM_CORE, "Can not get context for handle %d",
293 flush->dev_hdl);
Jing Zhoub524a852017-05-16 15:47:30 +0530294 return -EINVAL;
295 }
296
297 return cam_context_handle_crm_flush_req(ctx, flush);
Jing Zhou076a3092017-02-27 02:43:03 -0800298}
299
300int cam_node_deinit(struct cam_node *node)
301{
302 if (node)
303 memset(node, 0, sizeof(*node));
304
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700305 CAM_DBG(CAM_CORE, "deinit complete");
Jing Zhou076a3092017-02-27 02:43:03 -0800306
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700307 return 0;
Jing Zhou076a3092017-02-27 02:43:03 -0800308}
309
310int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf,
311 struct cam_context *ctx_list, uint32_t ctx_size, char *name)
312{
313 int rc = 0;
314 int i;
315
316 if (!node || !hw_mgr_intf ||
317 sizeof(node->hw_mgr_intf) != sizeof(*hw_mgr_intf)) {
318 return -EINVAL;
319 }
320
321 memset(node, 0, sizeof(*node));
322
323 strlcpy(node->name, name, sizeof(node->name));
324
325 memcpy(&node->hw_mgr_intf, hw_mgr_intf, sizeof(node->hw_mgr_intf));
Jing Zhoub524a852017-05-16 15:47:30 +0530326 node->crm_node_intf.apply_req = __cam_node_crm_apply_req;
327 node->crm_node_intf.get_dev_info = __cam_node_crm_get_dev_info;
328 node->crm_node_intf.link_setup = __cam_node_crm_link_setup;
329 node->crm_node_intf.flush_req = __cam_node_crm_flush_req;
Jing Zhou076a3092017-02-27 02:43:03 -0800330
331 mutex_init(&node->list_mutex);
332 INIT_LIST_HEAD(&node->free_ctx_list);
333 node->ctx_list = ctx_list;
334 node->ctx_size = ctx_size;
335 for (i = 0; i < ctx_size; i++) {
336 if (!ctx_list[i].state_machine) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700337 CAM_ERR(CAM_CORE,
338 "camera context %d is not initialized", i);
Jing Zhou076a3092017-02-27 02:43:03 -0800339 rc = -1;
340 goto err;
341 }
342 INIT_LIST_HEAD(&ctx_list[i].list);
343 list_add_tail(&ctx_list[i].list, &node->free_ctx_list);
344 }
345
346 node->state = CAM_NODE_STATE_INIT;
347err:
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700348 CAM_DBG(CAM_CORE, "Exit. (rc = %d)", rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800349 return rc;
350}
351
352int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
353{
354 int rc = 0;
355
356 if (!cmd)
357 return -EINVAL;
358
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700359 CAM_DBG(CAM_CORE, "handle cmd %d", cmd->op_code);
Jing Zhou076a3092017-02-27 02:43:03 -0800360
361 switch (cmd->op_code) {
362 case CAM_QUERY_CAP: {
363 struct cam_query_cap_cmd query;
364
365 if (copy_from_user(&query, (void __user *)cmd->handle,
366 sizeof(query))) {
367 rc = -EFAULT;
368 break;
369 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700370
Jing Zhou076a3092017-02-27 02:43:03 -0800371 rc = __cam_node_handle_query_cap(node, &query);
372 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700373 CAM_ERR(CAM_CORE, "querycap is failed(rc = %d)",
374 rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800375 break;
376 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700377
Jing Zhou076a3092017-02-27 02:43:03 -0800378 if (copy_to_user((void __user *)cmd->handle, &query,
379 sizeof(query)))
380 rc = -EFAULT;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700381
Jing Zhou076a3092017-02-27 02:43:03 -0800382 break;
383 }
384 case CAM_ACQUIRE_DEV: {
385 struct cam_acquire_dev_cmd acquire;
386
387 if (copy_from_user(&acquire, (void __user *)cmd->handle,
388 sizeof(acquire))) {
389 rc = -EFAULT;
390 break;
391 }
392 rc = __cam_node_handle_acquire_dev(node, &acquire);
393 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700394 CAM_ERR(CAM_CORE, "acquire device failed(rc = %d)",
395 rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800396 break;
397 }
398 if (copy_to_user((void __user *)cmd->handle, &acquire,
399 sizeof(acquire)))
400 rc = -EFAULT;
401 break;
402 }
403 case CAM_START_DEV: {
404 struct cam_start_stop_dev_cmd start;
405
406 if (copy_from_user(&start, (void __user *)cmd->handle,
407 sizeof(start)))
408 rc = -EFAULT;
409 else {
410 rc = __cam_node_handle_start_dev(node, &start);
411 if (rc)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700412 CAM_ERR(CAM_CORE,
413 "start device failed(rc = %d)", rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800414 }
415 break;
416 }
417 case CAM_STOP_DEV: {
418 struct cam_start_stop_dev_cmd stop;
419
420 if (copy_from_user(&stop, (void __user *)cmd->handle,
421 sizeof(stop)))
422 rc = -EFAULT;
423 else {
424 rc = __cam_node_handle_stop_dev(node, &stop);
425 if (rc)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700426 CAM_ERR(CAM_CORE,
427 "stop device failed(rc = %d)", rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800428 }
429 break;
430 }
431 case CAM_CONFIG_DEV: {
432 struct cam_config_dev_cmd config;
433
434 if (copy_from_user(&config, (void __user *)cmd->handle,
435 sizeof(config)))
436 rc = -EFAULT;
437 else {
438 rc = __cam_node_handle_config_dev(node, &config);
439 if (rc)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700440 CAM_ERR(CAM_CORE,
441 "config device failed(rc = %d)", rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800442 }
443 break;
444 }
445 case CAM_RELEASE_DEV: {
446 struct cam_release_dev_cmd release;
447
448 if (copy_from_user(&release, (void __user *)cmd->handle,
449 sizeof(release)))
450 rc = -EFAULT;
451 else {
452 rc = __cam_node_handle_release_dev(node, &release);
453 if (rc)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700454 CAM_ERR(CAM_CORE,
455 "release device failed(rc = %d)", rc);
Jing Zhou076a3092017-02-27 02:43:03 -0800456 }
457 break;
458 }
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700459 case CAM_SD_SHUTDOWN:
460 __cam_node_handle_shutdown(node);
461 break;
Jing Zhou076a3092017-02-27 02:43:03 -0800462 default:
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700463 CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code);
Jing Zhou076a3092017-02-27 02:43:03 -0800464 rc = -EINVAL;
465 }
466
467 return rc;
468}