linux/drivers/media/video/dpc7146.c
<<
>>
Prefs
   1/*
   2    dpc7146.c - v4l2 driver for the dpc7146 demonstration board
   3
   4    Copyright (C) 2000-2003 Michael Hunold <michael@mihu.de>
   5
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 2 of the License, or
   9    (at your option) any later version.
  10
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15
  16    You should have received a copy of the GNU General Public License
  17    along with this program; if not, write to the Free Software
  18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19*/
  20
  21#define DEBUG_VARIABLE debug
  22
  23#include <media/saa7146_vv.h>
  24#include <linux/video_decoder.h>        /* for saa7111a */
  25
  26#define I2C_SAA7111A            0x24
  27
  28/* All unused bytes are reserverd. */
  29#define SAA711X_CHIP_VERSION            0x00
  30#define SAA711X_ANALOG_INPUT_CONTROL_1  0x02
  31#define SAA711X_ANALOG_INPUT_CONTROL_2  0x03
  32#define SAA711X_ANALOG_INPUT_CONTROL_3  0x04
  33#define SAA711X_ANALOG_INPUT_CONTROL_4  0x05
  34#define SAA711X_HORIZONTAL_SYNC_START   0x06
  35#define SAA711X_HORIZONTAL_SYNC_STOP    0x07
  36#define SAA711X_SYNC_CONTROL            0x08
  37#define SAA711X_LUMINANCE_CONTROL       0x09
  38#define SAA711X_LUMINANCE_BRIGHTNESS    0x0A
  39#define SAA711X_LUMINANCE_CONTRAST      0x0B
  40#define SAA711X_CHROMA_SATURATION       0x0C
  41#define SAA711X_CHROMA_HUE_CONTROL      0x0D
  42#define SAA711X_CHROMA_CONTROL          0x0E
  43#define SAA711X_FORMAT_DELAY_CONTROL    0x10
  44#define SAA711X_OUTPUT_CONTROL_1        0x11
  45#define SAA711X_OUTPUT_CONTROL_2        0x12
  46#define SAA711X_OUTPUT_CONTROL_3        0x13
  47#define SAA711X_V_GATE_1_START          0x15
  48#define SAA711X_V_GATE_1_STOP           0x16
  49#define SAA711X_V_GATE_1_MSB            0x17
  50#define SAA711X_TEXT_SLICER_STATUS      0x1A
  51#define SAA711X_DECODED_BYTES_OF_TS_1   0x1B
  52#define SAA711X_DECODED_BYTES_OF_TS_2   0x1C
  53#define SAA711X_STATUS_BYTE             0x1F
  54
  55#define DPC_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
  56
  57static int debug = 0;
  58module_param(debug, int, 0);
  59MODULE_PARM_DESC(debug, "debug verbosity");
  60
  61static int dpc_num = 0;
  62
  63#define DPC_INPUTS      2
  64static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
  65        { 0, "Port A",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
  66        { 1, "Port B",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
  67};
  68
  69#define DPC_AUDIOS      0
  70
  71static struct saa7146_extension_ioctls ioctls[] = {
  72        { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
  73        { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
  74        { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
  75        { VIDIOC_S_STD,         SAA7146_AFTER },
  76        { 0,                    0 }
  77};
  78
  79struct dpc
  80{
  81        struct video_device     *video_dev;
  82        struct video_device     *vbi_dev;
  83
  84        struct i2c_adapter      i2c_adapter;
  85        struct i2c_client       *saa7111a;
  86
  87        int cur_input;  /* current input */
  88};
  89
  90/* fixme: add vbi stuff here */
  91static int dpc_probe(struct saa7146_dev* dev)
  92{
  93        struct dpc* dpc = NULL;
  94        struct i2c_client *client;
  95
  96        dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
  97        if( NULL == dpc ) {
  98                printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
  99                return -ENOMEM;
 100        }
 101
 102        /* FIXME: enable i2c-port pins, video-port-pins
 103           video port pins should be enabled here ?! */
 104        saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
 105
 106        dpc->i2c_adapter = (struct i2c_adapter) {
 107                .class = I2C_CLASS_TV_ANALOG,
 108                .name = "dpc7146",
 109        };
 110        saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
 111        if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
 112                DEB_S(("cannot register i2c-device. skipping.\n"));
 113                kfree(dpc);
 114                return -EFAULT;
 115        }
 116
 117        /* loop through all i2c-devices on the bus and look who is there */
 118        list_for_each_entry(client, &dpc->i2c_adapter.clients, list)
 119                if( I2C_SAA7111A == client->addr )
 120                        dpc->saa7111a = client;
 121
 122        /* check if all devices are present */
 123        if( 0 == dpc->saa7111a ) {
 124                DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
 125                i2c_del_adapter(&dpc->i2c_adapter);
 126                kfree(dpc);
 127                return -ENODEV;
 128        }
 129
 130        /* all devices are present, probe was successful */
 131        DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n"));
 132
 133        /* we store the pointer in our private data field */
 134        dev->ext_priv = dpc;
 135
 136        return 0;
 137}
 138
 139/* bring hardware to a sane state. this has to be done, just in case someone
 140   wants to capture from this device before it has been properly initialized.
 141   the capture engine would badly fail, because no valid signal arrives on the
 142   saa7146, thus leading to timeouts and stuff. */
 143static int dpc_init_done(struct saa7146_dev* dev)
 144{
 145        struct dpc* dpc = (struct dpc*)dev->ext_priv;
 146
 147        DEB_D(("dpc_v4l2.o: dpc_init_done called.\n"));
 148
 149        /* initialize the helper ics to useful values */
 150        i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11);
 151
 152        i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0);
 153        i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30);
 154        i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00);
 155        i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00);
 156        i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde);
 157        i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad);
 158        i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8);
 159        i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00);
 160        i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80);
 161        i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47);
 162        i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40);
 163        i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00);
 164        i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03);
 165
 166        i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0);
 167        i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c);
 168        i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1);
 169        i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30);
 170
 171        i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81);
 172
 173        return 0;
 174}
 175
 176static struct saa7146_ext_vv vv_data;
 177
 178/* this function only gets called when the probing was successful */
 179static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
 180{
 181        struct dpc* dpc = (struct dpc*)dev->ext_priv;
 182
 183        DEB_D(("dpc_v4l2.o: dpc_attach called.\n"));
 184
 185        /* checking for i2c-devices can be omitted here, because we
 186           already did this in "dpc_vl42_probe" */
 187
 188        saa7146_vv_init(dev,&vv_data);
 189        if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
 190                ERR(("cannot register capture v4l2 device. skipping.\n"));
 191                return -1;
 192        }
 193
 194        /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
 195        if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
 196                if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) {
 197                        ERR(("cannot register vbi v4l2 device. skipping.\n"));
 198                }
 199        }
 200
 201        i2c_use_client(dpc->saa7111a);
 202
 203        printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num);
 204        dpc_num++;
 205
 206        /* the rest */
 207        dpc->cur_input = 0;
 208        dpc_init_done(dev);
 209
 210        return 0;
 211}
 212
 213static int dpc_detach(struct saa7146_dev* dev)
 214{
 215        struct dpc* dpc = (struct dpc*)dev->ext_priv;
 216
 217        DEB_EE(("dev:%p\n",dev));
 218
 219        i2c_release_client(dpc->saa7111a);
 220
 221        saa7146_unregister_device(&dpc->video_dev,dev);
 222        if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
 223                saa7146_unregister_device(&dpc->vbi_dev,dev);
 224        }
 225        saa7146_vv_release(dev);
 226
 227        dpc_num--;
 228
 229        i2c_del_adapter(&dpc->i2c_adapter);
 230        kfree(dpc);
 231        return 0;
 232}
 233
 234#ifdef axa
 235int dpc_vbi_bypass(struct saa7146_dev* dev)
 236{
 237        struct dpc* dpc = (struct dpc*)dev->ext_priv;
 238
 239        int i = 1;
 240
 241        /* switch bypass in saa7111a */
 242        if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) {
 243                printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n");
 244                return -1;
 245        }
 246
 247        return 0;
 248}
 249#endif
 250
 251static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 252{
 253        struct saa7146_dev *dev = fh->dev;
 254        struct dpc* dpc = (struct dpc*)dev->ext_priv;
 255/*
 256        struct saa7146_vv *vv = dev->vv_data;
 257*/
 258        switch(cmd)
 259        {
 260        case VIDIOC_ENUMINPUT:
 261        {
 262                struct v4l2_input *i = arg;
 263                DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
 264
 265                if( i->index < 0 || i->index >= DPC_INPUTS) {
 266                        return -EINVAL;
 267                }
 268
 269                memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input));
 270
 271                DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index));
 272                return 0;
 273        }
 274        case VIDIOC_G_INPUT:
 275        {
 276                int *input = (int *)arg;
 277                *input = dpc->cur_input;
 278
 279                DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input));
 280                return 0;
 281        }
 282        case VIDIOC_S_INPUT:
 283        {
 284                int     input = *(int *)arg;
 285
 286                if (input < 0 || input >= DPC_INPUTS) {
 287                        return -EINVAL;
 288                }
 289
 290                dpc->cur_input = input;
 291
 292                /* fixme: switch input here, switch audio, too! */
 293//              saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
 294                printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n");
 295
 296                return 0;
 297        }
 298        default:
 299/*
 300                DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n"));
 301*/
 302                return -ENOIOCTLCMD;
 303        }
 304        return 0;
 305}
 306
 307static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
 308{
 309        return 0;
 310}
 311
 312static struct saa7146_standard standard[] = {
 313        {
 314                .name   = "PAL",        .id     = V4L2_STD_PAL,
 315                .v_offset       = 0x17, .v_field        = 288,
 316                .h_offset       = 0x14, .h_pixels       = 680,
 317                .v_max_out      = 576,  .h_max_out      = 768,
 318        }, {
 319                .name   = "NTSC",       .id     = V4L2_STD_NTSC,
 320                .v_offset       = 0x16, .v_field        = 240,
 321                .h_offset       = 0x06, .h_pixels       = 708,
 322                .v_max_out      = 480,  .h_max_out      = 640,
 323        }, {
 324                .name   = "SECAM",      .id     = V4L2_STD_SECAM,
 325                .v_offset       = 0x14, .v_field        = 288,
 326                .h_offset       = 0x14, .h_pixels       = 720,
 327                .v_max_out      = 576,  .h_max_out      = 768,
 328        }
 329};
 330
 331static struct saa7146_extension extension;
 332
 333static struct saa7146_pci_extension_data dpc = {
 334        .ext_priv = "Multimedia eXtension Board",
 335        .ext = &extension,
 336};
 337
 338static struct pci_device_id pci_tbl[] = {
 339        {
 340                .vendor    = PCI_VENDOR_ID_PHILIPS,
 341                .device    = PCI_DEVICE_ID_PHILIPS_SAA7146,
 342                .subvendor = 0x0000,
 343                .subdevice = 0x0000,
 344                .driver_data = (unsigned long)&dpc,
 345        }, {
 346                .vendor = 0,
 347        }
 348};
 349
 350MODULE_DEVICE_TABLE(pci, pci_tbl);
 351
 352static struct saa7146_ext_vv vv_data = {
 353        .inputs         = DPC_INPUTS,
 354        .capabilities   = V4L2_CAP_VBI_CAPTURE,
 355        .stds           = &standard[0],
 356        .num_stds       = sizeof(standard)/sizeof(struct saa7146_standard),
 357        .std_callback   = &std_callback,
 358        .ioctls         = &ioctls[0],
 359        .ioctl          = dpc_ioctl,
 360};
 361
 362static struct saa7146_extension extension = {
 363        .name           = "dpc7146 demonstration board",
 364        .flags          = SAA7146_USE_I2C_IRQ,
 365
 366        .pci_tbl        = &pci_tbl[0],
 367        .module         = THIS_MODULE,
 368
 369        .probe          = dpc_probe,
 370        .attach         = dpc_attach,
 371        .detach         = dpc_detach,
 372
 373        .irq_mask       = 0,
 374        .irq_func       = NULL,
 375};
 376
 377static int __init dpc_init_module(void)
 378{
 379        if( 0 != saa7146_register_extension(&extension)) {
 380                DEB_S(("failed to register extension.\n"));
 381                return -ENODEV;
 382        }
 383
 384        return 0;
 385}
 386
 387static void __exit dpc_cleanup_module(void)
 388{
 389        saa7146_unregister_extension(&extension);
 390}
 391
 392module_init(dpc_init_module);
 393module_exit(dpc_cleanup_module);
 394
 395MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'");
 396MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
 397MODULE_LICENSE("GPL");
 398