RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / dream / camera / msm_v4l2.c
blob963579359c37e46387738c0212529138bf45dea7
1 /*
3 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
5 */
7 #include <linux/workqueue.h>
8 #include <linux/delay.h>
9 #include <linux/types.h>
10 #include <linux/list.h>
11 #include <linux/ioctl.h>
12 #include <linux/spinlock.h>
13 #include <linux/videodev2.h>
14 #include <linux/proc_fs.h>
15 #include <linux/slab.h>
16 #include <media/v4l2-dev.h>
17 #include <media/msm_camera.h>
18 #include <mach/camera.h>
19 #include <media/v4l2-ioctl.h>
20 /*#include <linux/platform_device.h>*/
22 #define MSM_V4L2_START_SNAPSHOT _IOWR('V', BASE_VIDIOC_PRIVATE+1, \
23 struct v4l2_buffer)
25 #define MSM_V4L2_GET_PICTURE _IOWR('V', BASE_VIDIOC_PRIVATE+2, \
26 struct v4l2_buffer)
28 #define MSM_V4L2_DEVICE_NAME "msm_v4l2"
30 #define MSM_V4L2_PROC_NAME "msm_v4l2"
32 #define MSM_V4L2_DEVNUM_MPEG2 0
33 #define MSM_V4L2_DEVNUM_YUV 20
35 /* HVGA-P (portrait) and HVGA-L (landscape) */
36 #define MSM_V4L2_WIDTH 480
37 #define MSM_V4L2_HEIGHT 320
39 #define D(fmt, args...) printk(KERN_INFO "msm_v4l2: " fmt, ##args)
41 #define PREVIEW_FRAMES_NUM 4
43 struct msm_v4l2_device {
44 struct list_head read_queue;
45 struct v4l2_format current_cap_format;
46 struct v4l2_format current_pix_format;
47 struct video_device *pvdev;
48 struct msm_v4l2_driver *drv;
49 uint8_t opencnt;
51 spinlock_t read_queue_lock;
54 static struct msm_v4l2_device *g_pmsm_v4l2_dev;
57 static DEFINE_MUTEX(msm_v4l2_opencnt_lock);
59 static int msm_v4l2_open(struct file *f)
61 int rc = 0;
62 D("%s\n", __func__);
63 mutex_lock(&msm_v4l2_opencnt_lock);
64 if (!g_pmsm_v4l2_dev->opencnt) {
65 rc = g_pmsm_v4l2_dev->drv->open(
66 g_pmsm_v4l2_dev->drv->sync,
67 MSM_APPS_ID_V4L2);
69 g_pmsm_v4l2_dev->opencnt++;
70 mutex_unlock(&msm_v4l2_opencnt_lock);
71 return rc;
74 static int msm_v4l2_release(struct file *f)
76 int rc = 0;
77 D("%s\n", __func__);
78 mutex_lock(&msm_v4l2_opencnt_lock);
79 if (!g_pmsm_v4l2_dev->opencnt) {
80 g_pmsm_v4l2_dev->opencnt--;
81 if (!g_pmsm_v4l2_dev->opencnt) {
82 rc = g_pmsm_v4l2_dev->drv->release(
83 g_pmsm_v4l2_dev->drv->sync);
86 mutex_unlock(&msm_v4l2_opencnt_lock);
87 return rc;
90 static unsigned int msm_v4l2_poll(struct file *f, struct poll_table_struct *w)
92 return g_pmsm_v4l2_dev->drv->drv_poll(g_pmsm_v4l2_dev->drv->sync, f, w);
95 static long msm_v4l2_ioctl(struct file *filep,
96 unsigned int cmd, unsigned long arg)
98 struct msm_ctrl_cmd *ctrlcmd;
100 D("msm_v4l2_ioctl, cmd = %d, %d\n", cmd, __LINE__);
102 switch (cmd) {
103 case MSM_V4L2_START_SNAPSHOT:
105 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
106 if (!ctrlcmd) {
107 CDBG("msm_v4l2_ioctl: cannot allocate buffer\n");
108 return -ENOMEM;
111 ctrlcmd->length = 0;
112 ctrlcmd->value = NULL;
113 ctrlcmd->timeout_ms = 10000;
115 D("msm_v4l2_ioctl, MSM_V4L2_START_SNAPSHOT v4l2 ioctl %d\n",
116 cmd);
117 ctrlcmd->type = MSM_V4L2_SNAPSHOT;
118 return g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync,
119 ctrlcmd);
121 case MSM_V4L2_GET_PICTURE:
122 D("msm_v4l2_ioctl, MSM_V4L2_GET_PICTURE v4l2 ioctl %d\n", cmd);
123 ctrlcmd = (struct msm_ctrl_cmd *)arg;
124 return g_pmsm_v4l2_dev->drv->get_pict(
125 g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
127 default:
128 D("msm_v4l2_ioctl, standard v4l2 ioctl %d\n", cmd);
129 return video_ioctl2(filep, cmd, arg);
133 static void msm_v4l2_release_dev(struct video_device *d)
135 D("%s\n", __func__);
138 static int msm_v4l2_querycap(struct file *f,
139 void *pctx, struct v4l2_capability *pcaps)
141 D("%s\n", __func__);
142 strncpy(pcaps->driver, MSM_APPS_ID_V4L2, sizeof(pcaps->driver));
143 strncpy(pcaps->card,
144 MSM_V4L2_DEVICE_NAME, sizeof(pcaps->card));
145 pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
146 return 0;
149 static int msm_v4l2_s_std(struct file *f, void *pctx, v4l2_std_id *pnorm)
151 D("%s\n", __func__);
152 return 0;
155 static int msm_v4l2_queryctrl(struct file *f,
156 void *pctx, struct v4l2_queryctrl *pqctrl)
158 int rc = 0;
159 struct msm_ctrl_cmd *ctrlcmd;
161 D("%s\n", __func__);
163 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
164 if (!ctrlcmd) {
165 CDBG("msm_v4l2_queryctrl: cannot allocate buffer\n");
166 return -ENOMEM;
169 ctrlcmd->type = MSM_V4L2_QUERY_CTRL;
170 ctrlcmd->length = sizeof(struct v4l2_queryctrl);
171 ctrlcmd->value = pqctrl;
172 ctrlcmd->timeout_ms = 10000;
174 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
175 if (rc < 0)
176 return -1;
178 return ctrlcmd->status;
181 static int msm_v4l2_g_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
183 int rc = 0;
184 struct msm_ctrl_cmd *ctrlcmd;
186 D("%s\n", __func__);
188 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
189 if (!ctrlcmd) {
190 CDBG("msm_v4l2_g_ctrl: cannot allocate buffer\n");
191 return -ENOMEM;
194 ctrlcmd->type = MSM_V4L2_GET_CTRL;
195 ctrlcmd->length = sizeof(struct v4l2_control);
196 ctrlcmd->value = c;
197 ctrlcmd->timeout_ms = 10000;
199 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
200 if (rc < 0)
201 return -1;
203 return ctrlcmd->status;
206 static int msm_v4l2_s_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
208 int rc = 0;
209 struct msm_ctrl_cmd *ctrlcmd;
211 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
212 if (!ctrlcmd) {
213 CDBG("msm_v4l2_s_ctrl: cannot allocate buffer\n");
214 return -ENOMEM;
217 ctrlcmd->type = MSM_V4L2_SET_CTRL;
218 ctrlcmd->length = sizeof(struct v4l2_control);
219 ctrlcmd->value = c;
220 ctrlcmd->timeout_ms = 10000;
222 D("%s\n", __func__);
224 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
225 if (rc < 0)
226 return -1;
228 return ctrlcmd->status;
231 static int msm_v4l2_reqbufs(struct file *f,
232 void *pctx, struct v4l2_requestbuffers *b)
234 D("%s\n", __func__);
235 return 0;
238 static int msm_v4l2_querybuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
240 struct msm_pmem_info pmem_buf;
242 __u32 y_pad = pb->bytesused % 4;
244 /* V4L2 videodev will do the copy_from_user. */
246 memset(&pmem_buf, 0, sizeof(struct msm_pmem_info));
247 pmem_buf.type = MSM_PMEM_OUTPUT2;
248 pmem_buf.vaddr = (void *)pb->m.userptr;
249 pmem_buf.y_off = 0;
250 pmem_buf.fd = (int)pb->reserved;
251 /* pmem_buf.cbcr_off = (y_size + y_pad); */
252 pmem_buf.cbcr_off = (pb->bytesused + y_pad);
254 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync, &pmem_buf);
256 return 0;
259 static int msm_v4l2_qbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
262 __u32 y_size = 0;
263 __u32 y_pad = 0;
264 __u32 width = 0;
265 __u32 height = 0;
268 __u32 y_pad = 0;
270 struct msm_pmem_info meminfo;
271 struct msm_frame frame;
272 static int cnt;
274 if ((pb->flags >> 16) & 0x0001) {
275 /* this is for previwe */
277 y_pad = pb->bytesused % 4;
279 if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
280 /* this qbuf is actually for releasing */
282 frame.buffer = pb->m.userptr;
283 frame.y_off = 0;
284 /* frame.cbcr_off = (y_size + y_pad); */
285 frame.cbcr_off = (pb->bytesused + y_pad);
286 frame.fd = pb->reserved;
288 D("V4L2_BUF_TYPE_PRIVATE: pb->bytesused = %d \n",
289 pb->bytesused);
291 g_pmsm_v4l2_dev->drv->put_frame(
292 g_pmsm_v4l2_dev->drv->sync,
293 &frame);
295 return 0;
298 D("V4L2_BUF_TYPE_VIDEO_CAPTURE: pb->bytesused = %d \n",
299 pb->bytesused);
301 meminfo.type = MSM_PMEM_OUTPUT2;
302 meminfo.fd = (int)pb->reserved;
303 meminfo.vaddr = (void *)pb->m.userptr;
304 meminfo.y_off = 0;
305 /* meminfo.cbcr_off = (y_size + y_pad); */
306 meminfo.cbcr_off = (pb->bytesused + y_pad);
307 if (cnt == PREVIEW_FRAMES_NUM - 1)
308 meminfo.active = 0;
309 else
310 meminfo.active = 1;
311 cnt++;
312 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
313 &meminfo);
314 } else if ((pb->flags) & 0x0001) {
315 /* this is for snapshot */
317 __u32 y_size = 0;
319 if ((pb->flags >> 8) & 0x01) {
321 y_size = pb->bytesused;
323 meminfo.type = MSM_PMEM_THUMBAIL;
324 } else if ((pb->flags >> 9) & 0x01) {
326 y_size = pb->bytesused;
328 meminfo.type = MSM_PMEM_MAINIMG;
331 y_pad = y_size % 4;
333 meminfo.fd = (int)pb->reserved;
334 meminfo.vaddr = (void *)pb->m.userptr;
335 meminfo.y_off = 0;
336 /* meminfo.cbcr_off = (y_size + y_pad); */
337 meminfo.cbcr_off = (y_size + y_pad);
338 meminfo.active = 1;
339 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
340 &meminfo);
343 return 0;
346 static int msm_v4l2_dqbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
348 struct msm_frame frame;
349 D("%s\n", __func__);
351 /* V4L2 videodev will do the copy_to_user. */
352 if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
354 D("%s, %d\n", __func__, __LINE__);
356 g_pmsm_v4l2_dev->drv->get_frame(
357 g_pmsm_v4l2_dev->drv->sync,
358 &frame);
360 pb->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
361 pb->m.userptr = (unsigned long)frame.buffer;
362 pb->reserved = (int)frame.fd;
363 /* pb->length = (int)frame.cbcr_off; */
365 pb->bytesused = frame.cbcr_off;
367 } else if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
368 __u32 y_pad = pb->bytesused % 4;
370 frame.buffer = pb->m.userptr;
371 frame.y_off = 0;
372 /* frame.cbcr_off = (y_size + y_pad); */
373 frame.cbcr_off = (pb->bytesused + y_pad);
374 frame.fd = pb->reserved;
376 g_pmsm_v4l2_dev->drv->put_frame(
377 g_pmsm_v4l2_dev->drv->sync,
378 &frame);
381 return 0;
384 static int msm_v4l2_streamon(struct file *f, void *pctx, enum v4l2_buf_type i)
386 struct msm_ctrl_cmd *ctrlcmd;
388 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
389 if (!ctrlcmd) {
390 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
391 return -ENOMEM;
394 ctrlcmd->type = MSM_V4L2_STREAM_ON;
395 ctrlcmd->timeout_ms = 10000;
396 ctrlcmd->length = 0;
397 ctrlcmd->value = NULL;
399 D("%s\n", __func__);
401 g_pmsm_v4l2_dev->drv->ctrl(
402 g_pmsm_v4l2_dev->drv->sync,
403 ctrlcmd);
405 D("%s after drv->ctrl \n", __func__);
407 return 0;
410 static int msm_v4l2_streamoff(struct file *f, void *pctx, enum v4l2_buf_type i)
412 struct msm_ctrl_cmd *ctrlcmd;
414 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
415 if (!ctrlcmd) {
416 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
417 return -ENOMEM;
420 ctrlcmd->type = MSM_V4L2_STREAM_OFF;
421 ctrlcmd->timeout_ms = 10000;
422 ctrlcmd->length = 0;
423 ctrlcmd->value = NULL;
426 D("%s\n", __func__);
428 g_pmsm_v4l2_dev->drv->ctrl(
429 g_pmsm_v4l2_dev->drv->sync,
430 ctrlcmd);
432 return 0;
435 static int msm_v4l2_enum_fmt_overlay(struct file *f,
436 void *pctx, struct v4l2_fmtdesc *pfmtdesc)
438 D("%s\n", __func__);
439 return 0;
442 static int msm_v4l2_enum_fmt_cap(struct file *f,
443 void *pctx, struct v4l2_fmtdesc *pfmtdesc)
445 D("%s\n", __func__);
447 switch (pfmtdesc->index) {
448 case 0:
449 pfmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
450 pfmtdesc->flags = 0;
451 strncpy(pfmtdesc->description, "YUV 4:2:0",
452 sizeof(pfmtdesc->description));
453 pfmtdesc->pixelformat = V4L2_PIX_FMT_YVU420;
454 break;
455 default:
456 return -EINVAL;
459 return 0;
462 static int msm_v4l2_g_fmt_cap(struct file *f,
463 void *pctx, struct v4l2_format *pfmt)
465 D("%s\n", __func__);
466 pfmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
467 pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
468 pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
469 pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
470 pfmt->fmt.pix.field = V4L2_FIELD_ANY;
471 pfmt->fmt.pix.bytesperline = 0;
472 pfmt->fmt.pix.sizeimage = 0;
473 pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
474 pfmt->fmt.pix.priv = 0;
475 return 0;
478 static int msm_v4l2_s_fmt_cap(struct file *f,
479 void *pctx, struct v4l2_format *pfmt)
481 struct msm_ctrl_cmd *ctrlcmd;
483 D("%s\n", __func__);
485 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
486 if (!ctrlcmd) {
487 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
488 return -ENOMEM;
491 ctrlcmd->type = MSM_V4L2_VID_CAP_TYPE;
492 ctrlcmd->length = sizeof(struct v4l2_format);
493 ctrlcmd->value = pfmt;
494 ctrlcmd->timeout_ms = 10000;
496 if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
497 kfree(ctrlcmd);
498 return -1;
502 /* Ok, but check other params, too. */
505 g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
507 return 0;
510 static int msm_v4l2_g_fmt_overlay(struct file *f,
511 void *pctx, struct v4l2_format *pfmt)
513 D("%s\n", __func__);
514 pfmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
515 pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
516 pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
517 pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
518 pfmt->fmt.pix.field = V4L2_FIELD_ANY;
519 pfmt->fmt.pix.bytesperline = 0;
520 pfmt->fmt.pix.sizeimage = 0;
521 pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
522 pfmt->fmt.pix.priv = 0;
523 return 0;
526 static int msm_v4l2_s_fmt_overlay(struct file *f,
527 void *pctx, struct v4l2_format *pfmt)
529 D("%s\n", __func__);
530 return 0;
533 static int msm_v4l2_overlay(struct file *f, void *pctx, unsigned int i)
535 D("%s\n", __func__);
536 return 0;
539 static int msm_v4l2_g_jpegcomp(struct file *f,
540 void *pctx, struct v4l2_jpegcompression *pcomp)
542 D("%s\n", __func__);
543 return 0;
546 static int msm_v4l2_s_jpegcomp(struct file *f,
547 void *pctx, struct v4l2_jpegcompression *pcomp)
549 D("%s\n", __func__);
550 return 0;
553 #ifdef CONFIG_PROC_FS
554 int msm_v4l2_read_proc(char *pbuf, char **start, off_t offset,
555 int count, int *eof, void *data)
557 int len = 0;
558 len += snprintf(pbuf, strlen("stats\n") + 1, "stats\n");
560 if (g_pmsm_v4l2_dev) {
561 len += snprintf(pbuf, strlen("mode: ") + 1, "mode: ");
563 if (g_pmsm_v4l2_dev->current_cap_format.type
564 == V4L2_BUF_TYPE_VIDEO_CAPTURE)
565 len += snprintf(pbuf, strlen("capture\n") + 1,
566 "capture\n");
567 else
568 len += snprintf(pbuf, strlen("unknown\n") + 1,
569 "unknown\n");
571 len += snprintf(pbuf, 21, "resolution: %dx%d\n",
572 g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
573 width,
574 g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
575 height);
577 len += snprintf(pbuf,
578 strlen("pixel format: ") + 1, "pixel format: ");
579 if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.pixelformat
580 == V4L2_PIX_FMT_YVU420)
581 len += snprintf(pbuf, strlen("yvu420\n") + 1,
582 "yvu420\n");
583 else
584 len += snprintf(pbuf, strlen("unknown\n") + 1,
585 "unknown\n");
587 len += snprintf(pbuf, strlen("colorspace: ") + 1,
588 "colorspace: ");
589 if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.colorspace
590 == V4L2_COLORSPACE_JPEG)
591 len += snprintf(pbuf, strlen("jpeg\n") + 1, "jpeg\n");
592 else
593 len += snprintf(pbuf, strlen("unknown\n") + 1,
594 "unknown\n");
597 *eof = 1;
598 return len;
600 #endif
602 static const struct v4l2_file_operations msm_v4l2_fops = {
603 .owner = THIS_MODULE,
604 .open = msm_v4l2_open,
605 .poll = msm_v4l2_poll,
606 .release = msm_v4l2_release,
607 .ioctl = msm_v4l2_ioctl,
610 static void msm_v4l2_dev_init(struct msm_v4l2_device *pmsm_v4l2_dev)
612 pmsm_v4l2_dev->read_queue_lock =
613 __SPIN_LOCK_UNLOCKED(pmsm_v4l2_dev->read_queue_lock);
614 INIT_LIST_HEAD(&pmsm_v4l2_dev->read_queue);
617 static int msm_v4l2_try_fmt_cap(struct file *file,
618 void *fh, struct v4l2_format *f)
620 return 0;
623 static int mm_v4l2_try_fmt_type_private(struct file *file,
624 void *fh, struct v4l2_format *f)
626 return 0;
630 * should the following structure be used instead of the code in the function?
631 * static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
632 * .vidioc_querycap = ....
635 static const struct v4l2_ioctl_ops msm_ioctl_ops = {
636 .vidioc_querycap = msm_v4l2_querycap,
637 .vidioc_s_std = msm_v4l2_s_std,
639 .vidioc_queryctrl = msm_v4l2_queryctrl,
640 .vidioc_g_ctrl = msm_v4l2_g_ctrl,
641 .vidioc_s_ctrl = msm_v4l2_s_ctrl,
643 .vidioc_reqbufs = msm_v4l2_reqbufs,
644 .vidioc_querybuf = msm_v4l2_querybuf,
645 .vidioc_qbuf = msm_v4l2_qbuf,
646 .vidioc_dqbuf = msm_v4l2_dqbuf,
648 .vidioc_streamon = msm_v4l2_streamon,
649 .vidioc_streamoff = msm_v4l2_streamoff,
651 .vidioc_enum_fmt_vid_overlay = msm_v4l2_enum_fmt_overlay,
652 .vidioc_enum_fmt_vid_cap = msm_v4l2_enum_fmt_cap,
654 .vidioc_try_fmt_vid_cap = msm_v4l2_try_fmt_cap,
655 .vidioc_try_fmt_type_private = mm_v4l2_try_fmt_type_private,
657 .vidioc_g_fmt_vid_cap = msm_v4l2_g_fmt_cap,
658 .vidioc_s_fmt_vid_cap = msm_v4l2_s_fmt_cap,
659 .vidioc_g_fmt_vid_overlay = msm_v4l2_g_fmt_overlay,
660 .vidioc_s_fmt_vid_overlay = msm_v4l2_s_fmt_overlay,
661 .vidioc_overlay = msm_v4l2_overlay,
663 .vidioc_g_jpegcomp = msm_v4l2_g_jpegcomp,
664 .vidioc_s_jpegcomp = msm_v4l2_s_jpegcomp,
667 static int msm_v4l2_video_dev_init(struct video_device *pvd)
669 strncpy(pvd->name, MSM_APPS_ID_V4L2, sizeof(pvd->name));
670 pvd->vfl_type = 1;
671 pvd->fops = &msm_v4l2_fops;
672 pvd->release = msm_v4l2_release_dev;
673 pvd->minor = -1;
674 pvd->ioctl_ops = &msm_ioctl_ops;
675 return msm_v4l2_register(g_pmsm_v4l2_dev->drv);
678 static int __init msm_v4l2_init(void)
680 int rc = -ENOMEM;
681 struct video_device *pvdev = NULL;
682 struct msm_v4l2_device *pmsm_v4l2_dev = NULL;
683 D("%s\n", __func__);
685 pvdev = video_device_alloc();
686 if (pvdev == NULL)
687 return rc;
689 pmsm_v4l2_dev =
690 kzalloc(sizeof(struct msm_v4l2_device), GFP_KERNEL);
691 if (pmsm_v4l2_dev == NULL) {
692 video_device_release(pvdev);
693 return rc;
696 msm_v4l2_dev_init(pmsm_v4l2_dev);
698 g_pmsm_v4l2_dev = pmsm_v4l2_dev;
699 g_pmsm_v4l2_dev->pvdev = pvdev;
701 g_pmsm_v4l2_dev->drv =
702 kzalloc(sizeof(struct msm_v4l2_driver), GFP_KERNEL);
703 if (!g_pmsm_v4l2_dev->drv) {
704 video_device_release(pvdev);
705 kfree(pmsm_v4l2_dev);
706 return rc;
709 rc = msm_v4l2_video_dev_init(pvdev);
710 if (rc < 0) {
711 video_device_release(pvdev);
712 kfree(g_pmsm_v4l2_dev->drv);
713 kfree(pmsm_v4l2_dev);
714 return rc;
717 if (video_register_device(pvdev, VFL_TYPE_GRABBER,
718 MSM_V4L2_DEVNUM_YUV)) {
719 D("failed to register device\n");
720 video_device_release(pvdev);
721 kfree(g_pmsm_v4l2_dev);
722 g_pmsm_v4l2_dev = NULL;
723 return -ENOENT;
725 #ifdef CONFIG_PROC_FS
726 create_proc_read_entry(MSM_V4L2_PROC_NAME,
727 0, NULL, msm_v4l2_read_proc, NULL);
728 #endif
730 return 0;
733 static void __exit msm_v4l2_exit(void)
735 struct video_device *pvdev = g_pmsm_v4l2_dev->pvdev;
736 D("%s\n", __func__);
737 #ifdef CONFIG_PROC_FS
738 remove_proc_entry(MSM_V4L2_PROC_NAME, NULL);
739 #endif
740 video_unregister_device(pvdev);
741 video_device_release(pvdev);
743 msm_v4l2_unregister(g_pmsm_v4l2_dev->drv);
745 kfree(g_pmsm_v4l2_dev->drv);
746 g_pmsm_v4l2_dev->drv = NULL;
748 kfree(g_pmsm_v4l2_dev);
749 g_pmsm_v4l2_dev = NULL;
752 module_init(msm_v4l2_init);
753 module_exit(msm_v4l2_exit);
755 MODULE_DESCRIPTION("MSM V4L2 driver");
756 MODULE_LICENSE("GPL v2");