📄 mxb.c
字号:
switch( input ) { case TUNER: case AUX1: { if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { printk("VIDIOC_S_INPUT: could not address tea6415c #3\n"); return -EFAULT; } break; } default: { break; } } /* switch video in saa7111a */ if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); } /* switch the audio-source only if necessary */ if( 0 == mxb->cur_mute ) { mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]); } return 0; } case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; int byte = 0; if( 0 != t->index ) { DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); return -EINVAL; } DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); memset(t,0,sizeof(*t)); strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ /* FIXME: add the real signal strength here */ t->signal = 0xffff; t->afc = 0; mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); t->audmode = mxb->cur_mode; if( byte < 0 ) { t->rxsubchans = V4L2_TUNER_SUB_MONO; } else { switch(byte) { case TDA9840_MONO_DETECT: { t->rxsubchans = V4L2_TUNER_SUB_MONO; DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n")); break; } case TDA9840_DUAL_DETECT: { t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n")); break; } case TDA9840_STEREO_DETECT: { t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n")); break; } default: { /* TDA9840_INCORRECT_DETECT */ t->rxsubchans = V4L2_TUNER_MODE_MONO; DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n")); break; } } } return 0; } case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; int result = 0; int byte = 0; if( 0 != t->index ) { DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); return -EINVAL; } switch(t->audmode) { case V4L2_TUNER_MODE_STEREO: { mxb->cur_mode = V4L2_TUNER_MODE_STEREO; byte = TDA9840_SET_STEREO; DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); break; } case V4L2_TUNER_MODE_LANG1: { mxb->cur_mode = V4L2_TUNER_MODE_LANG1; byte = TDA9840_SET_LANG1; DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); break; } case V4L2_TUNER_MODE_LANG2: { mxb->cur_mode = V4L2_TUNER_MODE_LANG2; byte = TDA9840_SET_LANG2; DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); break; } default: { /* case V4L2_TUNER_MODE_MONO: {*/ mxb->cur_mode = V4L2_TUNER_MODE_MONO; byte = TDA9840_SET_MONO; DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); break; } } if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); } return 0; } case VIDIOC_G_FREQUENCY: { struct v4l2_frequency *f = arg; if(0 != mxb->cur_input) { DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); return -EINVAL; } *f = mxb->cur_freq; DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency)); return 0; } case VIDIOC_S_FREQUENCY: { struct v4l2_frequency *f = arg; if (0 != f->tuner) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; if(0 != mxb->cur_input) { DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); return -EINVAL; } mxb->cur_freq = *f; DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); /* tune in desired frequency */ mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); vv->vbi_fieldcount = 0; spin_unlock(&dev->slock); return 0; } case MXB_S_AUDIO_CD: { int i = *(int*)arg; if( i < 0 || i >= MXB_AUDIOS ) { DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); return -EINVAL; } DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i)); mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]); return 0; } case MXB_S_AUDIO_LINE: { int i = *(int*)arg; if( i < 0 || i >= MXB_AUDIOS ) { DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); return -EINVAL; } DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i)); mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]); mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]); return 0; } case VIDIOC_G_AUDIO: { struct v4l2_audio *a = arg; if( a->index < 0 || a->index > MXB_INPUTS ) { DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); return -EINVAL; } DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); return 0; } case VIDIOC_S_AUDIO: { struct v4l2_audio *a = arg; DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); return 0; } default:/* DEB2(printk("does not handle this ioctl.\n"));*/ return -ENOIOCTLCMD; } return 0;}static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std){ struct mxb* mxb = (struct mxb*)dev->ext_priv; int zero = 0; int one = 1; if(V4L2_STD_PAL_I == std->id ) { DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); } else { DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); } return 0;}static struct saa7146_standard standard[] = { { .name = "PAL-BG", .id = V4L2_STD_PAL_BG, .v_offset = 0x17, .v_field = 288, .h_offset = 0x14, .h_pixels = 680, .v_max_out = 576, .h_max_out = 768, }, { .name = "PAL-I", .id = V4L2_STD_PAL_I, .v_offset = 0x17, .v_field = 288, .h_offset = 0x14, .h_pixels = 680, .v_max_out = 576, .h_max_out = 768, }, { .name = "NTSC", .id = V4L2_STD_NTSC, .v_offset = 0x16, .v_field = 240, .h_offset = 0x06, .h_pixels = 708, .v_max_out = 480, .h_max_out = 640, }, { .name = "SECAM", .id = V4L2_STD_SECAM, .v_offset = 0x14, .v_field = 288, .h_offset = 0x14, .h_pixels = 720, .v_max_out = 576, .h_max_out = 768, }};static struct saa7146_pci_extension_data mxb = { .ext_priv = "Multimedia eXtension Board", .ext = &extension,};static struct pci_device_id pci_tbl[] = { { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7146, .subvendor = 0x0000, .subdevice = 0x0000, .driver_data = (unsigned long)&mxb, }, { .vendor = 0, }};MODULE_DEVICE_TABLE(pci, pci_tbl);static struct saa7146_ext_vv vv_data = { .inputs = MXB_INPUTS, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, .ioctls = &ioctls[0], .ioctl = mxb_ioctl,};static struct saa7146_extension extension = { .name = MXB_IDENTIFIER, .flags = SAA7146_USE_I2C_IRQ, .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, .probe = mxb_probe, .attach = mxb_attach, .detach = mxb_detach, .irq_mask = 0, .irq_func = NULL,}; static int __init mxb_init_module(void){ if( 0 != saa7146_register_extension(&extension)) { DEB_S(("failed to register extension.\n")); return -ENODEV; } return 0;}static void __exit mxb_cleanup_module(void){ saa7146_unregister_extension(&extension);}module_init(mxb_init_module);module_exit(mxb_cleanup_module);MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -