/kern_2.6.32/drivers/staging/dream/camera/msm_v4l2.c

http://omnia2droid.googlecode.com/ · C · 797 lines · 603 code · 157 blank · 37 comment · 49 complexity · 53043a6fac14b49fa2de1eb6bfe4a063 MD5 · raw file

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