1/* 2 mxb - v4l2 driver for the Multimedia eXtension Board 3 4 Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de> 5 6 Visit http://www.mihu.de/linux/saa7146/mxb/ 7 for further details about this card. 8 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> 28#include <linux/video_decoder.h> 29#include <media/v4l2-common.h> 30 31#include "mxb.h" 32#include "tea6415c.h" 33#include "tea6420.h" 34#include "tda9840.h" 35 36#define I2C_SAA7111 0x24 37 38#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) 39 40/* global variable */ 41static int mxb_num = 0; 42 43/* initial frequence the tuner will be tuned to. 44 in verden (lower saxony, germany) 4148 is a 45 channel called "phoenix" */ 46static int freq = 4148; 47module_param(freq, int, 0644); 48MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup"); 49 50static int debug = 0; 51module_param(debug, int, 0644); 52MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); 53 54#define MXB_INPUTS 4 55enum { TUNER, AUX1, AUX3, AUX3_YC }; 56 57static struct v4l2_input mxb_inputs[MXB_INPUTS] = { 58 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 59 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 60 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 61 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 62}; 63 64/* this array holds the information, which port of the saa7146 each 65 input actually uses. the mxb uses port 0 for every input */ 66static struct { 67 int hps_source; 68 int hps_sync; 69} input_port_selection[MXB_INPUTS] = { 70 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A }, 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}; 75 76/* this array holds the information of the audio source (mxb_audios), 77 which has to be switched corresponding to the video source (mxb_channels) */ 78static int video_audio_connect[MXB_INPUTS] = 79 { 0, 1, 3, 3 }; 80 81/* these are the necessary input-output-pins for bringing one audio source 82(see above) to the CD-output */ 83static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] = 84 { 85 {{1,1,0},{1,1,0}}, /* Tuner */ 86 {{5,1,0},{6,1,0}}, /* AUX 1 */ 87 {{4,1,0},{6,1,0}}, /* AUX 2 */ 88 {{3,1,0},{6,1,0}}, /* AUX 3 */ 89 {{1,1,0},{3,1,0}}, /* Radio */ 90 {{1,1,0},{2,1,0}}, /* CD-Rom */ 91 {{6,1,0},{6,1,0}} /* Mute */ 92 }; 93 94/* these are the necessary input-output-pins for bringing one audio source 95(see above) to the line-output */ 96static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] = 97 { 98 {{2,3,0},{1,2,0}}, 99 {{5,3,0},{6,2,0}}, 100 {{4,3,0},{6,2,0}}, 101 {{3,3,0},{6,2,0}}, 102 {{2,3,0},{3,2,0}}, 103 {{2,3,0},{2,2,0}}, 104 {{6,3,0},{6,2,0}} /* Mute */ 105 }; 106 107#define MAXCONTROLS 1 108static struct v4l2_queryctrl mxb_controls[] = { 109 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 }, 110}; 111 112static struct saa7146_extension_ioctls ioctls[] = { 113 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, 114 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, 115 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, 116 { VIDIOC_QUERYCTRL, SAA7146_BEFORE }, 117 { VIDIOC_G_CTRL, SAA7146_BEFORE }, 118 { VIDIOC_S_CTRL, SAA7146_BEFORE }, 119 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE }, 120 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, 121 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE }, 122 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, 123 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, 124 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, 125 { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ 126 { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ 127 { 0, 0 } 128}; 129 130struct mxb 131{ 132 struct video_device *video_dev; 133 struct video_device *vbi_dev; 134 135 struct i2c_adapter i2c_adapter; 136 137 struct i2c_client* saa7111a; 138 struct i2c_client* tda9840; 139 struct i2c_client* tea6415c; 140 struct i2c_client* tuner; 141 struct i2c_client* tea6420_1; 142 struct i2c_client* tea6420_2; 143 144 int cur_mode; /* current audio mode (mono, stereo, ...) */ 145 int cur_input; /* current input */ 146 int cur_mute; /* current mute status */ 147 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */ 148}; 149 150static struct saa7146_extension extension; 151 152static int mxb_probe(struct saa7146_dev* dev) 153{ 154 struct mxb* mxb = NULL; 155 struct i2c_client *client; 156 struct list_head *item; 157 int result; 158 159 if ((result = request_module("saa7111")) < 0) { 160 printk("mxb: saa7111 i2c module not available.\n"); 161 return -ENODEV; 162 } 163 if ((result = request_module("tea6420")) < 0) { 164 printk("mxb: tea6420 i2c module not available.\n"); 165 return -ENODEV; 166 } 167 if ((result = request_module("tea6415c")) < 0) { 168 printk("mxb: tea6415c i2c module not available.\n"); 169 return -ENODEV; 170 } 171 if ((result = request_module("tda9840")) < 0) { 172 printk("mxb: tda9840 i2c module not available.\n"); 173 return -ENODEV; 174 } 175 if ((result = request_module("tuner")) < 0) { 176 printk("mxb: tuner i2c module not available.\n"); 177 return -ENODEV; 178 } 179 180 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); 181 if( NULL == mxb ) { 182 DEB_D(("not enough kernel memory.\n")); 183 return -ENOMEM; 184 } 185 186 mxb->i2c_adapter = (struct i2c_adapter) { 187 .class = I2C_CLASS_TV_ANALOG, 188 .name = "mxb", 189 }; 190 191 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); 192 if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { 193 DEB_S(("cannot register i2c-device. skipping.\n")); 194 kfree(mxb); 195 return -EFAULT; 196 } 197 198 /* loop through all i2c-devices on the bus and look who is there */ 199 list_for_each(item,&mxb->i2c_adapter.clients) { 200 client = list_entry(item, struct i2c_client, list); 201 if( I2C_ADDR_TEA6420_1 == client->addr ) 202 mxb->tea6420_1 = client; 203 if( I2C_ADDR_TEA6420_2 == client->addr ) 204 mxb->tea6420_2 = client; 205 if( I2C_TEA6415C_2 == client->addr ) 206 mxb->tea6415c = client; 207 if( I2C_ADDR_TDA9840 == client->addr ) 208 mxb->tda9840 = client; 209 if( I2C_SAA7111 == client->addr ) 210 mxb->saa7111a = client; 211 if( 0x60 == client->addr ) 212 mxb->tuner = client; 213 } 214 215 /* check if all devices are present */ 216 if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c 217 || 0 == mxb->tda9840 || 0 == mxb->saa7111a || 0 == mxb->tuner ) { 218 219 printk("mxb: did not find all i2c devices. aborting\n"); 220 i2c_del_adapter(&mxb->i2c_adapter); 221 kfree(mxb); 222 return -ENODEV; 223 } 224 225 /* all devices are present, probe was successful */ 226 227 /* we store the pointer in our private data field */ 228 dev->ext_priv = mxb; 229 230 return 0; 231} 232 233/* some init data for the saa7740, the so-called 'sound arena module'. 234 there are no specs available, so we simply use some init values */ 235static struct { 236 int length; 237 char data[9]; 238} mxb_saa7740_init[] = { 239 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } }, 240 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } }, 241 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } }, 242 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } }, 243 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } }, 244 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } }, 245 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } }, 246 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } }, 247 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } }, 248 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } }, 249 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } }, 250 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } }, 251 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } }, 252 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } }, 253 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } }, 254 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } }, 255 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } }, 256 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } }, 257 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } }, 258 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } }, 259 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } }, 260 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } }, 261 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } }, 262 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } }, 263 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } }, 264 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } }, 265 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } }, 266 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } }, 267 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } }, 268 { 3, { 0x48, 0x00, 0x01 } }, 269 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } }, 270 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } }, 271 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } }, 272 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } }, 273 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } }, 274 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } }, 275 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } }, 276 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } }, 277 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } }, 278 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } }, 279 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } }, 280 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } }, 281 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } }, 282 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } }, 283 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, 284 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, 285 { 3, { 0x80, 0xb3, 0x0a } }, 286 {-1, { 0} } 287}; 288 289static const unsigned char mxb_saa7111_init[] = { 290 0x00, 0x00, /* 00 - ID byte */ 291 0x01, 0x00, /* 01 - reserved */ 292 293 /*front end */ 294 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ 295 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ 296 0x04, 0x00, /* 04 - GAI1=256 */ 297 0x05, 0x00, /* 05 - GAI2=256 */ 298 299 /* decoder */ 300 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ 301 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ 302 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ 303 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ 304 0x0a, 0x80, /* 0a - BRIG=128 */ 305 0x0b, 0x47, /* 0b - CONT=1.109 */ 306 0x0c, 0x40, /* 0c - SATN=1.0 */ 307 0x0d, 0x00, /* 0d - HUE=0 */ 308 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ 309 0x0f, 0x00, /* 0f - reserved */ 310 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ 311 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ 312 0x12, 0x80, /* 12 - xx output control 2 */ 313 0x13, 0x30, /* 13 - xx output control 3 */ 314 0x14, 0x00, /* 14 - reserved */ 315 0x15, 0x15, /* 15 - VBI */ 316 0x16, 0x04, /* 16 - VBI */ 317 0x17, 0x00, /* 17 - VBI */ 318}; 319 320/* bring hardware to a sane state. this has to be done, just in case someone 321 wants to capture from this device before it has been properly initialized. 322 the capture engine would badly fail, because no valid signal arrives on the 323 saa7146, thus leading to timeouts and stuff. */ 324static int mxb_init_done(struct saa7146_dev* dev) 325{ 326 struct mxb* mxb = (struct mxb*)dev->ext_priv; 327 struct video_decoder_init init; 328 struct i2c_msg msg; 329 struct tuner_setup tun_setup; 330 v4l2_std_id std = V4L2_STD_PAL_BG; 331 332 int i = 0, err = 0; 333 struct tea6415c_multiplex vm; 334 335 /* select video mode in saa7111a */ 336 i = VIDEO_MODE_PAL; 337 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); 338 339 /* write configuration to saa7111a */ 340 init.data = mxb_saa7111_init; 341 init.len = sizeof(mxb_saa7111_init); 342 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init); 343 344 /* select tuner-output on saa7111a */ 345 i = 0; 346 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i); 347 348 /* enable vbi bypass */ 349 i = 1; 350 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i); 351 352 /* select a tuner type */ 353 tun_setup.mode_mask = T_ANALOG_TV; 354 tun_setup.addr = ADDR_UNSET; 355 tun_setup.type = TUNER_PHILIPS_PAL; 356 mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup); 357 /* tune in some frequency on tuner */ 358 mxb->cur_freq.tuner = 0; 359 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; 360 mxb->cur_freq.frequency = freq; 361 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, 362 &mxb->cur_freq); 363 364 /* set a default video standard */ 365 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); 366 367 /* mute audio on tea6420s */ 368 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); 369 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); 370 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]); 371 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]); 372 373 /* switch to tuner-channel on tea6415c*/ 374 vm.out = 17; 375 vm.in = 3; 376 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); 377 378 /* select tuner-output on multicable on tea6415c*/ 379 vm.in = 3; 380 vm.out = 13; 381 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); 382 383 /* the rest for mxb */ 384 mxb->cur_input = 0; 385 mxb->cur_mute = 1; 386 387 mxb->cur_mode = V4L2_TUNER_MODE_STEREO; 388 mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode); 389 390 /* check if the saa7740 (aka 'sound arena module') is present 391 on the mxb. if so, we must initialize it. due to lack of 392 informations about the saa7740, the values were reverse 393 engineered. */ 394 msg.addr = 0x1b; 395 msg.flags = 0; 396 msg.len = mxb_saa7740_init[0].length; 397 msg.buf = &mxb_saa7740_init[0].data[0]; 398 399 if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { 400 /* the sound arena module is a pos, that's probably the reason 401 philips refuses to hand out a datasheet for the saa7740... 402 it seems to screw up the i2c bus, so we disable fast irq 403 based i2c transactions here and rely on the slow and safe 404 polling method ... */ 405 extension.flags &= ~SAA7146_USE_I2C_IRQ; 406 for(i = 1;;i++) { 407 if( -1 == mxb_saa7740_init[i].length ) { 408 break; 409 } 410 411 msg.len = mxb_saa7740_init[i].length; 412 msg.buf = &mxb_saa7740_init[i].data[0]; 413 if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { 414 DEB_D(("failed to initialize 'sound arena module'.\n")); 415 goto err; 416 } 417 } 418 INFO(("'sound arena module' detected.\n")); 419 } 420err: 421 /* the rest for saa7146: you should definitely set some basic values 422 for the input-port handling of the saa7146. */ 423 424 /* ext->saa has been filled by the core driver */ 425 426 /* some stuff is done via variables */ 427 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync); 428 429 /* some stuff is done via direct write to the registers */ 430 431 /* this is ugly, but because of the fact that this is completely 432 hardware dependend, it should be done directly... */ 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/* interrupt-handler. this gets called when irq_mask is != 0. 441 it must clear the interrupt-bits in irq_mask it has handled */ 442/* 443void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) 444{ 445 struct mxb* mxb = (struct mxb*)dev->ext_priv; 446} 447*/ 448 449static struct saa7146_ext_vv vv_data; 450 451/* this function only gets called when the probing was successful */ 452static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) 453{ 454 struct mxb* mxb = (struct mxb*)dev->ext_priv; 455 456 DEB_EE(("dev:%p\n",dev)); 457 458 /* checking for i2c-devices can be omitted here, because we 459 already did this in "mxb_vl42_probe" */ 460 461 saa7146_vv_init(dev,&vv_data); 462 if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { 463 ERR(("cannot register capture v4l2 device. skipping.\n")); 464 return -1; 465 } 466 467 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ 468 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { 469 if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { 470 ERR(("cannot register vbi v4l2 device. skipping.\n")); 471 } 472 } 473 474 i2c_use_client(mxb->tea6420_1); 475 i2c_use_client(mxb->tea6420_2); 476 i2c_use_client(mxb->tea6415c); 477 i2c_use_client(mxb->tda9840); 478 i2c_use_client(mxb->saa7111a); 479 i2c_use_client(mxb->tuner); 480 481 printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num); 482 483 mxb_num++; 484 mxb_init_done(dev); 485 return 0; 486} 487 488static int mxb_detach(struct saa7146_dev* dev) 489{ 490 struct mxb* mxb = (struct mxb*)dev->ext_priv; 491 492 DEB_EE(("dev:%p\n",dev)); 493 494 i2c_release_client(mxb->tea6420_1); 495 i2c_release_client(mxb->tea6420_2); 496 i2c_release_client(mxb->tea6415c); 497 i2c_release_client(mxb->tda9840); 498 i2c_release_client(mxb->saa7111a); 499 i2c_release_client(mxb->tuner); 500 501 saa7146_unregister_device(&mxb->video_dev,dev); 502 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { 503 saa7146_unregister_device(&mxb->vbi_dev,dev); 504 } 505 saa7146_vv_release(dev); 506 507 mxb_num--; 508 509 i2c_del_adapter(&mxb->i2c_adapter); 510 kfree(mxb); 511 512 return 0; 513} 514 515static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 516{ 517 struct saa7146_dev *dev = fh->dev; 518 struct mxb* mxb = (struct mxb*)dev->ext_priv; 519 struct saa7146_vv *vv = dev->vv_data; 520 521 switch(cmd) { 522 case VIDIOC_ENUMINPUT: 523 { 524 struct v4l2_input *i = arg; 525 526 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); 527 if( i->index < 0 || i->index >= MXB_INPUTS) { 528 return -EINVAL; 529 } 530 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); 531 532 return 0; 533 } 534 /* the saa7146 provides some controls (brightness, contrast, saturation) 535 which gets registered *after* this function. because of this we have 536 to return with a value != 0 even if the function succeded.. */ 537 case VIDIOC_QUERYCTRL: 538 { 539 struct v4l2_queryctrl *qc = arg; 540 int i; 541 542 for (i = MAXCONTROLS - 1; i >= 0; i--) { 543 if (mxb_controls[i].id == qc->id) { 544 *qc = mxb_controls[i]; 545 DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id)); 546 return 0; 547 } 548 } 549 return -EAGAIN; 550 } 551 case VIDIOC_G_CTRL: 552 { 553 struct v4l2_control *vc = arg; 554 int i; 555 556 for (i = MAXCONTROLS - 1; i >= 0; i--) { 557 if (mxb_controls[i].id == vc->id) { 558 break; 559 } 560 } 561 562 if( i < 0 ) { 563 return -EAGAIN; 564 } 565 566 switch (vc->id ) { 567 case V4L2_CID_AUDIO_MUTE: { 568 vc->value = mxb->cur_mute; 569 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); 570 return 0; 571 } 572 } 573 574 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); 575 return 0; 576 } 577 578 case VIDIOC_S_CTRL: 579 { 580 struct v4l2_control *vc = arg; 581 int i = 0; 582 583 for (i = MAXCONTROLS - 1; i >= 0; i--) { 584 if (mxb_controls[i].id == vc->id) { 585 break; 586 } 587 } 588 589 if( i < 0 ) { 590 return -EAGAIN; 591 } 592 593 switch (vc->id ) { 594 case V4L2_CID_AUDIO_MUTE: { 595 mxb->cur_mute = vc->value; 596 if( 0 == vc->value ) { 597 /* switch the audio-source */ 598 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); 599 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); 600 } else { 601 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); 602 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); 603 } 604 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value)); 605 break; 606 } 607 } 608 return 0; 609 } 610 case VIDIOC_G_INPUT: 611 { 612 int *input = (int *)arg; 613 *input = mxb->cur_input; 614 615 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); 616 return 0; 617 } 618 case VIDIOC_S_INPUT: 619 { 620 int input = *(int *)arg; 621 struct tea6415c_multiplex vm; 622 int i = 0; 623 624 DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); 625 626 if (input < 0 || input >= MXB_INPUTS) { 627 return -EINVAL; 628 } 629 630 631 632 mxb->cur_input = input; 633 634 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); 635 636 /* prepare switching of tea6415c and saa7111a; 637 have a look at the 'background'-file for further informations */ 638 switch( input ) { 639 640 case TUNER: 641 { 642 i = 0; 643 vm.in = 3; 644 vm.out = 17; 645 646 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { 647 printk("VIDIOC_S_INPUT: could not address tea6415c #1\n"); 648 return -EFAULT; 649 } 650 /* connect tuner-output always to multicable */ 651 vm.in = 3; 652 vm.out = 13; 653 break; 654 } 655 case AUX3_YC: 656 { 657 /* nothing to be done here. aux3_yc is 658 directly connected to the saa711a */ 659 i = 5; 660 break; 661 } 662 case AUX3: 663 { 664 /* nothing to be done here. aux3 is 665 directly connected to the saa711a */ 666 i = 1; 667 break; 668 } 669 case AUX1: 670 { 671 i = 0; 672 vm.in = 1; 673 vm.out = 17; 674 break; 675 } 676 } 677 678 /* switch video in tea6415c only if necessary */ 679 switch( input ) { 680 case TUNER: 681 case AUX1: 682 { 683 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { 684 printk("VIDIOC_S_INPUT: could not address tea6415c #3\n"); 685 return -EFAULT; 686 } 687 break; 688 } 689 default: 690 { 691 break; 692 } 693 } 694 695 /* switch video in saa7111a */ 696 if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { 697 printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); 698 } 699 700 /* switch the audio-source only if necessary */ 701 if( 0 == mxb->cur_mute ) { 702 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]); 703 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]); 704 } 705 706 return 0; 707 } 708 case VIDIOC_G_TUNER: 709 { 710 struct v4l2_tuner *t = arg; 711 int byte = 0; 712 713 if( 0 != t->index ) { 714 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); 715 return -EINVAL; 716 } 717 718 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); 719 720 memset(t,0,sizeof(*t)); 721 strcpy(t->name, "Television"); 722 723 t->type = V4L2_TUNER_ANALOG_TV; 724 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; 725 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ 726 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ 727 t->signal = 0xffff; 728 t->afc = 0; 729 730 mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); 731 t->audmode = mxb->cur_mode; 732 733 if( byte < 0 ) { 734 t->rxsubchans = V4L2_TUNER_SUB_MONO; 735 } else { 736 switch(byte) { 737 case TDA9840_MONO_DETECT: { 738 t->rxsubchans = V4L2_TUNER_SUB_MONO; 739 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n")); 740 break; 741 } 742 case TDA9840_DUAL_DETECT: { 743 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 744 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n")); 745 break; 746 } 747 case TDA9840_STEREO_DETECT: { 748 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; 749 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n")); 750 break; 751 } 752 default: { /* TDA9840_INCORRECT_DETECT */ 753 t->rxsubchans = V4L2_TUNER_MODE_MONO; 754 DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n")); 755 break; 756 } 757 } 758 } 759 760 return 0; 761 } 762 case VIDIOC_S_TUNER: 763 { 764 struct v4l2_tuner *t = arg; 765 int result = 0; 766 int byte = 0; 767 768 if( 0 != t->index ) { 769 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); 770 return -EINVAL; 771 } 772 773 switch(t->audmode) { 774 case V4L2_TUNER_MODE_STEREO: { 775 mxb->cur_mode = V4L2_TUNER_MODE_STEREO; 776 byte = TDA9840_SET_STEREO; 777 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); 778 break; 779 } 780 case V4L2_TUNER_MODE_LANG1_LANG2: { 781 mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2; 782 byte = TDA9840_SET_BOTH; 783 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n")); 784 break; 785 } 786 case V4L2_TUNER_MODE_LANG1: { 787 mxb->cur_mode = V4L2_TUNER_MODE_LANG1; 788 byte = TDA9840_SET_LANG1; 789 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); 790 break; 791 } 792 case V4L2_TUNER_MODE_LANG2: { 793 mxb->cur_mode = V4L2_TUNER_MODE_LANG2; 794 byte = TDA9840_SET_LANG2; 795 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); 796 break; 797 } 798 default: { /* case V4L2_TUNER_MODE_MONO: {*/ 799 mxb->cur_mode = V4L2_TUNER_MODE_MONO; 800 byte = TDA9840_SET_MONO; 801 DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); 802 break; 803 } 804 } 805 806 if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { 807 printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); 808 } 809 810 return 0; 811 } 812 case VIDIOC_G_FREQUENCY: 813 { 814 struct v4l2_frequency *f = arg; 815 816 if(0 != mxb->cur_input) { 817 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); 818 return -EINVAL; 819 } 820 821 *f = mxb->cur_freq; 822 823 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency)); 824 return 0; 825 } 826 case VIDIOC_S_FREQUENCY: 827 { 828 struct v4l2_frequency *f = arg; 829 830 if (0 != f->tuner) 831 return -EINVAL; 832 833 if (V4L2_TUNER_ANALOG_TV != f->type) 834 return -EINVAL; 835 836 if(0 != mxb->cur_input) { 837 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); 838 return -EINVAL; 839 } 840 841 mxb->cur_freq = *f; 842 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); 843 844 /* tune in desired frequency */ 845 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); 846 847 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ 848 spin_lock(&dev->slock); 849 vv->vbi_fieldcount = 0; 850 spin_unlock(&dev->slock); 851 852 return 0; 853 } 854 case MXB_S_AUDIO_CD: 855 { 856 int i = *(int*)arg; 857 858 if( i < 0 || i >= MXB_AUDIOS ) { 859 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); 860 return -EINVAL; 861 } 862 863 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i)); 864 865 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]); 866 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]); 867 868 return 0; 869 } 870 case MXB_S_AUDIO_LINE: 871 { 872 int i = *(int*)arg; 873 874 if( i < 0 || i >= MXB_AUDIOS ) { 875 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); 876 return -EINVAL; 877 } 878 879 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i)); 880 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]); 881 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]); 882 883 return 0; 884 } 885 case VIDIOC_G_AUDIO: 886 { 887 struct v4l2_audio *a = arg; 888 889 if( a->index < 0 || a->index > MXB_INPUTS ) { 890 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); 891 return -EINVAL; 892 } 893 894 DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); 895 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); 896 897 return 0; 898 } 899 case VIDIOC_S_AUDIO: 900 { 901 struct v4l2_audio *a = arg; 902 DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); 903 return 0; 904 } 905 default: 906/* 907 DEB2(printk("does not handle this ioctl.\n")); 908*/ 909 return -ENOIOCTLCMD; 910 } 911 return 0; 912} 913 914static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) 915{ 916 struct mxb* mxb = (struct mxb*)dev->ext_priv; 917 int zero = 0; 918 int one = 1; 919 920 if(V4L2_STD_PAL_I == std->id ) { 921 v4l2_std_id std = V4L2_STD_PAL_I; 922 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); 923 /* set the 7146 gpio register -- I don't know what this does exactly */ 924 saa7146_write(dev, GPIO_CTRL, 0x00404050); 925 /* unset the 7111 gpio register -- I don't know what this does exactly */ 926 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); 927 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); 928 } else { 929 v4l2_std_id std = V4L2_STD_PAL_BG; 930 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); 931 /* set the 7146 gpio register -- I don't know what this does exactly */ 932 saa7146_write(dev, GPIO_CTRL, 0x00404050); 933 /* set the 7111 gpio register -- I don't know what this does exactly */ 934 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); 935 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); 936 } 937 return 0; 938} 939 940static struct saa7146_standard standard[] = { 941 { 942 .name = "PAL-BG", .id = V4L2_STD_PAL_BG, 943 .v_offset = 0x17, .v_field = 288, 944 .h_offset = 0x14, .h_pixels = 680, 945 .v_max_out = 576, .h_max_out = 768, 946 }, { 947 .name = "PAL-I", .id = V4L2_STD_PAL_I, 948 .v_offset = 0x17, .v_field = 288, 949 .h_offset = 0x14, .h_pixels = 680, 950 .v_max_out = 576, .h_max_out = 768, 951 }, { 952 .name = "NTSC", .id = V4L2_STD_NTSC, 953 .v_offset = 0x16, .v_field = 240, 954 .h_offset = 0x06, .h_pixels = 708, 955 .v_max_out = 480, .h_max_out = 640, 956 }, { 957 .name = "SECAM", .id = V4L2_STD_SECAM, 958 .v_offset = 0x14, .v_field = 288, 959 .h_offset = 0x14, .h_pixels = 720, 960 .v_max_out = 576, .h_max_out = 768, 961 } 962}; 963 964static struct saa7146_pci_extension_data mxb = { 965 .ext_priv = "Multimedia eXtension Board", 966 .ext = &extension, 967}; 968 969static struct pci_device_id pci_tbl[] = { 970 { 971 .vendor = PCI_VENDOR_ID_PHILIPS, 972 .device = PCI_DEVICE_ID_PHILIPS_SAA7146, 973 .subvendor = 0x0000, 974 .subdevice = 0x0000, 975 .driver_data = (unsigned long)&mxb, 976 }, { 977 .vendor = 0, 978 } 979}; 980 981MODULE_DEVICE_TABLE(pci, pci_tbl); 982 983static struct saa7146_ext_vv vv_data = { 984 .inputs = MXB_INPUTS, 985 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, 986 .stds = &standard[0], 987 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), 988 .std_callback = &std_callback, 989 .ioctls = &ioctls[0], 990 .ioctl = mxb_ioctl, 991}; 992 993static struct saa7146_extension extension = { 994 .name = MXB_IDENTIFIER, 995 .flags = SAA7146_USE_I2C_IRQ, 996 997 .pci_tbl = &pci_tbl[0], 998 .module = THIS_MODULE, 999 1000 .probe = mxb_probe, 1001 .attach = mxb_attach, 1002 .detach = mxb_detach, 1003 1004 .irq_mask = 0, 1005 .irq_func = NULL, 1006}; 1007 1008static int __init mxb_init_module(void) 1009{ 1010 if( 0 != saa7146_register_extension(&extension)) { 1011 DEB_S(("failed to register extension.\n")); 1012 return -ENODEV; 1013 } 1014 1015 return 0; 1016} 1017 1018static void __exit mxb_cleanup_module(void) 1019{ 1020 saa7146_unregister_extension(&extension); 1021} 1022 1023module_init(mxb_init_module); 1024module_exit(mxb_cleanup_module); 1025 1026MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'"); 1027MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); 1028MODULE_LICENSE("GPL"); 1029