blob: d52d8bc4b96ad1103999433e3ac6d801c2236933 [file] [log] [blame]
Pratap Nirujogi6e759912018-01-17 17:51:17 +05301/* Copyright (c) 2012-2018, 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/of.h>
14#include <linux/module.h>
15#include <linux/workqueue.h>
16#include <linux/delay.h>
17#include <linux/types.h>
18#include <linux/list.h>
19#include <linux/ioctl.h>
20#include <linux/spinlock.h>
21#include <linux/proc_fs.h>
22#include <linux/atomic.h>
23#include <linux/videodev2.h>
24#include <linux/msm_ion.h>
25#include <linux/iommu.h>
26#include <linux/platform_device.h>
27#include <linux/debugfs.h>
28#include <media/v4l2-fh.h>
29#include "msm.h"
30#include "msm_vb2.h"
31#include "msm_sd.h"
32#include "cam_hw_ops.h"
33#include <media/msmb_generic_buf_mgr.h>
34
35static struct v4l2_device *msm_v4l2_dev;
36static struct list_head ordered_sd_list;
37static struct mutex ordered_sd_mtx;
38static struct mutex v4l2_event_mtx;
39
40static struct pm_qos_request msm_v4l2_pm_qos_request;
41
42static struct msm_queue_head *msm_session_q;
43
44/* This variable represent daemon status
45 * true = daemon present (default state)
46 * false = daemon is NOT present
47 */
48bool is_daemon_status = true;
49
50/* config node envent queue */
51static struct v4l2_fh *msm_eventq;
52static spinlock_t msm_eventq_lock;
53
54static struct pid *msm_pid;
55static spinlock_t msm_pid_lock;
56
57static uint32_t gpu_limit;
58
59/*
60 * It takes 20 bytes + NULL character to write the
61 * largest decimal value of an uint64_t
62 */
63#define LOGSYNC_PACKET_SIZE 21
64
65#define msm_dequeue(queue, type, member) ({ \
66 unsigned long flags; \
67 struct msm_queue_head *__q = (queue); \
68 type *node = NULL; \
69 spin_lock_irqsave(&__q->lock, flags); \
70 if (!list_empty(&__q->list)) { \
71 __q->len--; \
72 node = list_first_entry(&__q->list, \
73 type, member); \
74 if ((node) && (&node->member) && (&node->member.next)) \
75 list_del_init(&node->member); \
76 } \
77 spin_unlock_irqrestore(&__q->lock, flags); \
78 node; \
79})
80
81#define msm_delete_sd_entry(queue, type, member, q_node) ({ \
82 unsigned long flags; \
83 struct msm_queue_head *__q = (queue); \
84 type *node = NULL; \
85 spin_lock_irqsave(&__q->lock, flags); \
86 if (!list_empty(&__q->list)) { \
87 list_for_each_entry(node, &__q->list, member) \
88 if (node->sd == q_node) { \
89 __q->len--; \
90 list_del_init(&node->member); \
91 kzfree(node); \
92 break; \
93 } \
94 } \
95 spin_unlock_irqrestore(&__q->lock, flags); \
96})
97
98#define msm_delete_entry(queue, type, member, q_node) ({ \
99 unsigned long flags; \
100 struct msm_queue_head *__q = (queue); \
101 type *node = NULL; \
102 spin_lock_irqsave(&__q->lock, flags); \
103 if (!list_empty(&__q->list)) { \
104 list_for_each_entry(node, &__q->list, member) \
105 if (node == q_node) { \
106 __q->len--; \
107 list_del_init(&node->member); \
108 kzfree(node); \
109 break; \
110 } \
111 } \
112 spin_unlock_irqrestore(&__q->lock, flags); \
113})
114
115#define msm_queue_drain(queue, type, member) do { \
116 unsigned long flags; \
117 struct msm_queue_head *__q = (queue); \
118 type *node = NULL; \
119 spin_lock_irqsave(&__q->lock, flags); \
120 while (!list_empty(&__q->list)) { \
121 __q->len--; \
122 node = list_first_entry(&__q->list, \
123 type, member); \
124 if (node) { \
125 if (&node->member) \
126 list_del_init(&node->member); \
127 kzfree(node); \
128 } \
129 } \
130 spin_unlock_irqrestore(&__q->lock, flags); \
131} while (0)
132
133typedef int (*msm_queue_func)(void *d1, void *d2);
134#define msm_queue_traverse_action(queue, type, member, func, data) do {\
135 unsigned long flags; \
136 struct msm_queue_head *__q = (queue); \
137 type *node = NULL; \
138 msm_queue_func __f = (func); \
139 spin_lock_irqsave(&__q->lock, flags); \
140 if (!list_empty(&__q->list)) { \
141 list_for_each_entry(node, &__q->list, member) \
142 if (node && __f) { \
143 __f(node, data); \
144 } \
145 } \
146 spin_unlock_irqrestore(&__q->lock, flags); \
147} while (0)
148
149typedef int (*msm_queue_find_func)(void *d1, void *d2);
150#define msm_queue_find(queue, type, member, func, data) ({\
151 unsigned long flags; \
152 struct msm_queue_head *__q = (queue); \
153 type *node = NULL; \
154 typeof(node) __ret = NULL; \
155 msm_queue_find_func __f = (func); \
156 spin_lock_irqsave(&__q->lock, flags); \
157 if (!list_empty(&__q->list)) { \
158 list_for_each_entry(node, &__q->list, member) \
159 if ((__f) && __f(node, data)) { \
160 __ret = node; \
161 break; \
162 } \
163 } \
164 spin_unlock_irqrestore(&__q->lock, flags); \
165 __ret; \
166})
167
168static void msm_init_queue(struct msm_queue_head *qhead)
169{
170 if (WARN_ON(!qhead))
171 return;
172
173 INIT_LIST_HEAD(&qhead->list);
174 spin_lock_init(&qhead->lock);
175 qhead->len = 0;
176 qhead->max = 0;
177}
178
179static void msm_enqueue(struct msm_queue_head *qhead,
180 struct list_head *entry)
181{
182 unsigned long flags;
183
184 spin_lock_irqsave(&qhead->lock, flags);
185 qhead->len++;
186 if (qhead->len > qhead->max)
187 qhead->max = qhead->len;
188 list_add_tail(entry, &qhead->list);
189 spin_unlock_irqrestore(&qhead->lock, flags);
190}
191
192void msm_cam_copy_v4l2_subdev_fops(struct v4l2_file_operations *d1)
193{
194 *d1 = v4l2_subdev_fops;
195}
196EXPORT_SYMBOL(msm_cam_copy_v4l2_subdev_fops);
197
198static const struct v4l2_file_operations *msm_cam_get_v4l2_subdev_fops_ptr(
199 void)
200{
201 return &v4l2_subdev_fops;
202}
203
204/* index = session id */
205static inline int __msm_queue_find_session(void *d1, void *d2)
206{
207 struct msm_session *session = d1;
208
209 return (session->session_id == *(unsigned int *)d2) ? 1 : 0;
210}
211
212static inline int __msm_queue_find_stream(void *d1, void *d2)
213{
214 struct msm_stream *stream = d1;
215
216 return (stream->stream_id == *(unsigned int *)d2) ? 1 : 0;
217}
218
219static inline int __msm_queue_find_command_ack_q(void *d1, void *d2)
220{
221 struct msm_command_ack *ack = d1;
222
223 return (ack->stream_id == *(unsigned int *)d2) ? 1 : 0;
224}
225
226static void msm_pm_qos_add_request(void)
227{
228 pr_info("%s: add request", __func__);
229 pm_qos_add_request(&msm_v4l2_pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
230 PM_QOS_DEFAULT_VALUE);
231}
232
233static void msm_pm_qos_remove_request(void)
234{
235 pr_info("%s: remove request", __func__);
236 pm_qos_remove_request(&msm_v4l2_pm_qos_request);
237}
238
239void msm_pm_qos_update_request(int val)
240{
241 pr_info("%s: update request %d", __func__, val);
242 pm_qos_update_request(&msm_v4l2_pm_qos_request, val);
243}
244
245struct msm_session *msm_session_find(unsigned int session_id)
246{
247 struct msm_session *session;
248
249 session = msm_queue_find(msm_session_q, struct msm_session,
250 list, __msm_queue_find_session, &session_id);
251 if (WARN_ON(!session))
252 return NULL;
253 return session;
254}
255EXPORT_SYMBOL(msm_session_find);
256
257int msm_create_stream(unsigned int session_id,
258 unsigned int stream_id, struct vb2_queue *q)
259{
260 struct msm_session *session;
261 struct msm_stream *stream;
262
263 session = msm_queue_find(msm_session_q, struct msm_session,
264 list, __msm_queue_find_session, &session_id);
265 if (!session)
266 return -EINVAL;
267
268 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
269 if (!stream)
270 return -ENOMEM;
271
272 stream->stream_id = stream_id;
273 stream->vb2_q = q;
274 spin_lock_init(&stream->stream_lock);
275 msm_enqueue(&session->stream_q, &stream->list);
276 session->stream_q.len++;
277
278 INIT_LIST_HEAD(&stream->queued_list);
279
280 return 0;
281}
282EXPORT_SYMBOL(msm_create_stream);
283
284void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
285{
286 struct msm_session *session = NULL;
287 struct msm_stream *stream = NULL;
288 unsigned long flags;
289 int try_count = 0;
290
291 session = msm_queue_find(msm_session_q, struct msm_session,
292 list, __msm_queue_find_session, &session_id);
293
294 if (!session)
295 return;
296
297 while (1) {
298 unsigned long wl_flags;
299
300 if (try_count > 5) {
301 pr_err("%s : not able to delete stream %d\n",
302 __func__, __LINE__);
303 break;
304 }
305
306 write_lock_irqsave(&session->stream_rwlock, wl_flags);
307 try_count++;
308 stream = msm_queue_find(&session->stream_q, struct msm_stream,
309 list, __msm_queue_find_stream, &stream_id);
310
311 if (!stream) {
312 write_unlock_irqrestore(&session->stream_rwlock,
313 wl_flags);
314 return;
315 }
316
317 if (msm_vb2_get_stream_state(stream) != 1) {
318 write_unlock_irqrestore(&session->stream_rwlock,
319 wl_flags);
320 continue;
321 }
322
323 spin_lock_irqsave(&(session->stream_q.lock), flags);
324 list_del_init(&stream->list);
325 session->stream_q.len--;
326 kfree(stream);
327 stream = NULL;
328 spin_unlock_irqrestore(&(session->stream_q.lock), flags);
329 write_unlock_irqrestore(&session->stream_rwlock, wl_flags);
330 break;
331 }
332
333}
334EXPORT_SYMBOL(msm_delete_stream);
335
336static void msm_sd_unregister_subdev(struct video_device *vdev)
337{
338 struct v4l2_subdev *sd = video_get_drvdata(vdev);
339
340 sd->devnode = NULL;
341 kzfree(vdev);
342}
343
344static inline int __msm_sd_register_subdev(struct v4l2_subdev *sd)
345{
346 int rc = 0;
347 struct video_device *vdev;
348
349 if (!msm_v4l2_dev || !sd || !sd->name[0])
350 return -EINVAL;
351
352 rc = v4l2_device_register_subdev(msm_v4l2_dev, sd);
Trishansh Bhardwaj586ba082018-02-24 15:02:44 +0530353 if (rc < 0) {
354 pr_err("v4l2_device_register_subdev: failed for %s", sd->name);
355 WARN_ON(1);
Pratap Nirujogi6e759912018-01-17 17:51:17 +0530356 return rc;
Trishansh Bhardwaj586ba082018-02-24 15:02:44 +0530357 }
Pratap Nirujogi6e759912018-01-17 17:51:17 +0530358
359 /* Register a device node for every subdev marked with the
360 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
361 */
362 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
363 return rc;
364
365 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
366 if (!vdev) {
367 rc = -ENOMEM;
368 goto clean_up;
369 }
370
371 video_set_drvdata(vdev, sd);
372 strlcpy(vdev->name, sd->name, sizeof(vdev->name));
373 vdev->v4l2_dev = msm_v4l2_dev;
374 vdev->fops = msm_cam_get_v4l2_subdev_fops_ptr();
375 vdev->release = msm_sd_unregister_subdev;
376 rc = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
377 sd->owner);
378 if (rc < 0) {
379 kzfree(vdev);
380 goto clean_up;
381 }
382
383#if defined(CONFIG_MEDIA_CONTROLLER)
384 sd->entity.info.dev.major = VIDEO_MAJOR;
385 sd->entity.info.dev.minor = vdev->minor;
386 sd->entity.name = video_device_node_name(vdev);
387#endif
388 sd->devnode = vdev;
389 return 0;
390
391clean_up:
392 if (sd->devnode)
393 video_unregister_device(sd->devnode);
394 return rc;
395}
396
397static void msm_add_sd_in_position(struct msm_sd_subdev *msm_subdev,
398 struct list_head *sd_list)
399{
400 struct msm_sd_subdev *temp_sd;
401
402 list_for_each_entry(temp_sd, sd_list, list) {
403 if (temp_sd == msm_subdev) {
404 pr_err("%s :Fail to add the same sd %d\n",
405 __func__, __LINE__);
406 return;
407 }
408 if (msm_subdev->close_seq < temp_sd->close_seq) {
409 list_add_tail(&msm_subdev->list, &temp_sd->list);
410 return;
411 }
412 }
413 list_add_tail(&msm_subdev->list, sd_list);
414}
415
416int msm_sd_register(struct msm_sd_subdev *msm_subdev)
417{
418 if (WARN_ON(!msm_subdev))
419 return -EINVAL;
420
421 if (WARN_ON(!msm_v4l2_dev) || WARN_ON(!msm_v4l2_dev->dev))
422 return -EIO;
423
424 mutex_lock(&ordered_sd_mtx);
425 msm_add_sd_in_position(msm_subdev, &ordered_sd_list);
426 mutex_unlock(&ordered_sd_mtx);
427 return __msm_sd_register_subdev(&msm_subdev->sd);
428}
429EXPORT_SYMBOL(msm_sd_register);
430
431int msm_sd_unregister(struct msm_sd_subdev *msm_subdev)
432{
433 if (WARN_ON(!msm_subdev))
434 return -EINVAL;
435
436 v4l2_device_unregister_subdev(&msm_subdev->sd);
437 return 0;
438}
439EXPORT_SYMBOL(msm_sd_unregister);
440
441static struct v4l2_subdev *msm_sd_find(const char *name)
442{
443 unsigned long flags;
444 struct v4l2_subdev *subdev = NULL;
445 struct v4l2_subdev *subdev_out = NULL;
446
447 spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
448 if (!list_empty(&msm_v4l2_dev->subdevs)) {
449 list_for_each_entry(subdev, &msm_v4l2_dev->subdevs, list)
450 if (!strcmp(name, subdev->name)) {
451 subdev_out = subdev;
452 break;
453 }
454 }
455 spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
456
457 return subdev_out;
458}
459
460int msm_create_session(unsigned int session_id, struct video_device *vdev)
461{
462 struct msm_session *session = NULL;
463
464 if (!msm_session_q) {
465 pr_err("%s : session queue not available Line %d\n",
466 __func__, __LINE__);
467 return -ENODEV;
468 }
469
470 session = msm_queue_find(msm_session_q, struct msm_session,
471 list, __msm_queue_find_session, &session_id);
472 if (session) {
473 pr_err("%s: Session exist session_id=%d\n",
474 __func__, session_id);
475 return -EINVAL;
476 }
477
478 session = kzalloc(sizeof(*session), GFP_KERNEL);
479 if (!session)
480 return -ENOMEM;
481
482 session->session_id = session_id;
483 session->event_q.vdev = vdev;
484 msm_init_queue(&session->command_ack_q);
485 msm_init_queue(&session->stream_q);
486 msm_enqueue(msm_session_q, &session->list);
487 mutex_init(&session->lock);
488 mutex_init(&session->lock_q);
489 mutex_init(&session->close_lock);
490 rwlock_init(&session->stream_rwlock);
491
492 if (gpu_limit) {
493 session->sysfs_pwr_limit = kgsl_pwr_limits_add(KGSL_DEVICE_3D0);
494 if (session->sysfs_pwr_limit)
495 kgsl_pwr_limits_set_freq(session->sysfs_pwr_limit,
496 gpu_limit);
497 }
498
499 return 0;
500}
501EXPORT_SYMBOL(msm_create_session);
502
503int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id)
504{
505 struct msm_session *session;
506 struct msm_command_ack *cmd_ack;
507
508 if (!msm_session_q) {
509 pr_err("%s : Session queue not available Line %d\n",
510 __func__, __LINE__);
511 return -ENODEV;
512 }
513
514 session = msm_queue_find(msm_session_q, struct msm_session,
515 list, __msm_queue_find_session, &session_id);
516 if (!session) {
517 pr_err("%s : Session not found Line %d\n",
518 __func__, __LINE__);
519 return -EINVAL;
520 }
521 mutex_lock(&session->lock);
522 cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
523 if (!cmd_ack) {
524 mutex_unlock(&session->lock);
525 pr_err("%s : memory not available Line %d\n",
526 __func__, __LINE__);
527 return -ENOMEM;
528 }
529
530 msm_init_queue(&cmd_ack->command_q);
531 INIT_LIST_HEAD(&cmd_ack->list);
532 init_completion(&cmd_ack->wait_complete);
533 cmd_ack->stream_id = stream_id;
534
535 msm_enqueue(&session->command_ack_q, &cmd_ack->list);
536 session->command_ack_q.len++;
537 mutex_unlock(&session->lock);
538 return 0;
539}
540EXPORT_SYMBOL(msm_create_command_ack_q);
541
542void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id)
543{
544 struct msm_session *session;
545 struct msm_command_ack *cmd_ack;
546 unsigned long flags;
547
548 session = msm_queue_find(msm_session_q, struct msm_session,
549 list, __msm_queue_find_session, &session_id);
550 if (!session)
551 return;
552 mutex_lock(&session->lock);
553
554 cmd_ack = msm_queue_find(&session->command_ack_q,
555 struct msm_command_ack, list, __msm_queue_find_command_ack_q,
556 &stream_id);
557 if (!cmd_ack) {
558 mutex_unlock(&session->lock);
559 return;
560 }
561
562 msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
563
564 spin_lock_irqsave(&(session->command_ack_q.lock), flags);
565 list_del_init(&cmd_ack->list);
566 kzfree(cmd_ack);
567 session->command_ack_q.len--;
568 spin_unlock_irqrestore(&(session->command_ack_q.lock), flags);
569 mutex_unlock(&session->lock);
570}
571EXPORT_SYMBOL(msm_delete_command_ack_q);
572
573static inline int __msm_sd_close_subdevs(struct msm_sd_subdev *msm_sd,
574 struct msm_sd_close_ioctl *sd_close)
575{
576 struct v4l2_subdev *sd;
577
578 sd = &msm_sd->sd;
579 pr_debug("%s: Shutting down subdev %s", __func__, sd->name);
580
581 v4l2_subdev_call(sd, core, ioctl, MSM_SD_SHUTDOWN, sd_close);
582 v4l2_subdev_call(sd, core, s_power, 0);
583
584 return 0;
585}
586
587static inline int __msm_sd_notify_freeze_subdevs(struct msm_sd_subdev *msm_sd,
588 int enable)
589{
590 struct v4l2_subdev *sd;
591
592 sd = &msm_sd->sd;
593
594 if (enable)
595 v4l2_subdev_call(sd, core, ioctl, MSM_SD_NOTIFY_FREEZE, NULL);
596 else
597 v4l2_subdev_call(sd, core, ioctl, MSM_SD_UNNOTIFY_FREEZE, NULL);
598
599 return 0;
600}
601
602static inline int __msm_destroy_session_streams(void *d1, void *d2)
603{
604 struct msm_stream *stream = d1;
605 unsigned long flags;
606
607 pr_err("%s: Error: Destroyed list is not empty\n", __func__);
608 spin_lock_irqsave(&stream->stream_lock, flags);
609 INIT_LIST_HEAD(&stream->queued_list);
610 spin_unlock_irqrestore(&stream->stream_lock, flags);
611 return 0;
612}
613
614static void msm_destroy_session_streams(struct msm_session *session)
615{
616
617 if (!session)
618 return;
619
620 msm_queue_traverse_action(&session->stream_q, struct msm_stream, list,
621 __msm_destroy_session_streams, NULL);
622
623 msm_queue_drain(&session->stream_q, struct msm_stream, list);
624}
625
626static inline int __msm_remove_session_cmd_ack_q(void *d1, void *d2)
627{
628 struct msm_command_ack *cmd_ack = d1;
629
630 if (!(&cmd_ack->command_q))
631 return 0;
632
633 msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
634
635 return 0;
636}
637
638static void msm_remove_session_cmd_ack_q(struct msm_session *session)
639{
640 if ((!session) || !(&session->command_ack_q))
641 return;
642
643 mutex_lock(&session->lock);
644 /* to ensure error handling purpose, it needs to detach all subdevs
645 * which are being connected to streams
646 */
647 msm_queue_traverse_action(&session->command_ack_q,
648 struct msm_command_ack, list,
649 __msm_remove_session_cmd_ack_q, NULL);
650
651 msm_queue_drain(&session->command_ack_q, struct msm_command_ack, list);
652
653 mutex_unlock(&session->lock);
654}
655
656int msm_destroy_session(unsigned int session_id)
657{
658 struct msm_session *session;
659 struct v4l2_subdev *buf_mgr_subdev;
660 struct msm_sd_close_ioctl session_info;
661
662 session = msm_queue_find(msm_session_q, struct msm_session,
663 list, __msm_queue_find_session, &session_id);
664 if (!session)
665 return -EINVAL;
666
667 if (gpu_limit && session->sysfs_pwr_limit) {
668 kgsl_pwr_limits_set_default(session->sysfs_pwr_limit);
669 kgsl_pwr_limits_del(session->sysfs_pwr_limit);
670 }
671
672 msm_destroy_session_streams(session);
673 msm_remove_session_cmd_ack_q(session);
674 mutex_destroy(&session->lock);
675 mutex_destroy(&session->lock_q);
676 mutex_destroy(&session->close_lock);
677 msm_delete_entry(msm_session_q, struct msm_session,
678 list, session);
679 buf_mgr_subdev = msm_sd_find("msm_buf_mngr");
680 if (buf_mgr_subdev) {
681 session_info.session = session_id;
682 session_info.stream = 0;
683 v4l2_subdev_call(buf_mgr_subdev, core, ioctl,
684 MSM_SD_SHUTDOWN, &session_info);
685 } else {
686 pr_err("%s: Buff manger device node is NULL\n", __func__);
687 }
688
689 return 0;
690}
691EXPORT_SYMBOL(msm_destroy_session);
692
693static int __msm_close_destry_session_notify_apps(void *d1, void *d2)
694{
695 struct v4l2_event event;
696 struct msm_v4l2_event_data *event_data =
697 (struct msm_v4l2_event_data *)&event.u.data[0];
698 struct msm_session *session = d1;
699
700 event.type = MSM_CAMERA_V4L2_EVENT_TYPE;
701 event.id = MSM_CAMERA_MSM_NOTIFY;
702 event_data->command = MSM_CAMERA_PRIV_SHUTDOWN;
703
704 v4l2_event_queue(session->event_q.vdev, &event);
705
706 return 0;
707}
708
709static int __msm_wakeup_all_cmdack_session_stream(void *d1, void *d2)
710{
711 struct msm_stream *stream = d1;
712 struct msm_session *session = d2;
713 struct msm_command_ack *cmd_ack = NULL;
714 unsigned long spin_flags = 0;
715
716 cmd_ack = msm_queue_find(&session->command_ack_q,
717 struct msm_command_ack, list,
718 __msm_queue_find_command_ack_q,
719 &stream->stream_id);
720 if (cmd_ack) {
721 spin_lock_irqsave(&(session->command_ack_q.lock),
722 spin_flags);
723 complete(&cmd_ack->wait_complete);
724 spin_unlock_irqrestore(&(session->command_ack_q.lock),
725 spin_flags);
726 }
727 return 0;
728}
729
730static int __msm_close_wakeup_all_cmdack_session(void *d1, void *d2)
731{
732 struct msm_stream *stream = NULL;
733 struct msm_session *session = d1;
734
735 stream = msm_queue_find(&session->stream_q, struct msm_stream,
736 list, __msm_wakeup_all_cmdack_session_stream, d1);
737 return 0;
738}
739
740static long msm_private_ioctl(struct file *file, void *fh,
741 bool valid_prio, unsigned int cmd, void *arg)
742{
743 int rc = 0;
744 struct msm_v4l2_event_data *event_data = arg;
745 struct v4l2_event event;
746 struct msm_session *session;
747 unsigned int session_id;
748 unsigned int stream_id;
749 unsigned long spin_flags = 0;
750 struct msm_sd_subdev *msm_sd;
751
752 if (cmd == MSM_CAM_V4L2_IOCTL_DAEMON_DISABLED) {
753 is_daemon_status = false;
754 return 0;
755 }
756
757 if (!event_data)
758 return -EINVAL;
759
760 switch (cmd) {
761 case MSM_CAM_V4L2_IOCTL_NOTIFY:
762 case MSM_CAM_V4L2_IOCTL_CMD_ACK:
763 case MSM_CAM_V4L2_IOCTL_NOTIFY_DEBUG:
764 case MSM_CAM_V4L2_IOCTL_NOTIFY_ERROR:
765 break;
766 default:
767 return -ENOTTY;
768 }
769
770 memset(&event, 0, sizeof(struct v4l2_event));
771 session_id = event_data->session_id;
772 stream_id = event_data->stream_id;
773
774 session = msm_queue_find(msm_session_q, struct msm_session,
775 list, __msm_queue_find_session, &session_id);
776
777 if (!session)
778 return -EINVAL;
779
780 switch (cmd) {
781 case MSM_CAM_V4L2_IOCTL_NOTIFY: {
782 if (WARN_ON(!session->event_q.vdev)) {
783 rc = -EFAULT;
784 break;
785 }
786 event.type = event_data->v4l2_event_type;
787 event.id = event_data->v4l2_event_id;
788 memcpy(&event.u.data, event_data,
789 sizeof(struct msm_v4l2_event_data));
790 v4l2_event_queue(session->event_q.vdev,
791 &event);
792 }
793 break;
794
795 case MSM_CAM_V4L2_IOCTL_CMD_ACK: {
796 struct msm_command_ack *cmd_ack;
797 struct msm_command *ret_cmd;
798
799 ret_cmd = kzalloc(sizeof(*ret_cmd), GFP_KERNEL);
800 if (!ret_cmd) {
801 rc = -ENOMEM;
802 break;
803 }
804
805 cmd_ack = msm_queue_find(&session->command_ack_q,
806 struct msm_command_ack, list,
807 __msm_queue_find_command_ack_q,
808 &stream_id);
809 if (WARN_ON(!cmd_ack)) {
810 kzfree(ret_cmd);
811 rc = -EFAULT;
812 break;
813 }
814
815 spin_lock_irqsave(&(session->command_ack_q.lock),
816 spin_flags);
817 event.type = event_data->v4l2_event_type;
818 event.id = event_data->v4l2_event_id;
819 memcpy(&event.u.data, event_data,
820 sizeof(struct msm_v4l2_event_data));
821 memcpy(&ret_cmd->event, &event, sizeof(struct v4l2_event));
822 msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
823 complete(&cmd_ack->wait_complete);
824 spin_unlock_irqrestore(&(session->command_ack_q.lock),
825 spin_flags);
826 }
827 break;
828
829 case MSM_CAM_V4L2_IOCTL_NOTIFY_DEBUG: {
830 if (event_data->status) {
831 pr_err("%s:Notifying subdevs about potential sof freeze\n",
832 __func__);
833 } else {
834 pr_err("%s:Notifying subdevs about sof recover\n",
835 __func__);
836 }
837
838 mutex_lock(&ordered_sd_mtx);
839 if (!list_empty(&msm_v4l2_dev->subdevs)) {
840 list_for_each_entry(msm_sd, &ordered_sd_list, list)
841 __msm_sd_notify_freeze_subdevs(msm_sd,
842 event_data->status);
843 }
844 mutex_unlock(&ordered_sd_mtx);
845 }
846 break;
847
848 case MSM_CAM_V4L2_IOCTL_NOTIFY_ERROR:
849 /* send v4l2_event to HAL next*/
850 msm_queue_traverse_action(msm_session_q,
851 struct msm_session, list,
852 __msm_close_destry_session_notify_apps, NULL);
853 break;
854
855 default:
856 rc = -ENOTTY;
857 break;
858 }
859
860 return rc;
861}
862
863static int msm_unsubscribe_event(struct v4l2_fh *fh,
864 const struct v4l2_event_subscription *sub)
865{
866 int rc;
867
868 mutex_lock(&v4l2_event_mtx);
869 rc = v4l2_event_unsubscribe(fh, sub);
870 mutex_unlock(&v4l2_event_mtx);
871
872 return rc;
873}
874
875static int msm_subscribe_event(struct v4l2_fh *fh,
876 const struct v4l2_event_subscription *sub)
877{
878 int rc;
879
880 mutex_lock(&v4l2_event_mtx);
881 rc = v4l2_event_subscribe(fh, sub, 5, NULL);
882 mutex_unlock(&v4l2_event_mtx);
883
884 return rc;
885}
886
887static const struct v4l2_ioctl_ops g_msm_ioctl_ops = {
888 .vidioc_subscribe_event = msm_subscribe_event,
889 .vidioc_unsubscribe_event = msm_unsubscribe_event,
890 .vidioc_default = msm_private_ioctl,
891};
892
893static unsigned int msm_poll(struct file *f,
894 struct poll_table_struct *pll_table)
895{
896 int rc = 0;
897 struct v4l2_fh *eventq = f->private_data;
898
899 if (WARN_ON(!eventq))
900 goto err;
901
902 poll_wait(f, &eventq->wait, pll_table);
903
904 if (v4l2_event_pending(eventq))
905 rc = POLLIN | POLLRDNORM;
906
907err:
908 return rc;
909}
910
911static void msm_print_event_error(struct v4l2_event *event)
912{
913 struct msm_v4l2_event_data *event_data =
914 (struct msm_v4l2_event_data *)&event->u.data[0];
915
916 pr_err("Evt_type=%x Evt_id=%d Evt_cmd=%x\n", event->type,
917 event->id, event_data->command);
918 pr_err("Evt_session_id=%d Evt_stream_id=%d Evt_arg=%d\n",
919 event_data->session_id, event_data->stream_id,
920 event_data->arg_value);
921}
922
923/* something seriously wrong if msm_close is triggered
924 * !!! user space imaging server is shutdown !!!
925 */
926int msm_post_event(struct v4l2_event *event, int timeout)
927{
928 int rc = 0;
929 struct video_device *vdev;
930 struct msm_session *session;
931 struct msm_v4l2_event_data *event_data =
932 (struct msm_v4l2_event_data *)&event->u.data[0];
933 struct msm_command_ack *cmd_ack;
934 struct msm_command *cmd;
935 int session_id, stream_id;
936 unsigned long flags = 0;
937
938 session_id = event_data->session_id;
939 stream_id = event_data->stream_id;
940
941 spin_lock_irqsave(&msm_eventq_lock, flags);
942 if (!msm_eventq) {
943 spin_unlock_irqrestore(&msm_eventq_lock, flags);
944 pr_err("%s : msm event queue not available Line %d\n",
945 __func__, __LINE__);
946 return -ENODEV;
947 }
948 spin_unlock_irqrestore(&msm_eventq_lock, flags);
949
950 vdev = msm_eventq->vdev;
951
952 /* send to imaging server and wait for ACK */
953 session = msm_queue_find(msm_session_q, struct msm_session,
954 list, __msm_queue_find_session, &session_id);
955 if (WARN_ON(!session)) {
956 pr_err("%s : session not found Line %d\n",
957 __func__, __LINE__);
958 return -EIO;
959 }
960 mutex_lock(&session->lock);
961 cmd_ack = msm_queue_find(&session->command_ack_q,
962 struct msm_command_ack, list,
963 __msm_queue_find_command_ack_q, &stream_id);
964 if (WARN_ON(!cmd_ack)) {
965 mutex_unlock(&session->lock);
966 pr_err("%s : cmd_ack not found Line %d\n",
967 __func__, __LINE__);
968 return -EIO;
969 }
970
971 /*re-init wait_complete */
972 reinit_completion(&cmd_ack->wait_complete);
973
974 v4l2_event_queue(vdev, event);
975
976 if (timeout < 0) {
977 mutex_unlock(&session->lock);
978 pr_debug("%s : timeout cannot be negative Line %d\n",
979 __func__, __LINE__);
980 return rc;
981 }
982
983 /* should wait on session based condition */
984 rc = wait_for_completion_timeout(&cmd_ack->wait_complete,
985 msecs_to_jiffies(timeout));
986
987
988 if (list_empty_careful(&cmd_ack->command_q.list)) {
989 if (!rc) {
990 pr_err("%s: Timed out\n", __func__);
991 msm_print_event_error(event);
992 mutex_unlock(&session->lock);
993 return -ETIMEDOUT;
994 }
995 pr_err("%s: Error: No timeout but list empty!",
996 __func__);
997 msm_print_event_error(event);
998 mutex_unlock(&session->lock);
999 return -EINVAL;
1000 }
1001
1002 cmd = msm_dequeue(&cmd_ack->command_q,
1003 struct msm_command, list);
1004 if (!cmd) {
1005 mutex_unlock(&session->lock);
1006 pr_err("%s : cmd dequeue failed Line %d\n",
1007 __func__, __LINE__);
1008 return -EINVAL;
1009 }
1010
1011 event_data = (struct msm_v4l2_event_data *)cmd->event.u.data;
1012
1013 /* compare cmd_ret and event */
1014 if (WARN_ON(event->type != cmd->event.type) ||
1015 WARN_ON(event->id != cmd->event.id)) {
1016 pr_err("%s : Either event type or id didnot match Line %d\n",
1017 __func__, __LINE__);
1018 pr_err("%s : event->type %d event->id %d\n", __func__,
1019 event->type, event->id);
1020 pr_err("%s : cmd->event.type %d cmd->event.id %d\n", __func__,
1021 cmd->event.type, cmd->event.id);
1022 rc = -EINVAL;
1023 }
1024
1025 *event = cmd->event;
1026
1027 kzfree(cmd);
1028 mutex_unlock(&session->lock);
1029 return rc;
1030}
1031EXPORT_SYMBOL(msm_post_event);
1032
1033static int msm_close(struct file *filep)
1034{
1035 int rc = 0;
1036 unsigned long flags;
1037 struct msm_video_device *pvdev = video_drvdata(filep);
1038 struct msm_sd_close_ioctl sd_close;
1039 struct msm_sd_subdev *msm_sd;
1040
1041 /*stop all hardware blocks immediately*/
1042 mutex_lock(&ordered_sd_mtx);
1043 if (!list_empty(&msm_v4l2_dev->subdevs))
1044 list_for_each_entry(msm_sd, &ordered_sd_list, list)
1045 __msm_sd_close_subdevs(msm_sd, &sd_close);
1046 mutex_unlock(&ordered_sd_mtx);
1047
1048 /* remove msm_v4l2_pm_qos_request */
1049 msm_pm_qos_remove_request();
1050
1051 /* send v4l2_event to HAL next*/
1052 msm_queue_traverse_action(msm_session_q, struct msm_session, list,
1053 __msm_close_destry_session_notify_apps, NULL);
1054
1055 msm_queue_traverse_action(msm_session_q, struct msm_session, list,
1056 __msm_close_wakeup_all_cmdack_session, NULL);
1057
1058 spin_lock_irqsave(&msm_eventq_lock, flags);
1059 msm_eventq = NULL;
1060 spin_unlock_irqrestore(&msm_eventq_lock, flags);
1061 v4l2_fh_release(filep);
1062
1063 spin_lock_irqsave(&msm_pid_lock, flags);
1064 put_pid(msm_pid);
1065 msm_pid = NULL;
1066 spin_unlock_irqrestore(&msm_pid_lock, flags);
1067
1068 atomic_set(&pvdev->opened, 0);
1069
1070 return rc;
1071}
1072
1073static inline void msm_list_switch(struct list_head *l1,
1074 struct list_head *l2)
1075{
1076 l1->next = l2->next;
1077 l2->prev = l1->prev;
1078 l1->prev->next = l2;
1079 l2->next->prev = l1;
1080 l1->prev = l2;
1081 l2->next = l1;
1082}
1083
1084static int msm_open(struct file *filep)
1085{
1086 int rc = -1;
1087 unsigned long flags;
1088 struct msm_video_device *pvdev = video_drvdata(filep);
1089
1090 if (WARN_ON(!pvdev))
1091 return rc;
1092
1093 /* !!! only ONE open is allowed !!! */
1094 if (atomic_cmpxchg(&pvdev->opened, 0, 1))
1095 return -EBUSY;
1096
1097 spin_lock_irqsave(&msm_pid_lock, flags);
1098 msm_pid = get_pid(task_pid(current));
1099 spin_unlock_irqrestore(&msm_pid_lock, flags);
1100
1101 /* create event queue */
1102 rc = v4l2_fh_open(filep);
1103 if (rc < 0)
1104 return rc;
1105
1106 spin_lock_irqsave(&msm_eventq_lock, flags);
1107 msm_eventq = filep->private_data;
1108 spin_unlock_irqrestore(&msm_eventq_lock, flags);
1109
1110 /* register msm_v4l2_pm_qos_request */
1111 msm_pm_qos_add_request();
1112 return rc;
1113}
1114
1115static struct v4l2_file_operations msm_fops = {
1116 .owner = THIS_MODULE,
1117 .open = msm_open,
1118 .poll = msm_poll,
1119 .release = msm_close,
1120 .unlocked_ioctl = video_ioctl2,
1121#ifdef CONFIG_COMPAT
1122 .compat_ioctl32 = video_ioctl2,
1123#endif
1124};
1125
1126struct msm_session *msm_get_session(unsigned int session_id)
1127{
1128 struct msm_session *session;
1129
1130 session = msm_queue_find(msm_session_q, struct msm_session,
1131 list, __msm_queue_find_session, &session_id);
1132 if (!session)
1133 return ERR_PTR(-EINVAL);
1134
1135 return session;
1136}
1137EXPORT_SYMBOL(msm_get_session);
1138
1139
1140struct msm_stream *msm_get_stream(struct msm_session *session,
1141 unsigned int stream_id)
1142{
1143 struct msm_stream *stream;
1144
1145 stream = msm_queue_find(&session->stream_q, struct msm_stream,
1146 list, __msm_queue_find_stream, &stream_id);
1147
1148 if (!stream)
1149 return ERR_PTR(-EINVAL);
1150
1151 return stream;
1152}
1153EXPORT_SYMBOL(msm_get_stream);
1154
1155struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
1156 unsigned int stream_id)
1157{
1158 struct msm_session *session;
1159 struct msm_stream *stream;
1160
1161 session = msm_queue_find(msm_session_q, struct msm_session,
1162 list, __msm_queue_find_session, &session_id);
1163 if (!session)
1164 return NULL;
1165
1166 stream = msm_queue_find(&session->stream_q, struct msm_stream,
1167 list, __msm_queue_find_stream, &stream_id);
1168 if (!stream)
1169 return NULL;
1170
1171 return stream->vb2_q;
1172}
1173EXPORT_SYMBOL(msm_get_stream_vb2q);
1174
1175struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
1176{
1177 struct msm_session *session;
1178 struct msm_stream *stream;
1179 unsigned long flags1;
1180 unsigned long flags2;
1181
1182 spin_lock_irqsave(&msm_session_q->lock, flags1);
1183 list_for_each_entry(session, &(msm_session_q->list), list) {
1184 spin_lock_irqsave(&(session->stream_q.lock), flags2);
1185 list_for_each_entry(
1186 stream, &(session->stream_q.list), list) {
1187 if (stream->vb2_q == q) {
1188 spin_unlock_irqrestore
1189 (&(session->stream_q.lock), flags2);
1190 spin_unlock_irqrestore
1191 (&msm_session_q->lock, flags1);
1192 return stream;
1193 }
1194 }
1195 spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
1196 }
1197 spin_unlock_irqrestore(&msm_session_q->lock, flags1);
1198 return NULL;
1199}
1200EXPORT_SYMBOL(msm_get_stream_from_vb2q);
1201
1202struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q)
1203{
1204 struct msm_session *session;
1205 struct msm_stream *stream;
1206 unsigned long flags1;
1207 unsigned long flags2;
1208
1209 spin_lock_irqsave(&msm_session_q->lock, flags1);
1210 list_for_each_entry(session, &(msm_session_q->list), list) {
1211 spin_lock_irqsave(&(session->stream_q.lock), flags2);
1212 list_for_each_entry(
1213 stream, &(session->stream_q.list), list) {
1214 if (stream->vb2_q == q) {
1215 spin_unlock_irqrestore
1216 (&(session->stream_q.lock), flags2);
1217 spin_unlock_irqrestore
1218 (&msm_session_q->lock, flags1);
1219 return session;
1220 }
1221 }
1222 spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
1223 }
1224 spin_unlock_irqrestore(&msm_session_q->lock, flags1);
1225 return NULL;
1226}
1227EXPORT_SYMBOL(msm_get_session_from_vb2q);
1228
1229
1230#ifdef CONFIG_COMPAT
1231long msm_copy_camera_private_ioctl_args(unsigned long arg,
1232 struct msm_camera_private_ioctl_arg *k_ioctl,
1233 void __user **tmp_compat_ioctl_ptr)
1234{
1235 struct msm_camera_private_ioctl_arg up_ioctl;
1236
1237 if (WARN_ON(!arg || !k_ioctl || !tmp_compat_ioctl_ptr))
1238 return -EIO;
1239
1240 if (copy_from_user(&up_ioctl,
1241 (void __user *)arg,
1242 sizeof(struct msm_camera_private_ioctl_arg)))
1243 return -EFAULT;
1244
1245 k_ioctl->id = up_ioctl.id;
1246 k_ioctl->size = up_ioctl.size;
1247 k_ioctl->result = up_ioctl.result;
1248 k_ioctl->reserved = up_ioctl.reserved;
1249 *tmp_compat_ioctl_ptr = compat_ptr(up_ioctl.ioctl_ptr);
1250
1251 return 0;
1252}
1253EXPORT_SYMBOL(msm_copy_camera_private_ioctl_args);
1254#endif
1255
1256static void msm_sd_notify(struct v4l2_subdev *sd,
1257 unsigned int notification, void *arg)
1258{
1259 int rc = 0;
1260 struct v4l2_subdev *subdev = NULL;
1261
1262 if (WARN_ON(!sd))
1263 return;
1264
1265 if (WARN_ON(!arg))
1266 return;
1267
1268 /* Check if subdev exists before processing*/
1269 if (!msm_sd_find(sd->name))
1270 return;
1271
1272 switch (notification) {
1273 case MSM_SD_NOTIFY_GET_SD: {
1274 struct msm_sd_req_sd *get_sd = arg;
1275
1276 get_sd->subdev = msm_sd_find(get_sd->name);
1277 /* TODO: might need to add ref count on ret_sd */
1278 }
1279 break;
1280
1281 case MSM_SD_NOTIFY_PUT_SD: {
1282 struct msm_sd_req_sd *put_sd = arg;
1283
1284 subdev = msm_sd_find(put_sd->name);
1285 }
1286 break;
1287
1288 case MSM_SD_NOTIFY_REQ_CB: {
1289 struct msm_sd_req_vb2_q *req_sd = arg;
1290
1291 rc = msm_vb2_request_cb(req_sd);
1292 if (rc < 0)
1293 return;
1294 }
1295 break;
1296
1297 default:
1298 break;
1299 }
1300}
1301
1302static ssize_t write_logsync(struct file *file, const char __user *buf,
1303 size_t count, loff_t *ppos)
1304{
1305 char lbuf[LOGSYNC_PACKET_SIZE] = {0};
1306 uint64_t seq_num = 0;
1307 int ret;
1308
Trishansh Bhardwaj586ba082018-02-24 15:02:44 +05301309 if (copy_from_user(lbuf, buf, sizeof(lbuf) - 1))
Pratap Nirujogi6e759912018-01-17 17:51:17 +05301310 return -EFAULT;
1311
1312 ret = kstrtoull(lbuf, 0, &seq_num);
1313 if (ret != 1)
1314 pr_err("LOGSYNC (Kernel): Bad or malformed sequence number\n");
1315 else
1316 pr_debug("LOGSYNC (Kernel): seq_num = %llu\n", seq_num);
1317
1318 return count;
1319}
1320
1321
1322static const struct file_operations logsync_fops = {
1323 .write = write_logsync,
1324};
1325
1326static int msm_probe(struct platform_device *pdev)
1327{
1328 struct msm_video_device *pvdev = NULL;
1329 static struct dentry *cam_debugfs_root;
1330 int rc = 0;
1331
1332 msm_v4l2_dev = kzalloc(sizeof(*msm_v4l2_dev),
1333 GFP_KERNEL);
1334 if (WARN_ON(!msm_v4l2_dev)) {
1335 rc = -ENOMEM;
1336 goto probe_end;
1337 }
1338
1339 pvdev = kzalloc(sizeof(struct msm_video_device),
1340 GFP_KERNEL);
1341 if (WARN_ON(!pvdev)) {
1342 rc = -ENOMEM;
1343 goto pvdev_fail;
1344 }
1345
1346 pvdev->vdev = video_device_alloc();
1347 if (WARN_ON(!pvdev->vdev)) {
1348 rc = -ENOMEM;
1349 goto video_fail;
1350 }
1351
1352#if defined(CONFIG_MEDIA_CONTROLLER)
1353 msm_v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
1354 GFP_KERNEL);
1355 if (!msm_v4l2_dev->mdev) {
1356 rc = -ENOMEM;
1357 goto mdev_fail;
1358 }
1359 media_device_init(msm_v4l2_dev->mdev);
1360 strlcpy(msm_v4l2_dev->mdev->model, MSM_CONFIGURATION_NAME,
1361 sizeof(msm_v4l2_dev->mdev->model));
1362 msm_v4l2_dev->mdev->dev = &(pdev->dev);
1363
1364 rc = media_device_register(msm_v4l2_dev->mdev);
1365 if (WARN_ON(rc < 0))
1366 goto media_fail;
1367
1368 if (WARN_ON((rc == media_entity_pads_init(&pvdev->vdev->entity,
1369 0, NULL)) < 0))
1370 goto entity_fail;
1371
Trishansh Bhardwaj586ba082018-02-24 15:02:44 +05301372 pvdev->vdev->entity.function = QCAMERA_VNODE_GROUP_ID;
Pratap Nirujogi6e759912018-01-17 17:51:17 +05301373#endif
1374
1375 msm_v4l2_dev->notify = msm_sd_notify;
1376
1377 pvdev->vdev->v4l2_dev = msm_v4l2_dev;
1378
1379 rc = v4l2_device_register(&(pdev->dev), pvdev->vdev->v4l2_dev);
1380 if (WARN_ON(rc < 0))
1381 goto register_fail;
1382
1383 strlcpy(pvdev->vdev->name, "msm-config", sizeof(pvdev->vdev->name));
1384 pvdev->vdev->release = video_device_release;
1385 pvdev->vdev->fops = &msm_fops;
1386 pvdev->vdev->ioctl_ops = &g_msm_ioctl_ops;
1387 pvdev->vdev->minor = -1;
1388 pvdev->vdev->vfl_type = VFL_TYPE_GRABBER;
1389 rc = video_register_device(pvdev->vdev,
1390 VFL_TYPE_GRABBER, -1);
1391 if (WARN_ON(rc < 0))
1392 goto v4l2_fail;
1393
1394#if defined(CONFIG_MEDIA_CONTROLLER)
1395 /* FIXME: How to get rid of this messy? */
1396 pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
1397#endif
1398
1399 atomic_set(&pvdev->opened, 0);
1400 video_set_drvdata(pvdev->vdev, pvdev);
1401
1402 msm_session_q = kzalloc(sizeof(*msm_session_q), GFP_KERNEL);
1403 if (WARN_ON(!msm_session_q))
1404 goto v4l2_fail;
1405
1406 msm_init_queue(msm_session_q);
1407 spin_lock_init(&msm_eventq_lock);
1408 spin_lock_init(&msm_pid_lock);
1409 mutex_init(&ordered_sd_mtx);
1410 mutex_init(&v4l2_event_mtx);
1411 INIT_LIST_HEAD(&ordered_sd_list);
1412
1413 cam_debugfs_root = debugfs_create_dir(MSM_CAM_LOGSYNC_FILE_BASEDIR,
1414 NULL);
1415 if (!cam_debugfs_root) {
1416 pr_warn("NON-FATAL: failed to create logsync base directory\n");
1417 } else {
1418 if (!debugfs_create_file(MSM_CAM_LOGSYNC_FILE_NAME,
1419 0660,
1420 cam_debugfs_root,
1421 NULL,
1422 &logsync_fops))
1423 pr_warn("NON-FATAL: failed to create logsync debugfs file\n");
1424 }
1425
1426 rc = cam_ahb_clk_init(pdev);
1427 if (rc < 0) {
1428 pr_err("%s: failed to register ahb clocks\n", __func__);
1429 goto v4l2_fail;
1430 }
1431
1432 of_property_read_u32(pdev->dev.of_node,
1433 "qcom,gpu-limit", &gpu_limit);
1434
1435 goto probe_end;
1436
1437v4l2_fail:
1438 v4l2_device_unregister(pvdev->vdev->v4l2_dev);
1439register_fail:
1440#if defined(CONFIG_MEDIA_CONTROLLER)
1441 media_entity_cleanup(&pvdev->vdev->entity);
1442entity_fail:
1443 media_device_unregister(msm_v4l2_dev->mdev);
1444media_fail:
1445 kzfree(msm_v4l2_dev->mdev);
1446mdev_fail:
1447#endif
1448 video_device_release(pvdev->vdev);
1449video_fail:
1450 kzfree(pvdev);
1451pvdev_fail:
1452 kzfree(msm_v4l2_dev);
1453probe_end:
1454 return rc;
1455}
1456
1457static const struct of_device_id msm_dt_match[] = {
1458 {.compatible = "qcom,msm-cam"},
1459 {}
1460};
1461MODULE_DEVICE_TABLE(of, msm_dt_match);
1462
1463static struct platform_driver msm_driver = {
1464 .probe = msm_probe,
1465 .driver = {
1466 .name = "msm",
1467 .owner = THIS_MODULE,
1468 .of_match_table = msm_dt_match,
1469 },
1470};
1471
1472static int __init msm_init(void)
1473{
1474 return platform_driver_register(&msm_driver);
1475}
1476
1477static void __exit msm_exit(void)
1478{
1479 platform_driver_unregister(&msm_driver);
1480}
1481
1482
1483module_init(msm_init);
1484module_exit(msm_exit);
1485MODULE_DESCRIPTION("MSM V4L2 Camera");
1486MODULE_LICENSE("GPL v2");