24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26 #define DEBUG_VARIABLE debug
32 #include <linux/module.h>
39 #define I2C_SAA7111A 0x24
40 #define I2C_TDA9840 0x42
41 #define I2C_TEA6415C 0x43
42 #define I2C_TEA6420_1 0x4c
43 #define I2C_TEA6420_2 0x4d
44 #define I2C_TUNER 0x60
46 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
54 static int freq = 4148;
119 .name =
"Radio (X9)",
123 .name =
"CD-ROM (X10)",
131 { { 1, 1 }, { 1, 1 } },
132 { { 5, 1 }, { 6, 1 } },
133 { { 4, 1 }, { 6, 1 } },
134 { { 3, 1 }, { 6, 1 } },
135 { { 1, 1 }, { 3, 1 } },
136 { { 1, 1 }, { 2, 1 } },
137 { { 6, 1 }, { 6, 1 } }
143 { { 2, 3 }, { 1, 2 } },
144 { { 5, 3 }, { 6, 2 } },
145 { { 4, 3 }, { 6, 2 } },
146 { { 3, 3 }, { 6, 2 } },
147 { { 2, 3 }, { 3, 2 } },
148 { { 2, 3 }, { 2, 2 } },
149 { { 6, 3 }, { 6, 2 } }
173 #define saa7111a_call(mxb, o, f, args...) \
174 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
175 #define tda9840_call(mxb, o, f, args...) \
176 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
177 #define tea6415c_call(mxb, o, f, args...) \
178 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
179 #define tuner_call(mxb, o, f, args...) \
180 v4l2_subdev_call(mxb->tuner, o, f, ##args)
181 #define call_all(dev, o, f, args...) \
182 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
184 static void mxb_update_audmode(
struct mxb *
mxb)
193 static inline void tea6420_route(
struct mxb *
mxb,
int idx)
196 TEA6420_cd[idx][0].
input, TEA6420_cd[idx][0].
output, 0);
198 TEA6420_cd[idx][1].
input, TEA6420_cd[idx][1].
output, 0);
200 TEA6420_line[idx][0].
input, TEA6420_line[idx][0].
output, 0);
202 TEA6420_line[idx][1].
input, TEA6420_line[idx][1].
output, 0);
217 tea6420_route(mxb, ctrl->
val ? 6 :
227 .s_ctrl = mxb_s_ctrl,
233 struct mxb *mxb =
NULL;
239 mxb = kzalloc(
sizeof(
struct mxb),
GFP_KERNEL);
241 DEB_D(
"not enough kernel memory\n");
250 DEB_S(
"cannot register i2c-device. skipping.\n");
271 pr_err(
"did not find all i2c devices. aborting\n");
292 } mxb_saa7740_init[] = {
293 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
294 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
295 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
296 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
297 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
298 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
299 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
300 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
301 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
302 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
303 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
304 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
305 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
306 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
307 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
308 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
309 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
310 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
311 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
312 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
313 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
314 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
315 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
316 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
317 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
318 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
319 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
320 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
321 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
322 { 3, { 0x48, 0x00, 0x01 } },
323 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
324 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
325 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
326 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
327 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
328 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
329 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
330 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
331 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
332 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
333 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
334 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
335 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
336 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
337 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
338 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
339 { 3, { 0x80, 0xb3, 0x0a } },
349 struct mxb* mxb = (
struct mxb*)dev->
ext_priv;
351 struct tuner_setup tun_setup;
357 tea6420_route(mxb, 6);
368 tun_setup.mode_mask = T_ANALOG_TV;
369 tun_setup.addr = ADDR_UNSET;
370 tun_setup.type = TUNER_PHILIPS_PAL;
397 mxb_update_audmode(mxb);
405 msg.len = mxb_saa7740_init[0].length;
406 msg.buf = &mxb_saa7740_init[0].data[0];
417 if (-1 == mxb_saa7740_init[
i].
length)
420 msg.len = mxb_saa7740_init[
i].length;
421 msg.buf = &mxb_saa7740_init[
i].data[0];
424 DEB_D(
"failed to initialize 'sound arena module'\n");
428 pr_info(
"'sound arena module' detected\n");
438 input_port_selection[mxb->
cur_input].hps_sync);
469 static int vidioc_g_input(
struct file *file,
void *fh,
unsigned int *i)
472 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
475 DEB_EE(
"VIDIOC_G_INPUT %d\n", *i);
479 static int vidioc_s_input(
struct file *file,
void *fh,
unsigned int input)
482 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
486 DEB_EE(
"VIDIOC_S_INPUT %d\n", input);
494 input_port_selection[input].
hps_sync);
529 pr_err(
"VIDIOC_S_INPUT: could not address saa7111a\n");
536 mxb_update_audmode(mxb);
541 static int vidioc_g_tuner(
struct file *file,
void *fh,
struct v4l2_tuner *
t)
544 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
547 DEB_D(
"VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
563 static int vidioc_s_tuner(
struct file *file,
void *fh,
struct v4l2_tuner *t)
566 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
569 DEB_D(
"VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
578 static int vidioc_querystd(
struct file *file,
void *fh,
v4l2_std_id *norm)
582 return call_all(dev, video, querystd, norm);
585 static int vidioc_g_frequency(
struct file *file,
void *fh,
struct v4l2_frequency *
f)
588 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
598 static int vidioc_s_frequency(
struct file *file,
void *fh,
struct v4l2_frequency *f)
601 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
610 DEB_EE(
"VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->
cur_freq.frequency);
618 mxb_update_audmode(mxb);
624 spin_lock(&dev->
slock);
625 vv->vbi_fieldcount = 0;
626 spin_unlock(&dev->
slock);
631 static int vidioc_enumaudio(
struct file *file,
void *fh,
struct v4l2_audio *
a)
635 *a = mxb_audios[a->
index];
639 static int vidioc_g_audio(
struct file *file,
void *fh,
struct v4l2_audio *a)
642 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
644 DEB_EE(
"VIDIOC_G_AUDIO\n");
649 static int vidioc_s_audio(
struct file *file,
void *fh,
const struct v4l2_audio *a)
652 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
658 tea6420_route(mxb, a->
index);
660 mxb_update_audmode(mxb);
667 #ifdef CONFIG_VIDEO_ADV_DEBUG
683 static int vidioc_s_register(
struct file *file,
void *fh,
struct v4l2_dbg_register *reg)
708 if (mxb_probe(dev)) {
714 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
715 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
716 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
717 vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
718 vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
719 vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
720 vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
721 vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
722 vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
723 vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
724 vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
725 #ifdef CONFIG_VIDEO_ADV_DEBUG
726 vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
727 vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
730 ERR(
"cannot register capture v4l2 device. skipping.\n");
738 ERR(
"cannot register vbi v4l2 device. skipping.\n");
742 pr_info(
"found Multimedia eXtension Board #%d\n", mxb_num);
751 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
756 tea6420_route(mxb, 6);
773 struct mxb *mxb = (
struct mxb *)dev->
ext_priv;
778 DEB_D(
"VIDIOC_S_STD: setting mxb for PAL_I\n");
790 DEB_D(
"VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
804 .v_offset = 0x17, .v_field = 288,
805 .h_offset = 0x14, .h_pixels = 680,
806 .v_max_out = 576, .h_max_out = 768,
809 .v_offset = 0x17, .v_field = 288,
810 .h_offset = 0x14, .h_pixels = 680,
811 .v_max_out = 576, .h_max_out = 768,
814 .v_offset = 0x16, .v_field = 240,
815 .h_offset = 0x06, .h_pixels = 708,
816 .v_max_out = 480, .h_max_out = 640,
819 .v_offset = 0x14, .v_field = 288,
820 .h_offset = 0x14, .h_pixels = 720,
821 .v_max_out = 576, .h_max_out = 768,
826 .ext_priv =
"Multimedia eXtension Board",
836 .driver_data = (
unsigned long)&mxb,
847 .stds = &standard[0],
853 .name =
"Multimedia eXtension Board",
856 .pci_tbl = &pci_tbl[0],
859 .attach = mxb_attach,
860 .detach = mxb_detach,
866 static int __init mxb_init_module(
void)
869 DEB_S(
"failed to register extension\n");
876 static void __exit mxb_cleanup_module(
void)
884 MODULE_DESCRIPTION(
"video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");