saa7134-empress.c revision ce791139ec7f0e5878221dba8d5773e27bf057d3
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	struct saa7134_fh *fh;
89
90	/* allocate + initialize per filehandle data */
91	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
92	if (NULL == fh)
93		return -ENOMEM;
94
95	v4l2_fh_init(&fh->fh, vdev);
96	file->private_data = fh;
97	fh->is_empress = true;
98	v4l2_fh_add(&fh->fh);
99
100	/* Unmute audio */
101	saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
102		saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
103
104	return 0;
105}
106
107static int ts_release(struct file *file)
108{
109	struct saa7134_dev *dev = video_drvdata(file);
110	struct saa7134_fh *fh = file->private_data;
111
112	if (res_check(fh, RESOURCE_EMPRESS)) {
113		videobuf_stop(&dev->empress_tsq);
114		videobuf_mmap_free(&dev->empress_tsq);
115
116		/* stop the encoder */
117		ts_reset_encoder(dev);
118
119		/* Mute audio */
120		saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
121				saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
122	}
123
124	v4l2_fh_del(&fh->fh);
125	v4l2_fh_exit(&fh->fh);
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 = video_drvdata(file);
133
134	if (res_locked(dev, RESOURCE_EMPRESS))
135		return -EBUSY;
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 = video_drvdata(file);
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 = video_drvdata(file);
157
158	return videobuf_mmap_mapper(&dev->empress_tsq, vma);
159}
160
161static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
162					struct v4l2_fmtdesc *f)
163{
164	if (f->index != 0)
165		return -EINVAL;
166
167	strlcpy(f->description, "MPEG TS", sizeof(f->description));
168	f->pixelformat = V4L2_PIX_FMT_MPEG;
169	f->flags = V4L2_FMT_FLAG_COMPRESSED;
170	return 0;
171}
172
173static int empress_g_fmt_vid_cap(struct file *file, void *priv,
174				struct v4l2_format *f)
175{
176	struct saa7134_dev *dev = video_drvdata(file);
177	struct v4l2_mbus_framefmt mbus_fmt;
178
179	saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
180
181	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
182	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
183	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
184	f->fmt.pix.bytesperline = 0;
185	f->fmt.pix.priv = 0;
186
187	return 0;
188}
189
190static int empress_s_fmt_vid_cap(struct file *file, void *priv,
191				struct v4l2_format *f)
192{
193	struct saa7134_dev *dev = video_drvdata(file);
194	struct v4l2_mbus_framefmt mbus_fmt;
195
196	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
197	saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
198	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
199
200	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
201	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
202	f->fmt.pix.bytesperline = 0;
203	f->fmt.pix.priv = 0;
204
205	return 0;
206}
207
208static int empress_try_fmt_vid_cap(struct file *file, void *priv,
209				struct v4l2_format *f)
210{
211	struct saa7134_dev *dev = video_drvdata(file);
212	struct v4l2_mbus_framefmt mbus_fmt;
213
214	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
215	saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
216	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
217
218	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
219	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
220	f->fmt.pix.bytesperline = 0;
221	f->fmt.pix.priv = 0;
222
223	return 0;
224}
225
226static const struct v4l2_file_operations ts_fops =
227{
228	.owner	  = THIS_MODULE,
229	.open	  = ts_open,
230	.release  = ts_release,
231	.read	  = ts_read,
232	.poll	  = ts_poll,
233	.mmap	  = ts_mmap,
234	.ioctl	  = video_ioctl2,
235};
236
237static const struct v4l2_ioctl_ops ts_ioctl_ops = {
238	.vidioc_querycap		= saa7134_querycap,
239	.vidioc_enum_fmt_vid_cap	= empress_enum_fmt_vid_cap,
240	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
241	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
242	.vidioc_g_fmt_vid_cap		= empress_g_fmt_vid_cap,
243	.vidioc_reqbufs			= saa7134_reqbufs,
244	.vidioc_querybuf		= saa7134_querybuf,
245	.vidioc_qbuf			= saa7134_qbuf,
246	.vidioc_dqbuf			= saa7134_dqbuf,
247	.vidioc_streamon		= saa7134_streamon,
248	.vidioc_streamoff		= saa7134_streamoff,
249	.vidioc_g_frequency		= saa7134_g_frequency,
250	.vidioc_s_frequency		= saa7134_s_frequency,
251	.vidioc_g_tuner			= saa7134_g_tuner,
252	.vidioc_s_tuner			= saa7134_s_tuner,
253	.vidioc_enum_input		= saa7134_enum_input,
254	.vidioc_g_input			= saa7134_g_input,
255	.vidioc_s_input			= saa7134_s_input,
256	.vidioc_s_std			= saa7134_s_std,
257	.vidioc_g_std			= saa7134_g_std,
258};
259
260/* ----------------------------------------------------------- */
261
262static struct video_device saa7134_empress_template = {
263	.name          = "saa7134-empress",
264	.fops          = &ts_fops,
265	.ioctl_ops     = &ts_ioctl_ops,
266
267	.tvnorms			= SAA7134_NORMS,
268};
269
270static void empress_signal_update(struct work_struct *work)
271{
272	struct saa7134_dev* dev =
273		container_of(work, struct saa7134_dev, empress_workqueue);
274
275	if (dev->nosignal) {
276		dprintk("no video signal\n");
277	} else {
278		dprintk("video signal acquired\n");
279	}
280}
281
282static void empress_signal_change(struct saa7134_dev *dev)
283{
284	schedule_work(&dev->empress_workqueue);
285}
286
287static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl)
288{
289	switch (ctrl->id) {
290	case V4L2_CID_BRIGHTNESS:
291	case V4L2_CID_HUE:
292	case V4L2_CID_CONTRAST:
293	case V4L2_CID_SATURATION:
294	case V4L2_CID_AUDIO_MUTE:
295	case V4L2_CID_AUDIO_VOLUME:
296	case V4L2_CID_PRIVATE_INVERT:
297	case V4L2_CID_PRIVATE_AUTOMUTE:
298		return true;
299	default:
300		return false;
301	}
302}
303
304static int empress_init(struct saa7134_dev *dev)
305{
306	struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
307	int err;
308
309	dprintk("%s: %s\n",dev->name,__func__);
310	dev->empress_dev = video_device_alloc();
311	if (NULL == dev->empress_dev)
312		return -ENOMEM;
313	*(dev->empress_dev) = saa7134_empress_template;
314	dev->empress_dev->v4l2_dev  = &dev->v4l2_dev;
315	dev->empress_dev->release = video_device_release;
316	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
317		 "%s empress (%s)", dev->name,
318		 saa7134_boards[dev->board].name);
319	set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
320	v4l2_ctrl_handler_init(hdl, 21);
321	v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
322	if (dev->empress_sd)
323		v4l2_ctrl_add_handler(hdl, dev->empress_sd->ctrl_handler, NULL);
324	if (hdl->error) {
325		video_device_release(dev->empress_dev);
326		return hdl->error;
327	}
328	dev->empress_dev->ctrl_handler = hdl;
329
330	INIT_WORK(&dev->empress_workqueue, empress_signal_update);
331
332	video_set_drvdata(dev->empress_dev, dev);
333	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
334				    empress_nr[dev->nr]);
335	if (err < 0) {
336		printk(KERN_INFO "%s: can't register video device\n",
337		       dev->name);
338		video_device_release(dev->empress_dev);
339		dev->empress_dev = NULL;
340		return err;
341	}
342	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
343	       dev->name, video_device_node_name(dev->empress_dev));
344
345	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
346			    &dev->pci->dev, &dev->slock,
347			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
348			    V4L2_FIELD_ALTERNATE,
349			    sizeof(struct saa7134_buf),
350			    dev, NULL);
351
352	empress_signal_update(&dev->empress_workqueue);
353	return 0;
354}
355
356static int empress_fini(struct saa7134_dev *dev)
357{
358	dprintk("%s: %s\n",dev->name,__func__);
359
360	if (NULL == dev->empress_dev)
361		return 0;
362	flush_work(&dev->empress_workqueue);
363	video_unregister_device(dev->empress_dev);
364	v4l2_ctrl_handler_free(&dev->empress_ctrl_handler);
365	dev->empress_dev = NULL;
366	return 0;
367}
368
369static struct saa7134_mpeg_ops empress_ops = {
370	.type          = SAA7134_MPEG_EMPRESS,
371	.init          = empress_init,
372	.fini          = empress_fini,
373	.signal_change = empress_signal_change,
374};
375
376static int __init empress_register(void)
377{
378	return saa7134_ts_register(&empress_ops);
379}
380
381static void __exit empress_unregister(void)
382{
383	saa7134_ts_unregister(&empress_ops);
384}
385
386module_init(empress_register);
387module_exit(empress_unregister);
388
389/* ----------------------------------------------------------- */
390/*
391 * Local variables:
392 * c-basic-offset: 8
393 * End:
394 */
395