linux/drivers/staging/media/cxd2099/cxd2099.c
<<
>>
Prefs
   1/*
   2 * cxd2099.c: Driver for the CXD2099AR Common Interface Controller
   3 *
   4 * Copyright (C) 2010-2011 Digital Devices GmbH
   5 *
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * version 2 only, as published by the Free Software Foundation.
  10 *
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21 * 02110-1301, USA
  22 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  23 */
  24
  25#include <linux/slab.h>
  26#include <linux/kernel.h>
  27#include <linux/module.h>
  28#include <linux/i2c.h>
  29#include <linux/wait.h>
  30#include <linux/delay.h>
  31#include <linux/mutex.h>
  32#include <linux/io.h>
  33
  34#include "cxd2099.h"
  35
  36#define MAX_BUFFER_SIZE 248
  37
  38struct cxd {
  39        struct dvb_ca_en50221 en;
  40
  41        struct i2c_adapter *i2c;
  42        struct cxd2099_cfg cfg;
  43
  44        u8     regs[0x23];
  45        u8     lastaddress;
  46        u8     clk_reg_f;
  47        u8     clk_reg_b;
  48        int    mode;
  49        int    ready;
  50        int    dr;
  51        int    slot_stat;
  52
  53        u8     amem[1024];
  54        int    amem_read;
  55
  56        int    cammode;
  57        struct mutex lock;
  58};
  59
  60static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
  61                         u8 reg, u8 data)
  62{
  63        u8 m[2] = {reg, data};
  64        struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
  65
  66        if (i2c_transfer(adapter, &msg, 1) != 1) {
  67                dev_err(&adapter->dev,
  68                        "Failed to write to I2C register %02x@%02x!\n",
  69                        reg, adr);
  70                return -1;
  71        }
  72        return 0;
  73}
  74
  75static int i2c_write(struct i2c_adapter *adapter, u8 adr,
  76                     u8 *data, u8 len)
  77{
  78        struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
  79
  80        if (i2c_transfer(adapter, &msg, 1) != 1) {
  81                dev_err(&adapter->dev, "Failed to write to I2C!\n");
  82                return -1;
  83        }
  84        return 0;
  85}
  86
  87static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
  88                        u8 reg, u8 *val)
  89{
  90        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
  91                                   .buf = &reg, .len = 1},
  92                                  {.addr = adr, .flags = I2C_M_RD,
  93                                   .buf = val, .len = 1} };
  94
  95        if (i2c_transfer(adapter, msgs, 2) != 2) {
  96                dev_err(&adapter->dev, "error in i2c_read_reg\n");
  97                return -1;
  98        }
  99        return 0;
 100}
 101
 102static int i2c_read(struct i2c_adapter *adapter, u8 adr,
 103                    u8 reg, u8 *data, u8 n)
 104{
 105        struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
 106                                 .buf = &reg, .len = 1},
 107                                {.addr = adr, .flags = I2C_M_RD,
 108                                 .buf = data, .len = n} };
 109
 110        if (i2c_transfer(adapter, msgs, 2) != 2) {
 111                dev_err(&adapter->dev, "error in i2c_read\n");
 112                return -1;
 113        }
 114        return 0;
 115}
 116
 117static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n)
 118{
 119        int status;
 120
 121        status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
 122        if (!status) {
 123                ci->lastaddress = adr;
 124                status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n);
 125        }
 126        return status;
 127}
 128
 129static int read_reg(struct cxd *ci, u8 reg, u8 *val)
 130{
 131        return read_block(ci, reg, val, 1);
 132}
 133
 134
 135static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
 136{
 137        int status;
 138        u8 addr[3] = {2, address & 0xff, address >> 8};
 139
 140        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 141        if (!status)
 142                status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
 143        return status;
 144}
 145
 146static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
 147{
 148        int status;
 149        u8 addr[3] = {2, address & 0xff, address >> 8};
 150
 151        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 152        if (!status) {
 153                u8 buf[256] = {3};
 154
 155                memcpy(buf+1, data, n);
 156                status = i2c_write(ci->i2c, ci->cfg.adr, buf, n+1);
 157        }
 158        return status;
 159}
 160
 161static int read_io(struct cxd *ci, u16 address, u8 *val)
 162{
 163        int status;
 164        u8 addr[3] = {2, address & 0xff, address >> 8};
 165
 166        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 167        if (!status)
 168                status = i2c_read(ci->i2c, ci->cfg.adr, 3, val, 1);
 169        return status;
 170}
 171
 172static int write_io(struct cxd *ci, u16 address, u8 val)
 173{
 174        int status;
 175        u8 addr[3] = {2, address & 0xff, address >> 8};
 176        u8 buf[2] = {3, val};
 177
 178        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 179        if (!status)
 180                status = i2c_write(ci->i2c, ci->cfg.adr, buf, 2);
 181        return status;
 182}
 183
 184#if 0
 185static int read_io_data(struct cxd *ci, u8 *data, u8 n)
 186{
 187        int status;
 188        u8 addr[3] = { 2, 0, 0 };
 189
 190        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 191        if (!status)
 192                status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
 193        return 0;
 194}
 195
 196static int write_io_data(struct cxd *ci, u8 *data, u8 n)
 197{
 198        int status;
 199        u8 addr[3] = {2, 0, 0};
 200
 201        status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
 202        if (!status) {
 203                u8 buf[256] = {3};
 204
 205                memcpy(buf+1, data, n);
 206                status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
 207        }
 208        return 0;
 209}
 210#endif
 211
 212static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
 213{
 214        int status;
 215
 216        status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg);
 217        if (!status && reg >= 6 && reg <= 8 && mask != 0xff)
 218                status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]);
 219        ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
 220        if (!status) {
 221                ci->lastaddress = reg;
 222                status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]);
 223        }
 224        if (reg == 0x20)
 225                ci->regs[reg] &= 0x7f;
 226        return status;
 227}
 228
 229static int write_reg(struct cxd *ci, u8 reg, u8 val)
 230{
 231        return write_regm(ci, reg, val, 0xff);
 232}
 233
 234#ifdef BUFFER_MODE
 235static int write_block(struct cxd *ci, u8 adr, u8 *data, int n)
 236{
 237        int status;
 238        u8 buf[256] = {1};
 239
 240        status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
 241        if (!status) {
 242                ci->lastaddress = adr;
 243                memcpy(buf + 1, data, n);
 244                status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
 245        }
 246        return status;
 247}
 248#endif
 249
 250static void set_mode(struct cxd *ci, int mode)
 251{
 252        if (mode == ci->mode)
 253                return;
 254
 255        switch (mode) {
 256        case 0x00: /* IO mem */
 257                write_regm(ci, 0x06, 0x00, 0x07);
 258                break;
 259        case 0x01: /* ATT mem */
 260                write_regm(ci, 0x06, 0x02, 0x07);
 261                break;
 262        default:
 263                break;
 264        }
 265        ci->mode = mode;
 266}
 267
 268static void cam_mode(struct cxd *ci, int mode)
 269{
 270        if (mode == ci->cammode)
 271                return;
 272
 273        switch (mode) {
 274        case 0x00:
 275                write_regm(ci, 0x20, 0x80, 0x80);
 276                break;
 277        case 0x01:
 278#ifdef BUFFER_MODE
 279                if (!ci->en.read_data)
 280                        return;
 281                dev_info(&ci->i2c->dev, "enable cam buffer mode\n");
 282                /* write_reg(ci, 0x0d, 0x00); */
 283                /* write_reg(ci, 0x0e, 0x01); */
 284                write_regm(ci, 0x08, 0x40, 0x40);
 285                /* read_reg(ci, 0x12, &dummy); */
 286                write_regm(ci, 0x08, 0x80, 0x80);
 287#endif
 288                break;
 289        default:
 290                break;
 291        }
 292        ci->cammode = mode;
 293}
 294
 295
 296
 297static int init(struct cxd *ci)
 298{
 299        int status;
 300
 301        mutex_lock(&ci->lock);
 302        ci->mode = -1;
 303        do {
 304                status = write_reg(ci, 0x00, 0x00);
 305                if (status < 0)
 306                        break;
 307                status = write_reg(ci, 0x01, 0x00);
 308                if (status < 0)
 309                        break;
 310                status = write_reg(ci, 0x02, 0x10);
 311                if (status < 0)
 312                        break;
 313                status = write_reg(ci, 0x03, 0x00);
 314                if (status < 0)
 315                        break;
 316                status = write_reg(ci, 0x05, 0xFF);
 317                if (status < 0)
 318                        break;
 319                status = write_reg(ci, 0x06, 0x1F);
 320                if (status < 0)
 321                        break;
 322                status = write_reg(ci, 0x07, 0x1F);
 323                if (status < 0)
 324                        break;
 325                status = write_reg(ci, 0x08, 0x28);
 326                if (status < 0)
 327                        break;
 328                status = write_reg(ci, 0x14, 0x20);
 329                if (status < 0)
 330                        break;
 331
 332#if 0
 333                /* Input Mode C, BYPass Serial, TIVAL = low, MSB */
 334                status = write_reg(ci, 0x09, 0x4D);
 335                if (status < 0)
 336                        break;
 337#endif
 338                /* TOSTRT = 8, Mode B (gated clock), falling Edge,
 339                 * Serial, POL=HIGH, MSB */
 340                status = write_reg(ci, 0x0A, 0xA7);
 341                if (status < 0)
 342                        break;
 343
 344                status = write_reg(ci, 0x0B, 0x33);
 345                if (status < 0)
 346                        break;
 347                status = write_reg(ci, 0x0C, 0x33);
 348                if (status < 0)
 349                        break;
 350
 351                status = write_regm(ci, 0x14, 0x00, 0x0F);
 352                if (status < 0)
 353                        break;
 354                status = write_reg(ci, 0x15, ci->clk_reg_b);
 355                if (status < 0)
 356                        break;
 357                status = write_regm(ci, 0x16, 0x00, 0x0F);
 358                if (status < 0)
 359                        break;
 360                status = write_reg(ci, 0x17, ci->clk_reg_f);
 361                if (status < 0)
 362                        break;
 363
 364                if (ci->cfg.clock_mode) {
 365                        if (ci->cfg.polarity) {
 366                                status = write_reg(ci, 0x09, 0x6f);
 367                                if (status < 0)
 368                                        break;
 369                        } else {
 370                                status = write_reg(ci, 0x09, 0x6d);
 371                                if (status < 0)
 372                                        break;
 373                        }
 374                        status = write_reg(ci, 0x20, 0x68);
 375                        if (status < 0)
 376                                break;
 377                        status = write_reg(ci, 0x21, 0x00);
 378                        if (status < 0)
 379                                break;
 380                        status = write_reg(ci, 0x22, 0x02);
 381                        if (status < 0)
 382                                break;
 383                } else {
 384                        if (ci->cfg.polarity) {
 385                                status = write_reg(ci, 0x09, 0x4f);
 386                                if (status < 0)
 387                                        break;
 388                        } else {
 389                                status = write_reg(ci, 0x09, 0x4d);
 390                                if (status < 0)
 391                                        break;
 392                        }
 393
 394                        status = write_reg(ci, 0x20, 0x28);
 395                        if (status < 0)
 396                                break;
 397                        status = write_reg(ci, 0x21, 0x00);
 398                        if (status < 0)
 399                                break;
 400                        status = write_reg(ci, 0x22, 0x07);
 401                        if (status < 0)
 402                                break;
 403                }
 404
 405                status = write_regm(ci, 0x20, 0x80, 0x80);
 406                if (status < 0)
 407                        break;
 408                status = write_regm(ci, 0x03, 0x02, 0x02);
 409                if (status < 0)
 410                        break;
 411                status = write_reg(ci, 0x01, 0x04);
 412                if (status < 0)
 413                        break;
 414                status = write_reg(ci, 0x00, 0x31);
 415                if (status < 0)
 416                        break;
 417
 418                /* Put TS in bypass */
 419                status = write_regm(ci, 0x09, 0x08, 0x08);
 420                if (status < 0)
 421                        break;
 422                ci->cammode = -1;
 423                cam_mode(ci, 0);
 424        } while (0);
 425        mutex_unlock(&ci->lock);
 426
 427        return 0;
 428}
 429
 430static int read_attribute_mem(struct dvb_ca_en50221 *ca,
 431                              int slot, int address)
 432{
 433        struct cxd *ci = ca->data;
 434#if 0
 435        if (ci->amem_read) {
 436                if (address <= 0 || address > 1024)
 437                        return -EIO;
 438                return ci->amem[address];
 439        }
 440
 441        mutex_lock(&ci->lock);
 442        write_regm(ci, 0x06, 0x00, 0x05);
 443        read_pccard(ci, 0, &ci->amem[0], 128);
 444        read_pccard(ci, 128, &ci->amem[0], 128);
 445        read_pccard(ci, 256, &ci->amem[0], 128);
 446        read_pccard(ci, 384, &ci->amem[0], 128);
 447        write_regm(ci, 0x06, 0x05, 0x05);
 448        mutex_unlock(&ci->lock);
 449        return ci->amem[address];
 450#else
 451        u8 val;
 452
 453        mutex_lock(&ci->lock);
 454        set_mode(ci, 1);
 455        read_pccard(ci, address, &val, 1);
 456        mutex_unlock(&ci->lock);
 457        /* printk(KERN_INFO "%02x:%02x\n", address,val); */
 458        return val;
 459#endif
 460}
 461
 462static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
 463                               int address, u8 value)
 464{
 465        struct cxd *ci = ca->data;
 466
 467        mutex_lock(&ci->lock);
 468        set_mode(ci, 1);
 469        write_pccard(ci, address, &value, 1);
 470        mutex_unlock(&ci->lock);
 471        return 0;
 472}
 473
 474static int read_cam_control(struct dvb_ca_en50221 *ca,
 475                            int slot, u8 address)
 476{
 477        struct cxd *ci = ca->data;
 478        u8 val;
 479
 480        mutex_lock(&ci->lock);
 481        set_mode(ci, 0);
 482        read_io(ci, address, &val);
 483        mutex_unlock(&ci->lock);
 484        return val;
 485}
 486
 487static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
 488                             u8 address, u8 value)
 489{
 490        struct cxd *ci = ca->data;
 491
 492        mutex_lock(&ci->lock);
 493        set_mode(ci, 0);
 494        write_io(ci, address, value);
 495        mutex_unlock(&ci->lock);
 496        return 0;
 497}
 498
 499static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
 500{
 501        struct cxd *ci = ca->data;
 502
 503        mutex_lock(&ci->lock);
 504#if 0
 505        write_reg(ci, 0x00, 0x21);
 506        write_reg(ci, 0x06, 0x1F);
 507        write_reg(ci, 0x00, 0x31);
 508#else
 509#if 0
 510        write_reg(ci, 0x06, 0x1F);
 511        write_reg(ci, 0x06, 0x2F);
 512#else
 513        cam_mode(ci, 0);
 514        write_reg(ci, 0x00, 0x21);
 515        write_reg(ci, 0x06, 0x1F);
 516        write_reg(ci, 0x00, 0x31);
 517        write_regm(ci, 0x20, 0x80, 0x80);
 518        write_reg(ci, 0x03, 0x02);
 519        ci->ready = 0;
 520#endif
 521#endif
 522        ci->mode = -1;
 523        {
 524                int i;
 525#if 0
 526                u8 val;
 527#endif
 528                for (i = 0; i < 100; i++) {
 529                        usleep_range(10000, 11000);
 530#if 0
 531                        read_reg(ci, 0x06, &val);
 532                        dev_info(&ci->i2c->dev, "%d:%02x\n", i, val);
 533                        if (!(val&0x10))
 534                                break;
 535#else
 536                        if (ci->ready)
 537                                break;
 538#endif
 539                }
 540        }
 541        mutex_unlock(&ci->lock);
 542        /* msleep(500); */
 543        return 0;
 544}
 545
 546static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 547{
 548        struct cxd *ci = ca->data;
 549
 550        dev_info(&ci->i2c->dev, "slot_shutdown\n");
 551        mutex_lock(&ci->lock);
 552        write_regm(ci, 0x09, 0x08, 0x08);
 553        write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */
 554        write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */
 555        ci->mode = -1;
 556        mutex_unlock(&ci->lock);
 557        return 0;
 558}
 559
 560static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 561{
 562        struct cxd *ci = ca->data;
 563
 564        mutex_lock(&ci->lock);
 565        write_regm(ci, 0x09, 0x00, 0x08);
 566        set_mode(ci, 0);
 567#ifdef BUFFER_MODE
 568        cam_mode(ci, 1);
 569#endif
 570        mutex_unlock(&ci->lock);
 571        return 0;
 572}
 573
 574
 575static int campoll(struct cxd *ci)
 576{
 577        u8 istat;
 578
 579        read_reg(ci, 0x04, &istat);
 580        if (!istat)
 581                return 0;
 582        write_reg(ci, 0x05, istat);
 583
 584        if (istat&0x40) {
 585                ci->dr = 1;
 586                dev_info(&ci->i2c->dev, "DR\n");
 587        }
 588        if (istat&0x20)
 589                dev_info(&ci->i2c->dev, "WC\n");
 590
 591        if (istat&2) {
 592                u8 slotstat;
 593
 594                read_reg(ci, 0x01, &slotstat);
 595                if (!(2&slotstat)) {
 596                        if (!ci->slot_stat) {
 597                                ci->slot_stat = DVB_CA_EN50221_POLL_CAM_PRESENT;
 598                                write_regm(ci, 0x03, 0x08, 0x08);
 599                        }
 600
 601                } else {
 602                        if (ci->slot_stat) {
 603                                ci->slot_stat = 0;
 604                                write_regm(ci, 0x03, 0x00, 0x08);
 605                                dev_info(&ci->i2c->dev, "NO CAM\n");
 606                                ci->ready = 0;
 607                        }
 608                }
 609                if (istat&8 &&
 610                    ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) {
 611                        ci->ready = 1;
 612                        ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY;
 613                }
 614        }
 615        return 0;
 616}
 617
 618
 619static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
 620{
 621        struct cxd *ci = ca->data;
 622        u8 slotstat;
 623
 624        mutex_lock(&ci->lock);
 625        campoll(ci);
 626        read_reg(ci, 0x01, &slotstat);
 627        mutex_unlock(&ci->lock);
 628
 629        return ci->slot_stat;
 630}
 631
 632#ifdef BUFFER_MODE
 633static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
 634{
 635        struct cxd *ci = ca->data;
 636        u8 msb, lsb;
 637        u16 len;
 638
 639        mutex_lock(&ci->lock);
 640        campoll(ci);
 641        mutex_unlock(&ci->lock);
 642
 643        dev_info(&ci->i2c->dev, "read_data\n");
 644        if (!ci->dr)
 645                return 0;
 646
 647        mutex_lock(&ci->lock);
 648        read_reg(ci, 0x0f, &msb);
 649        read_reg(ci, 0x10, &lsb);
 650        len = (msb<<8)|lsb;
 651        read_block(ci, 0x12, ebuf, len);
 652        ci->dr = 0;
 653        mutex_unlock(&ci->lock);
 654
 655        return len;
 656}
 657
 658static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount)
 659{
 660        struct cxd *ci = ca->data;
 661
 662        mutex_lock(&ci->lock);
 663        printk(kern_INFO "write_data %d\n", ecount);
 664        write_reg(ci, 0x0d, ecount>>8);
 665        write_reg(ci, 0x0e, ecount&0xff);
 666        write_block(ci, 0x11, ebuf, ecount);
 667        mutex_unlock(&ci->lock);
 668        return ecount;
 669}
 670#endif
 671
 672static struct dvb_ca_en50221 en_templ = {
 673        .read_attribute_mem  = read_attribute_mem,
 674        .write_attribute_mem = write_attribute_mem,
 675        .read_cam_control    = read_cam_control,
 676        .write_cam_control   = write_cam_control,
 677        .slot_reset          = slot_reset,
 678        .slot_shutdown       = slot_shutdown,
 679        .slot_ts_enable      = slot_ts_enable,
 680        .poll_slot_status    = poll_slot_status,
 681#ifdef BUFFER_MODE
 682        .read_data           = read_data,
 683        .write_data          = write_data,
 684#endif
 685
 686};
 687
 688struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
 689                                      void *priv,
 690                                      struct i2c_adapter *i2c)
 691{
 692        struct cxd *ci;
 693        u8 val;
 694
 695        if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
 696                dev_info(&i2c->dev, "No CXD2099 detected at %02x\n", cfg->adr);
 697                return NULL;
 698        }
 699
 700        ci = kzalloc(sizeof(struct cxd), GFP_KERNEL);
 701        if (!ci)
 702                return NULL;
 703
 704        mutex_init(&ci->lock);
 705        ci->cfg = *cfg;
 706        ci->i2c = i2c;
 707        ci->lastaddress = 0xff;
 708        ci->clk_reg_b = 0x4a;
 709        ci->clk_reg_f = 0x1b;
 710
 711        ci->en = en_templ;
 712        ci->en.data = ci;
 713        init(ci);
 714        dev_info(&i2c->dev, "Attached CXD2099AR at %02x\n", ci->cfg.adr);
 715        return &ci->en;
 716}
 717EXPORT_SYMBOL(cxd2099_attach);
 718
 719MODULE_DESCRIPTION("cxd2099");
 720MODULE_AUTHOR("Ralph Metzler");
 721MODULE_LICENSE("GPL");
 722