This source file includes following definitions.
- mxb_update_audmode
- tea6420_route
- mxb_s_ctrl
- mxb_probe
- mxb_init_done
- vidioc_enum_input
- vidioc_g_input
- vidioc_s_input
- vidioc_g_tuner
- vidioc_s_tuner
- vidioc_querystd
- vidioc_g_frequency
- vidioc_s_frequency
- vidioc_enumaudio
- vidioc_g_audio
- vidioc_s_audio
- vidioc_g_register
- vidioc_s_register
- mxb_attach
- mxb_detach
- std_callback
- mxb_init_module
- mxb_cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #define DEBUG_VARIABLE debug
15
16 #include <media/drv-intf/saa7146_vv.h>
17 #include <media/tuner.h>
18 #include <media/v4l2-common.h>
19 #include <media/i2c/saa7115.h>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22
23 #include "tea6415c.h"
24 #include "tea6420.h"
25
26 #define MXB_AUDIOS 6
27
28 #define I2C_SAA7111A 0x24
29 #define I2C_TDA9840 0x42
30 #define I2C_TEA6415C 0x43
31 #define I2C_TEA6420_1 0x4c
32 #define I2C_TEA6420_2 0x4d
33 #define I2C_TUNER 0x60
34
35 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
36
37
38 static int mxb_num;
39
40
41
42
43 static int freq = 4148;
44 module_param(freq, int, 0644);
45 MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
46
47 static int debug;
48 module_param(debug, int, 0644);
49 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
50
51 #define MXB_INPUTS 4
52 enum { TUNER, AUX1, AUX3, AUX3_YC };
53
54 static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
55 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
56 V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
57 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
58 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
59 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
60 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
61 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
62 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
63 };
64
65
66
67 static struct {
68 int hps_source;
69 int hps_sync;
70 } input_port_selection[MXB_INPUTS] = {
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
78
79 static int video_audio_connect[MXB_INPUTS] =
80 { 0, 1, 3, 3 };
81
82 struct mxb_routing {
83 u32 input;
84 u32 output;
85 };
86
87
88
89 static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
90 {
91 .index = 0,
92 .name = "Tuner",
93 .capability = V4L2_AUDCAP_STEREO,
94 } , {
95 .index = 1,
96 .name = "AUX1",
97 .capability = V4L2_AUDCAP_STEREO,
98 } , {
99 .index = 2,
100 .name = "AUX2",
101 .capability = V4L2_AUDCAP_STEREO,
102 } , {
103 .index = 3,
104 .name = "AUX3",
105 .capability = V4L2_AUDCAP_STEREO,
106 } , {
107 .index = 4,
108 .name = "Radio (X9)",
109 .capability = V4L2_AUDCAP_STEREO,
110 } , {
111 .index = 5,
112 .name = "CD-ROM (X10)",
113 .capability = V4L2_AUDCAP_STEREO,
114 }
115 };
116
117
118
119 static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
120 { { 1, 1 }, { 1, 1 } },
121 { { 5, 1 }, { 6, 1 } },
122 { { 4, 1 }, { 6, 1 } },
123 { { 3, 1 }, { 6, 1 } },
124 { { 1, 1 }, { 3, 1 } },
125 { { 1, 1 }, { 2, 1 } },
126 { { 6, 1 }, { 6, 1 } }
127 };
128
129
130
131 static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
132 { { 2, 3 }, { 1, 2 } },
133 { { 5, 3 }, { 6, 2 } },
134 { { 4, 3 }, { 6, 2 } },
135 { { 3, 3 }, { 6, 2 } },
136 { { 2, 3 }, { 3, 2 } },
137 { { 2, 3 }, { 2, 2 } },
138 { { 6, 3 }, { 6, 2 } }
139 };
140
141 struct mxb
142 {
143 struct video_device video_dev;
144 struct video_device vbi_dev;
145
146 struct i2c_adapter i2c_adapter;
147
148 struct v4l2_subdev *saa7111a;
149 struct v4l2_subdev *tda9840;
150 struct v4l2_subdev *tea6415c;
151 struct v4l2_subdev *tuner;
152 struct v4l2_subdev *tea6420_1;
153 struct v4l2_subdev *tea6420_2;
154
155 int cur_mode;
156 int cur_input;
157 int cur_audinput;
158 int cur_mute;
159 struct v4l2_frequency cur_freq;
160 };
161
162 #define saa7111a_call(mxb, o, f, args...) \
163 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
164 #define tda9840_call(mxb, o, f, args...) \
165 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
166 #define tea6415c_call(mxb, o, f, args...) \
167 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
168 #define tuner_call(mxb, o, f, args...) \
169 v4l2_subdev_call(mxb->tuner, o, f, ##args)
170 #define call_all(dev, o, f, args...) \
171 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
172
173 static void mxb_update_audmode(struct mxb *mxb)
174 {
175 struct v4l2_tuner t = {
176 .audmode = mxb->cur_mode,
177 };
178
179 tda9840_call(mxb, tuner, s_tuner, &t);
180 }
181
182 static inline void tea6420_route(struct mxb *mxb, int idx)
183 {
184 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
185 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
186 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
187 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
188 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
189 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
190 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
191 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
192 }
193
194 static struct saa7146_extension extension;
195
196 static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
197 {
198 struct saa7146_dev *dev = container_of(ctrl->handler,
199 struct saa7146_dev, ctrl_handler);
200 struct mxb *mxb = dev->ext_priv;
201
202 switch (ctrl->id) {
203 case V4L2_CID_AUDIO_MUTE:
204 mxb->cur_mute = ctrl->val;
205
206 tea6420_route(mxb, ctrl->val ? 6 :
207 video_audio_connect[mxb->cur_input]);
208 break;
209 default:
210 return -EINVAL;
211 }
212 return 0;
213 }
214
215 static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
216 .s_ctrl = mxb_s_ctrl,
217 };
218
219 static int mxb_probe(struct saa7146_dev *dev)
220 {
221 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
222 struct mxb *mxb = NULL;
223
224 v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
225 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
226 if (hdl->error)
227 return hdl->error;
228 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
229 if (mxb == NULL) {
230 DEB_D("not enough kernel memory\n");
231 return -ENOMEM;
232 }
233
234
235 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
236
237 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
238 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
239 DEB_S("cannot register i2c-device. skipping.\n");
240 kfree(mxb);
241 return -EFAULT;
242 }
243
244 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
245 "saa7111", I2C_SAA7111A, NULL);
246 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
247 "tea6420", I2C_TEA6420_1, NULL);
248 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
249 "tea6420", I2C_TEA6420_2, NULL);
250 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
251 "tea6415c", I2C_TEA6415C, NULL);
252 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
253 "tda9840", I2C_TDA9840, NULL);
254 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
255 "tuner", I2C_TUNER, NULL);
256
257
258 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
259 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
260 pr_err("did not find all i2c devices. aborting\n");
261 i2c_del_adapter(&mxb->i2c_adapter);
262 kfree(mxb);
263 return -ENODEV;
264 }
265
266
267
268
269 dev->ext_priv = mxb;
270
271 v4l2_ctrl_handler_setup(hdl);
272
273 return 0;
274 }
275
276
277
278 static struct {
279 int length;
280 char data[9];
281 } mxb_saa7740_init[] = {
282 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
283 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
284 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
285 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
286 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
287 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
288 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
289 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
290 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
291 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
292 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
293 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
294 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
295 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
296 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
297 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
298 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
299 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
300 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
301 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
302 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
303 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
304 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
305 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
306 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
307 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
308 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
309 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
310 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
311 { 3, { 0x48, 0x00, 0x01 } },
312 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
313 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
314 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
315 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
316 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
317 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
318 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
319 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
320 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
321 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
322 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
323 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
324 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
325 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
326 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
327 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
328 { 3, { 0x80, 0xb3, 0x0a } },
329 {-1, { 0 } }
330 };
331
332
333
334
335
336 static int mxb_init_done(struct saa7146_dev* dev)
337 {
338 struct mxb* mxb = (struct mxb*)dev->ext_priv;
339 struct i2c_msg msg;
340 struct tuner_setup tun_setup;
341 v4l2_std_id std = V4L2_STD_PAL_BG;
342
343 int i = 0, err = 0;
344
345
346 tea6420_route(mxb, 6);
347
348
349 saa7111a_call(mxb, video, s_std, std);
350
351
352 i = 0;
353 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
354 SAA7111_FMT_CCIR, 0);
355
356
357 tun_setup.mode_mask = T_ANALOG_TV;
358 tun_setup.addr = ADDR_UNSET;
359 tun_setup.type = TUNER_PHILIPS_PAL;
360 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
361
362 mxb->cur_freq.tuner = 0;
363 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
364 mxb->cur_freq.frequency = freq;
365 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
366
367
368
369 saa7146_write(dev, GPIO_CTRL, 0x00404050);
370 saa7111a_call(mxb, core, s_gpio, 1);
371 saa7111a_call(mxb, video, s_std, std);
372 tuner_call(mxb, video, s_std, std);
373
374
375 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
376
377
378 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
379
380
381 mxb->cur_input = 0;
382 mxb->cur_audinput = video_audio_connect[mxb->cur_input];
383 mxb->cur_mute = 1;
384
385 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
386 mxb_update_audmode(mxb);
387
388
389
390
391
392 msg.addr = 0x1b;
393 msg.flags = 0;
394 msg.len = mxb_saa7740_init[0].length;
395 msg.buf = &mxb_saa7740_init[0].data[0];
396
397 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
398 if (err == 1) {
399
400
401
402
403
404 extension.flags &= ~SAA7146_USE_I2C_IRQ;
405 for (i = 1; ; i++) {
406 if (-1 == mxb_saa7740_init[i].length)
407 break;
408
409 msg.len = mxb_saa7740_init[i].length;
410 msg.buf = &mxb_saa7740_init[i].data[0];
411 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
412 if (err != 1) {
413 DEB_D("failed to initialize 'sound arena module'\n");
414 goto err;
415 }
416 }
417 pr_info("'sound arena module' detected\n");
418 }
419 err:
420
421
422
423
424
425
426 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
427 input_port_selection[mxb->cur_input].hps_sync);
428
429
430
431
432
433 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
434 saa7146_write(dev, DD1_INIT, 0x02000200);
435 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
436
437 return 0;
438 }
439
440
441
442
443
444
445
446
447
448
449 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
450 {
451 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
452 if (i->index >= MXB_INPUTS)
453 return -EINVAL;
454 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
455 return 0;
456 }
457
458 static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
459 {
460 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
461 struct mxb *mxb = (struct mxb *)dev->ext_priv;
462 *i = mxb->cur_input;
463
464 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
465 return 0;
466 }
467
468 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
469 {
470 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
471 struct mxb *mxb = (struct mxb *)dev->ext_priv;
472 int err = 0;
473 int i = 0;
474
475 DEB_EE("VIDIOC_S_INPUT %d\n", input);
476
477 if (input >= MXB_INPUTS)
478 return -EINVAL;
479
480 mxb->cur_input = input;
481
482 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
483 input_port_selection[input].hps_sync);
484
485
486
487 switch (input) {
488 case TUNER:
489 i = SAA7115_COMPOSITE0;
490
491 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
492
493
494 if (!err)
495 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
496 break;
497 case AUX3_YC:
498
499
500 i = SAA7115_SVIDEO1;
501 break;
502 case AUX3:
503
504
505 i = SAA7115_COMPOSITE1;
506 break;
507 case AUX1:
508 i = SAA7115_COMPOSITE0;
509 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
510 break;
511 }
512
513 if (err)
514 return err;
515
516
517 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
518 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
519
520 mxb->cur_audinput = video_audio_connect[input];
521
522 if (0 == mxb->cur_mute)
523 tea6420_route(mxb, mxb->cur_audinput);
524 if (mxb->cur_audinput == 0)
525 mxb_update_audmode(mxb);
526
527 return 0;
528 }
529
530 static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
531 {
532 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
533 struct mxb *mxb = (struct mxb *)dev->ext_priv;
534
535 if (t->index) {
536 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
537 t->index);
538 return -EINVAL;
539 }
540
541 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
542
543 memset(t, 0, sizeof(*t));
544 strscpy(t->name, "TV Tuner", sizeof(t->name));
545 t->type = V4L2_TUNER_ANALOG_TV;
546 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
547 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
548 t->audmode = mxb->cur_mode;
549 return call_all(dev, tuner, g_tuner, t);
550 }
551
552 static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
553 {
554 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
555 struct mxb *mxb = (struct mxb *)dev->ext_priv;
556
557 if (t->index) {
558 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
559 t->index);
560 return -EINVAL;
561 }
562
563 mxb->cur_mode = t->audmode;
564 return call_all(dev, tuner, s_tuner, t);
565 }
566
567 static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
568 {
569 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
570
571 return call_all(dev, video, querystd, norm);
572 }
573
574 static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
575 {
576 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
577 struct mxb *mxb = (struct mxb *)dev->ext_priv;
578
579 if (f->tuner)
580 return -EINVAL;
581 *f = mxb->cur_freq;
582
583 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
584 return 0;
585 }
586
587 static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
588 {
589 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
590 struct mxb *mxb = (struct mxb *)dev->ext_priv;
591 struct saa7146_vv *vv = dev->vv_data;
592
593 if (f->tuner)
594 return -EINVAL;
595
596 if (V4L2_TUNER_ANALOG_TV != f->type)
597 return -EINVAL;
598
599 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
600
601
602 tuner_call(mxb, tuner, s_frequency, f);
603
604 mxb->cur_freq = *f;
605 tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
606 if (mxb->cur_audinput == 0)
607 mxb_update_audmode(mxb);
608
609 if (mxb->cur_input)
610 return 0;
611
612
613 spin_lock(&dev->slock);
614 vv->vbi_fieldcount = 0;
615 spin_unlock(&dev->slock);
616
617 return 0;
618 }
619
620 static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
621 {
622 if (a->index >= MXB_AUDIOS)
623 return -EINVAL;
624 *a = mxb_audios[a->index];
625 return 0;
626 }
627
628 static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
629 {
630 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
631 struct mxb *mxb = (struct mxb *)dev->ext_priv;
632
633 DEB_EE("VIDIOC_G_AUDIO\n");
634 *a = mxb_audios[mxb->cur_audinput];
635 return 0;
636 }
637
638 static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
639 {
640 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
641 struct mxb *mxb = (struct mxb *)dev->ext_priv;
642
643 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
644 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
645 if (mxb->cur_audinput != a->index) {
646 mxb->cur_audinput = a->index;
647 tea6420_route(mxb, a->index);
648 if (mxb->cur_audinput == 0)
649 mxb_update_audmode(mxb);
650 }
651 return 0;
652 }
653 return -EINVAL;
654 }
655
656 #ifdef CONFIG_VIDEO_ADV_DEBUG
657 static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
658 {
659 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
660
661 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
662 return -EINVAL;
663 reg->val = saa7146_read(dev, reg->reg);
664 reg->size = 4;
665 return 0;
666 }
667
668 static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
669 {
670 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
671
672 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
673 return -EINVAL;
674 saa7146_write(dev, reg->reg, reg->val);
675 return 0;
676 }
677 #endif
678
679 static struct saa7146_ext_vv vv_data;
680
681
682 static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
683 {
684 struct mxb *mxb;
685
686 DEB_EE("dev:%p\n", dev);
687
688 saa7146_vv_init(dev, &vv_data);
689 if (mxb_probe(dev)) {
690 saa7146_vv_release(dev);
691 return -1;
692 }
693 mxb = (struct mxb *)dev->ext_priv;
694
695 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
696 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
697 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
698 vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
699 vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
700 vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
701 vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
702 vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
703 vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
704 vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
705 vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
706 #ifdef CONFIG_VIDEO_ADV_DEBUG
707 vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
708 vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
709 #endif
710 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
711 ERR("cannot register capture v4l2 device. skipping.\n");
712 saa7146_vv_release(dev);
713 return -1;
714 }
715
716
717 if (MXB_BOARD_CAN_DO_VBI(dev)) {
718 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
719 ERR("cannot register vbi v4l2 device. skipping.\n");
720 }
721 }
722
723 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
724
725 mxb_num++;
726 mxb_init_done(dev);
727 return 0;
728 }
729
730 static int mxb_detach(struct saa7146_dev *dev)
731 {
732 struct mxb *mxb = (struct mxb *)dev->ext_priv;
733
734 DEB_EE("dev:%p\n", dev);
735
736
737 tea6420_route(mxb, 6);
738
739 saa7146_unregister_device(&mxb->video_dev,dev);
740 if (MXB_BOARD_CAN_DO_VBI(dev))
741 saa7146_unregister_device(&mxb->vbi_dev, dev);
742 saa7146_vv_release(dev);
743
744 mxb_num--;
745
746 i2c_del_adapter(&mxb->i2c_adapter);
747 kfree(mxb);
748
749 return 0;
750 }
751
752 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
753 {
754 struct mxb *mxb = (struct mxb *)dev->ext_priv;
755
756 if (V4L2_STD_PAL_I == standard->id) {
757 v4l2_std_id std = V4L2_STD_PAL_I;
758
759 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
760
761 saa7146_write(dev, GPIO_CTRL, 0x00404050);
762 saa7111a_call(mxb, core, s_gpio, 0);
763 saa7111a_call(mxb, video, s_std, std);
764 if (mxb->cur_input == 0)
765 tuner_call(mxb, video, s_std, std);
766 } else {
767 v4l2_std_id std = V4L2_STD_PAL_BG;
768
769 if (mxb->cur_input)
770 std = standard->id;
771 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
772
773 saa7146_write(dev, GPIO_CTRL, 0x00404050);
774 saa7111a_call(mxb, core, s_gpio, 1);
775 saa7111a_call(mxb, video, s_std, std);
776 if (mxb->cur_input == 0)
777 tuner_call(mxb, video, s_std, std);
778 }
779 return 0;
780 }
781
782 static struct saa7146_standard standard[] = {
783 {
784 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
785 .v_offset = 0x17, .v_field = 288,
786 .h_offset = 0x14, .h_pixels = 680,
787 .v_max_out = 576, .h_max_out = 768,
788 }, {
789 .name = "PAL-I", .id = V4L2_STD_PAL_I,
790 .v_offset = 0x17, .v_field = 288,
791 .h_offset = 0x14, .h_pixels = 680,
792 .v_max_out = 576, .h_max_out = 768,
793 }, {
794 .name = "NTSC", .id = V4L2_STD_NTSC,
795 .v_offset = 0x16, .v_field = 240,
796 .h_offset = 0x06, .h_pixels = 708,
797 .v_max_out = 480, .h_max_out = 640,
798 }, {
799 .name = "SECAM", .id = V4L2_STD_SECAM,
800 .v_offset = 0x14, .v_field = 288,
801 .h_offset = 0x14, .h_pixels = 720,
802 .v_max_out = 576, .h_max_out = 768,
803 }
804 };
805
806 static struct saa7146_pci_extension_data mxb = {
807 .ext_priv = "Multimedia eXtension Board",
808 .ext = &extension,
809 };
810
811 static const struct pci_device_id pci_tbl[] = {
812 {
813 .vendor = PCI_VENDOR_ID_PHILIPS,
814 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
815 .subvendor = 0x0000,
816 .subdevice = 0x0000,
817 .driver_data = (unsigned long)&mxb,
818 }, {
819 .vendor = 0,
820 }
821 };
822
823 MODULE_DEVICE_TABLE(pci, pci_tbl);
824
825 static struct saa7146_ext_vv vv_data = {
826 .inputs = MXB_INPUTS,
827 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
828 .stds = &standard[0],
829 .num_stds = ARRAY_SIZE(standard),
830 .std_callback = &std_callback,
831 };
832
833 static struct saa7146_extension extension = {
834 .name = "Multimedia eXtension Board",
835 .flags = SAA7146_USE_I2C_IRQ,
836
837 .pci_tbl = &pci_tbl[0],
838 .module = THIS_MODULE,
839
840 .attach = mxb_attach,
841 .detach = mxb_detach,
842
843 .irq_mask = 0,
844 .irq_func = NULL,
845 };
846
847 static int __init mxb_init_module(void)
848 {
849 if (saa7146_register_extension(&extension)) {
850 DEB_S("failed to register extension\n");
851 return -ENODEV;
852 }
853
854 return 0;
855 }
856
857 static void __exit mxb_cleanup_module(void)
858 {
859 saa7146_unregister_extension(&extension);
860 }
861
862 module_init(mxb_init_module);
863 module_exit(mxb_cleanup_module);
864
865 MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
866 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
867 MODULE_LICENSE("GPL");