[PATCH] DVB: AV7110 DVB driver updates
[linux-2.6/history.git] / drivers / media / dvb / ttpci / av7110_v4l.c
blobfef348e130f69d8b070e7f96d8281450313658ca
1 /*
2 * av7110_v4l.c: av7110 video4linux interface for DVB and Siemens DVB-C analog module
4 * Copyright (C) 1999-2002 Ralph Metzler
5 * & Marcus Metzler for convergence integrated media GmbH
7 * originally based on code by:
8 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
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.
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.
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
25 * the project's page is at http://www.linuxtv.org/dvb/
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/types.h>
31 #include <linux/delay.h>
32 #include <linux/fs.h>
33 #include <linux/timer.h>
34 #include <linux/poll.h>
35 #include <linux/byteorder/swabb.h>
36 #include <linux/smp_lock.h>
38 #define DEBUG_VARIABLE av7110_debug
39 extern int av7110_debug;
41 #include "dvb_i2c.h"
42 #include "av7110.h"
43 #include "av7110_hw.h"
44 #include "av7110_av.h"
45 #include "dvb_functions.h"
48 int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
50 u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
51 struct dvb_i2c_bus *i2c = av7110->i2c_bus;
52 struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg };
54 if (i2c->xfer(i2c, &msgs, 1) != 1) {
55 printk("av7110(%d): %s(%u = %u) failed\n",
56 av7110->dvb_adapter->num, __FUNCTION__, reg, val);
57 return -EIO;
59 return 0;
62 int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
64 u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
65 u8 msg2[2];
66 struct dvb_i2c_bus *i2c = av7110->i2c_bus;
67 struct i2c_msg msgs[2] = {
68 { .flags = 0, .addr = 0x40, .len = 3, .buf = msg1 },
69 { .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 }
72 if (i2c->xfer(i2c, msgs, 2) != 2) {
73 printk("av7110(%d): %s(%u) failed\n",
74 av7110->dvb_adapter->num, __FUNCTION__, reg);
75 return -EIO;
77 *val = (msg2[0] << 8) | msg2[1];
78 return 0;
83 static struct v4l2_input inputs[2] = {
85 .index = 0,
86 .name = "DVB",
87 .type = V4L2_INPUT_TYPE_CAMERA,
88 .audioset = 1,
89 .tuner = 0, /* ignored */
90 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
91 .status = 0,
92 }, {
93 .index = 1,
94 .name = "Television",
95 .type = V4L2_INPUT_TYPE_TUNER,
96 .audioset = 2,
97 .tuner = 0,
98 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
99 .status = 0,
103 /* for Siemens DVB-C analog module: (taken from ves1820.c) */
104 static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data)
106 u8 addr = 0x09;
107 u8 buf[] = { 0x00, reg, data };
108 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
110 DEB_EE(("av7710: dev: %p\n", dev));
112 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
113 return -1;
114 return 0;
117 static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
119 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
121 DEB_EE(("av7710: dev: %p\n", dev));
123 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
124 return -1;
125 return 0;
130 * set up the downconverter frequency divisor for a
131 * reference clock comparision frequency of 62.5 kHz.
133 static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq)
135 u32 div;
136 u8 config;
137 u8 buf[4];
139 DEB_EE(("av7710: freq: 0x%08x\n", freq));
141 /* magic number: 614. tuning with the frequency given by v4l2
142 is always off by 614*62.5 = 38375 kHz...*/
143 div = freq + 614;
145 buf[0] = (div >> 8) & 0x7f;
146 buf[1] = div & 0xff;
147 buf[2] = 0x8e;
149 if (freq < (u32) (16 * 168.25))
150 config = 0xa0;
151 else if (freq < (u32) (16 * 447.25))
152 config = 0x90;
153 else
154 config = 0x30;
155 config &= ~0x02;
157 buf[3] = config;
159 return tuner_write(dev, 0x61, buf);
163 static struct saa7146_standard analog_standard[];
164 static struct saa7146_standard dvb_standard[];
165 static struct saa7146_standard standard[];
167 static struct v4l2_audio msp3400_v4l2_audio = {
168 .index = 0,
169 .name = "Television",
170 .capability = V4L2_AUDCAP_STEREO
173 int av7110_dvb_c_switch(struct saa7146_fh *fh)
175 struct saa7146_dev *dev = fh->dev;
176 struct saa7146_vv *vv = dev->vv_data;
177 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
178 u16 adswitch;
179 u8 band = 0;
180 int source, sync, err;
182 DEB_EE(("av7110: %p\n", av7110));
184 if ((vv->video_status & STATUS_OVERLAY) != 0) {
185 vv->ov_suspend = vv->video_fh;
186 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
187 if (err != 0) {
188 DEB_D(("warning: suspending video failed\n"));
189 vv->ov_suspend = NULL;
193 if (0 != av7110->current_input) {
194 adswitch = 1;
195 band = 0x60; /* analog band */
196 source = SAA7146_HPS_SOURCE_PORT_B;
197 sync = SAA7146_HPS_SYNC_PORT_B;
198 memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
199 printk("av7110: switching to analog TV\n");
200 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
201 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
202 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
203 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
204 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
205 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
206 } else {
207 adswitch = 0;
208 band = 0x20; /* digital band */
209 source = SAA7146_HPS_SOURCE_PORT_A;
210 sync = SAA7146_HPS_SYNC_PORT_A;
211 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
212 printk("av7110: switching DVB mode\n");
213 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
214 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
215 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
216 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
217 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
218 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
221 /* hmm, this does not do anything!? */
222 if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
223 printk("ADSwitch error\n");
225 if (ves1820_writereg(dev, 0x0f, band))
226 printk("setting band in demodulator failed.\n");
227 saa7146_set_hps_source_and_sync(dev, source, sync);
229 if (vv->ov_suspend != NULL) {
230 saa7146_start_preview(vv->ov_suspend);
231 vv->ov_suspend = NULL;
234 return 0;
237 int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
239 struct saa7146_dev *dev = fh->dev;
240 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
241 DEB_EE(("saa7146_dev: %p\n", dev));
243 switch (cmd) {
244 case VIDIOC_G_TUNER:
246 struct v4l2_tuner *t = arg;
247 u16 stereo_det;
248 s8 stereo;
250 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
252 if (!av7110->has_analog_tuner || t->index != 0)
253 return -EINVAL;
255 memset(t, 0, sizeof(*t));
256 strcpy(t->name, "Television");
258 t->type = V4L2_TUNER_ANALOG_TV;
259 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
260 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
261 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
262 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
263 /* FIXME: add the real signal strength here */
264 t->signal = 0xffff;
265 t->afc = 0;
267 // FIXME: standard / stereo detection is still broken
268 msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
269 printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
271 msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
272 printk("VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
273 stereo = (s8)(stereo_det >> 8);
274 if (stereo > 0x10) {
275 /* stereo */
276 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
277 t->audmode = V4L2_TUNER_MODE_STEREO;
279 else if (stereo < -0x10) {
280 /* bilingual*/
281 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
282 t->audmode = V4L2_TUNER_MODE_LANG1;
284 else /* mono */
285 t->rxsubchans = V4L2_TUNER_SUB_MONO;
287 return 0;
289 case VIDIOC_S_TUNER:
291 struct v4l2_tuner *t = arg;
292 u16 fm_matrix, src;
293 DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index));
295 if (!av7110->has_analog_tuner || av7110->current_input != 1)
296 return -EINVAL;
298 switch (t->audmode) {
299 case V4L2_TUNER_MODE_STEREO:
300 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
301 fm_matrix = 0x3001; // stereo
302 src = 0x0020;
303 break;
304 case V4L2_TUNER_MODE_LANG1:
305 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
306 fm_matrix = 0x3000; // mono
307 src = 0x0000;
308 break;
309 case V4L2_TUNER_MODE_LANG2:
310 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
311 fm_matrix = 0x3000; // mono
312 src = 0x0010;
313 break;
314 default: /* case V4L2_TUNER_MODE_MONO: {*/
315 DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
316 fm_matrix = 0x3000; // mono
317 src = 0x0030;
318 break;
320 msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
321 msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
322 msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
323 msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
324 return 0;
326 case VIDIOC_G_FREQUENCY:
328 struct v4l2_frequency *f = arg;
330 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency));
332 if (!av7110->has_analog_tuner || av7110->current_input != 1)
333 return -EINVAL;
335 memset(f, 0, sizeof(*f));
336 f->type = V4L2_TUNER_ANALOG_TV;
337 f->frequency = av7110->current_freq;
338 return 0;
340 case VIDIOC_S_FREQUENCY:
342 struct v4l2_frequency *f = arg;
344 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency));
346 if (!av7110->has_analog_tuner || av7110->current_input != 1)
347 return -EINVAL;
349 if (V4L2_TUNER_ANALOG_TV != f->type)
350 return -EINVAL;
352 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute
353 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
355 /* tune in desired frequency */
356 tuner_set_tv_freq(dev, f->frequency);
357 av7110->current_freq = f->frequency;
359 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
360 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
361 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
362 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
363 return 0;
365 case VIDIOC_ENUMINPUT:
367 struct v4l2_input *i = arg;
369 DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index));
371 if (av7110->has_analog_tuner ) {
372 if (i->index < 0 || i->index >= 2)
373 return -EINVAL;
374 } else {
375 if (i->index != 0)
376 return -EINVAL;
379 memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
381 return 0;
383 case VIDIOC_G_INPUT:
385 int *input = (int *)arg;
386 *input = av7110->current_input;
387 DEB_EE(("VIDIOC_G_INPUT: %d\n", *input));
388 return 0;
390 case VIDIOC_S_INPUT:
392 int input = *(int *)arg;
394 DEB_EE(("VIDIOC_S_INPUT: %d\n", input));
396 if (!av7110->has_analog_tuner )
397 return 0;
399 if (input < 0 || input >= 2)
400 return -EINVAL;
402 /* FIXME: switch inputs here */
403 av7110->current_input = input;
404 return av7110_dvb_c_switch(fh);
406 case VIDIOC_G_AUDIO:
408 struct v4l2_audio *a = arg;
410 DEB_EE(("VIDIOC_G_AUDIO: %d\n", a->index));
411 if (a->index != 0)
412 return -EINVAL;
413 memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
414 break;
416 case VIDIOC_S_AUDIO:
418 struct v4l2_audio *a = arg;
419 DEB_EE(("VIDIOC_S_AUDIO: %d\n", a->index));
420 break;
422 default:
423 printk("no such ioctl\n");
424 return -ENOIOCTLCMD;
426 return 0;
430 /****************************************************************************
431 * INITIALIZATION
432 ****************************************************************************/
434 struct saa7146_extension_ioctls ioctls[] = {
435 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
436 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
437 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
438 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
439 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
440 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
441 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
442 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
443 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
444 { 0, 0 }
447 static u8 saa7113_init_regs[] = {
448 0x02, 0xd0,
449 0x03, 0x23,
450 0x04, 0x00,
451 0x05, 0x00,
452 0x06, 0xe9,
453 0x07, 0x0d,
454 0x08, 0x98,
455 0x09, 0x02,
456 0x0a, 0x80,
457 0x0b, 0x40,
458 0x0c, 0x40,
459 0x0d, 0x00,
460 0x0e, 0x01,
461 0x0f, 0x7c,
462 0x10, 0x48,
463 0x11, 0x0c,
464 0x12, 0x8b,
465 0x13, 0x1a,
466 0x14, 0x00,
467 0x15, 0x00,
468 0x16, 0x00,
469 0x17, 0x00,
470 0x18, 0x00,
471 0x19, 0x00,
472 0x1a, 0x00,
473 0x1b, 0x00,
474 0x1c, 0x00,
475 0x1d, 0x00,
476 0x1e, 0x00,
478 0x41, 0x77,
479 0x42, 0x77,
480 0x43, 0x77,
481 0x44, 0x77,
482 0x45, 0x77,
483 0x46, 0x77,
484 0x47, 0x77,
485 0x48, 0x77,
486 0x49, 0x77,
487 0x4a, 0x77,
488 0x4b, 0x77,
489 0x4c, 0x77,
490 0x4d, 0x77,
491 0x4e, 0x77,
492 0x4f, 0x77,
493 0x50, 0x77,
494 0x51, 0x77,
495 0x52, 0x77,
496 0x53, 0x77,
497 0x54, 0x77,
498 0x55, 0x77,
499 0x56, 0x77,
500 0x57, 0xff,
502 0xff
506 static struct saa7146_ext_vv av7110_vv_data_st;
507 static struct saa7146_ext_vv av7110_vv_data_c;
509 int av7110_init_analog_module(struct av7110 *av7110)
511 u16 version1, version2;
513 if (i2c_writereg(av7110, 0x80, 0x0, 0x80) != 1
514 || i2c_writereg(av7110, 0x80, 0x0, 0) != 1)
515 return -ENODEV;
517 printk("av7110(%d): DVB-C analog module detected, initializing MSP3400\n",
518 av7110->dvb_adapter->num);
519 av7110->adac_type = DVB_ADAC_MSP;
520 dvb_delay(100); // the probing above resets the msp...
521 msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
522 msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
523 printk("av7110(%d): MSP3400 version 0x%04x 0x%04x\n",
524 av7110->dvb_adapter->num, version1, version2);
525 msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
526 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
527 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
528 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
529 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
530 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
531 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
532 msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x4800); // prescale SCART
534 if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
535 INFO(("saa7113 not accessible.\n"));
536 } else {
537 u8 *i = saa7113_init_regs;
538 av7110->has_analog_tuner = 1;
539 /* init the saa7113 */
540 while (*i != 0xff) {
541 if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
542 printk("av7110(%d): saa7113 initialization failed",
543 av7110->dvb_adapter->num);
544 break;
546 i += 2;
548 /* setup msp for analog sound: B/G Dual-FM */
549 msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
550 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
551 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
552 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
553 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
554 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
555 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
556 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
557 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
558 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
559 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
560 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
561 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
562 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
563 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
564 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
565 msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
566 msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
567 msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
568 msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
569 msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
570 msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
573 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
574 /* set dd1 stream a & b */
575 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
576 saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
577 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
579 return 0;
582 int av7110_init_v4l(struct av7110 *av7110)
584 struct saa7146_dev* dev = av7110->dev;
585 int ret;
587 /* special case DVB-C: these cards have an analog tuner
588 plus need some special handling, so we have separate
589 saa7146_ext_vv data for these... */
590 if (av7110->has_analog_tuner)
591 ret = saa7146_vv_init(dev, &av7110_vv_data_c);
592 else
593 ret = saa7146_vv_init(dev, &av7110_vv_data_st);
595 if (ret) {
596 ERR(("cannot init capture device. skipping.\n"));
597 return -ENODEV;
600 if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
601 ERR(("cannot register capture device. skipping.\n"));
602 saa7146_vv_release(dev);
603 return -ENODEV;
605 if (av7110->has_analog_tuner) {
606 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
607 ERR(("cannot register vbi v4l2 device. skipping.\n"));
608 } else
609 /* we use this to remember that this dvb-c card can do vbi */
610 av7110->has_analog_tuner = 2;
612 return 0;
615 int av7110_exit_v4l(struct av7110 *av7110)
617 saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
618 if (2 == av7110->has_analog_tuner)
619 saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
620 return 0;
625 /* FIXME: these values are experimental values that look better than the
626 values from the latest "official" driver -- at least for me... (MiHu) */
627 static struct saa7146_standard standard[] = {
629 .name = "PAL", .id = V4L2_STD_PAL_BG,
630 .v_offset = 0x15, .v_field = 288,
631 .h_offset = 0x48, .h_pixels = 708,
632 .v_max_out = 576, .h_max_out = 768,
633 }, {
634 .name = "NTSC", .id = V4L2_STD_NTSC,
635 .v_offset = 0x10, .v_field = 244,
636 .h_offset = 0x40, .h_pixels = 708,
637 .v_max_out = 480, .h_max_out = 640,
641 static struct saa7146_standard analog_standard[] = {
643 .name = "PAL", .id = V4L2_STD_PAL_BG,
644 .v_offset = 0x1b, .v_field = 288,
645 .h_offset = 0x08, .h_pixels = 708,
646 .v_max_out = 576, .h_max_out = 768,
647 }, {
648 .name = "NTSC", .id = V4L2_STD_NTSC,
649 .v_offset = 0x10, .v_field = 244,
650 .h_offset = 0x40, .h_pixels = 708,
651 .v_max_out = 480, .h_max_out = 640,
655 static struct saa7146_standard dvb_standard[] = {
657 .name = "PAL", .id = V4L2_STD_PAL_BG,
658 .v_offset = 0x14, .v_field = 288,
659 .h_offset = 0x48, .h_pixels = 708,
660 .v_max_out = 576, .h_max_out = 768,
661 }, {
662 .name = "NTSC", .id = V4L2_STD_NTSC,
663 .v_offset = 0x10, .v_field = 244,
664 .h_offset = 0x40, .h_pixels = 708,
665 .v_max_out = 480, .h_max_out = 640,
669 static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
671 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
673 if (std->id == V4L2_STD_PAL) {
674 av7110->vidmode = VIDEO_MODE_PAL;
675 av7110_set_vidmode(av7110, av7110->vidmode);
677 else if (std->id == V4L2_STD_NTSC) {
678 av7110->vidmode = VIDEO_MODE_NTSC;
679 av7110_set_vidmode(av7110, av7110->vidmode);
681 else
682 return -1;
684 return 0;
688 static struct saa7146_ext_vv av7110_vv_data_st = {
689 .inputs = 1,
690 .audios = 1,
691 .capabilities = 0,
692 .flags = 0,
694 .stds = &standard[0],
695 .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
696 .std_callback = &std_callback,
698 .ioctls = &ioctls[0],
699 .ioctl = av7110_ioctl,
702 static struct saa7146_ext_vv av7110_vv_data_c = {
703 .inputs = 1,
704 .audios = 1,
705 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
706 .flags = SAA7146_USE_PORT_B_FOR_VBI,
708 .stds = &standard[0],
709 .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
710 .std_callback = &std_callback,
712 .ioctls = &ioctls[0],
713 .ioctl = av7110_ioctl,