blob: 6af74f78b3e505a931d125814a12490b315b7efb [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>
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>
37
38#include "av7110.h"
39#include "av7110_hw.h"
40#include "av7110_av.h"
41
42int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
43{
44 u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
45 struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg };
46
47 if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
48 dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070049 av7110->dvb_adapter.num, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 return -EIO;
51 }
52 return 0;
53}
54
Johannes Stezenbachd91b7302005-05-16 21:54:38 -070055static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
57 u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
58 u8 msg2[2];
59 struct i2c_msg msgs[2] = {
60 { .flags = 0, .addr = 0x40, .len = 3, .buf = msg1 },
61 { .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 }
62 };
63
64 if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
65 dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070066 av7110->dvb_adapter.num, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 return -EIO;
68 }
69 *val = (msg2[0] << 8) | msg2[1];
70 return 0;
71}
72
thomas schorppf63f5342005-09-09 13:03:06 -070073static struct v4l2_input inputs[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 {
75 .index = 0,
76 .name = "DVB",
77 .type = V4L2_INPUT_TYPE_CAMERA,
78 .audioset = 1,
79 .tuner = 0, /* ignored */
80 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
81 .status = 0,
82 }, {
83 .index = 1,
84 .name = "Television",
85 .type = V4L2_INPUT_TYPE_TUNER,
86 .audioset = 2,
87 .tuner = 0,
88 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
89 .status = 0,
thomas schorppf63f5342005-09-09 13:03:06 -070090 }, {
91 .index = 2,
92 .name = "Video",
93 .type = V4L2_INPUT_TYPE_CAMERA,
94 .audioset = 0,
95 .tuner = 0,
96 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
97 .status = 0,
98 }, {
99 .index = 3,
100 .name = "Y/C",
101 .type = V4L2_INPUT_TYPE_CAMERA,
102 .audioset = 0,
103 .tuner = 0,
104 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
105 .status = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 }
107};
108
109static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
110{
111 u8 buf[] = { 0x00, reg, data };
112 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
113
114 dprintk(4, "dev: %p\n", dev);
115
116 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
117 return -1;
118 return 0;
119}
120
121static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
122{
123 u8 buf [] = { reg, data };
124 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 };
125
126 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
127 return -1;
128 return 0;
129}
130
131
132static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
133{
134 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
135
136 dprintk(4, "dev: %p\n", dev);
137
138 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
139 return -1;
140 return 0;
141}
142
143static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
144{
145 u32 div;
146 u8 config;
147 u8 buf[4];
148
149 dprintk(4, "freq: 0x%08x\n", freq);
150
151 /* magic number: 614. tuning with the frequency given by v4l2
152 is always off by 614*62.5 = 38375 kHz...*/
153 div = freq + 614;
154
155 buf[0] = (div >> 8) & 0x7f;
156 buf[1] = div & 0xff;
157 buf[2] = 0x8e;
158
159 if (freq < (u32) (16 * 168.25))
160 config = 0xa0;
161 else if (freq < (u32) (16 * 447.25))
162 config = 0x90;
163 else
164 config = 0x30;
165 config &= ~0x02;
166
167 buf[3] = config;
168
169 return tuner_write(dev, 0x61, buf);
170}
171
172static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
173{
174 u32 div;
175 u8 data[4];
176
177 div = (freq + 38900000 + 31250) / 62500;
178
179 data[0] = (div >> 8) & 0x7f;
180 data[1] = div & 0xff;
181 data[2] = 0xce;
182
183 if (freq < 45000000)
184 return -EINVAL;
185 else if (freq < 137000000)
186 data[3] = 0x01;
187 else if (freq < 403000000)
188 data[3] = 0x02;
189 else if (freq < 860000000)
190 data[3] = 0x04;
191 else
192 return -EINVAL;
193
194 stv0297_writereg(dev, 0x1C, 0x87, 0x78);
195 stv0297_writereg(dev, 0x1C, 0x86, 0xc8);
196 return tuner_write(dev, 0x63, data);
197}
198
199
200
201static struct saa7146_standard analog_standard[];
202static struct saa7146_standard dvb_standard[];
203static struct saa7146_standard standard[];
204
205static struct v4l2_audio msp3400_v4l2_audio = {
206 .index = 0,
207 .name = "Television",
208 .capability = V4L2_AUDCAP_STEREO
209};
210
211static int av7110_dvb_c_switch(struct saa7146_fh *fh)
212{
213 struct saa7146_dev *dev = fh->dev;
214 struct saa7146_vv *vv = dev->vv_data;
215 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
216 u16 adswitch;
217 int source, sync, err;
218
219 dprintk(4, "%p\n", av7110);
220
221 if ((vv->video_status & STATUS_OVERLAY) != 0) {
222 vv->ov_suspend = vv->video_fh;
223 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
224 if (err != 0) {
225 dprintk(2, "suspending video failed\n");
226 vv->ov_suspend = NULL;
227 }
228 }
229
230 if (0 != av7110->current_input) {
thomas schorppf63f5342005-09-09 13:03:06 -0700231 dprintk(1, "switching to analog TV:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 adswitch = 1;
233 source = SAA7146_HPS_SOURCE_PORT_B;
234 sync = SAA7146_HPS_SYNC_PORT_B;
235 memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
thomas schorppf63f5342005-09-09 13:03:06 -0700237 switch (av7110->current_input) {
238 case 1:
239 dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
240 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
241 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
242 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
243 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
244 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
245 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
246
247 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
248 if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
249 dprintk(1, "setting band in demodulator failed.\n");
250 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
251 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
252 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
253 }
254 if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
255 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
256 break;
257 case 2:
258 dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
259 if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
260 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
261 break;
262 case 3:
263 dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
264 if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
265 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
266 break;
267 default:
268 dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 }
270 } else {
271 adswitch = 0;
272 source = SAA7146_HPS_SOURCE_PORT_A;
273 sync = SAA7146_HPS_SYNC_PORT_A;
274 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
275 dprintk(1, "switching DVB mode\n");
276 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
277 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
278 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
279 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
280 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
281 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
282
283 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
284 if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
285 dprintk(1, "setting band in demodulator failed.\n");
286 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
287 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
288 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
289 }
290 }
291
292 /* hmm, this does not do anything!? */
293 if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
294 dprintk(1, "ADSwitch error\n");
295
296 saa7146_set_hps_source_and_sync(dev, source, sync);
297
298 if (vv->ov_suspend != NULL) {
299 saa7146_start_preview(vv->ov_suspend);
300 vv->ov_suspend = NULL;
301 }
302
303 return 0;
304}
305
306static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
307{
308 struct saa7146_dev *dev = fh->dev;
309 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
310 dprintk(4, "saa7146_dev: %p\n", dev);
311
312 switch (cmd) {
313 case VIDIOC_G_TUNER:
314 {
315 struct v4l2_tuner *t = arg;
316 u16 stereo_det;
317 s8 stereo;
318
319 dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
320
321 if (!av7110->analog_tuner_flags || t->index != 0)
322 return -EINVAL;
323
324 memset(t, 0, sizeof(*t));
325 strcpy(t->name, "Television");
326
327 t->type = V4L2_TUNER_ANALOG_TV;
328 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
329 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
330 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
331 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
332 /* FIXME: add the real signal strength here */
333 t->signal = 0xffff;
334 t->afc = 0;
335
336 // FIXME: standard / stereo detection is still broken
337 msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
338 dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
340 dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
341 stereo = (s8)(stereo_det >> 8);
342 if (stereo > 0x10) {
343 /* stereo */
344 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
345 t->audmode = V4L2_TUNER_MODE_STEREO;
346 }
347 else if (stereo < -0x10) {
thomas schorppf63f5342005-09-09 13:03:06 -0700348 /* bilingual */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
350 t->audmode = V4L2_TUNER_MODE_LANG1;
351 }
352 else /* mono */
353 t->rxsubchans = V4L2_TUNER_SUB_MONO;
354
355 return 0;
356 }
357 case VIDIOC_S_TUNER:
358 {
359 struct v4l2_tuner *t = arg;
360 u16 fm_matrix, src;
361 dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
362
363 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
364 return -EINVAL;
365
366 switch (t->audmode) {
367 case V4L2_TUNER_MODE_STEREO:
368 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
369 fm_matrix = 0x3001; // stereo
370 src = 0x0020;
371 break;
372 case V4L2_TUNER_MODE_LANG1:
373 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
374 fm_matrix = 0x3000; // mono
375 src = 0x0000;
376 break;
377 case V4L2_TUNER_MODE_LANG2:
378 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
379 fm_matrix = 0x3000; // mono
380 src = 0x0010;
381 break;
thomas schorppf63f5342005-09-09 13:03:06 -0700382 default: /* case V4L2_TUNER_MODE_MONO: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
384 fm_matrix = 0x3000; // mono
385 src = 0x0030;
386 break;
387 }
388 msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
389 msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
390 msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
391 msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
392 return 0;
393 }
394 case VIDIOC_G_FREQUENCY:
395 {
396 struct v4l2_frequency *f = arg;
397
398 dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
399
400 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
401 return -EINVAL;
402
403 memset(f, 0, sizeof(*f));
404 f->type = V4L2_TUNER_ANALOG_TV;
405 f->frequency = av7110->current_freq;
406 return 0;
407 }
408 case VIDIOC_S_FREQUENCY:
409 {
410 struct v4l2_frequency *f = arg;
411
412 dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
413
414 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
415 return -EINVAL;
416
417 if (V4L2_TUNER_ANALOG_TV != f->type)
418 return -EINVAL;
419
420 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute
421 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
422
423 /* tune in desired frequency */
424 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
425 ves1820_set_tv_freq(dev, f->frequency);
426 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
427 stv0297_set_tv_freq(dev, f->frequency);
428 }
429 av7110->current_freq = f->frequency;
430
431 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
432 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
433 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
434 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
435 return 0;
436 }
437 case VIDIOC_ENUMINPUT:
438 {
439 struct v4l2_input *i = arg;
440
441 dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
442
443 if (av7110->analog_tuner_flags) {
thomas schorppf63f5342005-09-09 13:03:06 -0700444 if (i->index < 0 || i->index >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 return -EINVAL;
446 } else {
447 if (i->index != 0)
448 return -EINVAL;
449 }
450
451 memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
452
453 return 0;
454 }
455 case VIDIOC_G_INPUT:
456 {
457 int *input = (int *)arg;
458 *input = av7110->current_input;
459 dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
460 return 0;
461 }
462 case VIDIOC_S_INPUT:
463 {
464 int input = *(int *)arg;
465
466 dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
467
468 if (!av7110->analog_tuner_flags)
469 return 0;
470
thomas schorppf63f5342005-09-09 13:03:06 -0700471 if (input < 0 || input >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 return -EINVAL;
473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 av7110->current_input = input;
475 return av7110_dvb_c_switch(fh);
476 }
477 case VIDIOC_G_AUDIO:
478 {
479 struct v4l2_audio *a = arg;
480
481 dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
482 if (a->index != 0)
483 return -EINVAL;
484 memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
485 break;
486 }
487 case VIDIOC_S_AUDIO:
488 {
489 struct v4l2_audio *a = arg;
490 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
491 break;
492 }
493 default:
494 printk("no such ioctl\n");
495 return -ENOIOCTLCMD;
496 }
497 return 0;
498}
499
500
501/****************************************************************************
502 * INITIALIZATION
503 ****************************************************************************/
504
505static struct saa7146_extension_ioctls ioctls[] = {
506 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
507 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
508 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
509 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
510 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
511 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
512 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
513 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
514 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
515 { 0, 0 }
516};
517
518static u8 saa7113_init_regs[] = {
519 0x02, 0xd0,
520 0x03, 0x23,
521 0x04, 0x00,
522 0x05, 0x00,
523 0x06, 0xe9,
524 0x07, 0x0d,
525 0x08, 0x98,
526 0x09, 0x02,
527 0x0a, 0x80,
528 0x0b, 0x40,
529 0x0c, 0x40,
530 0x0d, 0x00,
531 0x0e, 0x01,
532 0x0f, 0x7c,
533 0x10, 0x48,
534 0x11, 0x0c,
535 0x12, 0x8b,
536 0x13, 0x1a,
537 0x14, 0x00,
538 0x15, 0x00,
539 0x16, 0x00,
540 0x17, 0x00,
541 0x18, 0x00,
542 0x19, 0x00,
543 0x1a, 0x00,
544 0x1b, 0x00,
545 0x1c, 0x00,
546 0x1d, 0x00,
547 0x1e, 0x00,
548
549 0x41, 0x77,
550 0x42, 0x77,
551 0x43, 0x77,
552 0x44, 0x77,
553 0x45, 0x77,
554 0x46, 0x77,
555 0x47, 0x77,
556 0x48, 0x77,
557 0x49, 0x77,
558 0x4a, 0x77,
559 0x4b, 0x77,
560 0x4c, 0x77,
561 0x4d, 0x77,
562 0x4e, 0x77,
563 0x4f, 0x77,
564 0x50, 0x77,
565 0x51, 0x77,
566 0x52, 0x77,
567 0x53, 0x77,
568 0x54, 0x77,
569 0x55, 0x77,
570 0x56, 0x77,
571 0x57, 0xff,
572
573 0xff
574};
575
576
577static struct saa7146_ext_vv av7110_vv_data_st;
578static struct saa7146_ext_vv av7110_vv_data_c;
579
580int av7110_init_analog_module(struct av7110 *av7110)
581{
582 u16 version1, version2;
583
584 if (i2c_writereg(av7110, 0x80, 0x0, 0x80) != 1
585 || i2c_writereg(av7110, 0x80, 0x0, 0) != 1)
586 return -ENODEV;
587
588 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700589 av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 av7110->adac_type = DVB_ADAC_MSP;
591 msleep(100); // the probing above resets the msp...
592 msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
593 msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
594 dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700595 av7110->dvb_adapter.num, version1, version2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
597 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
598 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
599 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
600 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
601 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
602 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
603 msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x4800); // prescale SCART
604
605 if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
606 INFO(("saa7113 not accessible.\n"));
607 } else {
608 u8 *i = saa7113_init_regs;
609
610 if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
611 /* Fujitsu/Siemens DVB-Cable */
612 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
613 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
614 /* Hauppauge/TT DVB-C premium */
615 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
616 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
617 /* Hauppauge/TT DVB-C premium */
618 av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
619 }
620
621 /* setup for DVB by default */
622 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
623 if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
624 dprintk(1, "setting band in demodulator failed.\n");
625 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
626 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
627 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
628 }
629
630 /* init the saa7113 */
631 while (*i != 0xff) {
632 if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700633 dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 break;
635 }
636 i += 2;
637 }
638 /* setup msp for analog sound: B/G Dual-FM */
639 msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
640 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
641 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
642 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
643 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
644 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
645 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
646 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
647 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
648 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
649 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
650 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
651 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
652 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
653 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
654 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
655 msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
656 msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
657 msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
658 msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
659 msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
660 msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
661 }
662
663 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
664 /* set dd1 stream a & b */
665 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
666 saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
667 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
668
669 return 0;
670}
671
672int av7110_init_v4l(struct av7110 *av7110)
673{
674 struct saa7146_dev* dev = av7110->dev;
675 int ret;
676
677 /* special case DVB-C: these cards have an analog tuner
678 plus need some special handling, so we have separate
679 saa7146_ext_vv data for these... */
680 if (av7110->analog_tuner_flags)
681 ret = saa7146_vv_init(dev, &av7110_vv_data_c);
682 else
683 ret = saa7146_vv_init(dev, &av7110_vv_data_st);
684
685 if (ret) {
686 ERR(("cannot init capture device. skipping.\n"));
687 return -ENODEV;
688 }
689
690 if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
691 ERR(("cannot register capture device. skipping.\n"));
692 saa7146_vv_release(dev);
693 return -ENODEV;
694 }
695 if (av7110->analog_tuner_flags) {
696 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
697 ERR(("cannot register vbi v4l2 device. skipping.\n"));
698 } else {
699 av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
700 }
701 }
702 return 0;
703}
704
705int av7110_exit_v4l(struct av7110 *av7110)
706{
707 saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
708 if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI)
709 saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
710 return 0;
711}
712
713
714
715/* FIXME: these values are experimental values that look better than the
716 values from the latest "official" driver -- at least for me... (MiHu) */
717static struct saa7146_standard standard[] = {
718 {
719 .name = "PAL", .id = V4L2_STD_PAL_BG,
720 .v_offset = 0x15, .v_field = 288,
721 .h_offset = 0x48, .h_pixels = 708,
722 .v_max_out = 576, .h_max_out = 768,
723 }, {
724 .name = "NTSC", .id = V4L2_STD_NTSC,
725 .v_offset = 0x10, .v_field = 244,
726 .h_offset = 0x40, .h_pixels = 708,
727 .v_max_out = 480, .h_max_out = 640,
728 }
729};
730
731static struct saa7146_standard analog_standard[] = {
732 {
733 .name = "PAL", .id = V4L2_STD_PAL_BG,
734 .v_offset = 0x1b, .v_field = 288,
735 .h_offset = 0x08, .h_pixels = 708,
736 .v_max_out = 576, .h_max_out = 768,
737 }, {
738 .name = "NTSC", .id = V4L2_STD_NTSC,
739 .v_offset = 0x10, .v_field = 244,
740 .h_offset = 0x40, .h_pixels = 708,
741 .v_max_out = 480, .h_max_out = 640,
742 }
743};
744
745static struct saa7146_standard dvb_standard[] = {
746 {
747 .name = "PAL", .id = V4L2_STD_PAL_BG,
748 .v_offset = 0x14, .v_field = 288,
749 .h_offset = 0x48, .h_pixels = 708,
750 .v_max_out = 576, .h_max_out = 768,
751 }, {
752 .name = "NTSC", .id = V4L2_STD_NTSC,
753 .v_offset = 0x10, .v_field = 244,
754 .h_offset = 0x40, .h_pixels = 708,
755 .v_max_out = 480, .h_max_out = 640,
756 }
757};
758
759static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
760{
761 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
762
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700763 if (std->id & V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 av7110->vidmode = VIDEO_MODE_PAL;
765 av7110_set_vidmode(av7110, av7110->vidmode);
766 }
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700767 else if (std->id & V4L2_STD_NTSC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 av7110->vidmode = VIDEO_MODE_NTSC;
769 av7110_set_vidmode(av7110, av7110->vidmode);
770 }
771 else
772 return -1;
773
774 return 0;
775}
776
777
778static struct saa7146_ext_vv av7110_vv_data_st = {
779 .inputs = 1,
780 .audios = 1,
781 .capabilities = 0,
782 .flags = 0,
783
784 .stds = &standard[0],
785 .num_stds = ARRAY_SIZE(standard),
786 .std_callback = &std_callback,
787
788 .ioctls = &ioctls[0],
789 .ioctl = av7110_ioctl,
790};
791
792static struct saa7146_ext_vv av7110_vv_data_c = {
793 .inputs = 1,
794 .audios = 1,
795 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
796 .flags = SAA7146_USE_PORT_B_FOR_VBI,
797
798 .stds = &standard[0],
799 .num_stds = ARRAY_SIZE(standard),
800 .std_callback = &std_callback,
801
802 .ioctls = &ioctls[0],
803 .ioctl = av7110_ioctl,
804};
805