blob: 87afaebc07032721ba6a70e5f41e13bfc3b318a5 [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{
132 u8 buf[] = { 0x00, reg, data };
133 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
134
135 dprintk(4, "dev: %p\n", dev);
136
137 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
138 return -1;
139 return 0;
140}
141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
143{
144 struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
145
146 dprintk(4, "dev: %p\n", dev);
147
148 if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
149 return -1;
150 return 0;
151}
152
153static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
154{
155 u32 div;
156 u8 config;
157 u8 buf[4];
158
159 dprintk(4, "freq: 0x%08x\n", freq);
160
161 /* magic number: 614. tuning with the frequency given by v4l2
162 is always off by 614*62.5 = 38375 kHz...*/
163 div = freq + 614;
164
165 buf[0] = (div >> 8) & 0x7f;
166 buf[1] = div & 0xff;
167 buf[2] = 0x8e;
168
169 if (freq < (u32) (16 * 168.25))
170 config = 0xa0;
171 else if (freq < (u32) (16 * 447.25))
172 config = 0x90;
173 else
174 config = 0x30;
175 config &= ~0x02;
176
177 buf[3] = config;
178
179 return tuner_write(dev, 0x61, buf);
180}
181
182static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
183{
Marco Schluessler89e4d592007-02-13 09:31:07 -0300184 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 u32 div;
186 u8 data[4];
187
188 div = (freq + 38900000 + 31250) / 62500;
189
190 data[0] = (div >> 8) & 0x7f;
191 data[1] = div & 0xff;
192 data[2] = 0xce;
193
194 if (freq < 45000000)
195 return -EINVAL;
196 else if (freq < 137000000)
197 data[3] = 0x01;
198 else if (freq < 403000000)
199 data[3] = 0x02;
200 else if (freq < 860000000)
201 data[3] = 0x04;
202 else
203 return -EINVAL;
204
Marco Schluessler89e4d592007-02-13 09:31:07 -0300205 if (av7110->fe->ops.i2c_gate_ctrl)
206 av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 return tuner_write(dev, 0x63, data);
208}
209
210
211
212static struct saa7146_standard analog_standard[];
213static struct saa7146_standard dvb_standard[];
214static struct saa7146_standard standard[];
215
216static struct v4l2_audio msp3400_v4l2_audio = {
217 .index = 0,
218 .name = "Television",
219 .capability = V4L2_AUDCAP_STEREO
220};
221
222static int av7110_dvb_c_switch(struct saa7146_fh *fh)
223{
224 struct saa7146_dev *dev = fh->dev;
225 struct saa7146_vv *vv = dev->vv_data;
226 struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
227 u16 adswitch;
228 int source, sync, err;
229
230 dprintk(4, "%p\n", av7110);
231
232 if ((vv->video_status & STATUS_OVERLAY) != 0) {
233 vv->ov_suspend = vv->video_fh;
234 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
235 if (err != 0) {
236 dprintk(2, "suspending video failed\n");
237 vv->ov_suspend = NULL;
238 }
239 }
240
241 if (0 != av7110->current_input) {
thomas schorppf63f5342005-09-09 13:03:06 -0700242 dprintk(1, "switching to analog TV:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 adswitch = 1;
244 source = SAA7146_HPS_SOURCE_PORT_B;
245 sync = SAA7146_HPS_SYNC_PORT_B;
246 memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
thomas schorppf63f5342005-09-09 13:03:06 -0700248 switch (av7110->current_input) {
249 case 1:
250 dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
251 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
252 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
253 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
254 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
255 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
256 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
257
258 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
259 if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
260 dprintk(1, "setting band in demodulator failed.\n");
261 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300262 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
263 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
thomas schorppf63f5342005-09-09 13:03:06 -0700264 }
265 if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
266 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
267 break;
268 case 2:
269 dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
270 if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
271 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
272 break;
273 case 3:
274 dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
275 if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
276 dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
277 break;
278 default:
279 dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 }
281 } else {
282 adswitch = 0;
283 source = SAA7146_HPS_SOURCE_PORT_A;
284 sync = SAA7146_HPS_SYNC_PORT_A;
285 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
286 dprintk(1, "switching DVB mode\n");
287 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
288 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
289 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
290 msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
291 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
292 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
293
294 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
295 if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
296 dprintk(1, "setting band in demodulator failed.\n");
297 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300298 saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
299 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 }
301 }
302
303 /* hmm, this does not do anything!? */
304 if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
305 dprintk(1, "ADSwitch error\n");
306
307 saa7146_set_hps_source_and_sync(dev, source, sync);
308
309 if (vv->ov_suspend != NULL) {
310 saa7146_start_preview(vv->ov_suspend);
311 vv->ov_suspend = NULL;
312 }
313
314 return 0;
315}
316
317static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
318{
319 struct saa7146_dev *dev = fh->dev;
320 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
321 dprintk(4, "saa7146_dev: %p\n", dev);
322
323 switch (cmd) {
324 case VIDIOC_G_TUNER:
325 {
326 struct v4l2_tuner *t = arg;
327 u16 stereo_det;
328 s8 stereo;
329
330 dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
331
332 if (!av7110->analog_tuner_flags || t->index != 0)
333 return -EINVAL;
334
335 memset(t, 0, sizeof(*t));
Oliver Endriss804b4452007-07-12 20:37:50 -0300336 strcpy((char *)t->name, "Television");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 t->type = V4L2_TUNER_ANALOG_TV;
339 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
340 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
341 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
342 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
343 /* FIXME: add the real signal strength here */
344 t->signal = 0xffff;
345 t->afc = 0;
346
347 // FIXME: standard / stereo detection is still broken
348 msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
349 dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
351 dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
352 stereo = (s8)(stereo_det >> 8);
353 if (stereo > 0x10) {
354 /* stereo */
355 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
356 t->audmode = V4L2_TUNER_MODE_STEREO;
357 }
358 else if (stereo < -0x10) {
thomas schorppf63f5342005-09-09 13:03:06 -0700359 /* bilingual */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
361 t->audmode = V4L2_TUNER_MODE_LANG1;
362 }
363 else /* mono */
364 t->rxsubchans = V4L2_TUNER_SUB_MONO;
365
366 return 0;
367 }
368 case VIDIOC_S_TUNER:
369 {
370 struct v4l2_tuner *t = arg;
371 u16 fm_matrix, src;
372 dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
373
374 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
375 return -EINVAL;
376
377 switch (t->audmode) {
378 case V4L2_TUNER_MODE_STEREO:
379 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
380 fm_matrix = 0x3001; // stereo
381 src = 0x0020;
382 break;
Hans Verkuil301e22d2006-03-18 17:15:00 -0300383 case V4L2_TUNER_MODE_LANG1_LANG2:
384 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
385 fm_matrix = 0x3000; // bilingual
386 src = 0x0020;
387 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 case V4L2_TUNER_MODE_LANG1:
389 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
390 fm_matrix = 0x3000; // mono
391 src = 0x0000;
392 break;
393 case V4L2_TUNER_MODE_LANG2:
394 dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
395 fm_matrix = 0x3000; // mono
396 src = 0x0010;
397 break;
thomas schorppf63f5342005-09-09 13:03:06 -0700398 default: /* case V4L2_TUNER_MODE_MONO: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
400 fm_matrix = 0x3000; // mono
401 src = 0x0030;
402 break;
403 }
404 msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
405 msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
406 msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
407 msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
408 return 0;
409 }
410 case VIDIOC_G_FREQUENCY:
411 {
412 struct v4l2_frequency *f = arg;
413
414 dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
415
416 if (!av7110->analog_tuner_flags || av7110->current_input != 1)
417 return -EINVAL;
418
419 memset(f, 0, sizeof(*f));
420 f->type = V4L2_TUNER_ANALOG_TV;
421 f->frequency = av7110->current_freq;
422 return 0;
423 }
424 case VIDIOC_S_FREQUENCY:
425 {
426 struct v4l2_frequency *f = arg;
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 }
445 av7110->current_freq = f->frequency;
446
447 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
448 msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
449 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
450 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
451 return 0;
452 }
453 case VIDIOC_ENUMINPUT:
454 {
455 struct v4l2_input *i = arg;
456
457 dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
458
459 if (av7110->analog_tuner_flags) {
thomas schorppf63f5342005-09-09 13:03:06 -0700460 if (i->index < 0 || i->index >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 return -EINVAL;
462 } else {
463 if (i->index != 0)
464 return -EINVAL;
465 }
466
467 memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
468
469 return 0;
470 }
471 case VIDIOC_G_INPUT:
472 {
473 int *input = (int *)arg;
474 *input = av7110->current_input;
475 dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
476 return 0;
477 }
478 case VIDIOC_S_INPUT:
479 {
480 int input = *(int *)arg;
481
482 dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
483
484 if (!av7110->analog_tuner_flags)
485 return 0;
486
thomas schorppf63f5342005-09-09 13:03:06 -0700487 if (input < 0 || input >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 return -EINVAL;
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 av7110->current_input = input;
491 return av7110_dvb_c_switch(fh);
492 }
493 case VIDIOC_G_AUDIO:
494 {
495 struct v4l2_audio *a = arg;
496
497 dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
498 if (a->index != 0)
499 return -EINVAL;
500 memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
501 break;
502 }
503 case VIDIOC_S_AUDIO:
504 {
505 struct v4l2_audio *a = arg;
506 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
507 break;
508 }
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200509 case VIDIOC_G_SLICED_VBI_CAP:
510 {
511 struct v4l2_sliced_vbi_cap *cap = arg;
512 dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
513 memset(cap, 0, sizeof *cap);
514 if (FW_VERSION(av7110->arm_app) >= 0x2623) {
515 cap->service_set = V4L2_SLICED_WSS_625;
516 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
517 }
518 break;
519 }
520 case VIDIOC_G_FMT:
521 {
522 struct v4l2_format *f = arg;
523 dprintk(2, "VIDIOC_G_FMT:\n");
524 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
525 FW_VERSION(av7110->arm_app) < 0x2623)
526 return -EAGAIN; /* handled by core driver */
527 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
528 if (av7110->wssMode) {
529 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
530 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
531 f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
532 }
533 break;
534 }
535 case VIDIOC_S_FMT:
536 {
537 struct v4l2_format *f = arg;
538 dprintk(2, "VIDIOC_S_FMT\n");
539 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
540 FW_VERSION(av7110->arm_app) < 0x2623)
541 return -EAGAIN; /* handled by core driver */
542 if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
543 f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
544 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
545 /* WSS controlled by firmware */
546 av7110->wssMode = 0;
547 av7110->wssData = 0;
548 return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
549 SetWSSConfig, 1, 0);
550 } else {
551 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
552 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
553 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
554 f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
555 /* WSS controlled by userspace */
556 av7110->wssMode = 1;
557 av7110->wssData = 0;
558 }
559 break;
560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 default:
562 printk("no such ioctl\n");
563 return -ENOIOCTLCMD;
564 }
565 return 0;
566}
567
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200568static int av7110_vbi_reset(struct inode *inode, struct file *file)
569{
570 struct saa7146_fh *fh = file->private_data;
571 struct saa7146_dev *dev = fh->dev;
572 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
573
574 dprintk(2, "%s\n", __FUNCTION__);
575 av7110->wssMode = 0;
576 av7110->wssData = 0;
577 if (FW_VERSION(av7110->arm_app) < 0x2623)
578 return 0;
579 else
580 return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
581}
582
583static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
584{
585 struct saa7146_fh *fh = file->private_data;
586 struct saa7146_dev *dev = fh->dev;
587 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
588 struct v4l2_sliced_vbi_data d;
589 int rc;
590
591 dprintk(2, "%s\n", __FUNCTION__);
592 if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
593 return -EINVAL;
594 if (copy_from_user(&d, data, count))
595 return -EFAULT;
596 if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
597 return -EINVAL;
Oliver Endriss4caba422006-03-17 05:29:15 -0300598 if (d.id)
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200599 av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
Oliver Endriss4caba422006-03-17 05:29:15 -0300600 else
601 av7110->wssData = 0x8000;
602 rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200603 return (rc < 0) ? rc : count;
604}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606/****************************************************************************
607 * INITIALIZATION
608 ****************************************************************************/
609
610static struct saa7146_extension_ioctls ioctls[] = {
611 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
612 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
613 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
614 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
615 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
616 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
617 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
618 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
619 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200620 { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
621 { VIDIOC_G_FMT, SAA7146_BEFORE },
622 { VIDIOC_S_FMT, SAA7146_BEFORE },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 { 0, 0 }
624};
625
626static u8 saa7113_init_regs[] = {
627 0x02, 0xd0,
628 0x03, 0x23,
629 0x04, 0x00,
630 0x05, 0x00,
631 0x06, 0xe9,
632 0x07, 0x0d,
633 0x08, 0x98,
634 0x09, 0x02,
635 0x0a, 0x80,
636 0x0b, 0x40,
637 0x0c, 0x40,
638 0x0d, 0x00,
639 0x0e, 0x01,
640 0x0f, 0x7c,
641 0x10, 0x48,
642 0x11, 0x0c,
643 0x12, 0x8b,
644 0x13, 0x1a,
645 0x14, 0x00,
646 0x15, 0x00,
647 0x16, 0x00,
648 0x17, 0x00,
649 0x18, 0x00,
650 0x19, 0x00,
651 0x1a, 0x00,
652 0x1b, 0x00,
653 0x1c, 0x00,
654 0x1d, 0x00,
655 0x1e, 0x00,
656
657 0x41, 0x77,
658 0x42, 0x77,
659 0x43, 0x77,
660 0x44, 0x77,
661 0x45, 0x77,
662 0x46, 0x77,
663 0x47, 0x77,
664 0x48, 0x77,
665 0x49, 0x77,
666 0x4a, 0x77,
667 0x4b, 0x77,
668 0x4c, 0x77,
669 0x4d, 0x77,
670 0x4e, 0x77,
671 0x4f, 0x77,
672 0x50, 0x77,
673 0x51, 0x77,
674 0x52, 0x77,
675 0x53, 0x77,
676 0x54, 0x77,
677 0x55, 0x77,
678 0x56, 0x77,
679 0x57, 0xff,
680
681 0xff
682};
683
684
685static struct saa7146_ext_vv av7110_vv_data_st;
686static struct saa7146_ext_vv av7110_vv_data_c;
687
688int av7110_init_analog_module(struct av7110 *av7110)
689{
690 u16 version1, version2;
691
Tim Kaiser61391e02006-06-25 09:14:07 -0300692 if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
693 i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
694 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
695 av7110->dvb_adapter.num);
696 av7110->adac_type = DVB_ADAC_MSP34x0;
697 } else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
698 i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
699 printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
700 av7110->dvb_adapter.num);
701 av7110->adac_type = DVB_ADAC_MSP34x5;
702 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 return -ENODEV;
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 msleep(100); // the probing above resets the msp...
706 msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
707 msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
Tim Kaiser61391e02006-06-25 09:14:07 -0300708 dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700709 av7110->dvb_adapter.num, version1, version2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
711 msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
712 msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
713 msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
714 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
715 msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
716 msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
Tim Kaiser61391e02006-06-25 09:14:07 -0300717 msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719 if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
720 INFO(("saa7113 not accessible.\n"));
721 } else {
722 u8 *i = saa7113_init_regs;
723
724 if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
725 /* Fujitsu/Siemens DVB-Cable */
726 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
727 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
728 /* Hauppauge/TT DVB-C premium */
729 av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
730 } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
731 /* Hauppauge/TT DVB-C premium */
732 av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
733 }
734
735 /* setup for DVB by default */
736 if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
737 if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
738 dprintk(1, "setting band in demodulator failed.\n");
739 } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
Marco Schluessler6a857742006-07-10 03:34:16 -0300740 saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
741 saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
743
744 /* init the saa7113 */
745 while (*i != 0xff) {
746 if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700747 dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 break;
749 }
750 i += 2;
751 }
752 /* setup msp for analog sound: B/G Dual-FM */
753 msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
754 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 3); // FIR1
755 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
756 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
757 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
758 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
759 msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
760 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 4); // FIR2
761 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
762 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 0); // FIR2
763 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 3); // FIR2
764 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
765 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
766 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
767 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
768 msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
769 msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
770 msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
771 msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
772 msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
773 msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
774 msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
775 }
776
777 memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
778 /* set dd1 stream a & b */
779 saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
780 saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
781 saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
782
783 return 0;
784}
785
786int av7110_init_v4l(struct av7110 *av7110)
787{
788 struct saa7146_dev* dev = av7110->dev;
789 int ret;
790
791 /* special case DVB-C: these cards have an analog tuner
792 plus need some special handling, so we have separate
793 saa7146_ext_vv data for these... */
794 if (av7110->analog_tuner_flags)
795 ret = saa7146_vv_init(dev, &av7110_vv_data_c);
796 else
797 ret = saa7146_vv_init(dev, &av7110_vv_data_st);
798
799 if (ret) {
800 ERR(("cannot init capture device. skipping.\n"));
801 return -ENODEV;
802 }
803
804 if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
805 ERR(("cannot register capture device. skipping.\n"));
806 saa7146_vv_release(dev);
807 return -ENODEV;
808 }
Oliver Endriss78577352007-01-27 21:13:06 -0300809 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200810 ERR(("cannot register vbi v4l2 device. skipping.\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 return 0;
812}
813
814int av7110_exit_v4l(struct av7110 *av7110)
815{
Marco Schluesslere19c55f2007-01-31 14:32:29 -0300816 struct saa7146_dev* dev = av7110->dev;
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
Oliver Endriss78577352007-01-27 21:13:06 -0300819 saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
Marco Schluesslere19c55f2007-01-31 14:32:29 -0300820
821 saa7146_vv_release(dev);
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 return 0;
824}
825
826
827
828/* FIXME: these values are experimental values that look better than the
829 values from the latest "official" driver -- at least for me... (MiHu) */
830static struct saa7146_standard standard[] = {
831 {
832 .name = "PAL", .id = V4L2_STD_PAL_BG,
833 .v_offset = 0x15, .v_field = 288,
834 .h_offset = 0x48, .h_pixels = 708,
835 .v_max_out = 576, .h_max_out = 768,
836 }, {
837 .name = "NTSC", .id = V4L2_STD_NTSC,
838 .v_offset = 0x10, .v_field = 244,
839 .h_offset = 0x40, .h_pixels = 708,
840 .v_max_out = 480, .h_max_out = 640,
841 }
842};
843
844static struct saa7146_standard analog_standard[] = {
845 {
846 .name = "PAL", .id = V4L2_STD_PAL_BG,
847 .v_offset = 0x1b, .v_field = 288,
848 .h_offset = 0x08, .h_pixels = 708,
849 .v_max_out = 576, .h_max_out = 768,
850 }, {
851 .name = "NTSC", .id = V4L2_STD_NTSC,
852 .v_offset = 0x10, .v_field = 244,
853 .h_offset = 0x40, .h_pixels = 708,
854 .v_max_out = 480, .h_max_out = 640,
855 }
856};
857
858static struct saa7146_standard dvb_standard[] = {
859 {
860 .name = "PAL", .id = V4L2_STD_PAL_BG,
861 .v_offset = 0x14, .v_field = 288,
862 .h_offset = 0x48, .h_pixels = 708,
863 .v_max_out = 576, .h_max_out = 768,
864 }, {
865 .name = "NTSC", .id = V4L2_STD_NTSC,
866 .v_offset = 0x10, .v_field = 244,
867 .h_offset = 0x40, .h_pixels = 708,
868 .v_max_out = 480, .h_max_out = 640,
869 }
870};
871
872static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
873{
874 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
875
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700876 if (std->id & V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 av7110->vidmode = VIDEO_MODE_PAL;
878 av7110_set_vidmode(av7110, av7110->vidmode);
879 }
Johannes Stezenbach4ab3f082005-05-16 21:54:27 -0700880 else if (std->id & V4L2_STD_NTSC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 av7110->vidmode = VIDEO_MODE_NTSC;
882 av7110_set_vidmode(av7110, av7110->vidmode);
883 }
884 else
885 return -1;
886
887 return 0;
888}
889
890
891static struct saa7146_ext_vv av7110_vv_data_st = {
892 .inputs = 1,
893 .audios = 1,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200894 .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 .flags = 0,
896
897 .stds = &standard[0],
898 .num_stds = ARRAY_SIZE(standard),
899 .std_callback = &std_callback,
900
901 .ioctls = &ioctls[0],
902 .ioctl = av7110_ioctl,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200903
904 .vbi_fops.open = av7110_vbi_reset,
905 .vbi_fops.release = av7110_vbi_reset,
906 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907};
908
909static struct saa7146_ext_vv av7110_vv_data_c = {
910 .inputs = 1,
911 .audios = 1,
Oliver Endrissd7e7a152006-09-14 00:43:22 -0300912 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 .flags = SAA7146_USE_PORT_B_FOR_VBI,
914
915 .stds = &standard[0],
916 .num_stds = ARRAY_SIZE(standard),
917 .std_callback = &std_callback,
918
919 .ioctls = &ioctls[0],
920 .ioctl = av7110_ioctl,
Oliver Endriss5b0fa4f2006-01-09 18:21:37 -0200921
922 .vbi_fops.open = av7110_vbi_reset,
923 .vbi_fops.release = av7110_vbi_reset,
924 .vbi_fops.write = av7110_vbi_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925};
926