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