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