/drivers/media/video/omapgfx/gfx_init.c

https://bitbucket.org/wisechild/galaxy-nexus · C · 297 lines · 204 code · 59 blank · 34 comment · 25 complexity · 8ab0b4298947c0bb8e1054f705452c87 MD5 · raw file

  1. /*
  2. * drivers/media/video/omap/v4gfx.c
  3. *
  4. * Copyright (C) 2010 Texas Instruments.
  5. *
  6. * This file is licensed under the terms of the GNU General Public License
  7. * version 2. This program is licensed "as is" without any warranty of any
  8. * kind, whether express or implied.
  9. *
  10. */
  11. #include <linux/init.h>
  12. #include <linux/module.h>
  13. #include <linux/errno.h>
  14. #include <linux/kernel.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/types.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/version.h>
  19. #include <linux/omap_v4l2_gfx.h> /* private ioctls */
  20. #include <media/v4l2-ioctl.h>
  21. #include "v4gfx.h"
  22. #include "gfx_bc.h"
  23. MODULE_AUTHOR("Texas Instruments.");
  24. MODULE_DESCRIPTION("OMAP V4L2 GFX driver");
  25. MODULE_LICENSE("GPL");
  26. /*
  27. * Device node will be: /dev/video<VOUT_DEVICENODE_SUFFIX>
  28. * See also /sys/devices/virtual/video4linux/<node>/name which will be
  29. * whatever the value of VOUT_NAME is
  30. */
  31. #define VOUT_DEVICENODE_SUFFIX 100
  32. static struct gbl_v4gfx *gbl_dev;
  33. int debug; /* is used outside this compilation unit too */
  34. module_param(debug, int, 0644);
  35. /*
  36. * If bypass is set then buffer streaming operations will be bypassed. This
  37. * enables us to check what the raw performance of stack above the V4L2
  38. * driver is
  39. */
  40. static int bypass;
  41. module_param(bypass, int, 0644);
  42. static int bypass_vidioc_qbuf(
  43. struct file *file, void *fh, struct v4l2_buffer *buf) { return 0; }
  44. static int bypass_vidioc_dqbuf(
  45. struct file *file, void *fh, struct v4l2_buffer *buf) { return 0; }
  46. static int bypass_vidioc_streamon(
  47. struct file *file, void *fh, enum v4l2_buf_type i) { return 0; }
  48. static int bypass_vidioc_streamoff(
  49. struct file *file, void *fh, enum v4l2_buf_type i) { return 0; }
  50. static long bypass_vidioc_default(
  51. struct file *file, void *fh, int cmd, void *arg)
  52. {
  53. struct v4l2_gfx_buf_params *parms = (struct v4l2_gfx_buf_params *)arg;
  54. int rv = 0;
  55. switch (cmd) {
  56. case V4L2_GFX_IOC_CONSUMER:
  57. break;
  58. case V4L2_GFX_IOC_ACQ:
  59. /* In bypass mode default the first buffer */
  60. parms->bufid = 0;
  61. break;
  62. case V4L2_GFX_IOC_REL:
  63. break;
  64. default:
  65. rv = -EINVAL;
  66. }
  67. return rv;
  68. }
  69. /*
  70. * If the module is put in bypass mode the following ioctls
  71. * are effectively nops
  72. */
  73. static void v4gfx_enable_bypass(void)
  74. {
  75. v4gfx_ioctl_ops.vidioc_qbuf = bypass_vidioc_qbuf;
  76. v4gfx_ioctl_ops.vidioc_dqbuf = bypass_vidioc_dqbuf;
  77. v4gfx_ioctl_ops.vidioc_streamon = bypass_vidioc_streamon;
  78. v4gfx_ioctl_ops.vidioc_streamoff = bypass_vidioc_streamoff;
  79. v4gfx_ioctl_ops.vidioc_default = bypass_vidioc_default;
  80. }
  81. static void v4gfx_cleanup_device(struct v4gfx_device *vout)
  82. {
  83. struct video_device *vfd;
  84. if (!vout)
  85. return;
  86. vfd = vout->vfd;
  87. if (vfd) {
  88. if (vfd->minor == -1) {
  89. /*
  90. * The device was never registered, so release the
  91. * video_device struct directly.
  92. */
  93. video_device_release(vfd);
  94. } else {
  95. /*
  96. * The unregister function will release the video_device
  97. * struct as well as unregistering it.
  98. */
  99. video_unregister_device(vfd);
  100. }
  101. }
  102. v4gfx_tiler_buffer_free(vout, vout->buffer_allocated, 0);
  103. kfree(vout);
  104. }
  105. static int driver_remove(struct platform_device *pdev)
  106. {
  107. struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
  108. struct gbl_v4gfx *dev = container_of(v4l2_dev, struct
  109. gbl_v4gfx, v4l2_dev);
  110. int k;
  111. v4l2_device_unregister(v4l2_dev);
  112. for (k = 0; k < pdev->num_resources; k++)
  113. v4gfx_cleanup_device(dev->vouts[k]);
  114. kfree(gbl_dev);
  115. return 0;
  116. }
  117. static int driver_probe(struct platform_device *pdev)
  118. {
  119. printk(KERN_INFO "Probing: " VOUT_NAME);
  120. return 0;
  121. }
  122. static int v4gfx_create_instance(struct v4gfx_device **voutp)
  123. {
  124. int r = 0;
  125. struct v4gfx_device *vout = NULL;
  126. struct video_device *vfd = NULL;
  127. vout = kzalloc(sizeof(struct v4gfx_device), GFP_KERNEL);
  128. if (vout == NULL) {
  129. r = -ENOMEM;
  130. goto end;
  131. }
  132. mutex_init(&vout->lock);
  133. spin_lock_init(&vout->vbq_lock);
  134. /* TODO set this to an invalid value, need to change unit test though */
  135. vout->bpp = RGB565_BPP;
  136. vout->gbl_dev = gbl_dev;
  137. vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
  138. init_timer(&vout->acquire_timer);
  139. vout->acquire_timer.function = v4gfx_acquire_timer;
  140. vout->acquire_timer.data = (unsigned long)vout;
  141. init_waitqueue_head(&vout->sync_done);
  142. init_waitqueue_head(&vout->consumer_wait);
  143. vfd = vout->vfd = video_device_alloc();
  144. if (!vfd)
  145. goto end;
  146. strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
  147. vfd->vfl_type = VFL_TYPE_GRABBER;
  148. vfd->release = video_device_release;
  149. vfd->ioctl_ops = &v4gfx_ioctl_ops;
  150. vfd->fops = &v4gfx_fops;
  151. vfd->minor = -1;
  152. vfd->debug = debug;
  153. r = video_register_device(vfd, VFL_TYPE_GRABBER,
  154. VOUT_DEVICENODE_SUFFIX);
  155. if (r < 0)
  156. goto end;
  157. video_set_drvdata(vfd, vout);
  158. *voutp = vout;
  159. printk(KERN_INFO VOUT_NAME ":video device registered\n");
  160. return 0;
  161. end:
  162. if (vfd)
  163. video_device_release(vfd);
  164. kfree(vout); /* safe with null vout */
  165. return r;
  166. }
  167. static void v4gfx_delete_instance(
  168. struct v4l2_device *v4l2_dev, struct v4gfx_device *vout)
  169. {
  170. v4l2_info(v4l2_dev, "unregistering /dev/video%d\n", vout->vfd->num);
  171. video_unregister_device(vout->vfd);
  172. v4gfx_buffer_array_free(vout, vout->buffer_allocated);
  173. kfree(vout);
  174. return;
  175. }
  176. static struct platform_driver v4gfx_driver = {
  177. .driver = {
  178. .name = VOUT_NAME,
  179. },
  180. .probe = driver_probe,
  181. .remove = driver_remove,
  182. };
  183. static int module_init_v4gfx(void)
  184. {
  185. int rv;
  186. bool v4l2_dev_registered = false;
  187. bool bc_dev_registered = false;
  188. if (bypass) {
  189. printk(KERN_INFO VOUT_NAME ":Enable bypass mode\n");
  190. v4gfx_enable_bypass();
  191. }
  192. rv = platform_driver_register(&v4gfx_driver);
  193. if (rv != 0) {
  194. printk(KERN_ERR VOUT_NAME ":platform_driver_register failed\n");
  195. goto end;
  196. }
  197. gbl_dev = kzalloc(sizeof(struct gbl_v4gfx), GFP_KERNEL);
  198. if (gbl_dev == NULL) {
  199. rv = -ENOMEM;
  200. goto end;
  201. }
  202. snprintf(gbl_dev->v4l2_dev.name, sizeof(gbl_dev->v4l2_dev.name),
  203. "%s-%03d", VOUT_NAME, VOUT_DEVICENODE_SUFFIX);
  204. rv = v4l2_device_register(NULL, &gbl_dev->v4l2_dev);
  205. if (rv != 0) {
  206. printk(KERN_ERR VOUT_NAME ":v4l2_device_register failed\n");
  207. goto end;
  208. }
  209. v4l2_dev_registered = true;
  210. rv = v4gfx_create_instance(&gbl_dev->vouts[0]);
  211. if (rv != 0)
  212. goto end;
  213. rv = bc_init();
  214. if (rv != 0)
  215. goto end;
  216. bc_dev_registered = true;
  217. printk(KERN_INFO VOUT_NAME ":OMAP V4L2 GFX driver loaded ok\n");
  218. return rv;
  219. end:
  220. printk(KERN_INFO VOUT_NAME ":Error %d loading OMAP V4L2 GFX driver\n",
  221. rv);
  222. if (bc_dev_registered)
  223. bc_cleanup();
  224. if (v4l2_dev_registered)
  225. v4l2_device_unregister(&gbl_dev->v4l2_dev);
  226. kfree(gbl_dev); /* gbl_dev can be null */
  227. return rv;
  228. }
  229. static void module_exit_v4gfx(void)
  230. {
  231. bc_cleanup();
  232. v4gfx_delete_instance(&gbl_dev->v4l2_dev, gbl_dev->vouts[0]);
  233. v4l2_device_unregister(&gbl_dev->v4l2_dev);
  234. kfree(gbl_dev);
  235. platform_driver_unregister(&v4gfx_driver);
  236. }
  237. module_init(module_init_v4gfx);
  238. module_exit(module_exit_v4gfx);