blob: 2b371a376fd94b73514f425ecd69de64e9cf6b49 [file] [log] [blame]
Jigarkumar Zala35226272017-04-19 16:05:24 -07001/* 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
14#include <linux/module.h>
15#include "cam_flash_dev.h"
16#include "cam_flash_soc.h"
17#include "cam_flash_core.h"
18
19static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
20 void *arg, struct cam_flash_private_soc *soc_private)
21{
22 int rc = 0;
23 int i = 0;
24 struct cam_control *cmd = (struct cam_control *)arg;
25
26 if (!fctrl || !arg) {
27 CAM_ERR(CAM_FLASH, "fctrl/arg is NULL with arg:%pK fctrl%pK",
28 fctrl, arg);
29 return -EINVAL;
30 }
31
32 mutex_lock(&(fctrl->flash_mutex));
33 switch (cmd->op_code) {
34 case CAM_ACQUIRE_DEV: {
35 struct cam_sensor_acquire_dev flash_acq_dev;
36 struct cam_create_dev_hdl bridge_params;
37
38 CAM_DBG(CAM_FLASH, "CAM_ACQUIRE_DEV");
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -070039
40 if (fctrl->flash_state != CAM_FLASH_STATE_INIT) {
41 CAM_ERR(CAM_FLASH,
42 "Cannot apply Acquire dev: Prev state: %d",
43 fctrl->flash_state);
44 }
45
Jigarkumar Zala35226272017-04-19 16:05:24 -070046 if (fctrl->bridge_intf.device_hdl != -1) {
47 CAM_ERR(CAM_FLASH, "Device is already acquired");
48 rc = -EINVAL;
49 goto release_mutex;
50 }
51
52 rc = copy_from_user(&flash_acq_dev, (void __user *)cmd->handle,
53 sizeof(flash_acq_dev));
54 if (rc) {
55 CAM_ERR(CAM_FLASH, "Failed Copying from User");
56 goto release_mutex;
57 }
58
59 bridge_params.session_hdl = flash_acq_dev.session_handle;
60 bridge_params.ops = &fctrl->bridge_intf.ops;
61 bridge_params.v4l2_sub_dev_flag = 0;
62 bridge_params.media_entity_flag = 0;
63 bridge_params.priv = fctrl;
64
65 flash_acq_dev.device_handle =
66 cam_create_device_hdl(&bridge_params);
67 fctrl->bridge_intf.device_hdl =
68 flash_acq_dev.device_handle;
69 fctrl->bridge_intf.session_hdl =
70 flash_acq_dev.session_handle;
71
72 rc = copy_to_user((void __user *) cmd->handle, &flash_acq_dev,
73 sizeof(struct cam_sensor_acquire_dev));
74 if (rc) {
75 CAM_ERR(CAM_FLASH, "Failed Copy to User with rc = %d",
76 rc);
77 rc = -EFAULT;
78 goto release_mutex;
79 }
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -070080 fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -070081 break;
Jigarkumar Zala35226272017-04-19 16:05:24 -070082 }
83 case CAM_RELEASE_DEV: {
84 CAM_DBG(CAM_FLASH, "CAM_RELEASE_DEV");
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -070085 if (fctrl->flash_state != CAM_FLASH_STATE_ACQUIRE) {
86 CAM_WARN(CAM_FLASH,
87 "Cannot apply Release dev: Prev state:%d",
88 fctrl->flash_state);
89 }
90
91 if (fctrl->bridge_intf.device_hdl == -1 &&
92 fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) {
Jigarkumar Zala35226272017-04-19 16:05:24 -070093 CAM_ERR(CAM_FLASH,
94 "Invalid Handle: Link Hdl: %d device hdl: %d",
95 fctrl->bridge_intf.device_hdl,
96 fctrl->bridge_intf.link_hdl);
97 rc = -EINVAL;
98 goto release_mutex;
99 }
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700100 rc = cam_flash_release_dev(fctrl);
Jigarkumar Zala35226272017-04-19 16:05:24 -0700101 if (rc)
102 CAM_ERR(CAM_FLASH,
103 "Failed in destroying the device Handle rc= %d",
104 rc);
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700105 fctrl->flash_state = CAM_FLASH_STATE_INIT;
Jigarkumar Zala35226272017-04-19 16:05:24 -0700106 break;
107 }
108 case CAM_QUERY_CAP: {
Soundrapandian Jeyaprakash63045552017-09-20 16:55:34 -0700109 struct cam_flash_query_cap_info flash_cap = {0};
Jigarkumar Zala35226272017-04-19 16:05:24 -0700110
111 CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP");
112 flash_cap.slot_info = fctrl->soc_info.index;
113 for (i = 0; i < fctrl->flash_num_sources; i++) {
114 flash_cap.max_current_flash[i] =
115 soc_private->flash_max_current[i];
116 flash_cap.max_duration_flash[i] =
117 soc_private->flash_max_duration[i];
118 }
119
120 for (i = 0; i < fctrl->torch_num_sources; i++)
121 flash_cap.max_current_torch[i] =
122 soc_private->torch_max_current[i];
123
124 if (copy_to_user((void __user *) cmd->handle, &flash_cap,
125 sizeof(struct cam_flash_query_cap_info))) {
126 CAM_ERR(CAM_FLASH, "Failed Copy to User");
127 rc = -EFAULT;
128 goto release_mutex;
129 }
130 break;
131 }
132 case CAM_START_DEV: {
133 CAM_DBG(CAM_FLASH, "CAM_START_DEV");
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700134 if (fctrl->flash_state != CAM_FLASH_STATE_ACQUIRE) {
135 CAM_WARN(CAM_FLASH,
136 "Cannot apply Start Dev: Prev state: %d",
137 fctrl->flash_state);
138 rc = -EINVAL;
139 goto release_mutex;
140 }
141
142 rc = cam_flash_prepare(fctrl, CAM_FLASH_STATE_START);
Jigarkumar Zala35226272017-04-19 16:05:24 -0700143 if (rc) {
144 CAM_ERR(CAM_FLASH,
145 "Enable Regulator Failed rc = %d", rc);
146 goto release_mutex;
147 }
Jigarkumar Zala35226272017-04-19 16:05:24 -0700148 rc = cam_flash_apply_setting(fctrl, 0);
149 if (rc) {
150 CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc);
151 goto release_mutex;
152 }
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700153 fctrl->flash_state = CAM_FLASH_STATE_START;
Jigarkumar Zala35226272017-04-19 16:05:24 -0700154 break;
155 }
156 case CAM_STOP_DEV: {
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700157 if (fctrl->flash_state != CAM_FLASH_STATE_START) {
158 CAM_WARN(CAM_FLASH,
159 "Cannot apply Stop dev: Prev state is: %d",
160 fctrl->flash_state);
161 }
Jigarkumar Zala35226272017-04-19 16:05:24 -0700162
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700163 rc = cam_flash_stop_dev(fctrl);
Jigarkumar Zala35226272017-04-19 16:05:24 -0700164 if (rc) {
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700165 CAM_ERR(CAM_FLASH, "Stop Dev Failed rc = %d",
Jigarkumar Zala35226272017-04-19 16:05:24 -0700166 rc);
167 goto release_mutex;
168 }
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700169 fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
Jigarkumar Zala35226272017-04-19 16:05:24 -0700170 break;
171 }
172 case CAM_CONFIG_DEV: {
173 CAM_DBG(CAM_FLASH, "CAM_CONFIG_DEV");
174 rc = cam_flash_parser(fctrl, arg);
175 if (rc) {
176 CAM_ERR(CAM_FLASH, "Failed Flash Config: rc=%d\n", rc);
177 goto release_mutex;
178 }
179 break;
180 }
181 default:
182 CAM_ERR(CAM_FLASH, "Invalid Opcode: %d", cmd->op_code);
183 rc = -EINVAL;
184 }
185
186release_mutex:
187 mutex_unlock(&(fctrl->flash_mutex));
188 return rc;
189}
190
191static const struct of_device_id cam_flash_dt_match[] = {
192 {.compatible = "qcom,camera-flash", .data = NULL},
193 {}
194};
195
196static long cam_flash_subdev_ioctl(struct v4l2_subdev *sd,
197 unsigned int cmd, void *arg)
198{
199 int rc = 0;
200 struct cam_flash_ctrl *fctrl = NULL;
201 struct cam_flash_private_soc *soc_private = NULL;
202
203 CAM_DBG(CAM_FLASH, "Enter");
204
205 fctrl = v4l2_get_subdevdata(sd);
206 soc_private = fctrl->soc_info.soc_private;
207
208 switch (cmd) {
209 case VIDIOC_CAM_CONTROL: {
210 rc = cam_flash_driver_cmd(fctrl, arg,
211 soc_private);
212 break;
213 }
214 default:
215 CAM_ERR(CAM_FLASH, "Invalid ioctl cmd type");
216 rc = -EINVAL;
217 break;
218 }
219
220 CAM_DBG(CAM_FLASH, "Exit");
221 return rc;
222}
223
224#ifdef CONFIG_COMPAT
225static long cam_flash_subdev_do_ioctl(struct v4l2_subdev *sd,
226 unsigned int cmd, unsigned long arg)
227{
228 struct cam_control cmd_data;
229 int32_t rc = 0;
230
231 if (copy_from_user(&cmd_data, (void __user *)arg,
232 sizeof(cmd_data))) {
233 CAM_ERR(CAM_FLASH,
234 "Failed to copy from user_ptr=%pK size=%zu",
235 (void __user *)arg, sizeof(cmd_data));
236 return -EFAULT;
237 }
238
239 switch (cmd) {
240 case VIDIOC_CAM_CONTROL: {
241 rc = cam_flash_subdev_ioctl(sd, cmd, &cmd_data);
242 if (rc)
243 CAM_ERR(CAM_FLASH, "cam_flash_ioctl failed");
244 break;
245 }
246 default:
247 CAM_ERR(CAM_FLASH, "Invalid compat ioctl cmd_type:%d",
248 cmd);
249 rc = -EINVAL;
250 }
251
252 if (!rc) {
253 if (copy_to_user((void __user *)arg, &cmd_data,
254 sizeof(cmd_data))) {
255 CAM_ERR(CAM_FLASH,
256 "Failed to copy to user_ptr=%pK size=%zu",
257 (void __user *)arg, sizeof(cmd_data));
258 rc = -EFAULT;
259 }
260 }
261
262 return rc;
263}
264#endif
265
266static int cam_flash_platform_remove(struct platform_device *pdev)
267{
268 struct cam_flash_ctrl *fctrl;
269
270 fctrl = platform_get_drvdata(pdev);
271 if (!fctrl) {
272 CAM_ERR(CAM_FLASH, "Flash device is NULL");
273 return 0;
274 }
275
276 devm_kfree(&pdev->dev, fctrl);
277
278 return 0;
279}
280
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700281static int cam_flash_subdev_close(struct v4l2_subdev *sd,
282 struct v4l2_subdev_fh *fh)
283{
284 struct cam_flash_ctrl *flash_ctrl =
285 v4l2_get_subdevdata(sd);
286
287 if (!flash_ctrl) {
288 CAM_ERR(CAM_FLASH, "Flash ctrl ptr is NULL");
289 return -EINVAL;
290 }
291
292 mutex_lock(&flash_ctrl->flash_mutex);
293 cam_flash_shutdown(flash_ctrl);
294 mutex_unlock(&flash_ctrl->flash_mutex);
295
296 return 0;
297}
298
Jigarkumar Zala35226272017-04-19 16:05:24 -0700299static struct v4l2_subdev_core_ops cam_flash_subdev_core_ops = {
300 .ioctl = cam_flash_subdev_ioctl,
301#ifdef CONFIG_COMPAT
302 .compat_ioctl32 = cam_flash_subdev_do_ioctl
303#endif
304};
305
306static struct v4l2_subdev_ops cam_flash_subdev_ops = {
307 .core = &cam_flash_subdev_core_ops,
308};
309
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700310static const struct v4l2_subdev_internal_ops cam_flash_internal_ops = {
311 .close = cam_flash_subdev_close,
312};
Jigarkumar Zala35226272017-04-19 16:05:24 -0700313
314static int32_t cam_flash_platform_probe(struct platform_device *pdev)
315{
316 int32_t rc = 0;
317 struct cam_flash_ctrl *flash_ctrl = NULL;
318
319 CAM_DBG(CAM_FLASH, "Enter");
320 if (!pdev->dev.of_node) {
321 CAM_ERR(CAM_FLASH, "of_node NULL");
322 return -EINVAL;
323 }
324
325 flash_ctrl = kzalloc(sizeof(struct cam_flash_ctrl), GFP_KERNEL);
326 if (!flash_ctrl)
327 return -ENOMEM;
328
329 flash_ctrl->pdev = pdev;
330 flash_ctrl->soc_info.pdev = pdev;
Jigarkumar Zalab7b49f12017-08-21 16:45:38 -0700331 flash_ctrl->soc_info.dev = &pdev->dev;
332 flash_ctrl->soc_info.dev_name = pdev->name;
Jigarkumar Zala35226272017-04-19 16:05:24 -0700333
334 rc = cam_flash_get_dt_data(flash_ctrl, &flash_ctrl->soc_info);
335 if (rc) {
336 CAM_ERR(CAM_FLASH, "cam_flash_get_dt_data failed with %d", rc);
337 kfree(flash_ctrl);
338 return -EINVAL;
339 }
340
341 flash_ctrl->v4l2_dev_str.internal_ops =
342 &cam_flash_internal_ops;
343 flash_ctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops;
344 flash_ctrl->v4l2_dev_str.name = CAMX_FLASH_DEV_NAME;
345 flash_ctrl->v4l2_dev_str.sd_flags =
346 V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
347 flash_ctrl->v4l2_dev_str.ent_function = CAM_FLASH_DEVICE_TYPE;
348 flash_ctrl->v4l2_dev_str.token = flash_ctrl;
349
350 rc = cam_register_subdev(&(flash_ctrl->v4l2_dev_str));
351 if (rc) {
352 CAM_ERR(CAM_FLASH, "Fail to create subdev with %d", rc);
353 goto free_resource;
354 }
355 flash_ctrl->bridge_intf.device_hdl = -1;
356 flash_ctrl->bridge_intf.ops.get_dev_info = cam_flash_publish_dev_info;
357 flash_ctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
358 flash_ctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
359 flash_ctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
360
361 platform_set_drvdata(pdev, flash_ctrl);
362 v4l2_set_subdevdata(&flash_ctrl->v4l2_dev_str.sd, flash_ctrl);
363
364 mutex_init(&(flash_ctrl->flash_mutex));
365 mutex_init(&(flash_ctrl->flash_wq_mutex));
366
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700367 flash_ctrl->flash_state = CAM_FLASH_STATE_INIT;
Jigarkumar Zala35226272017-04-19 16:05:24 -0700368 CAM_DBG(CAM_FLASH, "Probe success");
369 return rc;
370free_resource:
371 kfree(flash_ctrl);
372 return rc;
373}
374
375MODULE_DEVICE_TABLE(of, cam_flash_dt_match);
376
377static struct platform_driver cam_flash_platform_driver = {
378 .probe = cam_flash_platform_probe,
379 .remove = cam_flash_platform_remove,
380 .driver = {
381 .name = "CAM-FLASH-DRIVER",
382 .owner = THIS_MODULE,
383 .of_match_table = cam_flash_dt_match,
384 },
385};
386
387static int __init cam_flash_init_module(void)
388{
389 int32_t rc = 0;
390
391 rc = platform_driver_register(&cam_flash_platform_driver);
392 if (rc)
393 CAM_ERR(CAM_FLASH, "platform probe for flash failed");
394
395 return rc;
396}
397
398static void __exit cam_flash_exit_module(void)
399{
400 platform_driver_unregister(&cam_flash_platform_driver);
401}
402
403module_init(cam_flash_init_module);
404module_exit(cam_flash_exit_module);
405MODULE_DESCRIPTION("CAM FLASH");
406MODULE_LICENSE("GPL v2");