PageRenderTime 27ms CodeModel.GetById 10ms app.highlight 14ms RepoModel.GetById 0ms app.codeStats 1ms

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