saa7134-empress.c revision b93a18d56057a6f8ccb79c5cd085dd31395331ff
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/delay.h>
25
26#include "saa7134-reg.h"
27#include "saa7134.h"
28
29#include <media/saa6752hs.h>
30#include <media/v4l2-common.h>
31
32/* ------------------------------------------------------------------ */
33
34MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
35MODULE_LICENSE("GPL");
36
37static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
38
39module_param_array(empress_nr, int, NULL, 0444);
40MODULE_PARM_DESC(empress_nr,"ts device number");
41
42static unsigned int debug;
43module_param(debug, int, 0644);
44MODULE_PARM_DESC(debug,"enable debug messages");
45
46#define dprintk(fmt, arg...)	if (debug)			\
47	printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
48
49/* ------------------------------------------------------------------ */
50
51static void ts_reset_encoder(struct saa7134_dev* dev)
52{
53	if (!dev->empress_started)
54		return;
55
56	saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
57	msleep(10);
58	saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
59	msleep(100);
60	dev->empress_started = 0;
61}
62
63static int ts_init_encoder(struct saa7134_dev* dev)
64{
65	u32 leading_null_bytes = 0;
66
67	/* If more cards start to need this, then this
68	   should probably be added to the card definitions. */
69	switch (dev->board) {
70	case SAA7134_BOARD_BEHOLD_M6:
71	case SAA7134_BOARD_BEHOLD_M63:
72	case SAA7134_BOARD_BEHOLD_M6_EXTRA:
73		leading_null_bytes = 1;
74		break;
75	}
76	ts_reset_encoder(dev);
77	saa_call_all(dev, core, init, leading_null_bytes);
78	dev->empress_started = 1;
79	return 0;
80}
81
82/* ------------------------------------------------------------------ */
83
84static int ts_open(struct file *file)
85{
86	struct video_device *vdev = video_devdata(file);
87	struct saa7134_dev *dev = video_drvdata(file);
88	int err;
89
90	dprintk("open dev=%s\n", video_device_node_name(vdev));
91	err = -EBUSY;
92	if (!mutex_trylock(&dev->empress_tsq.vb_lock))
93		return err;
94	if (atomic_read(&dev->empress_users))
95		goto done;
96
97	/* Unmute audio */
98	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
99		saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
100
101	atomic_inc(&dev->empress_users);
102	file->private_data = dev;
103	err = 0;
104
105done:
106	mutex_unlock(&dev->empress_tsq.vb_lock);
107	return err;
108}
109
110static int ts_release(struct file *file)
111{
112	struct saa7134_dev *dev = file->private_data;
113
114	videobuf_stop(&dev->empress_tsq);
115	videobuf_mmap_free(&dev->empress_tsq);
116
117	/* stop the encoder */
118	ts_reset_encoder(dev);
119
120	/* Mute audio */
121	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
122		saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
123
124	atomic_dec(&dev->empress_users);
125
126	return 0;
127}
128
129static ssize_t
130ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
131{
132	struct saa7134_dev *dev = file->private_data;
133
134	if (!dev->empress_started)
135		ts_init_encoder(dev);
136
137	return videobuf_read_stream(&dev->empress_tsq,
138				    data, count, ppos, 0,
139				    file->f_flags & O_NONBLOCK);
140}
141
142static unsigned int
143ts_poll(struct file *file, struct poll_table_struct *wait)
144{
145	struct saa7134_dev *dev = file->private_data;
146
147	return videobuf_poll_stream(file, &dev->empress_tsq, wait);
148}
149
150
151static int
152ts_mmap(struct file *file, struct vm_area_struct * vma)
153{
154	struct saa7134_dev *dev = file->private_data;
155
156	return videobuf_mmap_mapper(&dev->empress_tsq, vma);
157}
158
159static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
160					struct v4l2_fmtdesc *f)
161{
162	if (f->index != 0)
163		return -EINVAL;
164
165	strlcpy(f->description, "MPEG TS", sizeof(f->description));
166	f->pixelformat = V4L2_PIX_FMT_MPEG;
167	f->flags = V4L2_FMT_FLAG_COMPRESSED;
168	return 0;
169}
170
171static int empress_g_fmt_vid_cap(struct file *file, void *priv,
172				struct v4l2_format *f)
173{
174	struct saa7134_dev *dev = file->private_data;
175	struct v4l2_mbus_framefmt mbus_fmt;
176
177	saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
178
179	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
180	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
181	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
182	f->fmt.pix.bytesperline = 0;
183	f->fmt.pix.priv = 0;
184
185	return 0;
186}
187
188static int empress_s_fmt_vid_cap(struct file *file, void *priv,
189				struct v4l2_format *f)
190{
191	struct saa7134_dev *dev = file->private_data;
192	struct v4l2_mbus_framefmt mbus_fmt;
193
194	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
195	saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
196	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
197
198	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
199	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
200	f->fmt.pix.bytesperline = 0;
201	f->fmt.pix.priv = 0;
202
203	return 0;
204}
205
206static int empress_try_fmt_vid_cap(struct file *file, void *priv,
207				struct v4l2_format *f)
208{
209	struct saa7134_dev *dev = file->private_data;
210	struct v4l2_mbus_framefmt mbus_fmt;
211
212	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
213	saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
214	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
215
216	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
217	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
218	f->fmt.pix.bytesperline = 0;
219	f->fmt.pix.priv = 0;
220
221	return 0;
222}
223
224static int empress_reqbufs(struct file *file, void *priv,
225					struct v4l2_requestbuffers *p)
226{
227	struct saa7134_dev *dev = file->private_data;
228
229	return videobuf_reqbufs(&dev->empress_tsq, p);
230}
231
232static int empress_querybuf(struct file *file, void *priv,
233					struct v4l2_buffer *b)
234{
235	struct saa7134_dev *dev = file->private_data;
236
237	return videobuf_querybuf(&dev->empress_tsq, b);
238}
239
240static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
241{
242	struct saa7134_dev *dev = file->private_data;
243
244	return videobuf_qbuf(&dev->empress_tsq, b);
245}
246
247static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
248{
249	struct saa7134_dev *dev = file->private_data;
250
251	return videobuf_dqbuf(&dev->empress_tsq, b,
252				file->f_flags & O_NONBLOCK);
253}
254
255static int empress_streamon(struct file *file, void *priv,
256					enum v4l2_buf_type type)
257{
258	struct saa7134_dev *dev = file->private_data;
259
260	return videobuf_streamon(&dev->empress_tsq);
261}
262
263static int empress_streamoff(struct file *file, void *priv,
264					enum v4l2_buf_type type)
265{
266	struct saa7134_dev *dev = file->private_data;
267
268	return videobuf_streamoff(&dev->empress_tsq);
269}
270
271static const struct v4l2_file_operations ts_fops =
272{
273	.owner	  = THIS_MODULE,
274	.open	  = ts_open,
275	.release  = ts_release,
276	.read	  = ts_read,
277	.poll	  = ts_poll,
278	.mmap	  = ts_mmap,
279	.ioctl	  = video_ioctl2,
280};
281
282static const struct v4l2_ioctl_ops ts_ioctl_ops = {
283	.vidioc_querycap		= saa7134_querycap,
284	.vidioc_enum_fmt_vid_cap	= empress_enum_fmt_vid_cap,
285	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
286	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
287	.vidioc_g_fmt_vid_cap		= empress_g_fmt_vid_cap,
288	.vidioc_reqbufs			= empress_reqbufs,
289	.vidioc_querybuf		= empress_querybuf,
290	.vidioc_qbuf			= empress_qbuf,
291	.vidioc_dqbuf			= empress_dqbuf,
292	.vidioc_streamon		= empress_streamon,
293	.vidioc_streamoff		= empress_streamoff,
294	.vidioc_g_frequency		= saa7134_g_frequency,
295	.vidioc_s_frequency		= saa7134_s_frequency,
296	.vidioc_g_tuner			= saa7134_g_tuner,
297	.vidioc_s_tuner			= saa7134_s_tuner,
298	.vidioc_enum_input		= saa7134_enum_input,
299	.vidioc_g_input			= saa7134_g_input,
300	.vidioc_s_input			= saa7134_s_input,
301	.vidioc_s_std			= saa7134_s_std,
302	.vidioc_g_std			= saa7134_g_std,
303};
304
305/* ----------------------------------------------------------- */
306
307static struct video_device saa7134_empress_template = {
308	.name          = "saa7134-empress",
309	.fops          = &ts_fops,
310	.ioctl_ops     = &ts_ioctl_ops,
311
312	.tvnorms			= SAA7134_NORMS,
313};
314
315static void empress_signal_update(struct work_struct *work)
316{
317	struct saa7134_dev* dev =
318		container_of(work, struct saa7134_dev, empress_workqueue);
319
320	if (dev->nosignal) {
321		dprintk("no video signal\n");
322	} else {
323		dprintk("video signal acquired\n");
324	}
325}
326
327static void empress_signal_change(struct saa7134_dev *dev)
328{
329	schedule_work(&dev->empress_workqueue);
330}
331
332static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl)
333{
334	switch (ctrl->id) {
335	case V4L2_CID_BRIGHTNESS:
336	case V4L2_CID_HUE:
337	case V4L2_CID_CONTRAST:
338	case V4L2_CID_SATURATION:
339	case V4L2_CID_AUDIO_MUTE:
340	case V4L2_CID_AUDIO_VOLUME:
341	case V4L2_CID_PRIVATE_INVERT:
342	case V4L2_CID_PRIVATE_AUTOMUTE:
343		return true;
344	default:
345		return false;
346	}
347}
348
349static int empress_init(struct saa7134_dev *dev)
350{
351	struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
352	int err;
353
354	dprintk("%s: %s\n",dev->name,__func__);
355	dev->empress_dev = video_device_alloc();
356	if (NULL == dev->empress_dev)
357		return -ENOMEM;
358	*(dev->empress_dev) = saa7134_empress_template;
359	dev->empress_dev->v4l2_dev  = &dev->v4l2_dev;
360	dev->empress_dev->release = video_device_release;
361	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
362		 "%s empress (%s)", dev->name,
363		 saa7134_boards[dev->board].name);
364	v4l2_ctrl_handler_init(hdl, 21);
365	v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
366	if (dev->empress_sd)
367		v4l2_ctrl_add_handler(hdl, dev->empress_sd->ctrl_handler, NULL);
368	if (hdl->error) {
369		video_device_release(dev->empress_dev);
370		return hdl->error;
371	}
372	dev->empress_dev->ctrl_handler = hdl;
373
374	INIT_WORK(&dev->empress_workqueue, empress_signal_update);
375
376	video_set_drvdata(dev->empress_dev, dev);
377	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
378				    empress_nr[dev->nr]);
379	if (err < 0) {
380		printk(KERN_INFO "%s: can't register video device\n",
381		       dev->name);
382		video_device_release(dev->empress_dev);
383		dev->empress_dev = NULL;
384		return err;
385	}
386	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
387	       dev->name, video_device_node_name(dev->empress_dev));
388
389	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
390			    &dev->pci->dev, &dev->slock,
391			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
392			    V4L2_FIELD_ALTERNATE,
393			    sizeof(struct saa7134_buf),
394			    dev, NULL);
395
396	empress_signal_update(&dev->empress_workqueue);
397	return 0;
398}
399
400static int empress_fini(struct saa7134_dev *dev)
401{
402	dprintk("%s: %s\n",dev->name,__func__);
403
404	if (NULL == dev->empress_dev)
405		return 0;
406	flush_work(&dev->empress_workqueue);
407	video_unregister_device(dev->empress_dev);
408	v4l2_ctrl_handler_free(&dev->empress_ctrl_handler);
409	dev->empress_dev = NULL;
410	return 0;
411}
412
413static struct saa7134_mpeg_ops empress_ops = {
414	.type          = SAA7134_MPEG_EMPRESS,
415	.init          = empress_init,
416	.fini          = empress_fini,
417	.signal_change = empress_signal_change,
418};
419
420static int __init empress_register(void)
421{
422	return saa7134_ts_register(&empress_ops);
423}
424
425static void __exit empress_unregister(void)
426{
427	saa7134_ts_unregister(&empress_ops);
428}
429
430module_init(empress_register);
431module_exit(empress_unregister);
432
433/* ----------------------------------------------------------- */
434/*
435 * Local variables:
436 * c-basic-offset: 8
437 * End:
438 */
439