blob: 8416ceff524bf3f5900e5b684cf7e439fc19c4ec [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Michael Krufky5e453dc2006-01-09 15:32:31 -020029#include <media/v4l2-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31#include "mxb.h"
32#include "tea6415c.h"
33#include "tea6420.h"
34#include "tda9840.h"
35
36#define I2C_SAA7111 0x24
37
38#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
39
40/* global variable */
41static int mxb_num = 0;
42
43/* initial frequence the tuner will be tuned to.
44 in verden (lower saxony, germany) 4148 is a
45 channel called "phoenix" */
46static int freq = 4148;
47module_param(freq, int, 0644);
48MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
49
50static int debug = 0;
51module_param(debug, int, 0644);
52MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
53
54#define MXB_INPUTS 4
55enum { TUNER, AUX1, AUX3, AUX3_YC };
56
57static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
58 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
59 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
60 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
61 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
62};
63
64/* this array holds the information, which port of the saa7146 each
65 input actually uses. the mxb uses port 0 for every input */
66static struct {
67 int hps_source;
68 int hps_sync;
69} input_port_selection[MXB_INPUTS] = {
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 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
74};
75
76/* this array holds the information of the audio source (mxb_audios),
77 which has to be switched corresponding to the video source (mxb_channels) */
78static int video_audio_connect[MXB_INPUTS] =
79 { 0, 1, 3, 3 };
80
81/* these are the necessary input-output-pins for bringing one audio source
82(see above) to the CD-output */
83static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
84 {
85 {{1,1,0},{1,1,0}}, /* Tuner */
86 {{5,1,0},{6,1,0}}, /* AUX 1 */
87 {{4,1,0},{6,1,0}}, /* AUX 2 */
88 {{3,1,0},{6,1,0}}, /* AUX 3 */
89 {{1,1,0},{3,1,0}}, /* Radio */
90 {{1,1,0},{2,1,0}}, /* CD-Rom */
91 {{6,1,0},{6,1,0}} /* Mute */
92 };
93
94/* these are the necessary input-output-pins for bringing one audio source
95(see above) to the line-output */
96static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
97 {
98 {{2,3,0},{1,2,0}},
99 {{5,3,0},{6,2,0}},
100 {{4,3,0},{6,2,0}},
101 {{3,3,0},{6,2,0}},
102 {{2,3,0},{3,2,0}},
103 {{2,3,0},{2,2,0}},
104 {{6,3,0},{6,2,0}} /* Mute */
105 };
106
107#define MAXCONTROLS 1
108static struct v4l2_queryctrl mxb_controls[] = {
109 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
110};
111
112static struct saa7146_extension_ioctls ioctls[] = {
113 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
114 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
115 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
116 { VIDIOC_QUERYCTRL, SAA7146_BEFORE },
117 { VIDIOC_G_CTRL, SAA7146_BEFORE },
118 { VIDIOC_S_CTRL, SAA7146_BEFORE },
119 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
120 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
121 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
122 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
123 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
124 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
125 { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */
126 { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */
127 { 0, 0 }
128};
129
130struct mxb
131{
132 struct video_device *video_dev;
133 struct video_device *vbi_dev;
134
135 struct i2c_adapter i2c_adapter;
136
137 struct i2c_client* saa7111a;
138 struct i2c_client* tda9840;
139 struct i2c_client* tea6415c;
140 struct i2c_client* tuner;
141 struct i2c_client* tea6420_1;
142 struct i2c_client* tea6420_2;
143
144 int cur_mode; /* current audio mode (mono, stereo, ...) */
145 int cur_input; /* current input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700147 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148};
149
150static struct saa7146_extension extension;
151
152static int mxb_probe(struct saa7146_dev* dev)
153{
154 struct mxb* mxb = NULL;
155 struct i2c_client *client;
156 struct list_head *item;
157 int result;
158
159 if ((result = request_module("saa7111")) < 0) {
160 printk("mxb: saa7111 i2c module not available.\n");
161 return -ENODEV;
162 }
163 if ((result = request_module("tuner")) < 0) {
164 printk("mxb: tuner i2c module not available.\n");
165 return -ENODEV;
166 }
167 if ((result = request_module("tea6420")) < 0) {
168 printk("mxb: tea6420 i2c module not available.\n");
169 return -ENODEV;
170 }
171 if ((result = request_module("tea6415c")) < 0) {
172 printk("mxb: tea6415c i2c module not available.\n");
173 return -ENODEV;
174 }
175 if ((result = request_module("tda9840")) < 0) {
176 printk("mxb: tda9840 i2c module not available.\n");
177 return -ENODEV;
178 }
179
Panagiotis Issaris74081872006-01-11 19:40:56 -0200180 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 if( NULL == mxb ) {
182 DEB_D(("not enough kernel memory.\n"));
183 return -ENOMEM;
184 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
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;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700329 struct tuner_setup tun_setup;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
331 int i = 0, err = 0;
332 struct tea6415c_multiplex vm;
333
334 /* select video mode in saa7111a */
335 i = VIDEO_MODE_PAL;
336 /* fixme: currently pointless: gets overwritten by configuration below */
337 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
338
339 /* write configuration to saa7111a */
340 init.data = mxb_saa7111_init;
341 init.len = sizeof(mxb_saa7111_init);
342 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init);
343
344 /* select tuner-output on saa7111a */
345 i = 0;
346 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
347
348 /* enable vbi bypass */
349 i = 1;
350 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i);
351
352 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700353 tun_setup.mode_mask = T_ANALOG_TV;
354 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700355 tun_setup.type = TUNER_PHILIPS_PAL;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700356 mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700357 /* tune in some frequency on tuner */
358 mxb->cur_freq.tuner = 0;
359 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
360 mxb->cur_freq.frequency = freq;
361 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY,
362 &mxb->cur_freq);
363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 /* mute audio on tea6420s */
365 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
366 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
367 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
368 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
369
370 /* switch to tuner-channel on tea6415c*/
371 vm.out = 17;
372 vm.in = 3;
373 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
374
375 /* select tuner-output on multicable on tea6415c*/
376 vm.in = 3;
377 vm.out = 13;
378 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 /* the rest for mxb */
381 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 mxb->cur_mute = 1;
383
384 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
385 mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
386
387 /* check if the saa7740 (aka 'sound arena module') is present
388 on the mxb. if so, we must initialize it. due to lack of
389 informations about the saa7740, the values were reverse
390 engineered. */
391 msg.addr = 0x1b;
392 msg.flags = 0;
393 msg.len = mxb_saa7740_init[0].length;
394 msg.buf = &mxb_saa7740_init[0].data[0];
395
396 if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
397 /* the sound arena module is a pos, that's probably the reason
398 philips refuses to hand out a datasheet for the saa7740...
399 it seems to screw up the i2c bus, so we disable fast irq
400 based i2c transactions here and rely on the slow and safe
401 polling method ... */
402 extension.flags &= ~SAA7146_USE_I2C_IRQ;
403 for(i = 1;;i++) {
404 if( -1 == mxb_saa7740_init[i].length ) {
405 break;
406 }
407
408 msg.len = mxb_saa7740_init[i].length;
409 msg.buf = &mxb_saa7740_init[i].data[0];
410 if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
411 DEB_D(("failed to initialize 'sound arena module'.\n"));
412 goto err;
413 }
414 }
415 INFO(("'sound arena module' detected.\n"));
416 }
417err:
418 /* the rest for saa7146: you should definitely set some basic values
419 for the input-port handling of the saa7146. */
420
421 /* ext->saa has been filled by the core driver */
422
423 /* some stuff is done via variables */
424 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
425
426 /* some stuff is done via direct write to the registers */
427
428 /* this is ugly, but because of the fact that this is completely
429 hardware dependend, it should be done directly... */
430 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
431 saa7146_write(dev, DD1_INIT, 0x02000200);
432 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
433
434 return 0;
435}
436
437/* interrupt-handler. this gets called when irq_mask is != 0.
438 it must clear the interrupt-bits in irq_mask it has handled */
439/*
440void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
441{
442 struct mxb* mxb = (struct mxb*)dev->ext_priv;
443}
444*/
445
446static struct saa7146_ext_vv vv_data;
447
448/* this function only gets called when the probing was successful */
449static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
450{
451 struct mxb* mxb = (struct mxb*)dev->ext_priv;
452
453 DEB_EE(("dev:%p\n",dev));
454
455 /* checking for i2c-devices can be omitted here, because we
456 already did this in "mxb_vl42_probe" */
457
458 saa7146_vv_init(dev,&vv_data);
459 if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
460 ERR(("cannot register capture v4l2 device. skipping.\n"));
461 return -1;
462 }
463
464 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
465 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
466 if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
467 ERR(("cannot register vbi v4l2 device. skipping.\n"));
468 }
469 }
470
471 i2c_use_client(mxb->tea6420_1);
472 i2c_use_client(mxb->tea6420_2);
473 i2c_use_client(mxb->tea6415c);
474 i2c_use_client(mxb->tda9840);
475 i2c_use_client(mxb->saa7111a);
476 i2c_use_client(mxb->tuner);
477
478 printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
479
480 mxb_num++;
481 mxb_init_done(dev);
482 return 0;
483}
484
485static int mxb_detach(struct saa7146_dev* dev)
486{
487 struct mxb* mxb = (struct mxb*)dev->ext_priv;
488
489 DEB_EE(("dev:%p\n",dev));
490
491 i2c_release_client(mxb->tea6420_1);
492 i2c_release_client(mxb->tea6420_2);
493 i2c_release_client(mxb->tea6415c);
494 i2c_release_client(mxb->tda9840);
495 i2c_release_client(mxb->saa7111a);
496 i2c_release_client(mxb->tuner);
497
498 saa7146_unregister_device(&mxb->video_dev,dev);
499 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
500 saa7146_unregister_device(&mxb->vbi_dev,dev);
501 }
502 saa7146_vv_release(dev);
503
504 mxb_num--;
505
506 i2c_del_adapter(&mxb->i2c_adapter);
507 kfree(mxb);
508
509 return 0;
510}
511
512static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
513{
514 struct saa7146_dev *dev = fh->dev;
515 struct mxb* mxb = (struct mxb*)dev->ext_priv;
516 struct saa7146_vv *vv = dev->vv_data;
517
518 switch(cmd) {
519 case VIDIOC_ENUMINPUT:
520 {
521 struct v4l2_input *i = arg;
522
523 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
524 if( i->index < 0 || i->index >= MXB_INPUTS) {
525 return -EINVAL;
526 }
527 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
528
529 return 0;
530 }
531 /* the saa7146 provides some controls (brightness, contrast, saturation)
532 which gets registered *after* this function. because of this we have
533 to return with a value != 0 even if the function succeded.. */
534 case VIDIOC_QUERYCTRL:
535 {
536 struct v4l2_queryctrl *qc = arg;
537 int i;
538
539 for (i = MAXCONTROLS - 1; i >= 0; i--) {
540 if (mxb_controls[i].id == qc->id) {
541 *qc = mxb_controls[i];
542 DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
543 return 0;
544 }
545 }
546 return -EAGAIN;
547 }
548 case VIDIOC_G_CTRL:
549 {
550 struct v4l2_control *vc = arg;
551 int i;
552
553 for (i = MAXCONTROLS - 1; i >= 0; i--) {
554 if (mxb_controls[i].id == vc->id) {
555 break;
556 }
557 }
558
559 if( i < 0 ) {
560 return -EAGAIN;
561 }
562
563 switch (vc->id ) {
564 case V4L2_CID_AUDIO_MUTE: {
565 vc->value = mxb->cur_mute;
566 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
567 return 0;
568 }
569 }
570
571 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
572 return 0;
573 }
574
575 case VIDIOC_S_CTRL:
576 {
577 struct v4l2_control *vc = arg;
578 int i = 0;
579
580 for (i = MAXCONTROLS - 1; i >= 0; i--) {
581 if (mxb_controls[i].id == vc->id) {
582 break;
583 }
584 }
585
586 if( i < 0 ) {
587 return -EAGAIN;
588 }
589
590 switch (vc->id ) {
591 case V4L2_CID_AUDIO_MUTE: {
592 mxb->cur_mute = vc->value;
593 if( 0 == vc->value ) {
594 /* switch the audio-source */
595 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
596 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
597 } else {
598 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
599 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
600 }
601 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
602 break;
603 }
604 }
605 return 0;
606 }
607 case VIDIOC_G_INPUT:
608 {
609 int *input = (int *)arg;
610 *input = mxb->cur_input;
611
612 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
613 return 0;
614 }
615 case VIDIOC_S_INPUT:
616 {
617 int input = *(int *)arg;
618 struct tea6415c_multiplex vm;
619 int i = 0;
620
621 DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
622
623 if (input < 0 || input >= MXB_INPUTS) {
624 return -EINVAL;
625 }
626
627 /* fixme: locke das setzen des inputs mit hilfe des mutexes
628 down(&dev->lock);
629 video_mux(dev,*i);
630 up(&dev->lock);
631 */
632
633 /* fixme: check if streaming capture
634 if ( 0 != dev->streaming ) {
635 DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
636 return -EPERM;
637 }
638 */
639
640 mxb->cur_input = input;
641
642 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
643
644 /* prepare switching of tea6415c and saa7111a;
645 have a look at the 'background'-file for further informations */
646 switch( input ) {
647
648 case TUNER:
649 {
650 i = 0;
651 vm.in = 3;
652 vm.out = 17;
653
654 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
655 printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
656 return -EFAULT;
657 }
658 /* connect tuner-output always to multicable */
659 vm.in = 3;
660 vm.out = 13;
661 break;
662 }
663 case AUX3_YC:
664 {
665 /* nothing to be done here. aux3_yc is
666 directly connected to the saa711a */
667 i = 5;
668 break;
669 }
670 case AUX3:
671 {
672 /* nothing to be done here. aux3 is
673 directly connected to the saa711a */
674 i = 1;
675 break;
676 }
677 case AUX1:
678 {
679 i = 0;
680 vm.in = 1;
681 vm.out = 17;
682 break;
683 }
684 }
685
686 /* switch video in tea6415c only if necessary */
687 switch( input ) {
688 case TUNER:
689 case AUX1:
690 {
691 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
692 printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
693 return -EFAULT;
694 }
695 break;
696 }
697 default:
698 {
699 break;
700 }
701 }
702
703 /* switch video in saa7111a */
704 if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
705 printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
706 }
707
708 /* switch the audio-source only if necessary */
709 if( 0 == mxb->cur_mute ) {
710 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
711 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
712 }
713
714 return 0;
715 }
716 case VIDIOC_G_TUNER:
717 {
718 struct v4l2_tuner *t = arg;
719 int byte = 0;
720
721 if( 0 != t->index ) {
722 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
723 return -EINVAL;
724 }
725
726 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
727
728 memset(t,0,sizeof(*t));
729 strcpy(t->name, "Television");
730
731 t->type = V4L2_TUNER_ANALOG_TV;
732 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
733 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
734 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
735 /* FIXME: add the real signal strength here */
736 t->signal = 0xffff;
737 t->afc = 0;
738
739 mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte);
740 t->audmode = mxb->cur_mode;
741
742 if( byte < 0 ) {
743 t->rxsubchans = V4L2_TUNER_SUB_MONO;
744 } else {
745 switch(byte) {
746 case TDA9840_MONO_DETECT: {
747 t->rxsubchans = V4L2_TUNER_SUB_MONO;
748 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
749 break;
750 }
751 case TDA9840_DUAL_DETECT: {
752 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
753 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
754 break;
755 }
756 case TDA9840_STEREO_DETECT: {
757 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
758 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
759 break;
760 }
761 default: { /* TDA9840_INCORRECT_DETECT */
762 t->rxsubchans = V4L2_TUNER_MODE_MONO;
763 DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
764 break;
765 }
766 }
767 }
768
769 return 0;
770 }
771 case VIDIOC_S_TUNER:
772 {
773 struct v4l2_tuner *t = arg;
774 int result = 0;
775 int byte = 0;
776
777 if( 0 != t->index ) {
778 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
779 return -EINVAL;
780 }
781
782 switch(t->audmode) {
783 case V4L2_TUNER_MODE_STEREO: {
784 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
785 byte = TDA9840_SET_STEREO;
786 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
787 break;
788 }
789 case V4L2_TUNER_MODE_LANG1: {
790 mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
791 byte = TDA9840_SET_LANG1;
792 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
793 break;
794 }
795 case V4L2_TUNER_MODE_LANG2: {
796 mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
797 byte = TDA9840_SET_LANG2;
798 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
799 break;
800 }
801 default: { /* case V4L2_TUNER_MODE_MONO: {*/
802 mxb->cur_mode = V4L2_TUNER_MODE_MONO;
803 byte = TDA9840_SET_MONO;
804 DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
805 break;
806 }
807 }
808
809 if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
810 printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
811 }
812
813 return 0;
814 }
815 case VIDIOC_G_FREQUENCY:
816 {
817 struct v4l2_frequency *f = arg;
818
819 if(0 != mxb->cur_input) {
820 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
821 return -EINVAL;
822 }
823
Michael Hunold9d2599d2005-07-27 11:46:00 -0700824 *f = mxb->cur_freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Michael Hunold9d2599d2005-07-27 11:46:00 -0700826 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return 0;
828 }
829 case VIDIOC_S_FREQUENCY:
830 {
831 struct v4l2_frequency *f = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 if (0 != f->tuner)
834 return -EINVAL;
835
836 if (V4L2_TUNER_ANALOG_TV != f->type)
837 return -EINVAL;
838
839 if(0 != mxb->cur_input) {
840 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
841 return -EINVAL;
842 }
843
Michael Hunold9d2599d2005-07-27 11:46:00 -0700844 mxb->cur_freq = *f;
845 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847 /* tune in desired frequency */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700848 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
850 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
851 spin_lock(&dev->slock);
852 vv->vbi_fieldcount = 0;
853 spin_unlock(&dev->slock);
854
855 return 0;
856 }
857 case MXB_S_AUDIO_CD:
858 {
859 int i = *(int*)arg;
860
861 if( i < 0 || i >= MXB_AUDIOS ) {
862 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
863 return -EINVAL;
864 }
865
866 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
867
868 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
869 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
870
871 return 0;
872 }
873 case MXB_S_AUDIO_LINE:
874 {
875 int i = *(int*)arg;
876
877 if( i < 0 || i >= MXB_AUDIOS ) {
878 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
879 return -EINVAL;
880 }
881
882 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
883 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
884 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
885
886 return 0;
887 }
888 case VIDIOC_G_AUDIO:
889 {
890 struct v4l2_audio *a = arg;
891
892 if( a->index < 0 || a->index > MXB_INPUTS ) {
893 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
894 return -EINVAL;
895 }
896
897 DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
898 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
899
900 return 0;
901 }
902 case VIDIOC_S_AUDIO:
903 {
904 struct v4l2_audio *a = arg;
905 DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
906 return 0;
907 }
908 default:
909/*
910 DEB2(printk("does not handle this ioctl.\n"));
911*/
912 return -ENOIOCTLCMD;
913 }
914 return 0;
915}
916
917static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
918{
919 struct mxb* mxb = (struct mxb*)dev->ext_priv;
920 int zero = 0;
921 int one = 1;
922
923 if(V4L2_STD_PAL_I == std->id ) {
924 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
925 /* set the 7146 gpio register -- I don't know what this does exactly */
926 saa7146_write(dev, GPIO_CTRL, 0x00404050);
927 /* unset the 7111 gpio register -- I don't know what this does exactly */
928 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
929 } else {
930 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
931 /* set the 7146 gpio register -- I don't know what this does exactly */
932 saa7146_write(dev, GPIO_CTRL, 0x00404050);
933 /* set the 7111 gpio register -- I don't know what this does exactly */
934 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
935 }
936 return 0;
937}
938
939static struct saa7146_standard standard[] = {
940 {
941 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
942 .v_offset = 0x17, .v_field = 288,
943 .h_offset = 0x14, .h_pixels = 680,
944 .v_max_out = 576, .h_max_out = 768,
945 }, {
946 .name = "PAL-I", .id = V4L2_STD_PAL_I,
947 .v_offset = 0x17, .v_field = 288,
948 .h_offset = 0x14, .h_pixels = 680,
949 .v_max_out = 576, .h_max_out = 768,
950 }, {
951 .name = "NTSC", .id = V4L2_STD_NTSC,
952 .v_offset = 0x16, .v_field = 240,
953 .h_offset = 0x06, .h_pixels = 708,
954 .v_max_out = 480, .h_max_out = 640,
955 }, {
956 .name = "SECAM", .id = V4L2_STD_SECAM,
957 .v_offset = 0x14, .v_field = 288,
958 .h_offset = 0x14, .h_pixels = 720,
959 .v_max_out = 576, .h_max_out = 768,
960 }
961};
962
963static struct saa7146_pci_extension_data mxb = {
964 .ext_priv = "Multimedia eXtension Board",
965 .ext = &extension,
966};
967
968static struct pci_device_id pci_tbl[] = {
969 {
970 .vendor = PCI_VENDOR_ID_PHILIPS,
971 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
972 .subvendor = 0x0000,
973 .subdevice = 0x0000,
974 .driver_data = (unsigned long)&mxb,
975 }, {
976 .vendor = 0,
977 }
978};
979
980MODULE_DEVICE_TABLE(pci, pci_tbl);
981
982static struct saa7146_ext_vv vv_data = {
983 .inputs = MXB_INPUTS,
984 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
985 .stds = &standard[0],
986 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
987 .std_callback = &std_callback,
988 .ioctls = &ioctls[0],
989 .ioctl = mxb_ioctl,
990};
991
992static struct saa7146_extension extension = {
993 .name = MXB_IDENTIFIER,
994 .flags = SAA7146_USE_I2C_IRQ,
995
996 .pci_tbl = &pci_tbl[0],
997 .module = THIS_MODULE,
998
999 .probe = mxb_probe,
1000 .attach = mxb_attach,
1001 .detach = mxb_detach,
1002
1003 .irq_mask = 0,
1004 .irq_func = NULL,
1005};
1006
1007static int __init mxb_init_module(void)
1008{
1009 if( 0 != saa7146_register_extension(&extension)) {
1010 DEB_S(("failed to register extension.\n"));
1011 return -ENODEV;
1012 }
1013
1014 return 0;
1015}
1016
1017static void __exit mxb_cleanup_module(void)
1018{
1019 saa7146_unregister_extension(&extension);
1020}
1021
1022module_init(mxb_init_module);
1023module_exit(mxb_cleanup_module);
1024
1025MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
1026MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
1027MODULE_LICENSE("GPL");