blob: 64055461559dc918bcc325d732a52719c4000e0c [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 };
Tim Kaiser61391e02006-06-25 09:14:07 -030045 struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };
46
47 switch (av7110->adac_type) {
48 case DVB_ADAC_MSP34x0:
49 msgs.addr = 0x40;
50 break;
51 case DVB_ADAC_MSP34x5:
52 msgs.addr = 0x42;
53 break;
54 default:
55 return 0;
56 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58 if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
59 dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070060 av7110->dvb_adapter.num, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 return -EIO;
62 }
63 return 0;
64}
65
Johannes Stezenbachd91b7302005-05-16 21:54:38 -070066static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067{
68 u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
69 u8 msg2[2];
70 struct i2c_msg msgs[2] = {
Tim Kaiser61391e02006-06-25 09:14:07 -030071 { .flags = 0 , .len = 3, .buf = msg1 },
72 { .flags = I2C_M_RD, .len = 2, .buf = msg2 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 };
74
Tim Kaiser61391e02006-06-25 09:14:07 -030075 switch (av7110->adac_type) {
76 case DVB_ADAC_MSP34x0:
77 msgs[0].addr = 0x40;
78 msgs[1].addr = 0x40;
79 break;
80 case DVB_ADAC_MSP34x5:
81 msgs[0].addr = 0x42;
82 msgs[1].addr = 0x42;
83 break;
84 default:
85 return 0;
86 }
87
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
89 dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070090 av7110->dvb_adapter.num, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 return -EIO;
92 }
93 *val = (msg2[0] << 8) | msg2[1];
94 return 0;
95}
96
thomas schorppf63f5342005-09-09 13:03:06 -070097static struct v4l2_input inputs[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 {
99 .index = 0,
100 .name = "DVB",
101 .type = V4L2_INPUT_TYPE_CAMERA,
102 .audioset = 1,
103 .tuner = 0, /* ignored */
104 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
105 .status = 0,
106 }, {
107 .index = 1,
108 .name = "Television",
109 .type = V4L2_INPUT_TYPE_TUNER,
110 .audioset = 2,
111 .tuner = 0,
112 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
113 .status = 0,
thomas schorppf63f5342005-09-09 13:03:06 -0700114 }, {
115 .index = 2,
116 .name = "Video",
117 .type = V4L2_INPUT_TYPE_CAMERA,
118 .audioset = 0,
119 .tuner = 0,
120 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
121 .status = 0,
122 }, {
123 .index = 3,
124 .name = "Y/C",
125 .type = V4L2_INPUT_TYPE_CAMERA,
126 .audioset = 0,
127 .tuner = 0,
128 .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
129 .status = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 }
131};
132
133static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
134{
135 u8 buf[] = { 0x00, reg, data };
136 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
137
138 dprintk(4, "dev: %p\n", dev);
139
140 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
141 return -1;
142 return 0;
143}
144
145static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
146{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800147 u8 buf [] = { reg, data };
148 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
151 return -1;
152 return 0;
153}
154
155
156static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
157{
158 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
159
160 dprintk(4, "dev: %p\n", dev);
161
162 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
163 return -1;
164 return 0;
165}
166
167static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
168{
169 u32 div;
170 u8 config;
171 u8 buf[4];
172
173 dprintk(4, "freq: 0x%08x\n", freq);
174
175 /* magic number: 614. tuning with the frequency given by v4l2
176 is always off by 614*62.5 = 38375 kHz...*/
177 div = freq + 614;
178
179 buf[0] = (div >> 8) & 0x7f;
180 buf[1] = div & 0xff;
181 buf[2] = 0x8e;
182
183 if (freq < (u32) (16 * 168.25))
184 config = 0xa0;
185 else if (freq < (u32) (16 * 447.25))
186 config = 0x90;
187 else
188 config = 0x30;
189 config &= ~0x02;
190
191 buf[3] = config;
192
193 return tuner_write(dev, 0x61, buf);
194}
195
196static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
197{
198 u32 div;
199 u8 data[4];
200
201 div = (freq + 38900000 + 31250) / 62500;
202
203 data[0] = (div >> 8) & 0x7f;
204 data[1] = div & 0xff;
205 data[2] = 0xce;
206
207 if (freq < 45000000)
208 return -EINVAL;
209 else if (freq < 137000000)
210 data[3] = 0x01;
211 else if (freq < 403000000)
212 data[3] = 0x02;
213 else if (freq < 860000000)
214 data[3] = 0x04;
215 else
216 return -EINVAL;
217
218 stv0297_writereg(dev, 0x1C, 0x87, 0x78);
219 stv0297_writereg(dev, 0x1C, 0x86, 0xc8);
220 return tuner_write(dev, 0x63, data);
221}
222
223
224
225static struct saa7146_standard analog_standard[];
226static struct saa7146_standard dvb_standard[];
227static struct saa7146_standard standard[];
228
229static struct v4l2_audio msp3400_v4l2_audio = {
230 .index = 0,
231 .name = "Television",
232 .capability = V4L2_AUDCAP_STEREO
233};
234
235static int av7110_dvb_c_switch(struct saa7146_fh *fh)
236{
237 struct saa7146_dev *dev = fh->dev;
238 struct saa7146_vv *vv = dev->vv_data;
239 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
240 u16 adswitch;
241 int source, sync, err;
242
243 dprintk(4, "%p\n", av7110);
244
245 if ((vv->video_status & STATUS_OVERLAY) != 0) {
246 vv->ov_suspend = vv->video_fh;
247 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
248 if (err != 0) {
249 dprintk(2, "suspending video failed\n");
250 vv->ov_suspend = NULL;
251 }
252 }
253
254 if (0 != av7110->current_input) {
thomas schorppf63f5342005-09-09 13:03:06 -0700255 dprintk(1, "switching to analog TV:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 adswitch = 1;
257 source = SAA7146_HPS_SOURCE_PORT_B;
258 sync = SAA7146_HPS_SYNC_PORT_B;
259 memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
thomas schorppf63f5342005-09-09 13:03:06 -0700261 switch (av7110->current_input) {
262 case 1:
263 dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
264 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
265 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
266 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
267 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
268 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
269 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
270
271 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
272 if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
273 dprintk(1, "setting band in demodulator failed.\n");
274 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
275 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
276 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
277 }
278 if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
279 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
280 break;
281 case 2:
282 dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
283 if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
284 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
285 break;
286 case 3:
287 dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
288 if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
289 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
290 break;
291 default:
292 dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294 } else {
295 adswitch = 0;
296 source = SAA7146_HPS_SOURCE_PORT_A;
297 sync = SAA7146_HPS_SYNC_PORT_A;
298 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
299 dprintk(1, "switching DVB mode\n");
300 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
301 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
302 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
303 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
304 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
305 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
306
307 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
308 if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
309 dprintk(1, "setting band in demodulator failed.\n");
310 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
311 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
312 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
313 }
314 }
315
316 /* hmm, this does not do anything!? */
317 if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
318 dprintk(1, "ADSwitch error\n");
319
320 saa7146_set_hps_source_and_sync(dev, source, sync);
321
322 if (vv->ov_suspend != NULL) {
323 saa7146_start_preview(vv->ov_suspend);
324 vv->ov_suspend = NULL;
325 }
326
327 return 0;
328}
329
330static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
331{
332 struct saa7146_dev *dev = fh->dev;
333 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
334 dprintk(4, "saa7146_dev: %p\n", dev);
335
336 switch (cmd) {
337 case VIDIOC_G_TUNER:
338 {
339 struct v4l2_tuner *t = arg;
340 u16 stereo_det;
341 s8 stereo;
342
343 dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
344
345 if (!av7110->analog_tuner_flags || t->index != 0)
346 return -EINVAL;
347
348 memset(t, 0, sizeof(*t));
349 strcpy(t->name, "Television");
350
351 t->type = V4L2_TUNER_ANALOG_TV;
352 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
353 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
354 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
355 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
356 /* FIXME: add the real signal strength here */
357 t->signal = 0xffff;
358 t->afc = 0;
359
360 // FIXME: standard / stereo detection is still broken
361 msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
362 dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
364 dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
365 stereo = (s8)(stereo_det >> 8);
366 if (stereo > 0x10) {
367 /* stereo */
368 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
369 t->audmode = V4L2_TUNER_MODE_STEREO;
370 }
371 else if (stereo < -0x10) {
thomas schorppf63f5342005-09-09 13:03:06 -0700372 /* bilingual */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
374 t->audmode = V4L2_TUNER_MODE_LANG1;
375 }
376 else /* mono */
377 t->rxsubchans = V4L2_TUNER_SUB_MONO;
378
379 return 0;
380 }
381 case VIDIOC_S_TUNER:
382 {
383 struct v4l2_tuner *t = arg;
384 u16 fm_matrix, src;
385 dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
386
387 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
388 return -EINVAL;
389
390 switch (t->audmode) {
391 case V4L2_TUNER_MODE_STEREO:
392 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
393 fm_matrix = 0x3001; // stereo
394 src = 0x0020;
395 break;
Hans Verkuil301e22d2006-03-18 17:15:00 -0300396 case V4L2_TUNER_MODE_LANG1_LANG2:
397 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
398 fm_matrix = 0x3000; // bilingual
399 src = 0x0020;
400 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 case V4L2_TUNER_MODE_LANG1:
402 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
403 fm_matrix = 0x3000; // mono
404 src = 0x0000;
405 break;
406 case V4L2_TUNER_MODE_LANG2:
407 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
408 fm_matrix = 0x3000; // mono
409 src = 0x0010;
410 break;
thomas schorppf63f5342005-09-09 13:03:06 -0700411 default: /* case V4L2_TUNER_MODE_MONO: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
413 fm_matrix = 0x3000; // mono
414 src = 0x0030;
415 break;
416 }
417 msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
418 msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
419 msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
420 msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
421 return 0;
422 }
423 case VIDIOC_G_FREQUENCY:
424 {
425 struct v4l2_frequency *f = arg;
426
427 dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
428
429 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
430 return -EINVAL;
431
432 memset(f, 0, sizeof(*f));
433 f->type = V4L2_TUNER_ANALOG_TV;
434 f->frequency = av7110->current_freq;
435 return 0;
436 }
437 case VIDIOC_S_FREQUENCY:
438 {
439 struct v4l2_frequency *f = arg;
440
441 dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
442
443 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
444 return -EINVAL;
445
446 if (V4L2_TUNER_ANALOG_TV != f->type)
447 return -EINVAL;
448
449 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute
450 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
451
452 /* tune in desired frequency */
453 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
454 ves1820_set_tv_freq(dev, f->frequency);
455 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
456 stv0297_set_tv_freq(dev, f->frequency);
457 }
458 av7110->current_freq = f->frequency;
459
460 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
461 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
462 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
463 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
464 return 0;
465 }
466 case VIDIOC_ENUMINPUT:
467 {
468 struct v4l2_input *i = arg;
469
470 dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
471
472 if (av7110->analog_tuner_flags) {
thomas schorppf63f5342005-09-09 13:03:06 -0700473 if (i->index < 0 || i->index >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 return -EINVAL;
475 } else {
476 if (i->index != 0)
477 return -EINVAL;
478 }
479
480 memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
481
482 return 0;
483 }
484 case VIDIOC_G_INPUT:
485 {
486 int *input = (int *)arg;
487 *input = av7110->current_input;
488 dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
489 return 0;
490 }
491 case VIDIOC_S_INPUT:
492 {
493 int input = *(int *)arg;
494
495 dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
496
497 if (!av7110->analog_tuner_flags)
498 return 0;
499
thomas schorppf63f5342005-09-09 13:03:06 -0700500 if (input < 0 || input >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return -EINVAL;
502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 av7110->current_input = input;
504 return av7110_dvb_c_switch(fh);
505 }
506 case VIDIOC_G_AUDIO:
507 {
508 struct v4l2_audio *a = arg;
509
510 dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
511 if (a->index != 0)
512 return -EINVAL;
513 memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
514 break;
515 }
516 case VIDIOC_S_AUDIO:
517 {
518 struct v4l2_audio *a = arg;
519 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
520 break;
521 }
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200522 case VIDIOC_G_SLICED_VBI_CAP:
523 {
524 struct v4l2_sliced_vbi_cap *cap = arg;
525 dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
526 memset(cap, 0, sizeof *cap);
527 if (FW_VERSION(av7110->arm_app) >= 0x2623) {
528 cap->service_set = V4L2_SLICED_WSS_625;
529 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
530 }
531 break;
532 }
533 case VIDIOC_G_FMT:
534 {
535 struct v4l2_format *f = arg;
536 dprintk(2, "VIDIOC_G_FMT:\n");
537 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
538 FW_VERSION(av7110->arm_app) < 0x2623)
539 return -EAGAIN; /* handled by core driver */
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);
545 }
546 break;
547 }
548 case VIDIOC_S_FMT:
549 {
550 struct v4l2_format *f = arg;
551 dprintk(2, "VIDIOC_S_FMT\n");
552 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
553 FW_VERSION(av7110->arm_app) < 0x2623)
554 return -EAGAIN; /* handled by core driver */
555 if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
556 f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
557 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
558 /* WSS controlled by firmware */
559 av7110->wssMode = 0;
560 av7110->wssData = 0;
561 return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
562 SetWSSConfig, 1, 0);
563 } else {
564 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
565 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
566 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
567 f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
568 /* WSS controlled by userspace */
569 av7110->wssMode = 1;
570 av7110->wssData = 0;
571 }
572 break;
573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 default:
575 printk("no such ioctl\n");
576 return -ENOIOCTLCMD;
577 }
578 return 0;
579}
580
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200581static int av7110_vbi_reset(struct inode *inode, struct file *file)
582{
583 struct saa7146_fh *fh = file->private_data;
584 struct saa7146_dev *dev = fh->dev;
585 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
586
587 dprintk(2, "%s\n", __FUNCTION__);
588 av7110->wssMode = 0;
589 av7110->wssData = 0;
590 if (FW_VERSION(av7110->arm_app) < 0x2623)
591 return 0;
592 else
593 return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
594}
595
596static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
597{
598 struct saa7146_fh *fh = file->private_data;
599 struct saa7146_dev *dev = fh->dev;
600 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
601 struct v4l2_sliced_vbi_data d;
602 int rc;
603
604 dprintk(2, "%s\n", __FUNCTION__);
605 if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
606 return -EINVAL;
607 if (copy_from_user(&d, data, count))
608 return -EFAULT;
609 if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
610 return -EINVAL;
Oliver Endriss4caba422006-03-17 05:29:15 -0300611 if (d.id)
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200612 av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
Oliver Endriss4caba422006-03-17 05:29:15 -0300613 else
614 av7110->wssData = 0x8000;
615 rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200616 return (rc < 0) ? rc : count;
617}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
619/****************************************************************************
620 * INITIALIZATION
621 ****************************************************************************/
622
623static struct saa7146_extension_ioctls ioctls[] = {
624 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
625 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
626 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
627 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
628 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
629 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
630 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
631 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
632 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200633 { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
634 { VIDIOC_G_FMT, SAA7146_BEFORE },
635 { VIDIOC_S_FMT, SAA7146_BEFORE },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 { 0, 0 }
637};
638
639static u8 saa7113_init_regs[] = {
640 0x02, 0xd0,
641 0x03, 0x23,
642 0x04, 0x00,
643 0x05, 0x00,
644 0x06, 0xe9,
645 0x07, 0x0d,
646 0x08, 0x98,
647 0x09, 0x02,
648 0x0a, 0x80,
649 0x0b, 0x40,
650 0x0c, 0x40,
651 0x0d, 0x00,
652 0x0e, 0x01,
653 0x0f, 0x7c,
654 0x10, 0x48,
655 0x11, 0x0c,
656 0x12, 0x8b,
657 0x13, 0x1a,
658 0x14, 0x00,
659 0x15, 0x00,
660 0x16, 0x00,
661 0x17, 0x00,
662 0x18, 0x00,
663 0x19, 0x00,
664 0x1a, 0x00,
665 0x1b, 0x00,
666 0x1c, 0x00,
667 0x1d, 0x00,
668 0x1e, 0x00,
669
670 0x41, 0x77,
671 0x42, 0x77,
672 0x43, 0x77,
673 0x44, 0x77,
674 0x45, 0x77,
675 0x46, 0x77,
676 0x47, 0x77,
677 0x48, 0x77,
678 0x49, 0x77,
679 0x4a, 0x77,
680 0x4b, 0x77,
681 0x4c, 0x77,
682 0x4d, 0x77,
683 0x4e, 0x77,
684 0x4f, 0x77,
685 0x50, 0x77,
686 0x51, 0x77,
687 0x52, 0x77,
688 0x53, 0x77,
689 0x54, 0x77,
690 0x55, 0x77,
691 0x56, 0x77,
692 0x57, 0xff,
693
694 0xff
695};
696
697
698static struct saa7146_ext_vv av7110_vv_data_st;
699static struct saa7146_ext_vv av7110_vv_data_c;
700
701int av7110_init_analog_module(struct av7110 *av7110)
702{
703 u16 version1, version2;
704
Tim Kaiser61391e02006-06-25 09:14:07 -0300705 if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
706 i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
707 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
708 av7110->dvb_adapter.num);
709 av7110->adac_type = DVB_ADAC_MSP34x0;
710 } else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
711 i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
712 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
713 av7110->dvb_adapter.num);
714 av7110->adac_type = DVB_ADAC_MSP34x5;
715 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return -ENODEV;
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 msleep(100); // the probing above resets the msp...
719 msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
720 msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
Tim Kaiser61391e02006-06-25 09:14:07 -0300721 dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700722 av7110->dvb_adapter.num, version1, version2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
724 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
725 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
726 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
727 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
728 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
729 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
Tim Kaiser61391e02006-06-25 09:14:07 -0300730 msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
732 if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
733 INFO(("saa7113 not accessible.\n"));
734 } else {
735 u8 *i = saa7113_init_regs;
736
737 if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
738 /* Fujitsu/Siemens DVB-Cable */
739 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
740 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
741 /* Hauppauge/TT DVB-C premium */
742 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
743 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
744 /* Hauppauge/TT DVB-C premium */
745 av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
746 }
747
748 /* setup for DVB by default */
749 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
750 if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
751 dprintk(1, "setting band in demodulator failed.\n");
752 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
753 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
754 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
755 }
756
757 /* init the saa7113 */
758 while (*i != 0xff) {
759 if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700760 dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 break;
762 }
763 i += 2;
764 }
765 /* setup msp for analog sound: B/G Dual-FM */
766 msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
767 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
768 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
769 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
770 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
771 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
772 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
773 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
774 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
775 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
776 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
777 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
778 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
779 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
780 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
781 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
782 msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
783 msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
784 msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
785 msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
786 msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
787 msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
788 }
789
790 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
791 /* set dd1 stream a & b */
792 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
793 saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
794 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
795
796 return 0;
797}
798
799int av7110_init_v4l(struct av7110 *av7110)
800{
801 struct saa7146_dev* dev = av7110->dev;
802 int ret;
803
804 /* special case DVB-C: these cards have an analog tuner
805 plus need some special handling, so we have separate
806 saa7146_ext_vv data for these... */
807 if (av7110->analog_tuner_flags)
808 ret = saa7146_vv_init(dev, &av7110_vv_data_c);
809 else
810 ret = saa7146_vv_init(dev, &av7110_vv_data_st);
811
812 if (ret) {
813 ERR(("cannot init capture device. skipping.\n"));
814 return -ENODEV;
815 }
816
817 if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
818 ERR(("cannot register capture device. skipping.\n"));
819 saa7146_vv_release(dev);
820 return -ENODEV;
821 }
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200822 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
823 ERR(("cannot register vbi v4l2 device. skipping.\n"));
824 } else {
825 if (av7110->analog_tuner_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 }
828 return 0;
829}
830
831int av7110_exit_v4l(struct av7110 *av7110)
832{
833 saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
834 if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI)
835 saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
836 return 0;
837}
838
839
840
841/* FIXME: these values are experimental values that look better than the
842 values from the latest "official" driver -- at least for me... (MiHu) */
843static struct saa7146_standard standard[] = {
844 {
845 .name = "PAL", .id = V4L2_STD_PAL_BG,
846 .v_offset = 0x15, .v_field = 288,
847 .h_offset = 0x48, .h_pixels = 708,
848 .v_max_out = 576, .h_max_out = 768,
849 }, {
850 .name = "NTSC", .id = V4L2_STD_NTSC,
851 .v_offset = 0x10, .v_field = 244,
852 .h_offset = 0x40, .h_pixels = 708,
853 .v_max_out = 480, .h_max_out = 640,
854 }
855};
856
857static struct saa7146_standard analog_standard[] = {
858 {
859 .name = "PAL", .id = V4L2_STD_PAL_BG,
860 .v_offset = 0x1b, .v_field = 288,
861 .h_offset = 0x08, .h_pixels = 708,
862 .v_max_out = 576, .h_max_out = 768,
863 }, {
864 .name = "NTSC", .id = V4L2_STD_NTSC,
865 .v_offset = 0x10, .v_field = 244,
866 .h_offset = 0x40, .h_pixels = 708,
867 .v_max_out = 480, .h_max_out = 640,
868 }
869};
870
871static struct saa7146_standard dvb_standard[] = {
872 {
873 .name = "PAL", .id = V4L2_STD_PAL_BG,
874 .v_offset = 0x14, .v_field = 288,
875 .h_offset = 0x48, .h_pixels = 708,
876 .v_max_out = 576, .h_max_out = 768,
877 }, {
878 .name = "NTSC", .id = V4L2_STD_NTSC,
879 .v_offset = 0x10, .v_field = 244,
880 .h_offset = 0x40, .h_pixels = 708,
881 .v_max_out = 480, .h_max_out = 640,
882 }
883};
884
885static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
886{
887 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
888
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700889 if (std->id & V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 av7110->vidmode = VIDEO_MODE_PAL;
891 av7110_set_vidmode(av7110, av7110->vidmode);
892 }
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700893 else if (std->id & V4L2_STD_NTSC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 av7110->vidmode = VIDEO_MODE_NTSC;
895 av7110_set_vidmode(av7110, av7110->vidmode);
896 }
897 else
898 return -1;
899
900 return 0;
901}
902
903
904static struct saa7146_ext_vv av7110_vv_data_st = {
905 .inputs = 1,
906 .audios = 1,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200907 .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 .flags = 0,
909
910 .stds = &standard[0],
911 .num_stds = ARRAY_SIZE(standard),
912 .std_callback = &std_callback,
913
914 .ioctls = &ioctls[0],
915 .ioctl = av7110_ioctl,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200916
917 .vbi_fops.open = av7110_vbi_reset,
918 .vbi_fops.release = av7110_vbi_reset,
919 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920};
921
922static struct saa7146_ext_vv av7110_vv_data_c = {
923 .inputs = 1,
924 .audios = 1,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200925 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 .flags = SAA7146_USE_PORT_B_FOR_VBI,
927
928 .stds = &standard[0],
929 .num_stds = ARRAY_SIZE(standard),
930 .std_callback = &std_callback,
931
932 .ioctls = &ioctls[0],
933 .ioctl = av7110_ioctl,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200934
935 .vbi_fops.open = av7110_vbi_reset,
936 .vbi_fops.release = av7110_vbi_reset,
937 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938};
939