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