V4L/DVB (9834): wm8775: convert to v4l2_subdev.
[linux-2.6-block.git] / drivers / media / video / mxb.c
CommitLineData
1da177e4
LT
1/*
2 mxb - v4l2 driver for the Multimedia eXtension Board
a8733ca5 3
6acaba8e 4 Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
1da177e4
LT
5
6 Visit http://www.mihu.de/linux/saa7146/mxb/
7 for further details about this card.
a8733ca5 8
1da177e4
LT
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>
5e453dc7 29#include <media/v4l2-common.h>
707ecf46 30#include <media/saa7115.h>
1da177e4
LT
31
32#include "mxb.h"
33#include "tea6415c.h"
34#include "tea6420.h"
35#include "tda9840.h"
36
37#define I2C_SAA7111 0x24
38
a8733ca5 39#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
1da177e4
LT
40
41/* global variable */
ff699e6b 42static int mxb_num;
1da177e4 43
a8733ca5 44/* initial frequence the tuner will be tuned to.
1da177e4
LT
45 in verden (lower saxony, germany) 4148 is a
46 channel called "phoenix" */
47static int freq = 4148;
48module_param(freq, int, 0644);
49MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
50
ff699e6b 51static int debug;
1da177e4
LT
52module_param(debug, int, 0644);
53MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
54
55#define MXB_INPUTS 4
56enum { TUNER, AUX1, AUX3, AUX3_YC };
57
58static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
a8733ca5 59 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
1da177e4
LT
60 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
61 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
62 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
63};
64
65/* this array holds the information, which port of the saa7146 each
66 input actually uses. the mxb uses port 0 for every input */
67static struct {
68 int hps_source;
69 int hps_sync;
a8733ca5 70} input_port_selection[MXB_INPUTS] = {
1da177e4
LT
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 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
75};
76
77/* this array holds the information of the audio source (mxb_audios),
78 which has to be switched corresponding to the video source (mxb_channels) */
79static int video_audio_connect[MXB_INPUTS] =
80 { 0, 1, 3, 3 };
81
82/* these are the necessary input-output-pins for bringing one audio source
83(see above) to the CD-output */
84static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
a8733ca5 85 {
1da177e4
LT
86 {{1,1,0},{1,1,0}}, /* Tuner */
87 {{5,1,0},{6,1,0}}, /* AUX 1 */
88 {{4,1,0},{6,1,0}}, /* AUX 2 */
89 {{3,1,0},{6,1,0}}, /* AUX 3 */
90 {{1,1,0},{3,1,0}}, /* Radio */
91 {{1,1,0},{2,1,0}}, /* CD-Rom */
92 {{6,1,0},{6,1,0}} /* Mute */
93 };
94
95/* these are the necessary input-output-pins for bringing one audio source
96(see above) to the line-output */
97static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
98 {
99 {{2,3,0},{1,2,0}},
100 {{5,3,0},{6,2,0}},
101 {{4,3,0},{6,2,0}},
102 {{3,3,0},{6,2,0}},
103 {{2,3,0},{3,2,0}},
104 {{2,3,0},{2,2,0}},
105 {{6,3,0},{6,2,0}} /* Mute */
106 };
107
108#define MAXCONTROLS 1
109static struct v4l2_queryctrl mxb_controls[] = {
110 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
111};
112
113static struct saa7146_extension_ioctls ioctls[] = {
114 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
115 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
116 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
117 { VIDIOC_QUERYCTRL, SAA7146_BEFORE },
118 { VIDIOC_G_CTRL, SAA7146_BEFORE },
119 { VIDIOC_S_CTRL, SAA7146_BEFORE },
120 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
121 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
122 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
123 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
124 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
125 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
707ecf46
HV
126 { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE },
127 { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE },
a8733ca5
MCC
128 { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */
129 { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */
1da177e4
LT
130 { 0, 0 }
131};
132
133struct mxb
134{
135 struct video_device *video_dev;
136 struct video_device *vbi_dev;
137
a8733ca5 138 struct i2c_adapter i2c_adapter;
1da177e4 139
2633812f
HV
140 struct i2c_client *saa7111a;
141 struct i2c_client *tda9840;
142 struct i2c_client *tea6415c;
143 struct i2c_client *tuner;
144 struct i2c_client *tea6420_1;
145 struct i2c_client *tea6420_2;
1da177e4
LT
146
147 int cur_mode; /* current audio mode (mono, stereo, ...) */
148 int cur_input; /* current input */
1da177e4 149 int cur_mute; /* current mute status */
9d2599d9 150 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
1da177e4
LT
151};
152
153static struct saa7146_extension extension;
154
961f80f9
JD
155static int mxb_check_clients(struct device *dev, void *data)
156{
2633812f 157 struct mxb *mxb = data;
961f80f9
JD
158 struct i2c_client *client = i2c_verify_client(dev);
159
707ecf46 160 if (!client)
961f80f9
JD
161 return 0;
162
707ecf46 163 if (I2C_ADDR_TEA6420_1 == client->addr)
961f80f9 164 mxb->tea6420_1 = client;
707ecf46 165 if (I2C_ADDR_TEA6420_2 == client->addr)
961f80f9 166 mxb->tea6420_2 = client;
707ecf46 167 if (I2C_TEA6415C_2 == client->addr)
961f80f9 168 mxb->tea6415c = client;
707ecf46 169 if (I2C_ADDR_TDA9840 == client->addr)
961f80f9 170 mxb->tda9840 = client;
707ecf46 171 if (I2C_SAA7111 == client->addr)
961f80f9 172 mxb->saa7111a = client;
707ecf46 173 if (0x60 == client->addr)
961f80f9
JD
174 mxb->tuner = client;
175
176 return 0;
177}
178
1da177e4
LT
179static int mxb_probe(struct saa7146_dev* dev)
180{
181 struct mxb* mxb = NULL;
1da177e4
LT
182 int result;
183
707ecf46
HV
184 result = request_module("saa7115");
185 if (result < 0) {
1da177e4
LT
186 printk("mxb: saa7111 i2c module not available.\n");
187 return -ENODEV;
188 }
707ecf46
HV
189 result = request_module("tea6420");
190 if (result < 0) {
1da177e4
LT
191 printk("mxb: tea6420 i2c module not available.\n");
192 return -ENODEV;
193 }
707ecf46
HV
194 result = request_module("tea6415c");
195 if (result < 0) {
1da177e4
LT
196 printk("mxb: tea6415c i2c module not available.\n");
197 return -ENODEV;
198 }
707ecf46
HV
199 result = request_module("tda9840");
200 if (result < 0) {
1da177e4
LT
201 printk("mxb: tda9840 i2c module not available.\n");
202 return -ENODEV;
203 }
707ecf46
HV
204 result = request_module("tuner");
205 if (result < 0) {
a08cc44e
MH
206 printk("mxb: tuner i2c module not available.\n");
207 return -ENODEV;
208 }
1da177e4 209
7408187d 210 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
1da177e4
LT
211 if( NULL == mxb ) {
212 DEB_D(("not enough kernel memory.\n"));
213 return -ENOMEM;
214 }
1da177e4
LT
215
216 mxb->i2c_adapter = (struct i2c_adapter) {
217 .class = I2C_CLASS_TV_ANALOG,
1da177e4
LT
218 };
219
9ebeae56
HV
220 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
221
1da177e4
LT
222 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
223 if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
224 DEB_S(("cannot register i2c-device. skipping.\n"));
225 kfree(mxb);
226 return -EFAULT;
227 }
228
229 /* loop through all i2c-devices on the bus and look who is there */
961f80f9 230 device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients);
1da177e4
LT
231
232 /* check if all devices are present */
5fa1247a
AV
233 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
234 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
1da177e4
LT
235 printk("mxb: did not find all i2c devices. aborting\n");
236 i2c_del_adapter(&mxb->i2c_adapter);
237 kfree(mxb);
238 return -ENODEV;
239 }
240
a8733ca5 241 /* all devices are present, probe was successful */
1da177e4
LT
242
243 /* we store the pointer in our private data field */
244 dev->ext_priv = mxb;
245
246 return 0;
247}
248
a8733ca5 249/* some init data for the saa7740, the so-called 'sound arena module'.
1da177e4
LT
250 there are no specs available, so we simply use some init values */
251static struct {
252 int length;
253 char data[9];
254} mxb_saa7740_init[] = {
255 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
256 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
257 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
258 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
259 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
260 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
261 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
262 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
263 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
264 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
265 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
266 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
267 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
268 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
269 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
270 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
271 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
272 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
273 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
274 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
275 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
276 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
277 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
278 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
279 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
280 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
281 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
282 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
283 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
284 { 3, { 0x48, 0x00, 0x01 } },
285 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
286 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
287 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
288 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
289 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
290 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
291 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
292 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
293 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
294 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
295 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
296 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
297 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
298 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
299 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
300 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
301 { 3, { 0x80, 0xb3, 0x0a } },
2633812f 302 {-1, { 0 } }
1da177e4
LT
303};
304
1da177e4
LT
305/* bring hardware to a sane state. this has to be done, just in case someone
306 wants to capture from this device before it has been properly initialized.
307 the capture engine would badly fail, because no valid signal arrives on the
308 saa7146, thus leading to timeouts and stuff. */
309static int mxb_init_done(struct saa7146_dev* dev)
310{
311 struct mxb* mxb = (struct mxb*)dev->ext_priv;
1da177e4 312 struct i2c_msg msg;
85369df3 313 struct tuner_setup tun_setup;
6acaba8e 314 v4l2_std_id std = V4L2_STD_PAL_BG;
707ecf46 315 struct v4l2_routing route;
1da177e4
LT
316
317 int i = 0, err = 0;
2633812f 318 struct tea6415c_multiplex vm;
1da177e4
LT
319
320 /* select video mode in saa7111a */
707ecf46 321 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std);
1da177e4
LT
322
323 /* select tuner-output on saa7111a */
324 i = 0;
707ecf46
HV
325 route.input = SAA7115_COMPOSITE0;
326 route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
327 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route);
1da177e4
LT
328
329 /* select a tuner type */
85369df3
MCC
330 tun_setup.mode_mask = T_ANALOG_TV;
331 tun_setup.addr = ADDR_UNSET;
9d2599d9 332 tun_setup.type = TUNER_PHILIPS_PAL;
707ecf46 333 mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup);
9d2599d9
MH
334 /* tune in some frequency on tuner */
335 mxb->cur_freq.tuner = 0;
336 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
337 mxb->cur_freq.frequency = freq;
338 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY,
339 &mxb->cur_freq);
340
6acaba8e
MH
341 /* set a default video standard */
342 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
343
1da177e4 344 /* mute audio on tea6420s */
2633812f
HV
345 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]);
346 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]);
347 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]);
348 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]);
1da177e4
LT
349
350 /* switch to tuner-channel on tea6415c*/
351 vm.out = 17;
352 vm.in = 3;
2633812f 353 mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
1da177e4
LT
354
355 /* select tuner-output on multicable on tea6415c*/
356 vm.in = 3;
357 vm.out = 13;
2633812f 358 mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
a8733ca5 359
1da177e4
LT
360 /* the rest for mxb */
361 mxb->cur_input = 0;
1da177e4
LT
362 mxb->cur_mute = 1;
363
364 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
a8733ca5 365
1da177e4 366 /* check if the saa7740 (aka 'sound arena module') is present
a8733ca5 367 on the mxb. if so, we must initialize it. due to lack of
1da177e4
LT
368 informations about the saa7740, the values were reverse
369 engineered. */
370 msg.addr = 0x1b;
371 msg.flags = 0;
372 msg.len = mxb_saa7740_init[0].length;
373 msg.buf = &mxb_saa7740_init[0].data[0];
374
2633812f
HV
375 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
376 if (err == 1) {
1da177e4
LT
377 /* the sound arena module is a pos, that's probably the reason
378 philips refuses to hand out a datasheet for the saa7740...
379 it seems to screw up the i2c bus, so we disable fast irq
380 based i2c transactions here and rely on the slow and safe
381 polling method ... */
382 extension.flags &= ~SAA7146_USE_I2C_IRQ;
2633812f
HV
383 for (i = 1; ; i++) {
384 if (-1 == mxb_saa7740_init[i].length)
1da177e4 385 break;
1da177e4 386
a8733ca5 387 msg.len = mxb_saa7740_init[i].length;
1da177e4 388 msg.buf = &mxb_saa7740_init[i].data[0];
2633812f
HV
389 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
390 if (err != 1) {
1da177e4
LT
391 DEB_D(("failed to initialize 'sound arena module'.\n"));
392 goto err;
393 }
394 }
395 INFO(("'sound arena module' detected.\n"));
396 }
a8733ca5 397err:
1da177e4
LT
398 /* the rest for saa7146: you should definitely set some basic values
399 for the input-port handling of the saa7146. */
400
401 /* ext->saa has been filled by the core driver */
a8733ca5 402
1da177e4 403 /* some stuff is done via variables */
2633812f
HV
404 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
405 input_port_selection[mxb->cur_input].hps_sync);
1da177e4
LT
406
407 /* some stuff is done via direct write to the registers */
408
409 /* this is ugly, but because of the fact that this is completely
410 hardware dependend, it should be done directly... */
a8733ca5 411 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
1da177e4
LT
412 saa7146_write(dev, DD1_INIT, 0x02000200);
413 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
414
415 return 0;
416}
417
418/* interrupt-handler. this gets called when irq_mask is != 0.
419 it must clear the interrupt-bits in irq_mask it has handled */
420/*
421void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
422{
423 struct mxb* mxb = (struct mxb*)dev->ext_priv;
424}
425*/
426
427static struct saa7146_ext_vv vv_data;
428
429/* this function only gets called when the probing was successful */
2633812f 430static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1da177e4 431{
2633812f 432 struct mxb *mxb = (struct mxb *)dev->ext_priv;
a8733ca5 433
2633812f 434 DEB_EE(("dev:%p\n", dev));
1da177e4
LT
435
436 /* checking for i2c-devices can be omitted here, because we
437 already did this in "mxb_vl42_probe" */
438
a832781c
HV
439 saa7146_vv_init(dev, &vv_data);
440 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
1da177e4
LT
441 ERR(("cannot register capture v4l2 device. skipping.\n"));
442 return -1;
443 }
a8733ca5 444
1da177e4 445 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
a832781c
HV
446 if (MXB_BOARD_CAN_DO_VBI(dev)) {
447 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
1da177e4
LT
448 ERR(("cannot register vbi v4l2 device. skipping.\n"));
449 }
450 }
451
452 i2c_use_client(mxb->tea6420_1);
453 i2c_use_client(mxb->tea6420_2);
454 i2c_use_client(mxb->tea6415c);
455 i2c_use_client(mxb->tda9840);
456 i2c_use_client(mxb->saa7111a);
457 i2c_use_client(mxb->tuner);
458
a832781c 459 printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
1da177e4
LT
460
461 mxb_num++;
462 mxb_init_done(dev);
463 return 0;
464}
465
2633812f 466static int mxb_detach(struct saa7146_dev *dev)
1da177e4 467{
2633812f 468 struct mxb *mxb = (struct mxb *)dev->ext_priv;
1da177e4 469
2633812f 470 DEB_EE(("dev:%p\n", dev));
1da177e4
LT
471
472 i2c_release_client(mxb->tea6420_1);
473 i2c_release_client(mxb->tea6420_2);
474 i2c_release_client(mxb->tea6415c);
475 i2c_release_client(mxb->tda9840);
476 i2c_release_client(mxb->saa7111a);
477 i2c_release_client(mxb->tuner);
478
479 saa7146_unregister_device(&mxb->video_dev,dev);
2633812f
HV
480 if (MXB_BOARD_CAN_DO_VBI(dev))
481 saa7146_unregister_device(&mxb->vbi_dev, dev);
1da177e4
LT
482 saa7146_vv_release(dev);
483
484 mxb_num--;
485
486 i2c_del_adapter(&mxb->i2c_adapter);
487 kfree(mxb);
488
489 return 0;
490}
491
a8733ca5 492static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
1da177e4
LT
493{
494 struct saa7146_dev *dev = fh->dev;
2633812f 495 struct mxb *mxb = (struct mxb *)dev->ext_priv;
a8733ca5
MCC
496 struct saa7146_vv *vv = dev->vv_data;
497
1da177e4
LT
498 switch(cmd) {
499 case VIDIOC_ENUMINPUT:
500 {
501 struct v4l2_input *i = arg;
a8733ca5 502
1da177e4 503 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
2633812f 504 if (i->index < 0 || i->index >= MXB_INPUTS)
1da177e4 505 return -EINVAL;
1da177e4 506 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
1da177e4
LT
507 return 0;
508 }
509 /* the saa7146 provides some controls (brightness, contrast, saturation)
510 which gets registered *after* this function. because of this we have
511 to return with a value != 0 even if the function succeded.. */
512 case VIDIOC_QUERYCTRL:
513 {
514 struct v4l2_queryctrl *qc = arg;
515 int i;
516
517 for (i = MAXCONTROLS - 1; i >= 0; i--) {
518 if (mxb_controls[i].id == qc->id) {
519 *qc = mxb_controls[i];
2633812f 520 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
1da177e4
LT
521 return 0;
522 }
523 }
524 return -EAGAIN;
525 }
526 case VIDIOC_G_CTRL:
527 {
528 struct v4l2_control *vc = arg;
529 int i;
530
531 for (i = MAXCONTROLS - 1; i >= 0; i--) {
2633812f 532 if (mxb_controls[i].id == vc->id)
1da177e4 533 break;
1da177e4 534 }
a8733ca5 535
2633812f 536 if (i < 0)
1da177e4 537 return -EAGAIN;
a8733ca5 538
2633812f
HV
539 if (vc->id == V4L2_CID_AUDIO_MUTE) {
540 vc->value = mxb->cur_mute;
541 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
542 return 0;
1da177e4 543 }
a8733ca5 544
2633812f 545 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
1da177e4
LT
546 return 0;
547 }
548
549 case VIDIOC_S_CTRL:
550 {
2633812f 551 struct v4l2_control *vc = arg;
1da177e4 552 int i = 0;
a8733ca5 553
1da177e4 554 for (i = MAXCONTROLS - 1; i >= 0; i--) {
2633812f 555 if (mxb_controls[i].id == vc->id)
1da177e4 556 break;
1da177e4 557 }
a8733ca5 558
2633812f 559 if (i < 0)
1da177e4 560 return -EAGAIN;
a8733ca5 561
2633812f
HV
562 if (vc->id == V4L2_CID_AUDIO_MUTE) {
563 mxb->cur_mute = vc->value;
564 if (!vc->value) {
565 /* switch the audio-source */
566 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
567 &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
568 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
569 &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
570 } else {
571 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
572 &TEA6420_line[6][0]);
573 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
574 &TEA6420_line[6][1]);
1da177e4 575 }
2633812f 576 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
1da177e4
LT
577 }
578 return 0;
579 }
580 case VIDIOC_G_INPUT:
581 {
582 int *input = (int *)arg;
583 *input = mxb->cur_input;
584
2633812f 585 DEB_EE(("VIDIOC_G_INPUT %d.\n", *input));
a8733ca5
MCC
586 return 0;
587 }
1da177e4
LT
588 case VIDIOC_S_INPUT:
589 {
590 int input = *(int *)arg;
707ecf46
HV
591 struct tea6415c_multiplex vm;
592 struct v4l2_routing route;
1da177e4
LT
593 int i = 0;
594
2633812f 595 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
1da177e4 596
2633812f 597 if (input < 0 || input >= MXB_INPUTS)
1da177e4 598 return -EINVAL;
a8733ca5 599
1da177e4 600 mxb->cur_input = input;
a8733ca5 601
2633812f
HV
602 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
603 input_port_selection[input].hps_sync);
a8733ca5 604
1da177e4
LT
605 /* prepare switching of tea6415c and saa7111a;
606 have a look at the 'background'-file for further informations */
2633812f
HV
607 switch (input) {
608 case TUNER:
609 i = SAA7115_COMPOSITE0;
610 vm.in = 3;
611 vm.out = 17;
612
613 if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
614 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
615 return -EFAULT;
1da177e4 616 }
2633812f
HV
617 /* connect tuner-output always to multicable */
618 vm.in = 3;
619 vm.out = 13;
620 break;
621 case AUX3_YC:
622 /* nothing to be done here. aux3_yc is
623 directly connected to the saa711a */
624 i = SAA7115_SVIDEO1;
625 break;
626 case AUX3:
627 /* nothing to be done here. aux3 is
628 directly connected to the saa711a */
629 i = SAA7115_COMPOSITE1;
630 break;
631 case AUX1:
632 i = SAA7115_COMPOSITE0;
633 vm.in = 1;
634 vm.out = 17;
635 break;
1da177e4
LT
636 }
637
638 /* switch video in tea6415c only if necessary */
2633812f
HV
639 switch (input) {
640 case TUNER:
641 case AUX1:
642 if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
643 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
644 return -EFAULT;
1da177e4 645 }
2633812f
HV
646 break;
647 default:
648 break;
1da177e4 649 }
a8733ca5 650
1da177e4 651 /* switch video in saa7111a */
707ecf46
HV
652 route.input = i;
653 route.output = 0;
654 if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route))
1da177e4 655 printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
1da177e4
LT
656
657 /* switch the audio-source only if necessary */
658 if( 0 == mxb->cur_mute ) {
2633812f
HV
659 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
660 &TEA6420_line[video_audio_connect[input]][0]);
661 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
662 &TEA6420_line[video_audio_connect[input]][1]);
1da177e4
LT
663 }
664
665 return 0;
666 }
667 case VIDIOC_G_TUNER:
668 {
669 struct v4l2_tuner *t = arg;
1da177e4 670
707ecf46 671 if (t->index) {
1da177e4
LT
672 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
673 return -EINVAL;
674 }
675
676 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
677
707ecf46
HV
678 memset(t, 0, sizeof(*t));
679 i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
1da177e4 680
707ecf46 681 strlcpy(t->name, "TV Tuner", sizeof(t->name));
1da177e4 682 t->type = V4L2_TUNER_ANALOG_TV;
707ecf46
HV
683 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \
684 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
1da177e4 685 t->audmode = mxb->cur_mode;
1da177e4
LT
686 return 0;
687 }
688 case VIDIOC_S_TUNER:
689 {
690 struct v4l2_tuner *t = arg;
a8733ca5 691
707ecf46 692 if (t->index) {
1da177e4
LT
693 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
694 return -EINVAL;
695 }
a8733ca5 696
707ecf46
HV
697 mxb->cur_mode = t->audmode;
698 i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
1da177e4
LT
699 return 0;
700 }
701 case VIDIOC_G_FREQUENCY:
702 {
703 struct v4l2_frequency *f = arg;
704
2633812f
HV
705 if (mxb->cur_input) {
706 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
707 mxb->cur_input));
1da177e4
LT
708 return -EINVAL;
709 }
710
9d2599d9 711 *f = mxb->cur_freq;
1da177e4 712
9d2599d9 713 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
1da177e4
LT
714 return 0;
715 }
716 case VIDIOC_S_FREQUENCY:
717 {
718 struct v4l2_frequency *f = arg;
1da177e4 719
2633812f 720 if (f->tuner)
1da177e4
LT
721 return -EINVAL;
722
723 if (V4L2_TUNER_ANALOG_TV != f->type)
724 return -EINVAL;
a8733ca5 725
707ecf46
HV
726 if (mxb->cur_input) {
727 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
1da177e4
LT
728 return -EINVAL;
729 }
730
9d2599d9
MH
731 mxb->cur_freq = *f;
732 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
1da177e4 733
a8733ca5 734 /* tune in desired frequency */
9d2599d9 735 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq);
1da177e4
LT
736
737 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
738 spin_lock(&dev->slock);
739 vv->vbi_fieldcount = 0;
740 spin_unlock(&dev->slock);
741
742 return 0;
743 }
744 case MXB_S_AUDIO_CD:
745 {
746 int i = *(int*)arg;
a8733ca5 747
2633812f 748 if (i < 0 || i >= MXB_AUDIOS) {
1da177e4
LT
749 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
750 return -EINVAL;
751 }
a8733ca5 752
1da177e4
LT
753 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
754
755 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
756 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
757
758 return 0;
759 }
760 case MXB_S_AUDIO_LINE:
761 {
762 int i = *(int*)arg;
a8733ca5 763
2633812f 764 if (i < 0 || i >= MXB_AUDIOS) {
1da177e4
LT
765 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
766 return -EINVAL;
767 }
a8733ca5 768
1da177e4
LT
769 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
770 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
771 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
772
773 return 0;
774 }
775 case VIDIOC_G_AUDIO:
776 {
777 struct v4l2_audio *a = arg;
778
2633812f
HV
779 if (a->index < 0 || a->index > MXB_INPUTS) {
780 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
1da177e4
LT
781 return -EINVAL;
782 }
a8733ca5 783
2633812f 784 DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
1da177e4 785 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
a8733ca5 786
1da177e4
LT
787 return 0;
788 }
789 case VIDIOC_S_AUDIO:
790 {
791 struct v4l2_audio *a = arg;
2633812f
HV
792
793 DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
1da177e4 794 return 0;
a8733ca5 795 }
2633812f 796#ifdef CONFIG_VIDEO_ADV_DEBUG
707ecf46
HV
797 case VIDIOC_DBG_S_REGISTER:
798 case VIDIOC_DBG_G_REGISTER:
799 i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
2633812f
HV
800 return 0;
801#endif
1da177e4
LT
802 default:
803/*
804 DEB2(printk("does not handle this ioctl.\n"));
805*/
806 return -ENOIOCTLCMD;
807 }
808 return 0;
809}
810
c6eb8eaf 811static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
1da177e4 812{
c6eb8eaf 813 struct mxb *mxb = (struct mxb *)dev->ext_priv;
1da177e4
LT
814 int zero = 0;
815 int one = 1;
816
c6eb8eaf 817 if (V4L2_STD_PAL_I == standard->id) {
6acaba8e 818 v4l2_std_id std = V4L2_STD_PAL_I;
c6eb8eaf 819
1da177e4
LT
820 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
821 /* set the 7146 gpio register -- I don't know what this does exactly */
a8733ca5 822 saa7146_write(dev, GPIO_CTRL, 0x00404050);
1da177e4 823 /* unset the 7111 gpio register -- I don't know what this does exactly */
707ecf46 824 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero);
6acaba8e 825 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
1da177e4 826 } else {
6acaba8e 827 v4l2_std_id std = V4L2_STD_PAL_BG;
c6eb8eaf 828
1da177e4
LT
829 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
830 /* set the 7146 gpio register -- I don't know what this does exactly */
a8733ca5 831 saa7146_write(dev, GPIO_CTRL, 0x00404050);
1da177e4 832 /* set the 7111 gpio register -- I don't know what this does exactly */
707ecf46 833 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one);
6acaba8e 834 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
1da177e4
LT
835 }
836 return 0;
837}
838
839static struct saa7146_standard standard[] = {
840 {
841 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
842 .v_offset = 0x17, .v_field = 288,
843 .h_offset = 0x14, .h_pixels = 680,
844 .v_max_out = 576, .h_max_out = 768,
845 }, {
846 .name = "PAL-I", .id = V4L2_STD_PAL_I,
847 .v_offset = 0x17, .v_field = 288,
848 .h_offset = 0x14, .h_pixels = 680,
849 .v_max_out = 576, .h_max_out = 768,
850 }, {
851 .name = "NTSC", .id = V4L2_STD_NTSC,
852 .v_offset = 0x16, .v_field = 240,
853 .h_offset = 0x06, .h_pixels = 708,
854 .v_max_out = 480, .h_max_out = 640,
855 }, {
856 .name = "SECAM", .id = V4L2_STD_SECAM,
857 .v_offset = 0x14, .v_field = 288,
858 .h_offset = 0x14, .h_pixels = 720,
859 .v_max_out = 576, .h_max_out = 768,
860 }
861};
862
863static struct saa7146_pci_extension_data mxb = {
a8733ca5
MCC
864 .ext_priv = "Multimedia eXtension Board",
865 .ext = &extension,
1da177e4
LT
866};
867
868static struct pci_device_id pci_tbl[] = {
869 {
870 .vendor = PCI_VENDOR_ID_PHILIPS,
871 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
872 .subvendor = 0x0000,
873 .subdevice = 0x0000,
874 .driver_data = (unsigned long)&mxb,
875 }, {
876 .vendor = 0,
877 }
878};
879
880MODULE_DEVICE_TABLE(pci, pci_tbl);
881
882static struct saa7146_ext_vv vv_data = {
883 .inputs = MXB_INPUTS,
884 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
885 .stds = &standard[0],
886 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
a8733ca5 887 .std_callback = &std_callback,
1da177e4
LT
888 .ioctls = &ioctls[0],
889 .ioctl = mxb_ioctl,
890};
891
892static struct saa7146_extension extension = {
893 .name = MXB_IDENTIFIER,
894 .flags = SAA7146_USE_I2C_IRQ,
a8733ca5 895
1da177e4
LT
896 .pci_tbl = &pci_tbl[0],
897 .module = THIS_MODULE,
898
899 .probe = mxb_probe,
900 .attach = mxb_attach,
901 .detach = mxb_detach,
902
903 .irq_mask = 0,
904 .irq_func = NULL,
a8733ca5 905};
1da177e4
LT
906
907static int __init mxb_init_module(void)
908{
2633812f 909 if (saa7146_register_extension(&extension)) {
1da177e4
LT
910 DEB_S(("failed to register extension.\n"));
911 return -ENODEV;
912 }
a8733ca5 913
1da177e4
LT
914 return 0;
915}
916
917static void __exit mxb_cleanup_module(void)
918{
919 saa7146_unregister_extension(&extension);
920}
921
922module_init(mxb_init_module);
923module_exit(mxb_cleanup_module);
924
925MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
926MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
927MODULE_LICENSE("GPL");