blob: 8986d967d2f4bb03c0e67dae2458a686e718ad3e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * av7110_v4l.c: av7110 video4linux interface for DVB and Siemens DVB-C analog module
3 *
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
6 *
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
24 *
25 * the project's page is at http://www.linuxtv.org/dvb/
26 */
27
28#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/types.h>
30#include <linux/delay.h>
31#include <linux/fs.h>
32#include <linux/timer.h>
33#include <linux/poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35#include "av7110.h"
36#include "av7110_hw.h"
37#include "av7110_av.h"
38
39int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
40{
41 u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
Tim Kaiser61391e02006-06-25 09:14:07 -030042 struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };
43
44 switch (av7110->adac_type) {
45 case DVB_ADAC_MSP34x0:
46 msgs.addr = 0x40;
47 break;
48 case DVB_ADAC_MSP34x5:
49 msgs.addr = 0x42;
50 break;
51 default:
52 return 0;
53 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55 if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
56 dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070057 av7110->dvb_adapter.num, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 return -EIO;
59 }
60 return 0;
61}
62
Johannes Stezenbachd91b7302005-05-16 21:54:38 -070063static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070064{
65 u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
66 u8 msg2[2];
67 struct i2c_msg msgs[2] = {
Tim Kaiser61391e02006-06-25 09:14:07 -030068 { .flags = 0 , .len = 3, .buf = msg1 },
69 { .flags = I2C_M_RD, .len = 2, .buf = msg2 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 };
71
Tim Kaiser61391e02006-06-25 09:14:07 -030072 switch (av7110->adac_type) {
73 case DVB_ADAC_MSP34x0:
74 msgs[0].addr = 0x40;
75 msgs[1].addr = 0x40;
76 break;
77 case DVB_ADAC_MSP34x5:
78 msgs[0].addr = 0x42;
79 msgs[1].addr = 0x42;
80 break;
81 default:
82 return 0;
83 }
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
86 dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070087 av7110->dvb_adapter.num, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 return -EIO;
89 }
90 *val = (msg2[0] << 8) | msg2[1];
91 return 0;
92}
93
thomas schorppf63f5342005-09-09 13:03:06 -070094static struct v4l2_input inputs[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 {
96 .index = 0,
97 .name = "DVB",
98 .type = V4L2_INPUT_TYPE_CAMERA,
99 .audioset = 1,
100 .tuner = 0, /* ignored */
101 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
102 .status = 0,
103 }, {
104 .index = 1,
105 .name = "Television",
106 .type = V4L2_INPUT_TYPE_TUNER,
107 .audioset = 2,
108 .tuner = 0,
109 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
110 .status = 0,
thomas schorppf63f5342005-09-09 13:03:06 -0700111 }, {
112 .index = 2,
113 .name = "Video",
114 .type = V4L2_INPUT_TYPE_CAMERA,
115 .audioset = 0,
116 .tuner = 0,
117 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
118 .status = 0,
119 }, {
120 .index = 3,
121 .name = "Y/C",
122 .type = V4L2_INPUT_TYPE_CAMERA,
123 .audioset = 0,
124 .tuner = 0,
125 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
126 .status = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 }
128};
129
130static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
131{
Oliver Endriss36c15f82007-07-23 13:59:55 -0300132 struct av7110 *av7110 = dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 u8 buf[] = { 0x00, reg, data };
134 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
135
136 dprintk(4, "dev: %p\n", dev);
137
Oliver Endriss36c15f82007-07-23 13:59:55 -0300138 if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 return -1;
140 return 0;
141}
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
144{
Oliver Endriss36c15f82007-07-23 13:59:55 -0300145 struct av7110 *av7110 = dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
147
148 dprintk(4, "dev: %p\n", dev);
149
Oliver Endriss36c15f82007-07-23 13:59:55 -0300150 if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 return -1;
152 return 0;
153}
154
155static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
156{
157 u32 div;
158 u8 config;
159 u8 buf[4];
160
161 dprintk(4, "freq: 0x%08x\n", freq);
162
163 /* magic number: 614. tuning with the frequency given by v4l2
164 is always off by 614*62.5 = 38375 kHz...*/
165 div = freq + 614;
166
167 buf[0] = (div >> 8) & 0x7f;
168 buf[1] = div & 0xff;
169 buf[2] = 0x8e;
170
171 if (freq < (u32) (16 * 168.25))
172 config = 0xa0;
173 else if (freq < (u32) (16 * 447.25))
174 config = 0x90;
175 else
176 config = 0x30;
177 config &= ~0x02;
178
179 buf[3] = config;
180
181 return tuner_write(dev, 0x61, buf);
182}
183
184static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
185{
Marco Schluessler89e4d592007-02-13 09:31:07 -0300186 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 u32 div;
188 u8 data[4];
189
190 div = (freq + 38900000 + 31250) / 62500;
191
192 data[0] = (div >> 8) & 0x7f;
193 data[1] = div & 0xff;
194 data[2] = 0xce;
195
196 if (freq < 45000000)
197 return -EINVAL;
198 else if (freq < 137000000)
199 data[3] = 0x01;
200 else if (freq < 403000000)
201 data[3] = 0x02;
202 else if (freq < 860000000)
203 data[3] = 0x04;
204 else
205 return -EINVAL;
206
Marco Schluessler89e4d592007-02-13 09:31:07 -0300207 if (av7110->fe->ops.i2c_gate_ctrl)
208 av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 return tuner_write(dev, 0x63, data);
210}
211
212
213
214static struct saa7146_standard analog_standard[];
215static struct saa7146_standard dvb_standard[];
216static struct saa7146_standard standard[];
217
218static struct v4l2_audio msp3400_v4l2_audio = {
219 .index = 0,
220 .name = "Television",
221 .capability = V4L2_AUDCAP_STEREO
222};
223
224static int av7110_dvb_c_switch(struct saa7146_fh *fh)
225{
226 struct saa7146_dev *dev = fh->dev;
227 struct saa7146_vv *vv = dev->vv_data;
228 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
229 u16 adswitch;
230 int source, sync, err;
231
232 dprintk(4, "%p\n", av7110);
233
234 if ((vv->video_status & STATUS_OVERLAY) != 0) {
235 vv->ov_suspend = vv->video_fh;
236 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
237 if (err != 0) {
238 dprintk(2, "suspending video failed\n");
239 vv->ov_suspend = NULL;
240 }
241 }
242
243 if (0 != av7110->current_input) {
thomas schorppf63f5342005-09-09 13:03:06 -0700244 dprintk(1, "switching to analog TV:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 adswitch = 1;
246 source = SAA7146_HPS_SOURCE_PORT_B;
247 sync = SAA7146_HPS_SYNC_PORT_B;
248 memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
thomas schorppf63f5342005-09-09 13:03:06 -0700250 switch (av7110->current_input) {
251 case 1:
252 dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
253 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
254 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
255 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
256 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
257 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
258 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
259
260 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
261 if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
262 dprintk(1, "setting band in demodulator failed.\n");
263 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300264 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
265 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
thomas schorppf63f5342005-09-09 13:03:06 -0700266 }
267 if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
268 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
269 break;
270 case 2:
271 dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
272 if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
273 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
274 break;
275 case 3:
276 dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
277 if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
278 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
279 break;
280 default:
281 dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
283 } else {
284 adswitch = 0;
285 source = SAA7146_HPS_SOURCE_PORT_A;
286 sync = SAA7146_HPS_SYNC_PORT_A;
287 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
288 dprintk(1, "switching DVB mode\n");
289 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
290 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
291 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
292 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
293 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
294 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
295
296 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
297 if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
298 dprintk(1, "setting band in demodulator failed.\n");
299 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300300 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
301 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 }
303 }
304
305 /* hmm, this does not do anything!? */
306 if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
307 dprintk(1, "ADSwitch error\n");
308
309 saa7146_set_hps_source_and_sync(dev, source, sync);
310
311 if (vv->ov_suspend != NULL) {
312 saa7146_start_preview(vv->ov_suspend);
313 vv->ov_suspend = NULL;
314 }
315
316 return 0;
317}
318
Hans Verkuilb9600742009-01-18 19:59:11 -0300319static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
Hans Verkuilb9600742009-01-18 19:59:11 -0300321 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
322 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
323 u16 stereo_det;
324 s8 stereo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Hans Verkuilb9600742009-01-18 19:59:11 -0300326 dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Hans Verkuilb9600742009-01-18 19:59:11 -0300328 if (!av7110->analog_tuner_flags || t->index != 0)
329 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
Hans Verkuilb9600742009-01-18 19:59:11 -0300331 memset(t, 0, sizeof(*t));
332 strcpy((char *)t->name, "Television");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Hans Verkuilb9600742009-01-18 19:59:11 -0300334 t->type = V4L2_TUNER_ANALOG_TV;
335 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
336 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
337 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
338 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
339 /* FIXME: add the real signal strength here */
340 t->signal = 0xffff;
341 t->afc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Hans Verkuilb9600742009-01-18 19:59:11 -0300343 /* FIXME: standard / stereo detection is still broken */
344 msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
345 dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
346 msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
347 dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
348 stereo = (s8)(stereo_det >> 8);
349 if (stereo > 0x10) {
350 /* stereo */
351 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
352 t->audmode = V4L2_TUNER_MODE_STEREO;
353 } else if (stereo < -0x10) {
354 /* bilingual */
355 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
356 t->audmode = V4L2_TUNER_MODE_LANG1;
357 } else /* mono */
358 t->rxsubchans = V4L2_TUNER_SUB_MONO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Hans Verkuilb9600742009-01-18 19:59:11 -0300360 return 0;
361}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
Hans Verkuilb9600742009-01-18 19:59:11 -0300363static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
364{
365 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
366 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
367 u16 fm_matrix, src;
368 dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Hans Verkuilb9600742009-01-18 19:59:11 -0300370 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
371 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Hans Verkuilb9600742009-01-18 19:59:11 -0300373 switch (t->audmode) {
374 case V4L2_TUNER_MODE_STEREO:
375 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
376 fm_matrix = 0x3001; /* stereo */
377 src = 0x0020;
378 break;
379 case V4L2_TUNER_MODE_LANG1_LANG2:
380 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
381 fm_matrix = 0x3000; /* bilingual */
382 src = 0x0020;
383 break;
384 case V4L2_TUNER_MODE_LANG1:
385 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
386 fm_matrix = 0x3000; /* mono */
387 src = 0x0000;
388 break;
389 case V4L2_TUNER_MODE_LANG2:
390 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
391 fm_matrix = 0x3000; /* mono */
392 src = 0x0010;
393 break;
394 default: /* case V4L2_TUNER_MODE_MONO: */
395 dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
396 fm_matrix = 0x3000; /* mono */
397 src = 0x0030;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 break;
399 }
Hans Verkuilb9600742009-01-18 19:59:11 -0300400 msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
401 msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
402 msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
403 msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
404 return 0;
405}
406
407static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
408{
409 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
410 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
411
412 dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
413
414 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
415 return -EINVAL;
416
417 memset(f, 0, sizeof(*f));
418 f->type = V4L2_TUNER_ANALOG_TV;
419 f->frequency = av7110->current_freq;
420 return 0;
421}
422
423static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
424{
425 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
426 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
427
428 dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
429
430 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
431 return -EINVAL;
432
433 if (V4L2_TUNER_ANALOG_TV != f->type)
434 return -EINVAL;
435
436 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); /* fast mute */
437 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
438
439 /* tune in desired frequency */
440 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820)
441 ves1820_set_tv_freq(dev, f->frequency);
442 else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297)
443 stv0297_set_tv_freq(dev, f->frequency);
444 av7110->current_freq = f->frequency;
445
446 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); /* start stereo detection */
447 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
448 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); /* loudspeaker + headphone */
449 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); /* SCART 1 volume */
450 return 0;
451}
452
453static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
454{
455 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
456 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
457
458 dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
459
460 if (av7110->analog_tuner_flags) {
Roel Kluin223ffe52009-05-02 16:38:47 -0300461 if (i->index >= 4)
Hans Verkuilb9600742009-01-18 19:59:11 -0300462 return -EINVAL;
463 } else {
464 if (i->index != 0)
465 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 }
Hans Verkuilb9600742009-01-18 19:59:11 -0300467
468 memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
469
470 return 0;
471}
472
473static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
474{
475 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
476 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
477
478 *input = av7110->current_input;
479 dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
480 return 0;
481}
482
483static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
484{
485 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
486 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
487
488 dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
489
490 if (!av7110->analog_tuner_flags)
491 return 0;
492
Roel Kluinde81c3c2009-07-02 16:09:25 -0300493 if (input >= 4)
Hans Verkuilb9600742009-01-18 19:59:11 -0300494 return -EINVAL;
495
496 av7110->current_input = input;
497 return av7110_dvb_c_switch(fh);
498}
499
500static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
501{
502 dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
503 if (a->index != 0)
504 return -EINVAL;
505 memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
506 return 0;
507}
508
509static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
510{
511 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
512 return 0;
513}
514
515static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
516 struct v4l2_sliced_vbi_cap *cap)
517{
518 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
519 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
520
521 dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
Hans Verkuilf97d2072009-01-19 04:14:17 -0300522 if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
523 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300524 if (FW_VERSION(av7110->arm_app) >= 0x2623) {
525 cap->service_set = V4L2_SLICED_WSS_625;
526 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200527 }
Hans Verkuilb9600742009-01-18 19:59:11 -0300528 return 0;
529}
530
531static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
532 struct v4l2_format *f)
533{
534 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
535 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
536
537 dprintk(2, "VIDIOC_G_FMT:\n");
538 if (FW_VERSION(av7110->arm_app) < 0x2623)
539 return -EINVAL;
540 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
541 if (av7110->wssMode) {
542 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
543 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
544 f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200545 }
Hans Verkuilb9600742009-01-18 19:59:11 -0300546 return 0;
547}
548
549static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
550 struct v4l2_format *f)
551{
552 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
553 struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
554
555 dprintk(2, "VIDIOC_S_FMT\n");
556 if (FW_VERSION(av7110->arm_app) < 0x2623)
557 return -EINVAL;
558 if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
559 f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
560 memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
561 /* WSS controlled by firmware */
562 av7110->wssMode = 0;
563 av7110->wssData = 0;
564 return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
565 SetWSSConfig, 1, 0);
566 } else {
567 memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
568 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
569 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
570 f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
571 /* WSS controlled by userspace */
572 av7110->wssMode = 1;
573 av7110->wssData = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 }
575 return 0;
576}
577
Hans Verkuilbec43662008-12-30 06:58:20 -0300578static int av7110_vbi_reset(struct file *file)
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200579{
580 struct saa7146_fh *fh = file->private_data;
581 struct saa7146_dev *dev = fh->dev;
582 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
583
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300584 dprintk(2, "%s\n", __func__);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200585 av7110->wssMode = 0;
586 av7110->wssData = 0;
587 if (FW_VERSION(av7110->arm_app) < 0x2623)
588 return 0;
589 else
590 return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
591}
592
593static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
594{
595 struct saa7146_fh *fh = file->private_data;
596 struct saa7146_dev *dev = fh->dev;
597 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
598 struct v4l2_sliced_vbi_data d;
599 int rc;
600
Harvey Harrison3ca7fc82008-04-08 23:20:00 -0300601 dprintk(2, "%s\n", __func__);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200602 if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
603 return -EINVAL;
604 if (copy_from_user(&d, data, count))
605 return -EFAULT;
606 if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
607 return -EINVAL;
Oliver Endriss4caba422006-03-17 05:29:15 -0300608 if (d.id)
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200609 av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
Oliver Endriss4caba422006-03-17 05:29:15 -0300610 else
611 av7110->wssData = 0x8000;
612 rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200613 return (rc < 0) ? rc : count;
614}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
616/****************************************************************************
617 * INITIALIZATION
618 ****************************************************************************/
619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620static u8 saa7113_init_regs[] = {
621 0x02, 0xd0,
622 0x03, 0x23,
623 0x04, 0x00,
624 0x05, 0x00,
625 0x06, 0xe9,
626 0x07, 0x0d,
627 0x08, 0x98,
628 0x09, 0x02,
629 0x0a, 0x80,
630 0x0b, 0x40,
631 0x0c, 0x40,
632 0x0d, 0x00,
633 0x0e, 0x01,
634 0x0f, 0x7c,
635 0x10, 0x48,
636 0x11, 0x0c,
637 0x12, 0x8b,
638 0x13, 0x1a,
639 0x14, 0x00,
640 0x15, 0x00,
641 0x16, 0x00,
642 0x17, 0x00,
643 0x18, 0x00,
644 0x19, 0x00,
645 0x1a, 0x00,
646 0x1b, 0x00,
647 0x1c, 0x00,
648 0x1d, 0x00,
649 0x1e, 0x00,
650
651 0x41, 0x77,
652 0x42, 0x77,
653 0x43, 0x77,
654 0x44, 0x77,
655 0x45, 0x77,
656 0x46, 0x77,
657 0x47, 0x77,
658 0x48, 0x77,
659 0x49, 0x77,
660 0x4a, 0x77,
661 0x4b, 0x77,
662 0x4c, 0x77,
663 0x4d, 0x77,
664 0x4e, 0x77,
665 0x4f, 0x77,
666 0x50, 0x77,
667 0x51, 0x77,
668 0x52, 0x77,
669 0x53, 0x77,
670 0x54, 0x77,
671 0x55, 0x77,
672 0x56, 0x77,
673 0x57, 0xff,
674
675 0xff
676};
677
678
679static struct saa7146_ext_vv av7110_vv_data_st;
680static struct saa7146_ext_vv av7110_vv_data_c;
681
682int av7110_init_analog_module(struct av7110 *av7110)
683{
684 u16 version1, version2;
685
Tim Kaiser61391e02006-06-25 09:14:07 -0300686 if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
687 i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
688 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
689 av7110->dvb_adapter.num);
690 av7110->adac_type = DVB_ADAC_MSP34x0;
691 } else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
692 i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
693 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
694 av7110->dvb_adapter.num);
695 av7110->adac_type = DVB_ADAC_MSP34x5;
696 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 return -ENODEV;
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 msleep(100); // the probing above resets the msp...
700 msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
701 msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
Tim Kaiser61391e02006-06-25 09:14:07 -0300702 dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700703 av7110->dvb_adapter.num, version1, version2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
705 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
706 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
707 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
708 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
709 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
710 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
Tim Kaiser61391e02006-06-25 09:14:07 -0300711 msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
714 INFO(("saa7113 not accessible.\n"));
715 } else {
716 u8 *i = saa7113_init_regs;
717
718 if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
719 /* Fujitsu/Siemens DVB-Cable */
720 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
721 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
722 /* Hauppauge/TT DVB-C premium */
723 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
724 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
725 /* Hauppauge/TT DVB-C premium */
726 av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
727 }
728
729 /* setup for DVB by default */
730 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
731 if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
732 dprintk(1, "setting band in demodulator failed.\n");
733 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300734 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
735 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 }
737
738 /* init the saa7113 */
739 while (*i != 0xff) {
740 if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700741 dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 break;
743 }
744 i += 2;
745 }
746 /* setup msp for analog sound: B/G Dual-FM */
747 msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
748 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
749 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
750 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
751 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
752 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
753 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
754 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
755 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
756 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
757 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
758 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
759 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
760 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
761 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
762 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
763 msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
764 msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
765 msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
766 msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
767 msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
768 msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
769 }
770
771 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
772 /* set dd1 stream a & b */
773 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
774 saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
775 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
776
777 return 0;
778}
779
780int av7110_init_v4l(struct av7110 *av7110)
781{
782 struct saa7146_dev* dev = av7110->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300783 struct saa7146_ext_vv *vv_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 int ret;
785
786 /* special case DVB-C: these cards have an analog tuner
787 plus need some special handling, so we have separate
788 saa7146_ext_vv data for these... */
789 if (av7110->analog_tuner_flags)
Hans Verkuilb9600742009-01-18 19:59:11 -0300790 vv_data = &av7110_vv_data_c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 else
Hans Verkuilb9600742009-01-18 19:59:11 -0300792 vv_data = &av7110_vv_data_st;
793 ret = saa7146_vv_init(dev, vv_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 if (ret) {
796 ERR(("cannot init capture device. skipping.\n"));
797 return -ENODEV;
798 }
Hans Verkuilb9600742009-01-18 19:59:11 -0300799 vv_data->ops.vidioc_enum_input = vidioc_enum_input;
800 vv_data->ops.vidioc_g_input = vidioc_g_input;
801 vv_data->ops.vidioc_s_input = vidioc_s_input;
802 vv_data->ops.vidioc_g_tuner = vidioc_g_tuner;
803 vv_data->ops.vidioc_s_tuner = vidioc_s_tuner;
804 vv_data->ops.vidioc_g_frequency = vidioc_g_frequency;
805 vv_data->ops.vidioc_s_frequency = vidioc_s_frequency;
806 vv_data->ops.vidioc_g_audio = vidioc_g_audio;
807 vv_data->ops.vidioc_s_audio = vidioc_s_audio;
808 vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
809 vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
810 vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
813 ERR(("cannot register capture device. skipping.\n"));
814 saa7146_vv_release(dev);
815 return -ENODEV;
816 }
Oliver Endriss78577352007-01-27 21:13:06 -0300817 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200818 ERR(("cannot register vbi v4l2 device. skipping.\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 return 0;
820}
821
822int av7110_exit_v4l(struct av7110 *av7110)
823{
Marco Schluesslere19c55f2007-01-31 14:32:29 -0300824 struct saa7146_dev* dev = av7110->dev;
825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
Oliver Endriss78577352007-01-27 21:13:06 -0300827 saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
Marco Schluesslere19c55f2007-01-31 14:32:29 -0300828
829 saa7146_vv_release(dev);
830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 return 0;
832}
833
834
835
836/* FIXME: these values are experimental values that look better than the
837 values from the latest "official" driver -- at least for me... (MiHu) */
838static struct saa7146_standard standard[] = {
839 {
840 .name = "PAL", .id = V4L2_STD_PAL_BG,
841 .v_offset = 0x15, .v_field = 288,
842 .h_offset = 0x48, .h_pixels = 708,
843 .v_max_out = 576, .h_max_out = 768,
844 }, {
845 .name = "NTSC", .id = V4L2_STD_NTSC,
846 .v_offset = 0x10, .v_field = 244,
847 .h_offset = 0x40, .h_pixels = 708,
848 .v_max_out = 480, .h_max_out = 640,
849 }
850};
851
852static struct saa7146_standard analog_standard[] = {
853 {
854 .name = "PAL", .id = V4L2_STD_PAL_BG,
855 .v_offset = 0x1b, .v_field = 288,
856 .h_offset = 0x08, .h_pixels = 708,
857 .v_max_out = 576, .h_max_out = 768,
858 }, {
859 .name = "NTSC", .id = V4L2_STD_NTSC,
860 .v_offset = 0x10, .v_field = 244,
861 .h_offset = 0x40, .h_pixels = 708,
862 .v_max_out = 480, .h_max_out = 640,
863 }
864};
865
866static struct saa7146_standard dvb_standard[] = {
867 {
868 .name = "PAL", .id = V4L2_STD_PAL_BG,
869 .v_offset = 0x14, .v_field = 288,
870 .h_offset = 0x48, .h_pixels = 708,
871 .v_max_out = 576, .h_max_out = 768,
872 }, {
873 .name = "NTSC", .id = V4L2_STD_NTSC,
874 .v_offset = 0x10, .v_field = 244,
875 .h_offset = 0x40, .h_pixels = 708,
876 .v_max_out = 480, .h_max_out = 640,
877 }
878};
879
880static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
881{
882 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
883
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700884 if (std->id & V4L2_STD_PAL) {
Marco Schluessler58a44042007-10-31 01:20:42 -0300885 av7110->vidmode = AV7110_VIDEO_MODE_PAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 av7110_set_vidmode(av7110, av7110->vidmode);
887 }
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700888 else if (std->id & V4L2_STD_NTSC) {
Marco Schluessler58a44042007-10-31 01:20:42 -0300889 av7110->vidmode = AV7110_VIDEO_MODE_NTSC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 av7110_set_vidmode(av7110, av7110->vidmode);
891 }
892 else
893 return -1;
894
895 return 0;
896}
897
898
899static struct saa7146_ext_vv av7110_vv_data_st = {
900 .inputs = 1,
901 .audios = 1,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200902 .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 .flags = 0,
904
905 .stds = &standard[0],
906 .num_stds = ARRAY_SIZE(standard),
907 .std_callback = &std_callback,
908
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200909 .vbi_fops.open = av7110_vbi_reset,
910 .vbi_fops.release = av7110_vbi_reset,
911 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912};
913
914static struct saa7146_ext_vv av7110_vv_data_c = {
915 .inputs = 1,
916 .audios = 1,
Oliver Endrissd7e7a152006-09-14 00:43:22 -0300917 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 .flags = SAA7146_USE_PORT_B_FOR_VBI,
919
920 .stds = &standard[0],
921 .num_stds = ARRAY_SIZE(standard),
922 .std_callback = &std_callback,
923
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200924 .vbi_fops.open = av7110_vbi_reset,
925 .vbi_fops.release = av7110_vbi_reset,
926 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927};
928