1 /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
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.
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.
15 #include <linux/module.h>
16 #include <linux/workqueue.h>
17 #include <linux/delay.h>
18 #include <linux/types.h>
19 #include <linux/list.h>
20 #include <linux/ioctl.h>
21 #include <linux/spinlock.h>
22 #include <linux/proc_fs.h>
23 #include <linux/atomic.h>
24 #include <linux/wait.h>
25 #include <linux/videodev2.h>
26 #include <linux/msm_ion.h>
27 #include <linux/iommu.h>
28 #include <linux/platform_device.h>
29 #include <media/v4l2-fh.h>
30 #include <media/videobuf2-v4l2.h>
36 #define fh_to_private(__fh) \
37 container_of(__fh, struct camera_v4l2_private, fh)
39 struct camera_v4l2_private {
41 unsigned int stream_id;
42 unsigned int is_vb2_valid; /*0 if no vb2 buffers on stream, else 1*/
43 struct vb2_queue vb2_q;
48 static void camera_pack_event(struct file *filep, int evt_id,
49 int command, int value, struct v4l2_event *event)
51 struct msm_v4l2_event_data *event_data =
52 (struct msm_v4l2_event_data *)&event->u.data[0];
53 struct msm_video_device *pvdev = video_drvdata(filep);
54 struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
56 /* always MSM_CAMERA_V4L2_EVENT_TYPE */
57 event->type = MSM_CAMERA_V4L2_EVENT_TYPE;
59 event_data->command = command;
60 event_data->session_id = pvdev->vdev->num;
61 event_data->stream_id = sp->stream_id;
62 event_data->arg_value = value;
65 static int camera_check_event_status(struct v4l2_event *event)
67 struct msm_v4l2_event_data *event_data =
68 (struct msm_v4l2_event_data *)&event->u.data[0];
70 if (event_data->status > MSM_CAMERA_ERR_EVT_BASE) {
71 pr_err("%s : event_data status out of bounds\n",
73 pr_err("%s : Line %d event_data->status 0X%x\n",
74 __func__, __LINE__, event_data->status);
76 switch (event_data->status) {
77 case MSM_CAMERA_ERR_CMD_FAIL:
78 case MSM_CAMERA_ERR_MAPPING:
80 case MSM_CAMERA_ERR_DEVICE_BUSY:
90 static int camera_v4l2_querycap(struct file *filep, void *fh,
91 struct v4l2_capability *cap)
94 struct v4l2_event event;
96 if (msm_is_daemon_present() == false)
99 /* can use cap->driver to make differentiation */
100 camera_pack_event(filep, MSM_CAMERA_GET_PARM,
101 MSM_CAMERA_PRIV_QUERY_CAP, -1, &event);
103 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
107 rc = camera_check_event_status(&event);
112 static int camera_v4l2_s_crop(struct file *filep, void *fh,
113 const struct v4l2_crop *crop)
116 struct v4l2_event event;
118 if (msm_is_daemon_present() == false)
121 if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
123 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
124 MSM_CAMERA_PRIV_S_CROP, -1, &event);
126 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
130 rc = camera_check_event_status(&event);
136 static int camera_v4l2_g_crop(struct file *filep, void *fh,
137 struct v4l2_crop *crop)
140 struct v4l2_event event;
142 if (msm_is_daemon_present() == false)
145 if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
146 camera_pack_event(filep, MSM_CAMERA_GET_PARM,
147 MSM_CAMERA_PRIV_G_CROP, -1, &event);
149 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
153 rc = camera_check_event_status(&event);
159 static int camera_v4l2_queryctrl(struct file *filep, void *fh,
160 struct v4l2_queryctrl *ctrl)
163 struct v4l2_event event;
165 if (msm_is_daemon_present() == false)
168 if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
170 camera_pack_event(filep, MSM_CAMERA_GET_PARM,
171 ctrl->id, -1, &event);
173 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
177 rc = camera_check_event_status(&event);
183 static int camera_v4l2_g_ctrl(struct file *filep, void *fh,
184 struct v4l2_control *ctrl)
187 struct v4l2_event event;
188 struct msm_video_device *pvdev = video_drvdata(filep);
189 unsigned int session_id = pvdev->vdev->num;
191 if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
192 if (ctrl->id == MSM_CAMERA_PRIV_G_SESSION_ID) {
193 ctrl->value = session_id;
195 camera_pack_event(filep, MSM_CAMERA_GET_PARM,
196 ctrl->id, -1, &event);
198 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
202 rc = camera_check_event_status(&event);
209 static int camera_v4l2_s_ctrl(struct file *filep, void *fh,
210 struct v4l2_control *ctrl)
213 struct v4l2_event event;
214 struct msm_v4l2_event_data *event_data;
216 if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
217 camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id,
218 ctrl->value, &event);
220 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
223 event_data = (struct msm_v4l2_event_data *)event.u.data;
224 ctrl->value = event_data->ret_value;
225 rc = camera_check_event_status(&event);
231 static int camera_v4l2_reqbufs(struct file *filep, void *fh,
232 struct v4l2_requestbuffers *req)
235 struct msm_session *session;
236 struct camera_v4l2_private *sp = fh_to_private(fh);
237 struct msm_video_device *pvdev = video_drvdata(filep);
238 unsigned int session_id = pvdev->vdev->num;
240 session = msm_session_find(session_id);
241 if (WARN_ON(!session))
243 mutex_lock(&sp->lock);
244 ret = vb2_reqbufs(&sp->vb2_q, req);
245 mutex_unlock(&sp->lock);
249 static int camera_v4l2_querybuf(struct file *filep, void *fh,
250 struct v4l2_buffer *pb)
255 static int camera_v4l2_qbuf(struct file *filep, void *fh,
256 struct v4l2_buffer *pb)
259 struct msm_session *session;
260 struct camera_v4l2_private *sp = fh_to_private(fh);
261 struct msm_video_device *pvdev = video_drvdata(filep);
262 unsigned int session_id = pvdev->vdev->num;
264 session = msm_session_find(session_id);
265 if (WARN_ON(!session))
267 mutex_lock(&sp->lock);
268 ret = vb2_qbuf(&sp->vb2_q, pb);
269 mutex_unlock(&sp->lock);
273 static int camera_v4l2_dqbuf(struct file *filep, void *fh,
274 struct v4l2_buffer *pb)
277 struct msm_session *session;
278 struct camera_v4l2_private *sp = fh_to_private(fh);
279 struct msm_video_device *pvdev = video_drvdata(filep);
280 unsigned int session_id = pvdev->vdev->num;
282 session = msm_session_find(session_id);
283 if (WARN_ON(!session))
285 mutex_lock(&sp->lock);
286 ret = vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
287 mutex_unlock(&sp->lock);
291 static int camera_v4l2_streamon(struct file *filep, void *fh,
292 enum v4l2_buf_type buf_type)
294 struct v4l2_event event;
296 struct camera_v4l2_private *sp = fh_to_private(fh);
298 mutex_lock(&sp->lock);
299 rc = vb2_streamon(&sp->vb2_q, buf_type);
300 mutex_unlock(&sp->lock);
302 if (msm_is_daemon_present() == false)
305 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
306 MSM_CAMERA_PRIV_STREAM_ON, -1, &event);
308 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
312 rc = camera_check_event_status(&event);
316 static int camera_v4l2_streamoff(struct file *filep, void *fh,
317 enum v4l2_buf_type buf_type)
319 struct v4l2_event event;
321 struct camera_v4l2_private *sp = fh_to_private(fh);
323 if (msm_is_daemon_present() != false) {
324 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
325 MSM_CAMERA_PRIV_STREAM_OFF, -1, &event);
327 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
330 rc = camera_check_event_status(&event);
332 mutex_lock(&sp->lock);
333 vb2_streamoff(&sp->vb2_q, buf_type);
334 mutex_unlock(&sp->lock);
338 static int camera_v4l2_g_fmt_vid_cap_mplane(struct file *filep, void *fh,
339 struct v4l2_format *pfmt)
343 if (msm_is_daemon_present() == false)
346 if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
347 struct v4l2_event event;
349 camera_pack_event(filep, MSM_CAMERA_GET_PARM,
350 MSM_CAMERA_PRIV_G_FMT, -1, &event);
352 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
356 rc = camera_check_event_status(&event);
362 static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
363 struct v4l2_format *pfmt)
367 struct v4l2_event event;
368 struct camera_v4l2_private *sp = fh_to_private(fh);
369 struct msm_v4l2_format_data *user_fmt;
371 if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
373 if (WARN_ON(!sp->vb2_q.drv_priv))
376 memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data,
377 sizeof(struct msm_v4l2_format_data));
378 user_fmt = (struct msm_v4l2_format_data *)sp->vb2_q.drv_priv;
380 pr_debug("%s: num planes :%c\n", __func__,
381 user_fmt->num_planes);
382 /* num_planes need to bound checked, otherwise for loop
383 * can execute forever
385 if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES))
387 for (i = 0; i < user_fmt->num_planes; i++)
388 pr_debug("%s: plane size[%d]\n", __func__,
389 user_fmt->plane_sizes[i]);
391 if (msm_is_daemon_present() != false) {
392 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
393 MSM_CAMERA_PRIV_S_FMT, -1, &event);
395 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
399 rc = camera_check_event_status(&event);
403 sp->is_vb2_valid = 1;
409 static int camera_v4l2_try_fmt_vid_cap_mplane(struct file *filep, void *fh,
410 struct v4l2_format *pfmt)
416 static int camera_v4l2_g_parm(struct file *filep, void *fh,
417 struct v4l2_streamparm *a)
423 static int camera_v4l2_s_parm(struct file *filep, void *fh,
424 struct v4l2_streamparm *parm)
427 struct v4l2_event event;
428 struct msm_v4l2_event_data *event_data =
429 (struct msm_v4l2_event_data *)&event.u.data[0];
430 struct camera_v4l2_private *sp = fh_to_private(fh);
432 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
433 MSM_CAMERA_PRIV_NEW_STREAM, -1, &event);
435 rc = msm_create_stream(event_data->session_id,
436 event_data->stream_id, &sp->vb2_q);
440 if (msm_is_daemon_present() != false) {
441 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
445 rc = camera_check_event_status(&event);
449 /* use stream_id as stream index */
450 parm->parm.capture.extendedmode = sp->stream_id;
451 sp->stream_created = true;
456 msm_delete_stream(event_data->session_id,
457 event_data->stream_id);
461 static int camera_v4l2_subscribe_event(struct v4l2_fh *fh,
462 const struct v4l2_event_subscription *sub)
465 struct camera_v4l2_private *sp = fh_to_private(fh);
467 rc = v4l2_event_subscribe(&sp->fh, sub, 5, NULL);
472 static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh,
473 const struct v4l2_event_subscription *sub)
476 struct camera_v4l2_private *sp = fh_to_private(fh);
478 rc = v4l2_event_unsubscribe(&sp->fh, sub);
483 static long camera_v4l2_vidioc_private_ioctl(struct file *filep, void *fh,
484 bool valid_prio, unsigned int cmd, void *arg)
486 struct camera_v4l2_private *sp = fh_to_private(fh);
487 struct msm_video_device *pvdev = video_drvdata(filep);
488 struct msm_camera_private_ioctl_arg *k_ioctl = arg;
491 if (WARN_ON(!k_ioctl || !pvdev))
494 if (cmd != VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD)
497 switch (k_ioctl->id) {
498 case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: {
499 struct msm_camera_return_buf ptr, *tmp = NULL;
501 MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr,
503 if (copy_from_user(&ptr, (void __user *)tmp,
504 sizeof(struct msm_camera_return_buf))) {
507 rc = msm_vb2_return_buf_by_idx(pvdev->vdev->num, sp->stream_id,
512 pr_debug("unimplemented id %d", k_ioctl->id);
518 static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = {
519 .vidioc_querycap = camera_v4l2_querycap,
520 .vidioc_s_crop = camera_v4l2_s_crop,
521 .vidioc_g_crop = camera_v4l2_g_crop,
522 .vidioc_queryctrl = camera_v4l2_queryctrl,
523 .vidioc_g_ctrl = camera_v4l2_g_ctrl,
524 .vidioc_s_ctrl = camera_v4l2_s_ctrl,
525 .vidioc_reqbufs = camera_v4l2_reqbufs,
526 .vidioc_querybuf = camera_v4l2_querybuf,
527 .vidioc_qbuf = camera_v4l2_qbuf,
528 .vidioc_dqbuf = camera_v4l2_dqbuf,
529 .vidioc_streamon = camera_v4l2_streamon,
530 .vidioc_streamoff = camera_v4l2_streamoff,
531 .vidioc_g_fmt_vid_cap_mplane = camera_v4l2_g_fmt_vid_cap_mplane,
532 .vidioc_s_fmt_vid_cap_mplane = camera_v4l2_s_fmt_vid_cap_mplane,
533 .vidioc_try_fmt_vid_cap_mplane = camera_v4l2_try_fmt_vid_cap_mplane,
535 /* Stream type-dependent parameter ioctls */
536 .vidioc_g_parm = camera_v4l2_g_parm,
537 .vidioc_s_parm = camera_v4l2_s_parm,
539 /* event subscribe/unsubscribe */
540 .vidioc_subscribe_event = camera_v4l2_subscribe_event,
541 .vidioc_unsubscribe_event = camera_v4l2_unsubscribe_event,
542 .vidioc_default = camera_v4l2_vidioc_private_ioctl,
545 static int camera_v4l2_fh_open(struct file *filep)
547 struct msm_video_device *pvdev = video_drvdata(filep);
548 struct camera_v4l2_private *sp;
549 unsigned int stream_id;
551 sp = kzalloc(sizeof(*sp), GFP_KERNEL);
555 filep->private_data = &sp->fh;
557 /* stream_id = open id */
558 stream_id = atomic_read(&pvdev->opened);
559 sp->stream_id = find_first_zero_bit(
560 (const unsigned long *)&stream_id, MSM_CAMERA_STREAM_CNT_BITS);
561 pr_debug("%s: Found stream_id=%d\n", __func__, sp->stream_id);
563 mutex_init(&sp->lock);
565 v4l2_fh_init(&sp->fh, pvdev->vdev);
566 v4l2_fh_add(&sp->fh);
571 static int camera_v4l2_fh_release(struct file *filep)
573 struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
576 v4l2_fh_del(&sp->fh);
577 v4l2_fh_exit(&sp->fh);
580 mutex_destroy(&sp->lock);
585 static int camera_v4l2_vb2_q_init(struct file *filep)
587 struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
588 struct vb2_queue *q = &sp->vb2_q;
590 memset(q, 0, sizeof(struct vb2_queue));
592 /* free up this buffer when stream is done */
594 kzalloc(sizeof(struct msm_v4l2_format_data), GFP_KERNEL);
596 pr_err("%s : memory not available\n", __func__);
600 q->mem_ops = msm_vb2_get_q_mem_ops();
601 q->ops = msm_vb2_get_q_ops();
603 /* default queue type */
604 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
605 q->io_modes = VB2_USERPTR;
606 q->buf_struct_size = sizeof(struct msm_vb2_buffer);
607 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
608 return vb2_queue_init(q);
611 static void camera_v4l2_vb2_q_release(struct file *filep)
613 struct camera_v4l2_private *sp = filep->private_data;
615 kzfree(sp->vb2_q.drv_priv);
616 mutex_lock(&sp->lock);
617 vb2_queue_release(&sp->vb2_q);
618 mutex_unlock(&sp->lock);
621 static int camera_v4l2_open(struct file *filep)
624 struct v4l2_event event;
625 struct msm_video_device *pvdev = video_drvdata(filep);
626 unsigned int opn_idx, idx;
631 rc = camera_v4l2_fh_open(filep);
633 pr_err("%s : camera_v4l2_fh_open failed Line %d rc %d\n",
634 __func__, __LINE__, rc);
638 opn_idx = atomic_read(&pvdev->opened);
640 /* every stream has a vb2 queue */
641 rc = camera_v4l2_vb2_q_init(filep);
643 pr_err("%s : vb2 queue init fails Line %d rc %d\n",
644 __func__, __LINE__, rc);
648 if (!atomic_read(&pvdev->opened)) {
649 pm_stay_awake(&pvdev->vdev->dev);
651 /* Disable power collapse latency */
652 msm_pm_qos_update_request(CAMERA_DISABLE_PC_LATENCY);
654 /* create a new session when first opened */
655 rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
657 pr_err("%s : session creation failed Line %d rc %d\n",
658 __func__, __LINE__, rc);
662 rc = msm_create_command_ack_q(pvdev->vdev->num,
663 find_first_zero_bit((const unsigned long *)&opn_idx,
664 MSM_CAMERA_STREAM_CNT_BITS));
666 pr_err("%s : creation of command_ack queue failed\n",
668 pr_err("%s : Line %d rc %d\n", __func__, __LINE__, rc);
669 goto command_ack_q_fail;
672 if (msm_is_daemon_present() != false) {
673 camera_pack_event(filep, MSM_CAMERA_NEW_SESSION,
675 rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
677 pr_err("%s : NEW_SESSION event failed,rc %d\n",
682 rc = camera_check_event_status(&event);
686 /* Enable power collapse latency */
687 msm_pm_qos_update_request(CAMERA_ENABLE_PC_LATENCY);
689 rc = msm_create_command_ack_q(pvdev->vdev->num,
690 find_first_zero_bit((const unsigned long *)&opn_idx,
691 MSM_CAMERA_STREAM_CNT_BITS));
693 pr_err("%s : creation of command_ack queue failed Line %d rc %d\n",
694 __func__, __LINE__, rc);
698 idx |= (1 << find_first_zero_bit((const unsigned long *)&opn_idx,
699 MSM_CAMERA_STREAM_CNT_BITS));
700 atomic_cmpxchg(&pvdev->opened, opn_idx, idx);
705 msm_delete_command_ack_q(pvdev->vdev->num, 0);
707 msm_destroy_session(pvdev->vdev->num);
709 pm_relax(&pvdev->vdev->dev);
711 camera_v4l2_vb2_q_release(filep);
713 camera_v4l2_fh_release(filep);
718 static unsigned int camera_v4l2_poll(struct file *filep,
719 struct poll_table_struct *wait)
722 struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
724 if (sp->is_vb2_valid == 1)
725 rc = vb2_poll(&sp->vb2_q, filep, wait);
727 poll_wait(filep, &sp->fh.wait, wait);
728 if (v4l2_event_pending(&sp->fh))
734 static int camera_v4l2_close(struct file *filep)
736 struct v4l2_event event;
737 struct msm_video_device *pvdev = video_drvdata(filep);
738 struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
739 unsigned int opn_idx, mask;
740 struct msm_session *session;
745 session = msm_session_find(pvdev->vdev->num);
746 if (WARN_ON(!session))
749 mutex_lock(&session->close_lock);
750 opn_idx = atomic_read(&pvdev->opened);
751 mask = (1 << sp->stream_id);
753 atomic_set(&pvdev->opened, opn_idx);
755 if (msm_is_daemon_present() != false && sp->stream_created == true) {
756 pr_debug("%s: close stream_id=%d\n", __func__, sp->stream_id);
757 camera_pack_event(filep, MSM_CAMERA_SET_PARM,
758 MSM_CAMERA_PRIV_DEL_STREAM, -1, &event);
759 msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
762 if (sp->stream_created == true)
763 sp->stream_created = false;
765 if (atomic_read(&pvdev->opened) == 0) {
766 if (msm_is_daemon_present() != false) {
767 camera_pack_event(filep, MSM_CAMERA_DEL_SESSION,
769 msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
771 msm_delete_command_ack_q(pvdev->vdev->num, 0);
772 msm_delete_stream(pvdev->vdev->num, sp->stream_id);
773 mutex_unlock(&session->close_lock);
774 /* This should take care of both normal close
775 * and application crashes
777 camera_v4l2_vb2_q_release(filep);
778 msm_destroy_session(pvdev->vdev->num);
780 pm_relax(&pvdev->vdev->dev);
782 msm_delete_command_ack_q(pvdev->vdev->num,
785 camera_v4l2_vb2_q_release(filep);
786 msm_delete_stream(pvdev->vdev->num, sp->stream_id);
787 mutex_unlock(&session->close_lock);
790 camera_v4l2_fh_release(filep);
796 static long camera_handle_internal_compat_ioctl(struct file *file,
797 unsigned int cmd, unsigned long arg)
800 struct msm_camera_private_ioctl_arg k_ioctl;
801 void *tmp_compat_ioctl_ptr = NULL;
803 rc = msm_copy_camera_private_ioctl_args(arg,
804 &k_ioctl, &tmp_compat_ioctl_ptr);
806 pr_err("Subdev cmd %d failed\n", cmd);
809 switch (k_ioctl.id) {
810 case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: {
811 if (k_ioctl.size != sizeof(struct msm_camera_return_buf)) {
812 pr_debug("Invalid size for id %d with size %d",
813 k_ioctl.id, k_ioctl.size);
817 if (tmp_compat_ioctl_ptr == NULL) {
818 pr_debug("Invalid ptr for id %d", k_ioctl.id);
821 k_ioctl.ioctl_ptr = (__u64)(uintptr_t)tmp_compat_ioctl_ptr;
823 rc = camera_v4l2_vidioc_private_ioctl(file, file->private_data,
824 0, cmd, (void *)&k_ioctl);
828 pr_debug("unimplemented id %d", k_ioctl.id);
834 static long camera_v4l2_compat_ioctl(struct file *file, unsigned int cmd,
840 case VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD: {
841 ret = camera_handle_internal_compat_ioctl(file, cmd, arg);
843 pr_debug("Subdev cmd %d fail\n", cmd);
856 static struct v4l2_file_operations camera_v4l2_fops = {
857 .owner = THIS_MODULE,
858 .open = camera_v4l2_open,
859 .poll = camera_v4l2_poll,
860 .release = camera_v4l2_close,
861 .unlocked_ioctl = video_ioctl2,
863 .compat_ioctl32 = camera_v4l2_compat_ioctl,
867 int camera_init_v4l2(struct device *dev, unsigned int *session)
869 struct msm_video_device *pvdev;
870 struct v4l2_device *v4l2_dev;
873 pvdev = kzalloc(sizeof(struct msm_video_device),
880 pvdev->vdev = video_device_alloc();
886 v4l2_dev = kzalloc(sizeof(struct v4l2_device), GFP_KERNEL);
892 #if defined(CONFIG_MEDIA_CONTROLLER)
893 v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
895 if (!v4l2_dev->mdev) {
899 strlcpy(v4l2_dev->mdev->model, MSM_CAMERA_NAME,
900 sizeof(v4l2_dev->mdev->model));
902 v4l2_dev->mdev->dev = dev;
904 rc = media_device_register(v4l2_dev->mdev);
908 rc = media_entity_init(&pvdev->vdev->entity, 0, NULL, 0);
911 pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
912 pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
915 v4l2_dev->notify = NULL;
916 pvdev->vdev->v4l2_dev = v4l2_dev;
918 rc = v4l2_device_register(dev, pvdev->vdev->v4l2_dev);
922 strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name));
923 pvdev->vdev->release = video_device_release;
924 pvdev->vdev->fops = &camera_v4l2_fops;
925 pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
926 pvdev->vdev->minor = -1;
927 pvdev->vdev->vfl_type = VFL_TYPE_GRABBER;
928 rc = video_register_device(pvdev->vdev,
929 VFL_TYPE_GRABBER, -1);
931 goto video_register_fail;
932 #if defined(CONFIG_MEDIA_CONTROLLER)
933 /* FIXME: How to get rid of this messy? */
934 pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
937 *session = pvdev->vdev->num;
938 atomic_set(&pvdev->opened, 0);
939 video_set_drvdata(pvdev->vdev, pvdev);
940 device_init_wakeup(&pvdev->vdev->dev, 1);
944 v4l2_device_unregister(pvdev->vdev->v4l2_dev);
946 #if defined(CONFIG_MEDIA_CONTROLLER)
947 media_entity_cleanup(&pvdev->vdev->entity);
949 media_device_unregister(v4l2_dev->mdev);
951 kzfree(v4l2_dev->mdev);
956 video_device_release(pvdev->vdev);