aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mxb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/video/mxb.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/media/video/mxb.c')
-rw-r--r--drivers/media/video/mxb.c1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
new file mode 100644
index 000000000000..70bf1f1fad59
--- /dev/null
+++ b/drivers/media/video/mxb.c
@@ -0,0 +1,1035 @@
1/*
2 mxb - v4l2 driver for the Multimedia eXtension Board
3
4 Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
5
6 Visit http://www.mihu.de/linux/saa7146/mxb/
7 for further details about this card.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#define DEBUG_VARIABLE debug
25
26#include <media/saa7146_vv.h>
27#include <media/tuner.h>
28#include <linux/video_decoder.h>
29
30#include "mxb.h"
31#include "tea6415c.h"
32#include "tea6420.h"
33#include "tda9840.h"
34
35#define I2C_SAA7111 0x24
36
37#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
38
39/* global variable */
40static int mxb_num = 0;
41
42/* initial frequence the tuner will be tuned to.
43 in verden (lower saxony, germany) 4148 is a
44 channel called "phoenix" */
45static int freq = 4148;
46module_param(freq, int, 0644);
47MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
48
49static int debug = 0;
50module_param(debug, int, 0644);
51MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
52
53#define MXB_INPUTS 4
54enum { TUNER, AUX1, AUX3, AUX3_YC };
55
56static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
57 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
58 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
59 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
60 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
61};
62
63/* this array holds the information, which port of the saa7146 each
64 input actually uses. the mxb uses port 0 for every input */
65static struct {
66 int hps_source;
67 int hps_sync;
68} input_port_selection[MXB_INPUTS] = {
69 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
70 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
71 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
72 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
73};
74
75/* this array holds the information of the audio source (mxb_audios),
76 which has to be switched corresponding to the video source (mxb_channels) */
77static int video_audio_connect[MXB_INPUTS] =
78 { 0, 1, 3, 3 };
79
80/* these are the necessary input-output-pins for bringing one audio source
81(see above) to the CD-output */
82static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
83 {
84 {{1,1,0},{1,1,0}}, /* Tuner */
85 {{5,1,0},{6,1,0}}, /* AUX 1 */
86 {{4,1,0},{6,1,0}}, /* AUX 2 */
87 {{3,1,0},{6,1,0}}, /* AUX 3 */
88 {{1,1,0},{3,1,0}}, /* Radio */
89 {{1,1,0},{2,1,0}}, /* CD-Rom */
90 {{6,1,0},{6,1,0}} /* Mute */
91 };
92
93/* these are the necessary input-output-pins for bringing one audio source
94(see above) to the line-output */
95static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
96 {
97 {{2,3,0},{1,2,0}},
98 {{5,3,0},{6,2,0}},
99 {{4,3,0},{6,2,0}},
100 {{3,3,0},{6,2,0}},
101 {{2,3,0},{3,2,0}},
102 {{2,3,0},{2,2,0}},
103 {{6,3,0},{6,2,0}} /* Mute */
104 };
105
106#define MAXCONTROLS 1
107static struct v4l2_queryctrl mxb_controls[] = {
108 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
109};
110
111static struct saa7146_extension_ioctls ioctls[] = {
112 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
113 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
114 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
115 { VIDIOC_QUERYCTRL, SAA7146_BEFORE },
116 { VIDIOC_G_CTRL, SAA7146_BEFORE },
117 { VIDIOC_S_CTRL, SAA7146_BEFORE },
118 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
119 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
120 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
121 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
122 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
123 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
124 { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */
125 { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */
126 { 0, 0 }
127};
128
129struct mxb
130{
131 struct video_device *video_dev;
132 struct video_device *vbi_dev;
133
134 struct i2c_adapter i2c_adapter;
135
136 struct i2c_client* saa7111a;
137 struct i2c_client* tda9840;
138 struct i2c_client* tea6415c;
139 struct i2c_client* tuner;
140 struct i2c_client* tea6420_1;
141 struct i2c_client* tea6420_2;
142
143 int cur_mode; /* current audio mode (mono, stereo, ...) */
144 int cur_input; /* current input */
145 int cur_freq; /* current frequency the tuner is tuned to */
146 int cur_mute; /* current mute status */
147};
148
149static struct saa7146_extension extension;
150
151static int mxb_probe(struct saa7146_dev* dev)
152{
153 struct mxb* mxb = NULL;
154 struct i2c_client *client;
155 struct list_head *item;
156 int result;
157
158 if ((result = request_module("saa7111")) < 0) {
159 printk("mxb: saa7111 i2c module not available.\n");
160 return -ENODEV;
161 }
162 if ((result = request_module("tuner")) < 0) {
163 printk("mxb: tuner i2c module not available.\n");
164 return -ENODEV;
165 }
166 if ((result = request_module("tea6420")) < 0) {
167 printk("mxb: tea6420 i2c module not available.\n");
168 return -ENODEV;
169 }
170 if ((result = request_module("tea6415c")) < 0) {
171 printk("mxb: tea6415c i2c module not available.\n");
172 return -ENODEV;
173 }
174 if ((result = request_module("tda9840")) < 0) {
175 printk("mxb: tda9840 i2c module not available.\n");
176 return -ENODEV;
177 }
178
179 mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
180 if( NULL == mxb ) {
181 DEB_D(("not enough kernel memory.\n"));
182 return -ENOMEM;
183 }
184 memset(mxb, 0x0, sizeof(struct mxb));
185
186 mxb->i2c_adapter = (struct i2c_adapter) {
187 .class = I2C_CLASS_TV_ANALOG,
188 .name = "mxb",
189 };
190
191 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
192 if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
193 DEB_S(("cannot register i2c-device. skipping.\n"));
194 kfree(mxb);
195 return -EFAULT;
196 }
197
198 /* loop through all i2c-devices on the bus and look who is there */
199 list_for_each(item,&mxb->i2c_adapter.clients) {
200 client = list_entry(item, struct i2c_client, list);
201 if( I2C_TEA6420_1 == client->addr )
202 mxb->tea6420_1 = client;
203 if( I2C_TEA6420_2 == client->addr )
204 mxb->tea6420_2 = client;
205 if( I2C_TEA6415C_2 == client->addr )
206 mxb->tea6415c = client;
207 if( I2C_TDA9840 == client->addr )
208 mxb->tda9840 = client;
209 if( I2C_SAA7111 == client->addr )
210 mxb->saa7111a = client;
211 if( 0x60 == client->addr )
212 mxb->tuner = client;
213 }
214
215 /* check if all devices are present */
216 if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c
217 || 0 == mxb->tda9840 || 0 == mxb->saa7111a || 0 == mxb->tuner ) {
218
219 printk("mxb: did not find all i2c devices. aborting\n");
220 i2c_del_adapter(&mxb->i2c_adapter);
221 kfree(mxb);
222 return -ENODEV;
223 }
224
225 /* all devices are present, probe was successful */
226
227 /* we store the pointer in our private data field */
228 dev->ext_priv = mxb;
229
230 return 0;
231}
232
233/* some init data for the saa7740, the so-called 'sound arena module'.
234 there are no specs available, so we simply use some init values */
235static struct {
236 int length;
237 char data[9];
238} mxb_saa7740_init[] = {
239 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
240 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
241 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
242 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
243 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
244 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
245 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
246 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
247 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
248 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
249 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
250 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
251 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
252 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
253 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
254 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
255 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
256 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
257 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
258 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
259 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
260 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
261 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
262 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
263 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
264 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
265 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
266 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
267 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
268 { 3, { 0x48, 0x00, 0x01 } },
269 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
270 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
271 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
272 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
273 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
274 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
275 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
276 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
277 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
278 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
279 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
280 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
281 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
282 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
283 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
284 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
285 { 3, { 0x80, 0xb3, 0x0a } },
286 {-1, { 0} }
287};
288
289static const unsigned char mxb_saa7111_init[] = {
290 0x00, 0x00, /* 00 - ID byte */
291 0x01, 0x00, /* 01 - reserved */
292
293 /*front end */
294 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */
295 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
296 0x04, 0x00, /* 04 - GAI1=256 */
297 0x05, 0x00, /* 05 - GAI2=256 */
298
299 /* decoder */
300 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */
301 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */
302 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */
303 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */
304 0x0a, 0x80, /* 0a - BRIG=128 */
305 0x0b, 0x47, /* 0b - CONT=1.109 */
306 0x0c, 0x40, /* 0c - SATN=1.0 */
307 0x0d, 0x00, /* 0d - HUE=0 */
308 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
309 0x0f, 0x00, /* 0f - reserved */
310 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */
311 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
312 0x12, 0x80, /* 12 - xx output control 2 */
313 0x13, 0x30, /* 13 - xx output control 3 */
314 0x14, 0x00, /* 14 - reserved */
315 0x15, 0x15, /* 15 - VBI */
316 0x16, 0x04, /* 16 - VBI */
317 0x17, 0x00, /* 17 - VBI */
318};
319
320/* bring hardware to a sane state. this has to be done, just in case someone
321 wants to capture from this device before it has been properly initialized.
322 the capture engine would badly fail, because no valid signal arrives on the
323 saa7146, thus leading to timeouts and stuff. */
324static int mxb_init_done(struct saa7146_dev* dev)
325{
326 struct mxb* mxb = (struct mxb*)dev->ext_priv;
327 struct video_decoder_init init;
328 struct i2c_msg msg;
329
330 int i = 0, err = 0;
331 struct tea6415c_multiplex vm;
332
333 /* select video mode in saa7111a */
334 i = VIDEO_MODE_PAL;
335 /* fixme: currently pointless: gets overwritten by configuration below */
336 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
337
338 /* write configuration to saa7111a */
339 init.data = mxb_saa7111_init;
340 init.len = sizeof(mxb_saa7111_init);
341 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init);
342
343 /* select tuner-output on saa7111a */
344 i = 0;
345 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
346
347 /* enable vbi bypass */
348 i = 1;
349 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i);
350
351 /* select a tuner type */
352 i = 5;
353 mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE, &i);
354
355 /* mute audio on tea6420s */
356 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
357 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
358 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
359 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
360
361 /* switch to tuner-channel on tea6415c*/
362 vm.out = 17;
363 vm.in = 3;
364 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
365
366 /* select tuner-output on multicable on tea6415c*/
367 vm.in = 3;
368 vm.out = 13;
369 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
370
371 /* tune in some frequency on tuner */
372 mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &freq);
373
374 /* the rest for mxb */
375 mxb->cur_input = 0;
376 mxb->cur_freq = freq;
377 mxb->cur_mute = 1;
378
379 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
380 mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
381
382 /* check if the saa7740 (aka 'sound arena module') is present
383 on the mxb. if so, we must initialize it. due to lack of
384 informations about the saa7740, the values were reverse
385 engineered. */
386 msg.addr = 0x1b;
387 msg.flags = 0;
388 msg.len = mxb_saa7740_init[0].length;
389 msg.buf = &mxb_saa7740_init[0].data[0];
390
391 if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
392 /* the sound arena module is a pos, that's probably the reason
393 philips refuses to hand out a datasheet for the saa7740...
394 it seems to screw up the i2c bus, so we disable fast irq
395 based i2c transactions here and rely on the slow and safe
396 polling method ... */
397 extension.flags &= ~SAA7146_USE_I2C_IRQ;
398 for(i = 1;;i++) {
399 if( -1 == mxb_saa7740_init[i].length ) {
400 break;
401 }
402
403 msg.len = mxb_saa7740_init[i].length;
404 msg.buf = &mxb_saa7740_init[i].data[0];
405 if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
406 DEB_D(("failed to initialize 'sound arena module'.\n"));
407 goto err;
408 }
409 }
410 INFO(("'sound arena module' detected.\n"));
411 }
412err:
413 /* the rest for saa7146: you should definitely set some basic values
414 for the input-port handling of the saa7146. */
415
416 /* ext->saa has been filled by the core driver */
417
418 /* some stuff is done via variables */
419 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
420
421 /* some stuff is done via direct write to the registers */
422
423 /* this is ugly, but because of the fact that this is completely
424 hardware dependend, it should be done directly... */
425 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
426 saa7146_write(dev, DD1_INIT, 0x02000200);
427 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
428
429 return 0;
430}
431
432/* interrupt-handler. this gets called when irq_mask is != 0.
433 it must clear the interrupt-bits in irq_mask it has handled */
434/*
435void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
436{
437 struct mxb* mxb = (struct mxb*)dev->ext_priv;
438}
439*/
440
441static struct saa7146_ext_vv vv_data;
442
443/* this function only gets called when the probing was successful */
444static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
445{
446 struct mxb* mxb = (struct mxb*)dev->ext_priv;
447
448 DEB_EE(("dev:%p\n",dev));
449
450 /* checking for i2c-devices can be omitted here, because we
451 already did this in "mxb_vl42_probe" */
452
453 saa7146_vv_init(dev,&vv_data);
454 if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
455 ERR(("cannot register capture v4l2 device. skipping.\n"));
456 return -1;
457 }
458
459 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
460 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
461 if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
462 ERR(("cannot register vbi v4l2 device. skipping.\n"));
463 }
464 }
465
466 i2c_use_client(mxb->tea6420_1);
467 i2c_use_client(mxb->tea6420_2);
468 i2c_use_client(mxb->tea6415c);
469 i2c_use_client(mxb->tda9840);
470 i2c_use_client(mxb->saa7111a);
471 i2c_use_client(mxb->tuner);
472
473 printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
474
475 mxb_num++;
476 mxb_init_done(dev);
477 return 0;
478}
479
480static int mxb_detach(struct saa7146_dev* dev)
481{
482 struct mxb* mxb = (struct mxb*)dev->ext_priv;
483
484 DEB_EE(("dev:%p\n",dev));
485
486 i2c_release_client(mxb->tea6420_1);
487 i2c_release_client(mxb->tea6420_2);
488 i2c_release_client(mxb->tea6415c);
489 i2c_release_client(mxb->tda9840);
490 i2c_release_client(mxb->saa7111a);
491 i2c_release_client(mxb->tuner);
492
493 saa7146_unregister_device(&mxb->video_dev,dev);
494 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
495 saa7146_unregister_device(&mxb->vbi_dev,dev);
496 }
497 saa7146_vv_release(dev);
498
499 mxb_num--;
500
501 i2c_del_adapter(&mxb->i2c_adapter);
502 kfree(mxb);
503
504 return 0;
505}
506
507static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
508{
509 struct saa7146_dev *dev = fh->dev;
510 struct mxb* mxb = (struct mxb*)dev->ext_priv;
511 struct saa7146_vv *vv = dev->vv_data;
512
513 switch(cmd) {
514 case VIDIOC_ENUMINPUT:
515 {
516 struct v4l2_input *i = arg;
517
518 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
519 if( i->index < 0 || i->index >= MXB_INPUTS) {
520 return -EINVAL;
521 }
522 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
523
524 return 0;
525 }
526 /* the saa7146 provides some controls (brightness, contrast, saturation)
527 which gets registered *after* this function. because of this we have
528 to return with a value != 0 even if the function succeded.. */
529 case VIDIOC_QUERYCTRL:
530 {
531 struct v4l2_queryctrl *qc = arg;
532 int i;
533
534 for (i = MAXCONTROLS - 1; i >= 0; i--) {
535 if (mxb_controls[i].id == qc->id) {
536 *qc = mxb_controls[i];
537 DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
538 return 0;
539 }
540 }
541 return -EAGAIN;
542 }
543 case VIDIOC_G_CTRL:
544 {
545 struct v4l2_control *vc = arg;
546 int i;
547
548 for (i = MAXCONTROLS - 1; i >= 0; i--) {
549 if (mxb_controls[i].id == vc->id) {
550 break;
551 }
552 }
553
554 if( i < 0 ) {
555 return -EAGAIN;
556 }
557
558 switch (vc->id ) {
559 case V4L2_CID_AUDIO_MUTE: {
560 vc->value = mxb->cur_mute;
561 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
562 return 0;
563 }
564 }
565
566 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
567 return 0;
568 }
569
570 case VIDIOC_S_CTRL:
571 {
572 struct v4l2_control *vc = arg;
573 int i = 0;
574
575 for (i = MAXCONTROLS - 1; i >= 0; i--) {
576 if (mxb_controls[i].id == vc->id) {
577 break;
578 }
579 }
580
581 if( i < 0 ) {
582 return -EAGAIN;
583 }
584
585 switch (vc->id ) {
586 case V4L2_CID_AUDIO_MUTE: {
587 mxb->cur_mute = vc->value;
588 if( 0 == vc->value ) {
589 /* switch the audio-source */
590 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
591 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
592 } else {
593 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
594 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
595 }
596 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
597 break;
598 }
599 }
600 return 0;
601 }
602 case VIDIOC_G_INPUT:
603 {
604 int *input = (int *)arg;
605 *input = mxb->cur_input;
606
607 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
608 return 0;
609 }
610 case VIDIOC_S_INPUT:
611 {
612 int input = *(int *)arg;
613 struct tea6415c_multiplex vm;
614 int i = 0;
615
616 DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
617
618 if (input < 0 || input >= MXB_INPUTS) {
619 return -EINVAL;
620 }
621
622 /* fixme: locke das setzen des inputs mit hilfe des mutexes
623 down(&dev->lock);
624 video_mux(dev,*i);
625 up(&dev->lock);
626 */
627
628 /* fixme: check if streaming capture
629 if ( 0 != dev->streaming ) {
630 DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
631 return -EPERM;
632 }
633 */
634
635 mxb->cur_input = input;
636
637 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
638
639 /* prepare switching of tea6415c and saa7111a;
640 have a look at the 'background'-file for further informations */
641 switch( input ) {
642
643 case TUNER:
644 {
645 i = 0;
646 vm.in = 3;
647 vm.out = 17;
648
649 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
650 printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
651 return -EFAULT;
652 }
653 /* connect tuner-output always to multicable */
654 vm.in = 3;
655 vm.out = 13;
656 break;
657 }
658 case AUX3_YC:
659 {
660 /* nothing to be done here. aux3_yc is
661 directly connected to the saa711a */
662 i = 5;
663 break;
664 }
665 case AUX3:
666 {
667 /* nothing to be done here. aux3 is
668 directly connected to the saa711a */
669 i = 1;
670 break;
671 }
672 case AUX1:
673 {
674 i = 0;
675 vm.in = 1;
676 vm.out = 17;
677 break;
678 }
679 }
680
681 /* switch video in tea6415c only if necessary */
682 switch( input ) {
683 case TUNER:
684 case AUX1:
685 {
686 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
687 printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
688 return -EFAULT;
689 }
690 break;
691 }
692 default:
693 {
694 break;
695 }
696 }
697
698 /* switch video in saa7111a */
699 if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
700 printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
701 }
702
703 /* switch the audio-source only if necessary */
704 if( 0 == mxb->cur_mute ) {
705 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
706 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
707 }
708
709 return 0;
710 }
711 case VIDIOC_G_TUNER:
712 {
713 struct v4l2_tuner *t = arg;
714 int byte = 0;
715
716 if( 0 != t->index ) {
717 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
718 return -EINVAL;
719 }
720
721 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
722
723 memset(t,0,sizeof(*t));
724 strcpy(t->name, "Television");
725
726 t->type = V4L2_TUNER_ANALOG_TV;
727 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
728 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
729 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
730 /* FIXME: add the real signal strength here */
731 t->signal = 0xffff;
732 t->afc = 0;
733
734 mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte);
735 t->audmode = mxb->cur_mode;
736
737 if( byte < 0 ) {
738 t->rxsubchans = V4L2_TUNER_SUB_MONO;
739 } else {
740 switch(byte) {
741 case TDA9840_MONO_DETECT: {
742 t->rxsubchans = V4L2_TUNER_SUB_MONO;
743 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
744 break;
745 }
746 case TDA9840_DUAL_DETECT: {
747 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
748 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
749 break;
750 }
751 case TDA9840_STEREO_DETECT: {
752 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
753 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
754 break;
755 }
756 default: { /* TDA9840_INCORRECT_DETECT */
757 t->rxsubchans = V4L2_TUNER_MODE_MONO;
758 DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
759 break;
760 }
761 }
762 }
763
764 return 0;
765 }
766 case VIDIOC_S_TUNER:
767 {
768 struct v4l2_tuner *t = arg;
769 int result = 0;
770 int byte = 0;
771
772 if( 0 != t->index ) {
773 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
774 return -EINVAL;
775 }
776
777 switch(t->audmode) {
778 case V4L2_TUNER_MODE_STEREO: {
779 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
780 byte = TDA9840_SET_STEREO;
781 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
782 break;
783 }
784 case V4L2_TUNER_MODE_LANG1: {
785 mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
786 byte = TDA9840_SET_LANG1;
787 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
788 break;
789 }
790 case V4L2_TUNER_MODE_LANG2: {
791 mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
792 byte = TDA9840_SET_LANG2;
793 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
794 break;
795 }
796 default: { /* case V4L2_TUNER_MODE_MONO: {*/
797 mxb->cur_mode = V4L2_TUNER_MODE_MONO;
798 byte = TDA9840_SET_MONO;
799 DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
800 break;
801 }
802 }
803
804 if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
805 printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
806 }
807
808 return 0;
809 }
810 case VIDIOC_G_FREQUENCY:
811 {
812 struct v4l2_frequency *f = arg;
813
814 if(0 != mxb->cur_input) {
815 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
816 return -EINVAL;
817 }
818
819 memset(f,0,sizeof(*f));
820 f->type = V4L2_TUNER_ANALOG_TV;
821 f->frequency = mxb->cur_freq;
822
823 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq));
824 return 0;
825 }
826 case VIDIOC_S_FREQUENCY:
827 {
828 struct v4l2_frequency *f = arg;
829 int t_locked = 0;
830 int v_byte = 0;
831
832 if (0 != f->tuner)
833 return -EINVAL;
834
835 if (V4L2_TUNER_ANALOG_TV != f->type)
836 return -EINVAL;
837
838 if(0 != mxb->cur_input) {
839 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
840 return -EINVAL;
841 }
842
843 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
844
845 mxb->cur_freq = f->frequency;
846
847 /* tune in desired frequency */
848 mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &mxb->cur_freq);
849
850 /* check if pll of tuner & saa7111a is locked */
851// mxb->tuner->driver->command(mxb->tuner,TUNER_IS_LOCKED, &t_locked);
852 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_GET_STATUS, &v_byte);
853
854 /* not locked -- anything to do here ? */
855 if( 0 == t_locked || 0 == (v_byte & DECODER_STATUS_GOOD)) {
856 }
857
858 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
859 spin_lock(&dev->slock);
860 vv->vbi_fieldcount = 0;
861 spin_unlock(&dev->slock);
862
863 return 0;
864 }
865 case MXB_S_AUDIO_CD:
866 {
867 int i = *(int*)arg;
868
869 if( i < 0 || i >= MXB_AUDIOS ) {
870 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
871 return -EINVAL;
872 }
873
874 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
875
876 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
877 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
878
879 return 0;
880 }
881 case MXB_S_AUDIO_LINE:
882 {
883 int i = *(int*)arg;
884
885 if( i < 0 || i >= MXB_AUDIOS ) {
886 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
887 return -EINVAL;
888 }
889
890 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
891 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
892 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
893
894 return 0;
895 }
896 case VIDIOC_G_AUDIO:
897 {
898 struct v4l2_audio *a = arg;
899
900 if( a->index < 0 || a->index > MXB_INPUTS ) {
901 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
902 return -EINVAL;
903 }
904
905 DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
906 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
907
908 return 0;
909 }
910 case VIDIOC_S_AUDIO:
911 {
912 struct v4l2_audio *a = arg;
913 DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
914 return 0;
915 }
916 default:
917/*
918 DEB2(printk("does not handle this ioctl.\n"));
919*/
920 return -ENOIOCTLCMD;
921 }
922 return 0;
923}
924
925static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
926{
927 struct mxb* mxb = (struct mxb*)dev->ext_priv;
928 int zero = 0;
929 int one = 1;
930
931 if(V4L2_STD_PAL_I == std->id ) {
932 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
933 /* set the 7146 gpio register -- I don't know what this does exactly */
934 saa7146_write(dev, GPIO_CTRL, 0x00404050);
935 /* unset the 7111 gpio register -- I don't know what this does exactly */
936 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
937 } else {
938 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
939 /* set the 7146 gpio register -- I don't know what this does exactly */
940 saa7146_write(dev, GPIO_CTRL, 0x00404050);
941 /* set the 7111 gpio register -- I don't know what this does exactly */
942 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
943 }
944 return 0;
945}
946
947static struct saa7146_standard standard[] = {
948 {
949 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
950 .v_offset = 0x17, .v_field = 288,
951 .h_offset = 0x14, .h_pixels = 680,
952 .v_max_out = 576, .h_max_out = 768,
953 }, {
954 .name = "PAL-I", .id = V4L2_STD_PAL_I,
955 .v_offset = 0x17, .v_field = 288,
956 .h_offset = 0x14, .h_pixels = 680,
957 .v_max_out = 576, .h_max_out = 768,
958 }, {
959 .name = "NTSC", .id = V4L2_STD_NTSC,
960 .v_offset = 0x16, .v_field = 240,
961 .h_offset = 0x06, .h_pixels = 708,
962 .v_max_out = 480, .h_max_out = 640,
963 }, {
964 .name = "SECAM", .id = V4L2_STD_SECAM,
965 .v_offset = 0x14, .v_field = 288,
966 .h_offset = 0x14, .h_pixels = 720,
967 .v_max_out = 576, .h_max_out = 768,
968 }
969};
970
971static struct saa7146_pci_extension_data mxb = {
972 .ext_priv = "Multimedia eXtension Board",
973 .ext = &extension,
974};
975
976static struct pci_device_id pci_tbl[] = {
977 {
978 .vendor = PCI_VENDOR_ID_PHILIPS,
979 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
980 .subvendor = 0x0000,
981 .subdevice = 0x0000,
982 .driver_data = (unsigned long)&mxb,
983 }, {
984 .vendor = 0,
985 }
986};
987
988MODULE_DEVICE_TABLE(pci, pci_tbl);
989
990static struct saa7146_ext_vv vv_data = {
991 .inputs = MXB_INPUTS,
992 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
993 .stds = &standard[0],
994 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
995 .std_callback = &std_callback,
996 .ioctls = &ioctls[0],
997 .ioctl = mxb_ioctl,
998};
999
1000static struct saa7146_extension extension = {
1001 .name = MXB_IDENTIFIER,
1002 .flags = SAA7146_USE_I2C_IRQ,
1003
1004 .pci_tbl = &pci_tbl[0],
1005 .module = THIS_MODULE,
1006
1007 .probe = mxb_probe,
1008 .attach = mxb_attach,
1009 .detach = mxb_detach,
1010
1011 .irq_mask = 0,
1012 .irq_func = NULL,
1013};
1014
1015static int __init mxb_init_module(void)
1016{
1017 if( 0 != saa7146_register_extension(&extension)) {
1018 DEB_S(("failed to register extension.\n"));
1019 return -ENODEV;
1020 }
1021
1022 return 0;
1023}
1024
1025static void __exit mxb_cleanup_module(void)
1026{
1027 saa7146_unregister_extension(&extension);
1028}
1029
1030module_init(mxb_init_module);
1031module_exit(mxb_cleanup_module);
1032
1033MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
1034MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
1035MODULE_LICENSE("GPL");