blob: 32a353d162e7950ef6f856297359434a2eebca15 [file] [log] [blame]
Steven Toth9b8b0192010-07-31 14:39:44 -03001/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
Steven Toth63a412e2015-03-23 16:08:15 -03004 * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
Steven Toth9b8b0192010-07-31 14:39:44 -03005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "saa7164.h"
23
Steven Toth7615e432010-07-31 14:44:53 -030024#define ENCODER_MAX_BITRATE 6500000
25#define ENCODER_MIN_BITRATE 1000000
26#define ENCODER_DEF_BITRATE 5000000
27
Hans Verkuil031d2292015-08-28 08:48:30 -030028/*
29 * This is a dummy non-zero value for the sizeimage field of v4l2_pix_format.
30 * It is not actually used for anything since this driver does not support
31 * stream I/O, only read(), and because this driver produces an MPEG stream
32 * and not discrete frames. But the V4L2 spec doesn't allow for this value
33 * to be 0, so set it to 0x10000 instead.
34 *
35 * If we ever change this driver to support stream I/O, then this field
36 * will be the size of the streaming buffers.
37 */
38#define SAA7164_SIZEIMAGE (0x10000)
39
Steven Toth7615e432010-07-31 14:44:53 -030040static struct saa7164_tvnorm saa7164_tvnorms[] = {
41 {
42 .name = "NTSC-M",
43 .id = V4L2_STD_NTSC_M,
44 }, {
45 .name = "NTSC-JP",
46 .id = V4L2_STD_NTSC_M_JP,
47 }
48};
49
Steven Toth7615e432010-07-31 14:44:53 -030050/* Take the encoder configuration form the port struct and
51 * flush it to the hardware.
52 */
53static void saa7164_encoder_configure(struct saa7164_port *port)
54{
55 struct saa7164_dev *dev = port->dev;
56 dprintk(DBGLVL_ENC, "%s()\n", __func__);
57
58 port->encoder_params.width = port->width;
59 port->encoder_params.height = port->height;
60 port->encoder_params.is_50hz =
61 (port->encodernorm.id & V4L2_STD_625_50) != 0;
62
63 /* Set up the DIF (enable it) for analog mode by default */
64 saa7164_api_initialize_dif(port);
65
66 /* Configure the correct video standard */
67 saa7164_api_configure_dif(port, port->encodernorm.id);
68
69 /* Ensure the audio decoder is correct configured */
70 saa7164_api_set_audio_std(port);
71}
72
Steven Toth1b0e8e42010-07-31 16:01:00 -030073static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port)
74{
75 struct list_head *c, *n, *p, *q, *l, *v;
76 struct saa7164_dev *dev = port->dev;
77 struct saa7164_buffer *buf;
78 struct saa7164_user_buffer *ubuf;
79
80 /* Remove any allocated buffers */
81 mutex_lock(&port->dmaqueue_lock);
82
83 dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr);
84 list_for_each_safe(c, n, &port->dmaqueue.list) {
85 buf = list_entry(c, struct saa7164_buffer, list);
86 list_del(c);
87 saa7164_buffer_dealloc(buf);
88 }
89
90 dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr);
91 list_for_each_safe(p, q, &port->list_buf_used.list) {
92 ubuf = list_entry(p, struct saa7164_user_buffer, list);
93 list_del(p);
94 saa7164_buffer_dealloc_user(ubuf);
95 }
96
97 dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr);
98 list_for_each_safe(l, v, &port->list_buf_free.list) {
99 ubuf = list_entry(l, struct saa7164_user_buffer, list);
100 list_del(l);
101 saa7164_buffer_dealloc_user(ubuf);
102 }
103
104 mutex_unlock(&port->dmaqueue_lock);
105 dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
106
107 return 0;
108}
109
110/* Dynamic buffer switch at encoder start time */
111static int saa7164_encoder_buffers_alloc(struct saa7164_port *port)
Steven Toth7615e432010-07-31 14:44:53 -0300112{
113 struct saa7164_dev *dev = port->dev;
Steven Toth1b0e8e42010-07-31 16:01:00 -0300114 struct saa7164_buffer *buf;
115 struct saa7164_user_buffer *ubuf;
Mauro Carvalho Chehab4d270cf2010-10-11 17:17:45 -0300116 struct tmHWStreamParameters *params = &port->hw_streamingparams;
Steven Toth1b0e8e42010-07-31 16:01:00 -0300117 int result = -ENODEV, i;
118 int len = 0;
Steven Toth7615e432010-07-31 14:44:53 -0300119
120 dprintk(DBGLVL_ENC, "%s()\n", __func__);
121
Steven Tothbc250682010-11-12 18:32:36 -0300122 if (port->encoder_params.stream_type ==
123 V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
124 dprintk(DBGLVL_ENC,
125 "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n",
126 __func__);
Steven Toth1b0e8e42010-07-31 16:01:00 -0300127 params->samplesperline = 128;
128 params->numberoflines = 256;
129 params->pitch = 128;
130 params->numpagetables = 2 +
131 ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE);
132 } else
Steven Tothbc250682010-11-12 18:32:36 -0300133 if (port->encoder_params.stream_type ==
134 V4L2_MPEG_STREAM_TYPE_MPEG2_TS) {
135 dprintk(DBGLVL_ENC,
136 "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n",
137 __func__);
Steven Toth1b0e8e42010-07-31 16:01:00 -0300138 params->samplesperline = 188;
139 params->numberoflines = 312;
140 params->pitch = 188;
141 params->numpagetables = 2 +
142 ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
143 } else
144 BUG();
Steven Toth7615e432010-07-31 14:44:53 -0300145
Steven Toth1b0e8e42010-07-31 16:01:00 -0300146 /* Init and establish defaults */
147 params->bitspersample = 8;
148 params->linethreshold = 0;
Peter Huewe61ca15002011-01-30 16:33:01 -0300149 params->pagetablelistvirt = NULL;
150 params->pagetablelistphys = NULL;
Steven Toth1b0e8e42010-07-31 16:01:00 -0300151 params->numpagetableentries = port->hwcfg.buffercount;
152
153 /* Allocate the PCI resources, buffers (hard) */
154 for (i = 0; i < port->hwcfg.buffercount; i++) {
155 buf = saa7164_buffer_alloc(port,
156 params->numberoflines *
157 params->pitch);
158
159 if (!buf) {
160 printk(KERN_ERR "%s() failed "
161 "(errno = %d), unable to allocate buffer\n",
162 __func__, result);
163 result = -ENOMEM;
164 goto failed;
165 } else {
166
167 mutex_lock(&port->dmaqueue_lock);
168 list_add_tail(&buf->list, &port->dmaqueue.list);
169 mutex_unlock(&port->dmaqueue_lock);
170
171 }
172 }
173
Justin P. Mattock70f23fd2011-05-10 10:16:21 +0200174 /* Allocate some kernel buffers for copying
Steven Toth1b0e8e42010-07-31 16:01:00 -0300175 * to userpsace.
176 */
177 len = params->numberoflines * params->pitch;
178
179 if (encoder_buffers < 16)
180 encoder_buffers = 16;
181 if (encoder_buffers > 512)
182 encoder_buffers = 512;
183
184 for (i = 0; i < encoder_buffers; i++) {
185
186 ubuf = saa7164_buffer_alloc_user(dev, len);
187 if (ubuf) {
188 mutex_lock(&port->dmaqueue_lock);
189 list_add_tail(&ubuf->list, &port->list_buf_free.list);
190 mutex_unlock(&port->dmaqueue_lock);
191 }
192
193 }
194
195 result = 0;
196
197failed:
198 return result;
199}
200
201static int saa7164_encoder_initialize(struct saa7164_port *port)
202{
203 saa7164_encoder_configure(port);
Steven Toth7615e432010-07-31 14:44:53 -0300204 return 0;
205}
206
207/* -- V4L2 --------------------------------------------------------- */
Hans Verkuil225b7832015-08-28 08:48:33 -0300208int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id)
Steven Toth7615e432010-07-31 14:44:53 -0300209{
Steven Toth7615e432010-07-31 14:44:53 -0300210 struct saa7164_dev *dev = port->dev;
211 unsigned int i;
212
Hans Verkuil314527acb2013-03-15 06:10:40 -0300213 dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)id);
Steven Toth7615e432010-07-31 14:44:53 -0300214
215 for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
Hans Verkuil314527acb2013-03-15 06:10:40 -0300216 if (id & saa7164_tvnorms[i].id)
Steven Toth7615e432010-07-31 14:44:53 -0300217 break;
218 }
219 if (i == ARRAY_SIZE(saa7164_tvnorms))
220 return -EINVAL;
221
222 port->encodernorm = saa7164_tvnorms[i];
Hans Verkuil8d2d41e2013-06-03 05:36:45 -0300223 port->std = id;
Steven Toth7615e432010-07-31 14:44:53 -0300224
225 /* Update the audio decoder while is not running in
226 * auto detect mode.
227 */
228 saa7164_api_set_audio_std(port);
229
Hans Verkuil314527acb2013-03-15 06:10:40 -0300230 dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)id);
Steven Toth7615e432010-07-31 14:44:53 -0300231
232 return 0;
233}
234
Hans Verkuil225b7832015-08-28 08:48:33 -0300235static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
Hans Verkuil8d2d41e2013-06-03 05:36:45 -0300236{
237 struct saa7164_encoder_fh *fh = file->private_data;
Hans Verkuil8d2d41e2013-06-03 05:36:45 -0300238
Hans Verkuil225b7832015-08-28 08:48:33 -0300239 return saa7164_s_std(fh->port, id);
240}
241
242int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id)
243{
Hans Verkuil8d2d41e2013-06-03 05:36:45 -0300244 *id = port->std;
245 return 0;
246}
247
Hans Verkuil225b7832015-08-28 08:48:33 -0300248static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
249{
250 struct saa7164_encoder_fh *fh = file->private_data;
251
252 return saa7164_g_std(fh->port, id);
253}
254
255int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i)
Steven Toth7615e432010-07-31 14:44:53 -0300256{
Hans Verkuil6b996122015-08-28 08:48:32 -0300257 static const char * const inputs[] = {
258 "tuner", "composite", "svideo", "aux",
259 "composite 2", "svideo 2", "aux 2"
260 };
Steven Toth7615e432010-07-31 14:44:53 -0300261 int n;
262
Steven Toth7615e432010-07-31 14:44:53 -0300263 if (i->index >= 7)
264 return -EINVAL;
265
Mauro Carvalho Chehabc7e242ba2010-10-11 17:39:06 -0300266 strcpy(i->name, inputs[i->index]);
Steven Toth7615e432010-07-31 14:44:53 -0300267
268 if (i->index == 0)
269 i->type = V4L2_INPUT_TYPE_TUNER;
270 else
271 i->type = V4L2_INPUT_TYPE_CAMERA;
272
273 for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
274 i->std |= saa7164_tvnorms[n].id;
275
276 return 0;
277}
278
Hans Verkuil225b7832015-08-28 08:48:33 -0300279int saa7164_g_input(struct saa7164_port *port, unsigned int *i)
Steven Toth7615e432010-07-31 14:44:53 -0300280{
Steven Toth7615e432010-07-31 14:44:53 -0300281 struct saa7164_dev *dev = port->dev;
282
283 if (saa7164_api_get_videomux(port) != SAA_OK)
284 return -EIO;
285
286 *i = (port->mux_input - 1);
287
288 dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, *i);
289
290 return 0;
291}
292
Hans Verkuil225b7832015-08-28 08:48:33 -0300293static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Steven Toth7615e432010-07-31 14:44:53 -0300294{
Steven Toth96d84202010-07-31 16:04:59 -0300295 struct saa7164_encoder_fh *fh = file->private_data;
Hans Verkuil225b7832015-08-28 08:48:33 -0300296
297 return saa7164_g_input(fh->port, i);
298}
299
300int saa7164_s_input(struct saa7164_port *port, unsigned int i)
301{
Steven Toth7615e432010-07-31 14:44:53 -0300302 struct saa7164_dev *dev = port->dev;
303
304 dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
305
306 if (i >= 7)
307 return -EINVAL;
308
309 port->mux_input = i + 1;
310
311 if (saa7164_api_set_videomux(port) != SAA_OK)
312 return -EIO;
313
314 return 0;
315}
316
Hans Verkuil225b7832015-08-28 08:48:33 -0300317static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
318{
319 struct saa7164_encoder_fh *fh = file->private_data;
320
321 return saa7164_s_input(fh->port, i);
322}
323
324int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
Steven Toth7615e432010-07-31 14:44:53 -0300325{
Steven Toth96d84202010-07-31 16:04:59 -0300326 struct saa7164_encoder_fh *fh = file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300327 struct saa7164_port *port = fh->port;
328 struct saa7164_dev *dev = port->dev;
329
330 if (0 != t->index)
331 return -EINVAL;
332
333 strcpy(t->name, "tuner");
Steven Toth7615e432010-07-31 14:44:53 -0300334 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
Hans Verkuil6b996122015-08-28 08:48:32 -0300335 t->rangelow = SAA7164_TV_MIN_FREQ;
336 t->rangehigh = SAA7164_TV_MAX_FREQ;
Steven Toth7615e432010-07-31 14:44:53 -0300337
338 dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
339
340 return 0;
341}
342
Hans Verkuil225b7832015-08-28 08:48:33 -0300343int saa7164_s_tuner(struct file *file, void *priv,
344 const struct v4l2_tuner *t)
Steven Toth7615e432010-07-31 14:44:53 -0300345{
Hans Verkuil6b996122015-08-28 08:48:32 -0300346 if (0 != t->index)
347 return -EINVAL;
348
Steven Toth7615e432010-07-31 14:44:53 -0300349 /* Update the A/V core */
Steven Toth7615e432010-07-31 14:44:53 -0300350 return 0;
351}
352
Hans Verkuil225b7832015-08-28 08:48:33 -0300353int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f)
Steven Toth7615e432010-07-31 14:44:53 -0300354{
Hans Verkuil6b996122015-08-28 08:48:32 -0300355 if (f->tuner)
356 return -EINVAL;
357
Steven Toth7615e432010-07-31 14:44:53 -0300358 f->frequency = port->freq;
Steven Toth7615e432010-07-31 14:44:53 -0300359 return 0;
360}
361
Hans Verkuil225b7832015-08-28 08:48:33 -0300362static int vidioc_g_frequency(struct file *file, void *priv,
363 struct v4l2_frequency *f)
Steven Toth7615e432010-07-31 14:44:53 -0300364{
Steven Toth96d84202010-07-31 16:04:59 -0300365 struct saa7164_encoder_fh *fh = file->private_data;
Hans Verkuil225b7832015-08-28 08:48:33 -0300366
367 return saa7164_g_frequency(fh->port, f);
368}
369
370int saa7164_s_frequency(struct saa7164_port *port,
371 const struct v4l2_frequency *f)
372{
Steven Toth7615e432010-07-31 14:44:53 -0300373 struct saa7164_dev *dev = port->dev;
374 struct saa7164_port *tsport;
375 struct dvb_frontend *fe;
376
377 /* TODO: Pull this for the std */
378 struct analog_parameters params = {
379 .mode = V4L2_TUNER_ANALOG_TV,
380 .audmode = V4L2_TUNER_MODE_STEREO,
381 .std = port->encodernorm.id,
382 .frequency = f->frequency
383 };
384
385 /* Stop the encoder */
386 dprintk(DBGLVL_ENC, "%s() frequency=%d tuner=%d\n", __func__,
387 f->frequency, f->tuner);
388
389 if (f->tuner != 0)
390 return -EINVAL;
391
Hans Verkuil6b996122015-08-28 08:48:32 -0300392 port->freq = clamp(f->frequency,
393 SAA7164_TV_MIN_FREQ, SAA7164_TV_MAX_FREQ);
Steven Toth7615e432010-07-31 14:44:53 -0300394
395 /* Update the hardware */
396 if (port->nr == SAA7164_PORT_ENC1)
Mauro Carvalho Chehabc7e242ba2010-10-11 17:39:06 -0300397 tsport = &dev->ports[SAA7164_PORT_TS1];
Hans Verkuil225b7832015-08-28 08:48:33 -0300398 else if (port->nr == SAA7164_PORT_ENC2)
Mauro Carvalho Chehabc7e242ba2010-10-11 17:39:06 -0300399 tsport = &dev->ports[SAA7164_PORT_TS2];
Steven Toth7615e432010-07-31 14:44:53 -0300400 else
401 BUG();
402
403 fe = tsport->dvb.frontend;
404
405 if (fe && fe->ops.tuner_ops.set_analog_params)
406 fe->ops.tuner_ops.set_analog_params(fe, &params);
407 else
408 printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
409
410 saa7164_encoder_initialize(port);
411
412 return 0;
413}
414
Hans Verkuil225b7832015-08-28 08:48:33 -0300415static int vidioc_s_frequency(struct file *file, void *priv,
416 const struct v4l2_frequency *f)
417{
418 struct saa7164_encoder_fh *fh = file->private_data;
419
420 return saa7164_s_frequency(fh->port, f);
421}
422
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300423static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl)
Steven Toth7615e432010-07-31 14:44:53 -0300424{
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300425 struct saa7164_port *port =
426 container_of(ctrl->handler, struct saa7164_port, ctrl_handler);
Steven Toth7615e432010-07-31 14:44:53 -0300427 struct saa7164_encoder_params *params = &port->encoder_params;
428 int ret = 0;
429
430 switch (ctrl->id) {
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300431 case V4L2_CID_BRIGHTNESS:
432 port->ctl_brightness = ctrl->val;
433 saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
434 break;
435 case V4L2_CID_CONTRAST:
436 port->ctl_contrast = ctrl->val;
437 saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
438 break;
439 case V4L2_CID_SATURATION:
440 port->ctl_saturation = ctrl->val;
441 saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
442 break;
443 case V4L2_CID_HUE:
444 port->ctl_hue = ctrl->val;
445 saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
446 break;
447 case V4L2_CID_SHARPNESS:
448 port->ctl_sharpness = ctrl->val;
449 saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
450 break;
451 case V4L2_CID_AUDIO_VOLUME:
452 port->ctl_volume = ctrl->val;
453 saa7164_api_set_audio_volume(port, port->ctl_volume);
454 break;
Steven Toth7615e432010-07-31 14:44:53 -0300455 case V4L2_CID_MPEG_VIDEO_BITRATE:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300456 params->bitrate = ctrl->val;
Steven Toth7615e432010-07-31 14:44:53 -0300457 break;
458 case V4L2_CID_MPEG_STREAM_TYPE:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300459 params->stream_type = ctrl->val;
Steven Toth7615e432010-07-31 14:44:53 -0300460 break;
461 case V4L2_CID_MPEG_AUDIO_MUTE:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300462 params->ctl_mute = ctrl->val;
Steven Toth7615e432010-07-31 14:44:53 -0300463 ret = saa7164_api_audio_mute(port, params->ctl_mute);
464 if (ret != SAA_OK) {
465 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
466 ret);
467 ret = -EIO;
468 }
469 break;
470 case V4L2_CID_MPEG_VIDEO_ASPECT:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300471 params->ctl_aspect = ctrl->val;
Steven Toth7615e432010-07-31 14:44:53 -0300472 ret = saa7164_api_set_aspect_ratio(port);
473 if (ret != SAA_OK) {
474 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
475 ret);
476 ret = -EIO;
477 }
478 break;
Steven Toth2600d712010-07-31 14:51:30 -0300479 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300480 params->bitrate_mode = ctrl->val;
Steven Toth2600d712010-07-31 14:51:30 -0300481 break;
Steven Toth3ed43cf2010-07-31 14:58:35 -0300482 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300483 params->refdist = ctrl->val;
Steven Toth3ed43cf2010-07-31 14:58:35 -0300484 break;
Steven Toth968b11b2010-07-31 14:59:38 -0300485 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300486 params->bitrate_peak = ctrl->val;
Steven Toth968b11b2010-07-31 14:59:38 -0300487 break;
Steven Toth5fa56cc2010-07-31 15:05:35 -0300488 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300489 params->gop_size = ctrl->val;
Steven Toth5fa56cc2010-07-31 15:05:35 -0300490 break;
Steven Toth7615e432010-07-31 14:44:53 -0300491 default:
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300492 ret = -EINVAL;
Steven Toth7615e432010-07-31 14:44:53 -0300493 }
494
Steven Toth7615e432010-07-31 14:44:53 -0300495 return ret;
496}
497
Steven Toth7615e432010-07-31 14:44:53 -0300498static int vidioc_querycap(struct file *file, void *priv,
499 struct v4l2_capability *cap)
500{
Steven Toth96d84202010-07-31 16:04:59 -0300501 struct saa7164_encoder_fh *fh = file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300502 struct saa7164_port *port = fh->port;
503 struct saa7164_dev *dev = port->dev;
504
505 strcpy(cap->driver, dev->name);
506 strlcpy(cap->card, saa7164_boards[dev->board].name,
507 sizeof(cap->card));
508 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
509
Hans Verkuil534bc3e2015-03-27 15:17:56 -0300510 cap->device_caps =
Steven Toth7615e432010-07-31 14:44:53 -0300511 V4L2_CAP_VIDEO_CAPTURE |
Hans Verkuil534bc3e2015-03-27 15:17:56 -0300512 V4L2_CAP_READWRITE |
513 V4L2_CAP_TUNER;
Steven Toth7615e432010-07-31 14:44:53 -0300514
Hans Verkuil534bc3e2015-03-27 15:17:56 -0300515 cap->capabilities = cap->device_caps |
516 V4L2_CAP_VBI_CAPTURE |
517 V4L2_CAP_DEVICE_CAPS;
Steven Toth7615e432010-07-31 14:44:53 -0300518
519 return 0;
520}
521
522static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
523 struct v4l2_fmtdesc *f)
524{
525 if (f->index != 0)
526 return -EINVAL;
527
528 strlcpy(f->description, "MPEG", sizeof(f->description));
529 f->pixelformat = V4L2_PIX_FMT_MPEG;
530
531 return 0;
532}
533
Hans Verkuil031d2292015-08-28 08:48:30 -0300534static int vidioc_fmt_vid_cap(struct file *file, void *priv,
Steven Toth7615e432010-07-31 14:44:53 -0300535 struct v4l2_format *f)
536{
Steven Toth96d84202010-07-31 16:04:59 -0300537 struct saa7164_encoder_fh *fh = file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300538 struct saa7164_port *port = fh->port;
Steven Toth7615e432010-07-31 14:44:53 -0300539
540 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
541 f->fmt.pix.bytesperline = 0;
Hans Verkuil031d2292015-08-28 08:48:30 -0300542 f->fmt.pix.sizeimage = SAA7164_SIZEIMAGE;
543 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
544 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
Steven Toth7615e432010-07-31 14:44:53 -0300545 f->fmt.pix.width = port->width;
546 f->fmt.pix.height = port->height;
Steven Toth7615e432010-07-31 14:44:53 -0300547 return 0;
548}
549
Steven Toth7615e432010-07-31 14:44:53 -0300550static int saa7164_encoder_stop_port(struct saa7164_port *port)
551{
552 struct saa7164_dev *dev = port->dev;
553 int ret;
554
555 ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
556 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
557 printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
558 __func__, ret);
559 ret = -EIO;
560 } else {
561 dprintk(DBGLVL_ENC, "%s() Stopped\n", __func__);
562 ret = 0;
563 }
564
565 return ret;
566}
567
568static int saa7164_encoder_acquire_port(struct saa7164_port *port)
569{
570 struct saa7164_dev *dev = port->dev;
571 int ret;
572
573 ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
574 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
575 printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
576 __func__, ret);
577 ret = -EIO;
578 } else {
579 dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
580 ret = 0;
581 }
582
583 return ret;
584}
585
586static int saa7164_encoder_pause_port(struct saa7164_port *port)
587{
588 struct saa7164_dev *dev = port->dev;
589 int ret;
590
591 ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
592 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
593 printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
594 __func__, ret);
595 ret = -EIO;
596 } else {
597 dprintk(DBGLVL_ENC, "%s() Paused\n", __func__);
598 ret = 0;
599 }
600
601 return ret;
602}
603
604/* Firmware is very windows centric, meaning you have to transition
605 * the part through AVStream / KS Windows stages, forwards or backwards.
606 * States are: stopped, acquired (h/w), paused, started.
607 * We have to leave here will all of the soft buffers on the free list,
608 * else the cfg_post() func won't have soft buffers to correctly configure.
609 */
610static int saa7164_encoder_stop_streaming(struct saa7164_port *port)
611{
612 struct saa7164_dev *dev = port->dev;
613 struct saa7164_buffer *buf;
614 struct saa7164_user_buffer *ubuf;
615 struct list_head *c, *n;
616 int ret;
617
618 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
619
620 ret = saa7164_encoder_pause_port(port);
621 ret = saa7164_encoder_acquire_port(port);
622 ret = saa7164_encoder_stop_port(port);
623
624 dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__,
625 port->nr);
626
Steven Toth1b0e8e42010-07-31 16:01:00 -0300627 /* Reset the state of any allocated buffer resources */
Steven Toth7615e432010-07-31 14:44:53 -0300628 mutex_lock(&port->dmaqueue_lock);
629
630 /* Reset the hard and soft buffer state */
631 list_for_each_safe(c, n, &port->dmaqueue.list) {
632 buf = list_entry(c, struct saa7164_buffer, list);
633 buf->flags = SAA7164_BUFFER_FREE;
634 buf->pos = 0;
635 }
636
637 list_for_each_safe(c, n, &port->list_buf_used.list) {
638 ubuf = list_entry(c, struct saa7164_user_buffer, list);
639 ubuf->pos = 0;
640 list_move_tail(&ubuf->list, &port->list_buf_free.list);
641 }
642
643 mutex_unlock(&port->dmaqueue_lock);
Steven Toth1b0e8e42010-07-31 16:01:00 -0300644
645 /* Free any allocated resources */
646 saa7164_encoder_buffers_dealloc(port);
647
Steven Toth7615e432010-07-31 14:44:53 -0300648 dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr);
649
650 return ret;
651}
652
653static int saa7164_encoder_start_streaming(struct saa7164_port *port)
654{
655 struct saa7164_dev *dev = port->dev;
656 int result, ret = 0;
657
658 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
659
Steven Toth1b0e8e42010-07-31 16:01:00 -0300660 port->done_first_interrupt = 0;
661
662 /* allocate all of the PCIe DMA buffer resources on the fly,
663 * allowing switching between TS and PS payloads without
664 * requiring a complete driver reload.
665 */
666 saa7164_encoder_buffers_alloc(port);
667
Steven Toth7615e432010-07-31 14:44:53 -0300668 /* Configure the encoder with any cache values */
669 saa7164_api_set_encoder(port);
Steven Toth12d32032010-07-31 15:13:45 -0300670 saa7164_api_get_encoder(port);
Steven Toth7615e432010-07-31 14:44:53 -0300671
Steven Toth1b0e8e42010-07-31 16:01:00 -0300672 /* Place the empty buffers on the hardware */
Steven Toth7615e432010-07-31 14:44:53 -0300673 saa7164_buffer_cfg_port(port);
674
675 /* Acquire the hardware */
676 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
677 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
678 printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
679 __func__, result);
680
681 /* Stop the hardware, regardless */
682 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
683 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
684 printk(KERN_ERR "%s() acquire/forced stop transition "
685 "failed, res = 0x%x\n", __func__, result);
686 }
687 ret = -EIO;
688 goto out;
689 } else
690 dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
691
692 /* Pause the hardware */
693 result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
694 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
695 printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
696 __func__, result);
697
698 /* Stop the hardware, regardless */
699 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
700 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
701 printk(KERN_ERR "%s() pause/forced stop transition "
702 "failed, res = 0x%x\n", __func__, result);
703 }
704
705 ret = -EIO;
706 goto out;
707 } else
708 dprintk(DBGLVL_ENC, "%s() Paused\n", __func__);
709
710 /* Start the hardware */
711 result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
712 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
713 printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
714 __func__, result);
715
716 /* Stop the hardware, regardless */
717 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
718 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
719 printk(KERN_ERR "%s() run/forced stop transition "
720 "failed, res = 0x%x\n", __func__, result);
721 }
722
723 ret = -EIO;
724 } else
725 dprintk(DBGLVL_ENC, "%s() Running\n", __func__);
726
727out:
728 return ret;
729}
730
731static int fops_open(struct file *file)
732{
Steven Toth214ce3f2010-10-06 21:52:22 -0300733 struct saa7164_dev *dev;
734 struct saa7164_port *port;
Steven Toth96d84202010-07-31 16:04:59 -0300735 struct saa7164_encoder_fh *fh;
Steven Toth214ce3f2010-10-06 21:52:22 -0300736
737 port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
738 if (!port)
739 return -ENODEV;
740
741 dev = port->dev;
Steven Toth7615e432010-07-31 14:44:53 -0300742
743 dprintk(DBGLVL_ENC, "%s()\n", __func__);
744
Steven Toth7615e432010-07-31 14:44:53 -0300745 /* allocate + initialize per filehandle data */
746 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Steven Toth214ce3f2010-10-06 21:52:22 -0300747 if (NULL == fh)
Steven Toth7615e432010-07-31 14:44:53 -0300748 return -ENOMEM;
Steven Toth7615e432010-07-31 14:44:53 -0300749
Steven Toth7615e432010-07-31 14:44:53 -0300750 fh->port = port;
Hans Verkuild6d3fe22015-08-28 08:48:27 -0300751 v4l2_fh_init(&fh->fh, video_devdata(file));
752 v4l2_fh_add(&fh->fh);
753 file->private_data = fh;
Steven Toth7615e432010-07-31 14:44:53 -0300754
Steven Toth7615e432010-07-31 14:44:53 -0300755 return 0;
756}
757
758static int fops_release(struct file *file)
759{
Steven Toth96d84202010-07-31 16:04:59 -0300760 struct saa7164_encoder_fh *fh = file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300761 struct saa7164_port *port = fh->port;
762 struct saa7164_dev *dev = port->dev;
763
764 dprintk(DBGLVL_ENC, "%s()\n", __func__);
765
766 /* Shut device down on last close */
767 if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
768 if (atomic_dec_return(&port->v4l_reader_count) == 0) {
769 /* stop mpeg capture then cancel buffers */
770 saa7164_encoder_stop_streaming(port);
771 }
772 }
773
Hans Verkuild6d3fe22015-08-28 08:48:27 -0300774 v4l2_fh_del(&fh->fh);
775 v4l2_fh_exit(&fh->fh);
Steven Toth7615e432010-07-31 14:44:53 -0300776 kfree(fh);
777
778 return 0;
779}
780
Mauro Carvalho Chehab5faf7db2012-10-27 13:11:11 -0300781static struct
782saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
Steven Toth7615e432010-07-31 14:44:53 -0300783{
Peter Huewe61ca15002011-01-30 16:33:01 -0300784 struct saa7164_user_buffer *ubuf = NULL;
Steven Toth7615e432010-07-31 14:44:53 -0300785 struct saa7164_dev *dev = port->dev;
Steven Toth12d32032010-07-31 15:13:45 -0300786 u32 crc;
Steven Toth7615e432010-07-31 14:44:53 -0300787
788 mutex_lock(&port->dmaqueue_lock);
789 if (!list_empty(&port->list_buf_used.list)) {
Steven Toth1b0e8e42010-07-31 16:01:00 -0300790 ubuf = list_first_entry(&port->list_buf_used.list,
Steven Toth7615e432010-07-31 14:44:53 -0300791 struct saa7164_user_buffer, list);
Steven Toth12d32032010-07-31 15:13:45 -0300792
Steven Toth1b0e8e42010-07-31 16:01:00 -0300793 if (crc_checking) {
794 crc = crc32(0, ubuf->data, ubuf->actual_size);
795 if (crc != ubuf->crc) {
Steven Tothbc250682010-11-12 18:32:36 -0300796 printk(KERN_ERR
797 "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
798 __func__,
Steven Toth1b0e8e42010-07-31 16:01:00 -0300799 ubuf, ubuf->crc, crc);
800 }
Steven Toth12d32032010-07-31 15:13:45 -0300801 }
802
Steven Toth7615e432010-07-31 14:44:53 -0300803 }
804 mutex_unlock(&port->dmaqueue_lock);
805
Steven Toth1b0e8e42010-07-31 16:01:00 -0300806 dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf);
Steven Toth7615e432010-07-31 14:44:53 -0300807
Steven Toth1b0e8e42010-07-31 16:01:00 -0300808 return ubuf;
Steven Toth7615e432010-07-31 14:44:53 -0300809}
810
811static ssize_t fops_read(struct file *file, char __user *buffer,
812 size_t count, loff_t *pos)
813{
Steven Toth96d84202010-07-31 16:04:59 -0300814 struct saa7164_encoder_fh *fh = file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300815 struct saa7164_port *port = fh->port;
816 struct saa7164_user_buffer *ubuf = NULL;
817 struct saa7164_dev *dev = port->dev;
Gavin Hurlbutf20a07d2010-09-29 15:18:20 -0300818 int ret = 0;
Steven Toth7615e432010-07-31 14:44:53 -0300819 int rem, cnt;
820 u8 *p;
821
Steven Toth58acca12010-07-31 15:10:52 -0300822 port->last_read_msecs_diff = port->last_read_msecs;
823 port->last_read_msecs = jiffies_to_msecs(jiffies);
824 port->last_read_msecs_diff = port->last_read_msecs -
825 port->last_read_msecs_diff;
826
827 saa7164_histogram_update(&port->read_interval,
828 port->last_read_msecs_diff);
829
Steven Toth46eeb8d2010-07-31 15:11:59 -0300830 if (*pos) {
831 printk(KERN_ERR "%s() ESPIPE\n", __func__);
Steven Toth7615e432010-07-31 14:44:53 -0300832 return -ESPIPE;
Steven Toth46eeb8d2010-07-31 15:11:59 -0300833 }
Steven Toth7615e432010-07-31 14:44:53 -0300834
835 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
836 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
837
Steven Toth46eeb8d2010-07-31 15:11:59 -0300838 if (saa7164_encoder_initialize(port) < 0) {
839 printk(KERN_ERR "%s() EINVAL\n", __func__);
Steven Toth7615e432010-07-31 14:44:53 -0300840 return -EINVAL;
Steven Toth46eeb8d2010-07-31 15:11:59 -0300841 }
Steven Toth7615e432010-07-31 14:44:53 -0300842
843 saa7164_encoder_start_streaming(port);
844 msleep(200);
845 }
846 }
847
848 /* blocking wait for buffer */
849 if ((file->f_flags & O_NONBLOCK) == 0) {
850 if (wait_event_interruptible(port->wait_read,
851 saa7164_enc_next_buf(port))) {
Steven Toth46eeb8d2010-07-31 15:11:59 -0300852 printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
Steven Toth7615e432010-07-31 14:44:53 -0300853 return -ERESTARTSYS;
854 }
855 }
856
857 /* Pull the first buffer from the used list */
858 ubuf = saa7164_enc_next_buf(port);
859
860 while ((count > 0) && ubuf) {
861
862 /* set remaining bytes to copy */
863 rem = ubuf->actual_size - ubuf->pos;
864 cnt = rem > count ? count : rem;
865
866 p = ubuf->data + ubuf->pos;
867
868 dprintk(DBGLVL_ENC,
869 "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
870 __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
871
872 if (copy_to_user(buffer, p, cnt)) {
873 printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
Steven Toth46eeb8d2010-07-31 15:11:59 -0300874 if (!ret) {
875 printk(KERN_ERR "%s() EFAULT\n", __func__);
Steven Toth7615e432010-07-31 14:44:53 -0300876 ret = -EFAULT;
Steven Toth46eeb8d2010-07-31 15:11:59 -0300877 }
Steven Toth7615e432010-07-31 14:44:53 -0300878 goto err;
879 }
880
881 ubuf->pos += cnt;
882 count -= cnt;
883 buffer += cnt;
884 ret += cnt;
885
Steven Tothbc250682010-11-12 18:32:36 -0300886 if (ubuf->pos > ubuf->actual_size)
Steven Toth46eeb8d2010-07-31 15:11:59 -0300887 printk(KERN_ERR "read() pos > actual, huh?\n");
Steven Toth46eeb8d2010-07-31 15:11:59 -0300888
Steven Toth7615e432010-07-31 14:44:53 -0300889 if (ubuf->pos == ubuf->actual_size) {
890
891 /* finished with current buffer, take next buffer */
892
893 /* Requeue the buffer on the free list */
894 ubuf->pos = 0;
895
896 mutex_lock(&port->dmaqueue_lock);
897 list_move_tail(&ubuf->list, &port->list_buf_free.list);
898 mutex_unlock(&port->dmaqueue_lock);
899
900 /* Dequeue next */
901 if ((file->f_flags & O_NONBLOCK) == 0) {
902 if (wait_event_interruptible(port->wait_read,
903 saa7164_enc_next_buf(port))) {
904 break;
905 }
906 }
907 ubuf = saa7164_enc_next_buf(port);
908 }
909 }
910err:
Steven Tothbc250682010-11-12 18:32:36 -0300911 if (!ret && !ubuf)
Steven Toth7615e432010-07-31 14:44:53 -0300912 ret = -EAGAIN;
913
914 return ret;
915}
916
917static unsigned int fops_poll(struct file *file, poll_table *wait)
918{
Hans Verkuil45053ed2015-08-28 08:48:28 -0300919 unsigned long req_events = poll_requested_events(wait);
Steven Tothbc250682010-11-12 18:32:36 -0300920 struct saa7164_encoder_fh *fh =
921 (struct saa7164_encoder_fh *)file->private_data;
Steven Toth7615e432010-07-31 14:44:53 -0300922 struct saa7164_port *port = fh->port;
Hans Verkuil245b5ae2015-08-28 08:48:29 -0300923 unsigned int mask = v4l2_ctrl_poll(file, wait);
Steven Toth7615e432010-07-31 14:44:53 -0300924
Steven Toth58acca12010-07-31 15:10:52 -0300925 port->last_poll_msecs_diff = port->last_poll_msecs;
926 port->last_poll_msecs = jiffies_to_msecs(jiffies);
927 port->last_poll_msecs_diff = port->last_poll_msecs -
928 port->last_poll_msecs_diff;
929
930 saa7164_histogram_update(&port->poll_interval,
931 port->last_poll_msecs_diff);
932
Hans Verkuil45053ed2015-08-28 08:48:28 -0300933 if (!(req_events & (POLLIN | POLLRDNORM)))
934 return mask;
Steven Toth7615e432010-07-31 14:44:53 -0300935
936 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
937 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
938 if (saa7164_encoder_initialize(port) < 0)
Hans Verkuil245b5ae2015-08-28 08:48:29 -0300939 return mask | POLLERR;
Steven Toth7615e432010-07-31 14:44:53 -0300940 saa7164_encoder_start_streaming(port);
941 msleep(200);
942 }
943 }
944
Steven Toth7615e432010-07-31 14:44:53 -0300945 /* Pull the first buffer from the used list */
Dan Carpenter061d55e2010-11-24 02:36:57 -0300946 if (!list_empty(&port->list_buf_used.list))
Steven Toth7615e432010-07-31 14:44:53 -0300947 mask |= POLLIN | POLLRDNORM;
948
949 return mask;
950}
951
Hans Verkuil1a708ea2015-08-28 08:48:26 -0300952static const struct v4l2_ctrl_ops saa7164_ctrl_ops = {
953 .s_ctrl = saa7164_s_ctrl,
954};
955
Steven Toth7615e432010-07-31 14:44:53 -0300956static const struct v4l2_file_operations mpeg_fops = {
957 .owner = THIS_MODULE,
958 .open = fops_open,
959 .release = fops_release,
960 .read = fops_read,
961 .poll = fops_poll,
962 .unlocked_ioctl = video_ioctl2,
963};
964
Steven Toth7615e432010-07-31 14:44:53 -0300965static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
966 .vidioc_s_std = vidioc_s_std,
Hans Verkuil8d2d41e2013-06-03 05:36:45 -0300967 .vidioc_g_std = vidioc_g_std,
Hans Verkuil225b7832015-08-28 08:48:33 -0300968 .vidioc_enum_input = saa7164_enum_input,
Steven Toth7615e432010-07-31 14:44:53 -0300969 .vidioc_g_input = vidioc_g_input,
970 .vidioc_s_input = vidioc_s_input,
Hans Verkuil225b7832015-08-28 08:48:33 -0300971 .vidioc_g_tuner = saa7164_g_tuner,
972 .vidioc_s_tuner = saa7164_s_tuner,
Steven Toth7615e432010-07-31 14:44:53 -0300973 .vidioc_g_frequency = vidioc_g_frequency,
974 .vidioc_s_frequency = vidioc_s_frequency,
Steven Toth7615e432010-07-31 14:44:53 -0300975 .vidioc_querycap = vidioc_querycap,
976 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
Hans Verkuil031d2292015-08-28 08:48:30 -0300977 .vidioc_g_fmt_vid_cap = vidioc_fmt_vid_cap,
978 .vidioc_try_fmt_vid_cap = vidioc_fmt_vid_cap,
979 .vidioc_s_fmt_vid_cap = vidioc_fmt_vid_cap,
Hans Verkuil245b5ae2015-08-28 08:48:29 -0300980 .vidioc_log_status = v4l2_ctrl_log_status,
981 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
982 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Steven Toth7615e432010-07-31 14:44:53 -0300983};
984
985static struct video_device saa7164_mpeg_template = {
986 .name = "saa7164",
987 .fops = &mpeg_fops,
988 .ioctl_ops = &mpeg_ioctl_ops,
989 .minor = -1,
990 .tvnorms = SAA7164_NORMS,
Steven Toth7615e432010-07-31 14:44:53 -0300991};
992
993static struct video_device *saa7164_encoder_alloc(
994 struct saa7164_port *port,
995 struct pci_dev *pci,
996 struct video_device *template,
997 char *type)
998{
999 struct video_device *vfd;
1000 struct saa7164_dev *dev = port->dev;
1001
1002 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1003
1004 vfd = video_device_alloc();
1005 if (NULL == vfd)
1006 return NULL;
1007
1008 *vfd = *template;
1009 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
1010 type, saa7164_boards[dev->board].name);
1011
Hans Verkuild66de792013-06-12 05:49:50 -03001012 vfd->v4l2_dev = &dev->v4l2_dev;
Steven Toth7615e432010-07-31 14:44:53 -03001013 vfd->release = video_device_release;
1014 return vfd;
1015}
1016
1017int saa7164_encoder_register(struct saa7164_port *port)
1018{
1019 struct saa7164_dev *dev = port->dev;
Hans Verkuil1a708ea2015-08-28 08:48:26 -03001020 struct v4l2_ctrl_handler *hdl = &port->ctrl_handler;
Steven Toth1b0e8e42010-07-31 16:01:00 -03001021 int result = -ENODEV;
Steven Toth7615e432010-07-31 14:44:53 -03001022
1023 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1024
Amitoj Kaur Chawla2aefee02016-05-28 13:43:39 -03001025 BUG_ON(port->type != SAA7164_MPEG_ENCODER);
Steven Toth7615e432010-07-31 14:44:53 -03001026
1027 /* Sanity check that the PCI configuration space is active */
1028 if (port->hwcfg.BARLocation == 0) {
1029 printk(KERN_ERR "%s() failed "
1030 "(errno = %d), NO PCI configuration\n",
1031 __func__, result);
1032 result = -ENOMEM;
1033 goto failed;
1034 }
1035
Steven Toth7615e432010-07-31 14:44:53 -03001036 /* Establish encoder defaults here */
1037 /* Set default TV standard */
1038 port->encodernorm = saa7164_tvnorms[0];
1039 port->width = 720;
1040 port->mux_input = 1; /* Composite */
Steven Toth7615e432010-07-31 14:44:53 -03001041 port->video_format = EU_VIDEO_FORMAT_MPEG_2;
1042 port->audio_format = 0;
1043 port->video_resolution = 0;
Hans Verkuil6b996122015-08-28 08:48:32 -03001044 port->freq = SAA7164_TV_MIN_FREQ;
Hans Verkuil1a708ea2015-08-28 08:48:26 -03001045
1046 v4l2_ctrl_handler_init(hdl, 14);
1047 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1048 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1049 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1050 V4L2_CID_CONTRAST, 0, 255, 1, 66);
1051 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1052 V4L2_CID_SATURATION, 0, 255, 1, 62);
1053 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1054 V4L2_CID_HUE, 0, 255, 1, 128);
1055 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1056 V4L2_CID_SHARPNESS, 0x0, 0x0f, 1, 8);
1057 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1058 V4L2_CID_MPEG_AUDIO_MUTE, 0x0, 0x01, 1, 0);
1059 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1060 V4L2_CID_AUDIO_VOLUME, -83, 24, 1, 20);
1061 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1062 V4L2_CID_MPEG_VIDEO_BITRATE,
1063 ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
1064 100000, ENCODER_DEF_BITRATE);
1065 v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
1066 V4L2_CID_MPEG_STREAM_TYPE,
1067 V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0,
1068 V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
1069 v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
1070 V4L2_CID_MPEG_VIDEO_ASPECT,
1071 V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
1072 V4L2_MPEG_VIDEO_ASPECT_4x3);
1073 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1074 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, 15);
1075 v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
1076 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1077 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
1078 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1079 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1080 V4L2_CID_MPEG_VIDEO_B_FRAMES, 1, 3, 1, 1);
1081 v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
1082 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1083 ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
1084 100000, ENCODER_DEF_BITRATE);
1085 if (hdl->error) {
1086 result = hdl->error;
1087 goto failed;
1088 }
1089
Hans Verkuil8d2d41e2013-06-03 05:36:45 -03001090 port->std = V4L2_STD_NTSC_M;
Steven Toth7615e432010-07-31 14:44:53 -03001091
1092 if (port->encodernorm.id & V4L2_STD_525_60)
1093 port->height = 480;
1094 else
1095 port->height = 576;
1096
1097 /* Allocate and register the video device node */
1098 port->v4l_device = saa7164_encoder_alloc(port,
1099 dev->pci, &saa7164_mpeg_template, "mpeg");
1100
Peter Huewe61ca15002011-01-30 16:33:01 -03001101 if (!port->v4l_device) {
Steven Toth7615e432010-07-31 14:44:53 -03001102 printk(KERN_INFO "%s: can't allocate mpeg device\n",
1103 dev->name);
1104 result = -ENOMEM;
1105 goto failed;
1106 }
1107
Hans Verkuil1a708ea2015-08-28 08:48:26 -03001108 port->v4l_device->ctrl_handler = hdl;
1109 v4l2_ctrl_handler_setup(hdl);
Steven Toth214ce3f2010-10-06 21:52:22 -03001110 video_set_drvdata(port->v4l_device, port);
Steven Toth7615e432010-07-31 14:44:53 -03001111 result = video_register_device(port->v4l_device,
1112 VFL_TYPE_GRABBER, -1);
1113 if (result < 0) {
1114 printk(KERN_INFO "%s: can't register mpeg device\n",
1115 dev->name);
1116 /* TODO: We're going to leak here if we don't dealloc
1117 The buffers above. The unreg function can't deal wit it.
1118 */
1119 goto failed;
1120 }
1121
1122 printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
1123 dev->name, port->v4l_device->num);
1124
1125 /* Configure the hardware defaults */
1126 saa7164_api_set_videomux(port);
1127 saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
1128 saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
1129 saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
1130 saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
1131 saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
1132 saa7164_api_audio_mute(port, 0);
1133 saa7164_api_set_audio_volume(port, 20);
1134 saa7164_api_set_aspect_ratio(port);
1135
1136 /* Disable audio standard detection, it's buggy */
1137 saa7164_api_set_audio_detection(port, 0);
1138
1139 saa7164_api_set_encoder(port);
1140 saa7164_api_get_encoder(port);
1141
1142 result = 0;
1143failed:
1144 return result;
1145}
1146
1147void saa7164_encoder_unregister(struct saa7164_port *port)
1148{
1149 struct saa7164_dev *dev = port->dev;
Steven Toth7615e432010-07-31 14:44:53 -03001150
1151 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
1152
Amitoj Kaur Chawla2aefee02016-05-28 13:43:39 -03001153 BUG_ON(port->type != SAA7164_MPEG_ENCODER);
Steven Toth7615e432010-07-31 14:44:53 -03001154
1155 if (port->v4l_device) {
1156 if (port->v4l_device->minor != -1)
1157 video_unregister_device(port->v4l_device);
1158 else
1159 video_device_release(port->v4l_device);
1160
1161 port->v4l_device = NULL;
1162 }
Hans Verkuil1a708ea2015-08-28 08:48:26 -03001163 v4l2_ctrl_handler_free(&port->ctrl_handler);
Steven Toth7615e432010-07-31 14:44:53 -03001164
Steven Toth7615e432010-07-31 14:44:53 -03001165 dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
1166}
1167