46a6eb1cf53f4f28c04248477e8dbc86c2f26585
[deliverable/linux.git] / drivers / staging / dream / camera / msm_v4l2.c
1 /*
2 *
3 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
4 *
5 */
6
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 <media/v4l2-dev.h>
16 #include <media/msm_camera.h>
17 #include <mach/camera.h>
18 #include <media/v4l2-ioctl.h>
19 /*#include <linux/platform_device.h>*/
20
21 #define MSM_V4L2_START_SNAPSHOT _IOWR('V', BASE_VIDIOC_PRIVATE+1, \
22 struct v4l2_buffer)
23
24 #define MSM_V4L2_GET_PICTURE _IOWR('V', BASE_VIDIOC_PRIVATE+2, \
25 struct v4l2_buffer)
26
27 #define MSM_V4L2_DEVICE_NAME "msm_v4l2"
28
29 #define MSM_V4L2_PROC_NAME "msm_v4l2"
30
31 #define MSM_V4L2_DEVNUM_MPEG2 0
32 #define MSM_V4L2_DEVNUM_YUV 20
33
34 /* HVGA-P (portrait) and HVGA-L (landscape) */
35 #define MSM_V4L2_WIDTH 480
36 #define MSM_V4L2_HEIGHT 320
37
38 #if 1
39 #define D(fmt, args...) printk(KERN_INFO "msm_v4l2: " fmt, ##args)
40 #else
41 #define D(fmt, args...) do {} while (0)
42 #endif
43
44 #define PREVIEW_FRAMES_NUM 4
45
46 struct msm_v4l2_device {
47 struct list_head read_queue;
48 struct v4l2_format current_cap_format;
49 struct v4l2_format current_pix_format;
50 struct video_device *pvdev;
51 struct msm_v4l2_driver *drv;
52 uint8_t opencnt;
53
54 spinlock_t read_queue_lock;
55 };
56
57 static struct msm_v4l2_device *g_pmsm_v4l2_dev;
58
59
60 static DEFINE_MUTEX(msm_v4l2_opencnt_lock);
61
62 static int msm_v4l2_open(struct file *f)
63 {
64 int rc = 0;
65 D("%s\n", __func__);
66 mutex_lock(&msm_v4l2_opencnt_lock);
67 if (!g_pmsm_v4l2_dev->opencnt) {
68 rc = g_pmsm_v4l2_dev->drv->open(
69 g_pmsm_v4l2_dev->drv->sync,
70 MSM_APPS_ID_V4L2);
71 }
72 g_pmsm_v4l2_dev->opencnt++;
73 mutex_unlock(&msm_v4l2_opencnt_lock);
74 return rc;
75 }
76
77 static int msm_v4l2_release(struct file *f)
78 {
79 int rc = 0;
80 D("%s\n", __func__);
81 mutex_lock(&msm_v4l2_opencnt_lock);
82 if (!g_pmsm_v4l2_dev->opencnt) {
83 g_pmsm_v4l2_dev->opencnt--;
84 if (!g_pmsm_v4l2_dev->opencnt) {
85 rc = g_pmsm_v4l2_dev->drv->release(
86 g_pmsm_v4l2_dev->drv->sync);
87 }
88 }
89 mutex_unlock(&msm_v4l2_opencnt_lock);
90 return rc;
91 }
92
93 static unsigned int msm_v4l2_poll(struct file *f, struct poll_table_struct *w)
94 {
95 return g_pmsm_v4l2_dev->drv->drv_poll(g_pmsm_v4l2_dev->drv->sync, f, w);
96 }
97
98 static long msm_v4l2_ioctl(struct file *filep,
99 unsigned int cmd, unsigned long arg)
100 {
101 struct msm_ctrl_cmd *ctrlcmd;
102
103 D("msm_v4l2_ioctl, cmd = %d, %d\n", cmd, __LINE__);
104
105 switch (cmd) {
106 case MSM_V4L2_START_SNAPSHOT:
107
108 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
109 if (!ctrlcmd) {
110 CDBG("msm_v4l2_ioctl: cannot allocate buffer\n");
111 return -ENOMEM;
112 }
113
114 ctrlcmd->length = 0;
115 ctrlcmd->value = NULL;
116 ctrlcmd->timeout_ms = 10000;
117
118 D("msm_v4l2_ioctl, MSM_V4L2_START_SNAPSHOT v4l2 ioctl %d\n",
119 cmd);
120 ctrlcmd->type = MSM_V4L2_SNAPSHOT;
121 return g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync,
122 ctrlcmd);
123
124 case MSM_V4L2_GET_PICTURE:
125 D("msm_v4l2_ioctl, MSM_V4L2_GET_PICTURE v4l2 ioctl %d\n", cmd);
126 ctrlcmd = (struct msm_ctrl_cmd *)arg;
127 return g_pmsm_v4l2_dev->drv->get_pict(
128 g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
129
130 default:
131 D("msm_v4l2_ioctl, standard v4l2 ioctl %d\n", cmd);
132 return video_ioctl2(filep, cmd, arg);
133 }
134 }
135
136 static void msm_v4l2_release_dev(struct video_device *d)
137 {
138 D("%s\n", __func__);
139 }
140
141 static int msm_v4l2_querycap(struct file *f,
142 void *pctx, struct v4l2_capability *pcaps)
143 {
144 D("%s\n", __func__);
145 strncpy(pcaps->driver, MSM_APPS_ID_V4L2, sizeof(pcaps->driver));
146 strncpy(pcaps->card,
147 MSM_V4L2_DEVICE_NAME, sizeof(pcaps->card));
148 pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
149 return 0;
150 }
151
152 static int msm_v4l2_s_std(struct file *f, void *pctx, v4l2_std_id *pnorm)
153 {
154 D("%s\n", __func__);
155 return 0;
156 }
157
158 static int msm_v4l2_queryctrl(struct file *f,
159 void *pctx, struct v4l2_queryctrl *pqctrl)
160 {
161 int rc = 0;
162 struct msm_ctrl_cmd *ctrlcmd;
163
164 D("%s\n", __func__);
165
166 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
167 if (!ctrlcmd) {
168 CDBG("msm_v4l2_queryctrl: cannot allocate buffer\n");
169 return -ENOMEM;
170 }
171
172 ctrlcmd->type = MSM_V4L2_QUERY_CTRL;
173 ctrlcmd->length = sizeof(struct v4l2_queryctrl);
174 ctrlcmd->value = pqctrl;
175 ctrlcmd->timeout_ms = 10000;
176
177 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
178 if (rc < 0)
179 return -1;
180
181 return ctrlcmd->status;
182 }
183
184 static int msm_v4l2_g_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
185 {
186 int rc = 0;
187 struct msm_ctrl_cmd *ctrlcmd;
188
189 D("%s\n", __func__);
190
191 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
192 if (!ctrlcmd) {
193 CDBG("msm_v4l2_g_ctrl: cannot allocate buffer\n");
194 return -ENOMEM;
195 }
196
197 ctrlcmd->type = MSM_V4L2_GET_CTRL;
198 ctrlcmd->length = sizeof(struct v4l2_control);
199 ctrlcmd->value = c;
200 ctrlcmd->timeout_ms = 10000;
201
202 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
203 if (rc < 0)
204 return -1;
205
206 return ctrlcmd->status;
207 }
208
209 static int msm_v4l2_s_ctrl(struct file *f, void *pctx, struct v4l2_control *c)
210 {
211 int rc = 0;
212 struct msm_ctrl_cmd *ctrlcmd;
213
214 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
215 if (!ctrlcmd) {
216 CDBG("msm_v4l2_s_ctrl: cannot allocate buffer\n");
217 return -ENOMEM;
218 }
219
220 ctrlcmd->type = MSM_V4L2_SET_CTRL;
221 ctrlcmd->length = sizeof(struct v4l2_control);
222 ctrlcmd->value = c;
223 ctrlcmd->timeout_ms = 10000;
224
225 D("%s\n", __func__);
226
227 rc = g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
228 if (rc < 0)
229 return -1;
230
231 return ctrlcmd->status;
232 }
233
234 static int msm_v4l2_reqbufs(struct file *f,
235 void *pctx, struct v4l2_requestbuffers *b)
236 {
237 D("%s\n", __func__);
238 return 0;
239 }
240
241 static int msm_v4l2_querybuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
242 {
243 struct msm_pmem_info pmem_buf;
244 #if 0
245 __u32 width = 0;
246 __u32 height = 0;
247 __u32 y_size = 0;
248 __u32 y_pad = 0;
249
250 /* FIXME: g_pmsm_v4l2_dev->current_pix_format.fmt.pix.width; */
251 width = 640;
252 /* FIXME: g_pmsm_v4l2_dev->current_pix_format.fmt.pix.height; */
253 height = 480;
254
255 D("%s: width = %d, height = %d\n", __func__, width, height);
256
257 y_size = width * height;
258 y_pad = y_size % 4;
259 #endif
260
261 __u32 y_pad = pb->bytesused % 4;
262
263 /* V4L2 videodev will do the copy_from_user. */
264
265 memset(&pmem_buf, 0, sizeof(struct msm_pmem_info));
266 pmem_buf.type = MSM_PMEM_OUTPUT2;
267 pmem_buf.vaddr = (void *)pb->m.userptr;
268 pmem_buf.y_off = 0;
269 pmem_buf.fd = (int)pb->reserved;
270 /* pmem_buf.cbcr_off = (y_size + y_pad); */
271 pmem_buf.cbcr_off = (pb->bytesused + y_pad);
272
273 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync, &pmem_buf);
274
275 return 0;
276 }
277
278 static int msm_v4l2_qbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
279 {
280 /*
281 __u32 y_size = 0;
282 __u32 y_pad = 0;
283 __u32 width = 0;
284 __u32 height = 0;
285 */
286
287 __u32 y_pad = 0;
288
289 struct msm_pmem_info meminfo;
290 struct msm_frame frame;
291 static int cnt;
292
293 if ((pb->flags >> 16) & 0x0001) {
294 /* this is for previwe */
295 #if 0
296 width = 640;
297 height = 480;
298
299 /* V4L2 videodev will do the copy_from_user. */
300 D("%s: width = %d, height = %d\n", __func__, width, height);
301 y_size = width * height;
302 y_pad = y_size % 4;
303 #endif
304
305 y_pad = pb->bytesused % 4;
306
307 if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
308 /* this qbuf is actually for releasing */
309
310 frame.buffer = pb->m.userptr;
311 frame.y_off = 0;
312 /* frame.cbcr_off = (y_size + y_pad); */
313 frame.cbcr_off = (pb->bytesused + y_pad);
314 frame.fd = pb->reserved;
315
316 D("V4L2_BUF_TYPE_PRIVATE: pb->bytesused = %d \n",
317 pb->bytesused);
318
319 g_pmsm_v4l2_dev->drv->put_frame(
320 g_pmsm_v4l2_dev->drv->sync,
321 &frame);
322
323 return 0;
324 }
325
326 D("V4L2_BUF_TYPE_VIDEO_CAPTURE: pb->bytesused = %d \n",
327 pb->bytesused);
328
329 meminfo.type = MSM_PMEM_OUTPUT2;
330 meminfo.fd = (int)pb->reserved;
331 meminfo.vaddr = (void *)pb->m.userptr;
332 meminfo.y_off = 0;
333 /* meminfo.cbcr_off = (y_size + y_pad); */
334 meminfo.cbcr_off = (pb->bytesused + y_pad);
335 if (cnt == PREVIEW_FRAMES_NUM - 1)
336 meminfo.active = 0;
337 else
338 meminfo.active = 1;
339 cnt++;
340 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
341 &meminfo);
342 } else if ((pb->flags) & 0x0001) {
343 /* this is for snapshot */
344
345 __u32 y_size = 0;
346
347 if ((pb->flags >> 8) & 0x01) {
348
349 y_size = pb->bytesused;
350
351 meminfo.type = MSM_PMEM_THUMBAIL;
352 } else if ((pb->flags >> 9) & 0x01) {
353
354 y_size = pb->bytesused;
355
356 meminfo.type = MSM_PMEM_MAINIMG;
357 }
358
359 y_pad = y_size % 4;
360
361 meminfo.fd = (int)pb->reserved;
362 meminfo.vaddr = (void *)pb->m.userptr;
363 meminfo.y_off = 0;
364 /* meminfo.cbcr_off = (y_size + y_pad); */
365 meminfo.cbcr_off = (y_size + y_pad);
366 meminfo.active = 1;
367 g_pmsm_v4l2_dev->drv->reg_pmem(g_pmsm_v4l2_dev->drv->sync,
368 &meminfo);
369 }
370
371 return 0;
372 }
373
374 static int msm_v4l2_dqbuf(struct file *f, void *pctx, struct v4l2_buffer *pb)
375 {
376 struct msm_frame frame;
377 D("%s\n", __func__);
378
379 /* V4L2 videodev will do the copy_to_user. */
380 if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
381
382 D("%s, %d\n", __func__, __LINE__);
383
384 g_pmsm_v4l2_dev->drv->get_frame(
385 g_pmsm_v4l2_dev->drv->sync,
386 &frame);
387
388 pb->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
389 pb->m.userptr = (unsigned long)frame.buffer; /* FIXME */
390 pb->reserved = (int)frame.fd;
391 /* pb->length = (int)frame.cbcr_off; */
392
393 pb->bytesused = frame.cbcr_off;
394
395 } else if (pb->type == V4L2_BUF_TYPE_PRIVATE) {
396 __u32 y_pad = pb->bytesused % 4;
397
398 frame.buffer = pb->m.userptr;
399 frame.y_off = 0;
400 /* frame.cbcr_off = (y_size + y_pad); */
401 frame.cbcr_off = (pb->bytesused + y_pad);
402 frame.fd = pb->reserved;
403
404 g_pmsm_v4l2_dev->drv->put_frame(
405 g_pmsm_v4l2_dev->drv->sync,
406 &frame);
407 }
408
409 return 0;
410 }
411
412 static int msm_v4l2_streamon(struct file *f, void *pctx, enum v4l2_buf_type i)
413 {
414 struct msm_ctrl_cmd *ctrlcmd;
415
416 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
417 if (!ctrlcmd) {
418 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
419 return -ENOMEM;
420 }
421
422 ctrlcmd->type = MSM_V4L2_STREAM_ON;
423 ctrlcmd->timeout_ms = 10000;
424 ctrlcmd->length = 0;
425 ctrlcmd->value = NULL;
426
427 D("%s\n", __func__);
428
429 g_pmsm_v4l2_dev->drv->ctrl(
430 g_pmsm_v4l2_dev->drv->sync,
431 ctrlcmd);
432
433 D("%s after drv->ctrl \n", __func__);
434
435 return 0;
436 }
437
438 static int msm_v4l2_streamoff(struct file *f, void *pctx, enum v4l2_buf_type i)
439 {
440 struct msm_ctrl_cmd *ctrlcmd;
441
442 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
443 if (!ctrlcmd) {
444 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
445 return -ENOMEM;
446 }
447
448 ctrlcmd->type = MSM_V4L2_STREAM_OFF;
449 ctrlcmd->timeout_ms = 10000;
450 ctrlcmd->length = 0;
451 ctrlcmd->value = NULL;
452
453
454 D("%s\n", __func__);
455
456 g_pmsm_v4l2_dev->drv->ctrl(
457 g_pmsm_v4l2_dev->drv->sync,
458 ctrlcmd);
459
460 return 0;
461 }
462
463 static int msm_v4l2_enum_fmt_overlay(struct file *f,
464 void *pctx, struct v4l2_fmtdesc *pfmtdesc)
465 {
466 D("%s\n", __func__);
467 return 0;
468 }
469
470 static int msm_v4l2_enum_fmt_cap(struct file *f,
471 void *pctx, struct v4l2_fmtdesc *pfmtdesc)
472 {
473 D("%s\n", __func__);
474
475 switch (pfmtdesc->index) {
476 case 0:
477 pfmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
478 pfmtdesc->flags = 0;
479 strncpy(pfmtdesc->description, "YUV 4:2:0",
480 sizeof(pfmtdesc->description));
481 pfmtdesc->pixelformat = V4L2_PIX_FMT_YVU420;
482 break;
483 default:
484 return -EINVAL;
485 }
486
487 return 0;
488 }
489
490 static int msm_v4l2_g_fmt_cap(struct file *f,
491 void *pctx, struct v4l2_format *pfmt)
492 {
493 D("%s\n", __func__);
494 pfmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
495 pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
496 pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
497 pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
498 pfmt->fmt.pix.field = V4L2_FIELD_ANY;
499 pfmt->fmt.pix.bytesperline = 0;
500 pfmt->fmt.pix.sizeimage = 0;
501 pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
502 pfmt->fmt.pix.priv = 0;
503 return 0;
504 }
505
506 static int msm_v4l2_s_fmt_cap(struct file *f,
507 void *pctx, struct v4l2_format *pfmt)
508 {
509 struct msm_ctrl_cmd *ctrlcmd;
510
511 D("%s\n", __func__);
512
513 ctrlcmd = kmalloc(sizeof(struct msm_ctrl_cmd), GFP_ATOMIC);
514 if (!ctrlcmd) {
515 CDBG("msm_v4l2_s_fmt_cap: cannot allocate buffer\n");
516 return -ENOMEM;
517 }
518
519 ctrlcmd->type = MSM_V4L2_VID_CAP_TYPE;
520 ctrlcmd->length = sizeof(struct v4l2_format);
521 ctrlcmd->value = pfmt;
522 ctrlcmd->timeout_ms = 10000;
523
524 if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
525 return -1;
526
527 #if 0
528 /* FIXEME */
529 if (pfmt->fmt.pix.pixelformat != V4L2_PIX_FMT_YVU420)
530 return -EINVAL;
531 #endif
532
533 /* Ok, but check other params, too. */
534
535 #if 0
536 memcpy(&g_pmsm_v4l2_dev->current_pix_format.fmt.pix, pfmt,
537 sizeof(struct v4l2_format));
538 #endif
539
540 g_pmsm_v4l2_dev->drv->ctrl(g_pmsm_v4l2_dev->drv->sync, ctrlcmd);
541
542 return 0;
543 }
544
545 static int msm_v4l2_g_fmt_overlay(struct file *f,
546 void *pctx, struct v4l2_format *pfmt)
547 {
548 D("%s\n", __func__);
549 pfmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
550 pfmt->fmt.pix.width = MSM_V4L2_WIDTH;
551 pfmt->fmt.pix.height = MSM_V4L2_HEIGHT;
552 pfmt->fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
553 pfmt->fmt.pix.field = V4L2_FIELD_ANY;
554 pfmt->fmt.pix.bytesperline = 0;
555 pfmt->fmt.pix.sizeimage = 0;
556 pfmt->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
557 pfmt->fmt.pix.priv = 0;
558 return 0;
559 }
560
561 static int msm_v4l2_s_fmt_overlay(struct file *f,
562 void *pctx, struct v4l2_format *pfmt)
563 {
564 D("%s\n", __func__);
565 return 0;
566 }
567
568 static int msm_v4l2_overlay(struct file *f, void *pctx, unsigned int i)
569 {
570 D("%s\n", __func__);
571 return 0;
572 }
573
574 static int msm_v4l2_g_jpegcomp(struct file *f,
575 void *pctx, struct v4l2_jpegcompression *pcomp)
576 {
577 D("%s\n", __func__);
578 return 0;
579 }
580
581 static int msm_v4l2_s_jpegcomp(struct file *f,
582 void *pctx, struct v4l2_jpegcompression *pcomp)
583 {
584 D("%s\n", __func__);
585 return 0;
586 }
587
588 #ifdef CONFIG_PROC_FS
589 int msm_v4l2_read_proc(char *pbuf, char **start, off_t offset,
590 int count, int *eof, void *data)
591 {
592 int len = 0;
593 len += snprintf(pbuf, strlen("stats\n") + 1, "stats\n");
594
595 if (g_pmsm_v4l2_dev) {
596 len += snprintf(pbuf, strlen("mode: ") + 1, "mode: ");
597
598 if (g_pmsm_v4l2_dev->current_cap_format.type
599 == V4L2_BUF_TYPE_VIDEO_CAPTURE)
600 len += snprintf(pbuf, strlen("capture\n") + 1,
601 "capture\n");
602 else
603 len += snprintf(pbuf, strlen("unknown\n") + 1,
604 "unknown\n");
605
606 len += snprintf(pbuf, 21, "resolution: %dx%d\n",
607 g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
608 width,
609 g_pmsm_v4l2_dev->current_cap_format.fmt.pix.
610 height);
611
612 len += snprintf(pbuf,
613 strlen("pixel format: ") + 1, "pixel format: ");
614 if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.pixelformat
615 == V4L2_PIX_FMT_YVU420)
616 len += snprintf(pbuf, strlen("yvu420\n") + 1,
617 "yvu420\n");
618 else
619 len += snprintf(pbuf, strlen("unknown\n") + 1,
620 "unknown\n");
621
622 len += snprintf(pbuf, strlen("colorspace: ") + 1,
623 "colorspace: ");
624 if (g_pmsm_v4l2_dev->current_cap_format.fmt.pix.colorspace
625 == V4L2_COLORSPACE_JPEG)
626 len += snprintf(pbuf, strlen("jpeg\n") + 1, "jpeg\n");
627 else
628 len += snprintf(pbuf, strlen("unknown\n") + 1,
629 "unknown\n");
630 }
631
632 *eof = 1;
633 return len;
634 }
635 #endif
636
637 static const struct v4l2_file_operations msm_v4l2_fops = {
638 .owner = THIS_MODULE,
639 .open = msm_v4l2_open,
640 .poll = msm_v4l2_poll,
641 .release = msm_v4l2_release,
642 .ioctl = msm_v4l2_ioctl,
643 };
644
645 static void msm_v4l2_dev_init(struct msm_v4l2_device *pmsm_v4l2_dev)
646 {
647 pmsm_v4l2_dev->read_queue_lock =
648 __SPIN_LOCK_UNLOCKED(pmsm_v4l2_dev->read_queue_lock);
649 INIT_LIST_HEAD(&pmsm_v4l2_dev->read_queue);
650 }
651
652 static int msm_v4l2_try_fmt_cap(struct file *file,
653 void *fh, struct v4l2_format *f)
654 {
655 /* FIXME */
656 return 0;
657 }
658
659 static int mm_v4l2_try_fmt_type_private(struct file *file,
660 void *fh, struct v4l2_format *f)
661 {
662 /* FIXME */
663 return 0;
664 }
665
666 /*
667 * should the following structure be used instead of the code in the function?
668 * static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
669 * .vidioc_querycap = ....
670 * }
671 */
672 static const struct v4l2_ioctl_ops msm_ioctl_ops = {
673 .vidioc_querycap = msm_v4l2_querycap,
674 .vidioc_s_std = msm_v4l2_s_std,
675
676 .vidioc_queryctrl = msm_v4l2_queryctrl,
677 .vidioc_g_ctrl = msm_v4l2_g_ctrl,
678 .vidioc_s_ctrl = msm_v4l2_s_ctrl,
679
680 .vidioc_reqbufs = msm_v4l2_reqbufs,
681 .vidioc_querybuf = msm_v4l2_querybuf,
682 .vidioc_qbuf = msm_v4l2_qbuf,
683 .vidioc_dqbuf = msm_v4l2_dqbuf,
684
685 .vidioc_streamon = msm_v4l2_streamon,
686 .vidioc_streamoff = msm_v4l2_streamoff,
687
688 .vidioc_enum_fmt_vid_overlay = msm_v4l2_enum_fmt_overlay,
689 .vidioc_enum_fmt_vid_cap = msm_v4l2_enum_fmt_cap,
690
691 .vidioc_try_fmt_vid_cap = msm_v4l2_try_fmt_cap,
692 .vidioc_try_fmt_type_private = mm_v4l2_try_fmt_type_private,
693
694 .vidioc_g_fmt_vid_cap = msm_v4l2_g_fmt_cap,
695 .vidioc_s_fmt_vid_cap = msm_v4l2_s_fmt_cap,
696 .vidioc_g_fmt_vid_overlay = msm_v4l2_g_fmt_overlay,
697 .vidioc_s_fmt_vid_overlay = msm_v4l2_s_fmt_overlay,
698 .vidioc_overlay = msm_v4l2_overlay,
699
700 .vidioc_g_jpegcomp = msm_v4l2_g_jpegcomp,
701 .vidioc_s_jpegcomp = msm_v4l2_s_jpegcomp,
702 };
703
704 static int msm_v4l2_video_dev_init(struct video_device *pvd)
705 {
706 strncpy(pvd->name, MSM_APPS_ID_V4L2, sizeof(pvd->name));
707 pvd->vfl_type = 1;
708 pvd->fops = &msm_v4l2_fops;
709 pvd->release = msm_v4l2_release_dev;
710 pvd->minor = -1;
711 pvd->ioctl_ops = &msm_ioctl_ops;
712 return msm_v4l2_register(g_pmsm_v4l2_dev->drv);
713 }
714
715 static int __init msm_v4l2_init(void)
716 {
717 int rc = -ENOMEM;
718 struct video_device *pvdev = NULL;
719 struct msm_v4l2_device *pmsm_v4l2_dev = NULL;
720 D("%s\n", __func__);
721
722 pvdev = video_device_alloc();
723 if (pvdev == NULL)
724 return rc;
725
726 pmsm_v4l2_dev =
727 kzalloc(sizeof(struct msm_v4l2_device), GFP_KERNEL);
728 if (pmsm_v4l2_dev == NULL) {
729 video_device_release(pvdev);
730 return rc;
731 }
732
733 msm_v4l2_dev_init(pmsm_v4l2_dev);
734
735 g_pmsm_v4l2_dev = pmsm_v4l2_dev;
736 g_pmsm_v4l2_dev->pvdev = pvdev;
737
738 g_pmsm_v4l2_dev->drv =
739 kzalloc(sizeof(struct msm_v4l2_driver), GFP_KERNEL);
740 if (!g_pmsm_v4l2_dev->drv) {
741 video_device_release(pvdev);
742 kfree(pmsm_v4l2_dev);
743 return rc;
744 }
745
746 rc = msm_v4l2_video_dev_init(pvdev);
747 if (rc < 0) {
748 video_device_release(pvdev);
749 kfree(g_pmsm_v4l2_dev->drv);
750 kfree(pmsm_v4l2_dev);
751 return rc;
752 }
753
754 if (video_register_device(pvdev, VFL_TYPE_GRABBER,
755 MSM_V4L2_DEVNUM_YUV)) {
756 D("failed to register device\n");
757 video_device_release(pvdev);
758 kfree(g_pmsm_v4l2_dev);
759 g_pmsm_v4l2_dev = NULL;
760 return -ENOENT;
761 }
762 #ifdef CONFIG_PROC_FS
763 create_proc_read_entry(MSM_V4L2_PROC_NAME,
764 0, NULL, msm_v4l2_read_proc, NULL);
765 #endif
766
767 return 0;
768 }
769
770 static void __exit msm_v4l2_exit(void)
771 {
772 struct video_device *pvdev = g_pmsm_v4l2_dev->pvdev;
773 D("%s\n", __func__);
774 #ifdef CONFIG_PROC_FS
775 remove_proc_entry(MSM_V4L2_PROC_NAME, NULL);
776 #endif
777 video_unregister_device(pvdev);
778 video_device_release(pvdev);
779
780 msm_v4l2_unregister(g_pmsm_v4l2_dev->drv);
781
782 kfree(g_pmsm_v4l2_dev->drv);
783 g_pmsm_v4l2_dev->drv = NULL;
784
785 kfree(g_pmsm_v4l2_dev);
786 g_pmsm_v4l2_dev = NULL;
787 }
788
789 module_init(msm_v4l2_init);
790 module_exit(msm_v4l2_exit);
791
792 MODULE_DESCRIPTION("MSM V4L2 driver");
793 MODULE_LICENSE("GPL v2");
This page took 0.046856 seconds and 4 git commands to generate.