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