• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/saa7134/
1/*
2 *
3 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
4 *
5 *  This program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/init.h>
21#include <linux/list.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/smp_lock.h>
25#include <linux/delay.h>
26
27#include "saa7134-reg.h"
28#include "saa7134.h"
29
30#include <media/saa6752hs.h>
31#include <media/v4l2-common.h>
32#include <media/v4l2-chip-ident.h>
33
34/* ------------------------------------------------------------------ */
35
36MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
37MODULE_LICENSE("GPL");
38
39static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
40
41module_param_array(empress_nr, int, NULL, 0444);
42MODULE_PARM_DESC(empress_nr,"ts device number");
43
44static unsigned int debug;
45module_param(debug, int, 0644);
46MODULE_PARM_DESC(debug,"enable debug messages");
47
48#define dprintk(fmt, arg...)	if (debug)			\
49	printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
50
51/* ------------------------------------------------------------------ */
52
53static void ts_reset_encoder(struct saa7134_dev* dev)
54{
55	if (!dev->empress_started)
56		return;
57
58	saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
59	msleep(10);
60	saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
61	msleep(100);
62	dev->empress_started = 0;
63}
64
65static int ts_init_encoder(struct saa7134_dev* dev)
66{
67	u32 leading_null_bytes = 0;
68
69	/* If more cards start to need this, then this
70	   should probably be added to the card definitions. */
71	switch (dev->board) {
72	case SAA7134_BOARD_BEHOLD_M6:
73	case SAA7134_BOARD_BEHOLD_M63:
74	case SAA7134_BOARD_BEHOLD_M6_EXTRA:
75		leading_null_bytes = 1;
76		break;
77	}
78	ts_reset_encoder(dev);
79	saa_call_all(dev, core, init, leading_null_bytes);
80	dev->empress_started = 1;
81	return 0;
82}
83
84/* ------------------------------------------------------------------ */
85
86static int ts_open(struct file *file)
87{
88	struct video_device *vdev = video_devdata(file);
89	struct saa7134_dev *dev = video_drvdata(file);
90	int err;
91
92	dprintk("open dev=%s\n", video_device_node_name(vdev));
93	err = -EBUSY;
94	if (!mutex_trylock(&dev->empress_tsq.vb_lock))
95		return err;
96	if (atomic_read(&dev->empress_users))
97		goto done;
98
99	/* Unmute audio */
100	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
101		saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
102
103	atomic_inc(&dev->empress_users);
104	file->private_data = dev;
105	err = 0;
106
107done:
108	mutex_unlock(&dev->empress_tsq.vb_lock);
109	return err;
110}
111
112static int ts_release(struct file *file)
113{
114	struct saa7134_dev *dev = file->private_data;
115
116	videobuf_stop(&dev->empress_tsq);
117	videobuf_mmap_free(&dev->empress_tsq);
118
119	/* stop the encoder */
120	ts_reset_encoder(dev);
121
122	/* Mute audio */
123	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
124		saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
125
126	atomic_dec(&dev->empress_users);
127
128	return 0;
129}
130
131static ssize_t
132ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
133{
134	struct saa7134_dev *dev = file->private_data;
135
136	if (!dev->empress_started)
137		ts_init_encoder(dev);
138
139	return videobuf_read_stream(&dev->empress_tsq,
140				    data, count, ppos, 0,
141				    file->f_flags & O_NONBLOCK);
142}
143
144static unsigned int
145ts_poll(struct file *file, struct poll_table_struct *wait)
146{
147	struct saa7134_dev *dev = file->private_data;
148
149	return videobuf_poll_stream(file, &dev->empress_tsq, wait);
150}
151
152
153static int
154ts_mmap(struct file *file, struct vm_area_struct * vma)
155{
156	struct saa7134_dev *dev = file->private_data;
157
158	return videobuf_mmap_mapper(&dev->empress_tsq, vma);
159}
160
161/*
162 * This function is _not_ called directly, but from
163 * video_generic_ioctl (and maybe others).  userspace
164 * copying is done already, arg is a kernel pointer.
165 */
166
167static int empress_querycap(struct file *file, void  *priv,
168					struct v4l2_capability *cap)
169{
170	struct saa7134_dev *dev = file->private_data;
171
172	strcpy(cap->driver, "saa7134");
173	strlcpy(cap->card, saa7134_boards[dev->board].name,
174		sizeof(cap->card));
175	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
176	cap->version = SAA7134_VERSION_CODE;
177	cap->capabilities =
178		V4L2_CAP_VIDEO_CAPTURE |
179		V4L2_CAP_READWRITE |
180		V4L2_CAP_STREAMING;
181	return 0;
182}
183
184static int empress_enum_input(struct file *file, void *priv,
185					struct v4l2_input *i)
186{
187	if (i->index != 0)
188		return -EINVAL;
189
190	i->type = V4L2_INPUT_TYPE_CAMERA;
191	strcpy(i->name, "CCIR656");
192
193	return 0;
194}
195
196static int empress_g_input(struct file *file, void *priv, unsigned int *i)
197{
198	*i = 0;
199	return 0;
200}
201
202static int empress_s_input(struct file *file, void *priv, unsigned int i)
203{
204	if (i != 0)
205		return -EINVAL;
206
207	return 0;
208}
209
210static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
211					struct v4l2_fmtdesc *f)
212{
213	if (f->index != 0)
214		return -EINVAL;
215
216	strlcpy(f->description, "MPEG TS", sizeof(f->description));
217	f->pixelformat = V4L2_PIX_FMT_MPEG;
218
219	return 0;
220}
221
222static int empress_g_fmt_vid_cap(struct file *file, void *priv,
223				struct v4l2_format *f)
224{
225	struct saa7134_dev *dev = file->private_data;
226	struct v4l2_mbus_framefmt mbus_fmt;
227
228	saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
229
230	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
231	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
232	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
233
234	return 0;
235}
236
237static int empress_s_fmt_vid_cap(struct file *file, void *priv,
238				struct v4l2_format *f)
239{
240	struct saa7134_dev *dev = file->private_data;
241	struct v4l2_mbus_framefmt mbus_fmt;
242
243	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
244	saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
245	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
246
247	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
248	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
249
250	return 0;
251}
252
253static int empress_try_fmt_vid_cap(struct file *file, void *priv,
254				struct v4l2_format *f)
255{
256	struct saa7134_dev *dev = file->private_data;
257
258	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
259	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
260
261	return 0;
262}
263
264static int empress_reqbufs(struct file *file, void *priv,
265					struct v4l2_requestbuffers *p)
266{
267	struct saa7134_dev *dev = file->private_data;
268
269	return videobuf_reqbufs(&dev->empress_tsq, p);
270}
271
272static int empress_querybuf(struct file *file, void *priv,
273					struct v4l2_buffer *b)
274{
275	struct saa7134_dev *dev = file->private_data;
276
277	return videobuf_querybuf(&dev->empress_tsq, b);
278}
279
280static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
281{
282	struct saa7134_dev *dev = file->private_data;
283
284	return videobuf_qbuf(&dev->empress_tsq, b);
285}
286
287static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
288{
289	struct saa7134_dev *dev = file->private_data;
290
291	return videobuf_dqbuf(&dev->empress_tsq, b,
292				file->f_flags & O_NONBLOCK);
293}
294
295static int empress_streamon(struct file *file, void *priv,
296					enum v4l2_buf_type type)
297{
298	struct saa7134_dev *dev = file->private_data;
299
300	return videobuf_streamon(&dev->empress_tsq);
301}
302
303static int empress_streamoff(struct file *file, void *priv,
304					enum v4l2_buf_type type)
305{
306	struct saa7134_dev *dev = file->private_data;
307
308	return videobuf_streamoff(&dev->empress_tsq);
309}
310
311static int empress_s_ext_ctrls(struct file *file, void *priv,
312			       struct v4l2_ext_controls *ctrls)
313{
314	struct saa7134_dev *dev = file->private_data;
315	int err;
316
317	/* count == 0 is abused in saa6752hs.c, so that special
318		case is handled here explicitly. */
319	if (ctrls->count == 0)
320		return 0;
321
322	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
323		return -EINVAL;
324
325	err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
326	ts_init_encoder(dev);
327
328	return err;
329}
330
331static int empress_g_ext_ctrls(struct file *file, void *priv,
332			       struct v4l2_ext_controls *ctrls)
333{
334	struct saa7134_dev *dev = file->private_data;
335
336	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
337		return -EINVAL;
338	return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
339}
340
341static int empress_g_ctrl(struct file *file, void *priv,
342					struct v4l2_control *c)
343{
344	struct saa7134_dev *dev = file->private_data;
345
346	return saa7134_g_ctrl_internal(dev, NULL, c);
347}
348
349static int empress_s_ctrl(struct file *file, void *priv,
350					struct v4l2_control *c)
351{
352	struct saa7134_dev *dev = file->private_data;
353
354	return saa7134_s_ctrl_internal(dev, NULL, c);
355}
356
357static int empress_queryctrl(struct file *file, void *priv,
358					struct v4l2_queryctrl *c)
359{
360	/* Must be sorted from low to high control ID! */
361	static const u32 user_ctrls[] = {
362		V4L2_CID_USER_CLASS,
363		V4L2_CID_BRIGHTNESS,
364		V4L2_CID_CONTRAST,
365		V4L2_CID_SATURATION,
366		V4L2_CID_HUE,
367		V4L2_CID_AUDIO_VOLUME,
368		V4L2_CID_AUDIO_MUTE,
369		V4L2_CID_HFLIP,
370		0
371	};
372
373	/* Must be sorted from low to high control ID! */
374	static const u32 mpeg_ctrls[] = {
375		V4L2_CID_MPEG_CLASS,
376		V4L2_CID_MPEG_STREAM_TYPE,
377		V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
378		V4L2_CID_MPEG_AUDIO_ENCODING,
379		V4L2_CID_MPEG_AUDIO_L2_BITRATE,
380		V4L2_CID_MPEG_VIDEO_ENCODING,
381		V4L2_CID_MPEG_VIDEO_ASPECT,
382		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
383		V4L2_CID_MPEG_VIDEO_BITRATE,
384		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
385		0
386	};
387	static const u32 *ctrl_classes[] = {
388		user_ctrls,
389		mpeg_ctrls,
390		NULL
391	};
392	struct saa7134_dev *dev = file->private_data;
393
394	c->id = v4l2_ctrl_next(ctrl_classes, c->id);
395	if (c->id == 0)
396		return -EINVAL;
397	if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
398		return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
399	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
400		return saa7134_queryctrl(file, priv, c);
401	return saa_call_empress(dev, core, queryctrl, c);
402}
403
404static int empress_querymenu(struct file *file, void *priv,
405					struct v4l2_querymenu *c)
406{
407	struct saa7134_dev *dev = file->private_data;
408
409	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
410		return -EINVAL;
411	return saa_call_empress(dev, core, querymenu, c);
412}
413
414static int empress_g_chip_ident(struct file *file, void *fh,
415	       struct v4l2_dbg_chip_ident *chip)
416{
417	struct saa7134_dev *dev = file->private_data;
418
419	chip->ident = V4L2_IDENT_NONE;
420	chip->revision = 0;
421	if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
422	    !strcmp(chip->match.name, "saa6752hs"))
423		return saa_call_empress(dev, core, g_chip_ident, chip);
424	if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
425		return saa_call_empress(dev, core, g_chip_ident, chip);
426	return -EINVAL;
427}
428
429static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
430{
431	struct saa7134_dev *dev = file->private_data;
432
433	return saa7134_s_std_internal(dev, NULL, id);
434}
435
436static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
437{
438	struct saa7134_dev *dev = file->private_data;
439
440	*id = dev->tvnorm->id;
441	return 0;
442}
443
444static const struct v4l2_file_operations ts_fops =
445{
446	.owner	  = THIS_MODULE,
447	.open	  = ts_open,
448	.release  = ts_release,
449	.read	  = ts_read,
450	.poll	  = ts_poll,
451	.mmap	  = ts_mmap,
452	.ioctl	  = video_ioctl2,
453};
454
455static const struct v4l2_ioctl_ops ts_ioctl_ops = {
456	.vidioc_querycap		= empress_querycap,
457	.vidioc_enum_fmt_vid_cap	= empress_enum_fmt_vid_cap,
458	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
459	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
460	.vidioc_g_fmt_vid_cap		= empress_g_fmt_vid_cap,
461	.vidioc_reqbufs			= empress_reqbufs,
462	.vidioc_querybuf		= empress_querybuf,
463	.vidioc_qbuf			= empress_qbuf,
464	.vidioc_dqbuf			= empress_dqbuf,
465	.vidioc_streamon		= empress_streamon,
466	.vidioc_streamoff		= empress_streamoff,
467	.vidioc_s_ext_ctrls		= empress_s_ext_ctrls,
468	.vidioc_g_ext_ctrls		= empress_g_ext_ctrls,
469	.vidioc_enum_input		= empress_enum_input,
470	.vidioc_g_input			= empress_g_input,
471	.vidioc_s_input			= empress_s_input,
472	.vidioc_queryctrl		= empress_queryctrl,
473	.vidioc_querymenu		= empress_querymenu,
474	.vidioc_g_ctrl			= empress_g_ctrl,
475	.vidioc_s_ctrl			= empress_s_ctrl,
476	.vidioc_g_chip_ident 		= empress_g_chip_ident,
477	.vidioc_s_std			= empress_s_std,
478	.vidioc_g_std			= empress_g_std,
479};
480
481/* ----------------------------------------------------------- */
482
483static struct video_device saa7134_empress_template = {
484	.name          = "saa7134-empress",
485	.fops          = &ts_fops,
486	.ioctl_ops     = &ts_ioctl_ops,
487
488	.tvnorms			= SAA7134_NORMS,
489	.current_norm			= V4L2_STD_PAL,
490};
491
492static void empress_signal_update(struct work_struct *work)
493{
494	struct saa7134_dev* dev =
495		container_of(work, struct saa7134_dev, empress_workqueue);
496
497	if (dev->nosignal) {
498		dprintk("no video signal\n");
499	} else {
500		dprintk("video signal acquired\n");
501	}
502}
503
504static void empress_signal_change(struct saa7134_dev *dev)
505{
506	schedule_work(&dev->empress_workqueue);
507}
508
509
510static int empress_init(struct saa7134_dev *dev)
511{
512	int err;
513
514	dprintk("%s: %s\n",dev->name,__func__);
515	dev->empress_dev = video_device_alloc();
516	if (NULL == dev->empress_dev)
517		return -ENOMEM;
518	*(dev->empress_dev) = saa7134_empress_template;
519	dev->empress_dev->parent  = &dev->pci->dev;
520	dev->empress_dev->release = video_device_release;
521	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
522		 "%s empress (%s)", dev->name,
523		 saa7134_boards[dev->board].name);
524
525	INIT_WORK(&dev->empress_workqueue, empress_signal_update);
526
527	video_set_drvdata(dev->empress_dev, dev);
528	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
529				    empress_nr[dev->nr]);
530	if (err < 0) {
531		printk(KERN_INFO "%s: can't register video device\n",
532		       dev->name);
533		video_device_release(dev->empress_dev);
534		dev->empress_dev = NULL;
535		return err;
536	}
537	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
538	       dev->name, video_device_node_name(dev->empress_dev));
539
540	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
541			    &dev->pci->dev, &dev->slock,
542			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
543			    V4L2_FIELD_ALTERNATE,
544			    sizeof(struct saa7134_buf),
545			    dev);
546
547	empress_signal_update(&dev->empress_workqueue);
548	return 0;
549}
550
551static int empress_fini(struct saa7134_dev *dev)
552{
553	dprintk("%s: %s\n",dev->name,__func__);
554
555	if (NULL == dev->empress_dev)
556		return 0;
557	flush_scheduled_work();
558	video_unregister_device(dev->empress_dev);
559	dev->empress_dev = NULL;
560	return 0;
561}
562
563static struct saa7134_mpeg_ops empress_ops = {
564	.type          = SAA7134_MPEG_EMPRESS,
565	.init          = empress_init,
566	.fini          = empress_fini,
567	.signal_change = empress_signal_change,
568};
569
570static int __init empress_register(void)
571{
572	return saa7134_ts_register(&empress_ops);
573}
574
575static void __exit empress_unregister(void)
576{
577	saa7134_ts_unregister(&empress_ops);
578}
579
580module_init(empress_register);
581module_exit(empress_unregister);
582
583/* ----------------------------------------------------------- */
584/*
585 * Local variables:
586 * c-basic-offset: 8
587 * End:
588 */
589