Share Pastebin
Guest
Public paste!

pershoot

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