linux/drivers/media/usb/dvb-usb/az6027.c
<<
>>
Prefs
   1/* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)
   2 * receiver.
   3 *
   4 * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn>
   5 *
   6 *      This program is free software; you can redistribute it and/or modify it
   7 *      under the terms of the GNU General Public License as published by the Free
   8 *      Software Foundation, version 2.
   9 *
  10 * see Documentation/dvb/README.dvb-usb for more information
  11 */
  12#include "az6027.h"
  13
  14#include "stb0899_drv.h"
  15#include "stb0899_reg.h"
  16#include "stb0899_cfg.h"
  17
  18#include "stb6100.h"
  19#include "stb6100_cfg.h"
  20#include "dvb_ca_en50221.h"
  21
  22int dvb_usb_az6027_debug;
  23module_param_named(debug, dvb_usb_az6027_debug, int, 0644);
  24MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
  25
  26DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  27
  28struct az6027_device_state {
  29        struct dvb_ca_en50221 ca;
  30        struct mutex ca_mutex;
  31        u8 power_state;
  32};
  33
  34static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
  35
  36        /* 0x0000000b, SYSREG */
  37        { STB0899_DEV_ID                , 0x30 },
  38        { STB0899_DISCNTRL1             , 0x32 },
  39        { STB0899_DISCNTRL2             , 0x80 },
  40        { STB0899_DISRX_ST0             , 0x04 },
  41        { STB0899_DISRX_ST1             , 0x00 },
  42        { STB0899_DISPARITY             , 0x00 },
  43        { STB0899_DISSTATUS             , 0x20 },
  44        { STB0899_DISF22                , 0x99 },
  45        { STB0899_DISF22RX              , 0xa8 },
  46        /* SYSREG ? */
  47        { STB0899_ACRPRESC              , 0x11 },
  48        { STB0899_ACRDIV1               , 0x0a },
  49        { STB0899_ACRDIV2               , 0x05 },
  50        { STB0899_DACR1                 , 0x00 },
  51        { STB0899_DACR2                 , 0x00 },
  52        { STB0899_OUTCFG                , 0x00 },
  53        { STB0899_MODECFG               , 0x00 },
  54        { STB0899_IRQSTATUS_3           , 0xfe },
  55        { STB0899_IRQSTATUS_2           , 0x03 },
  56        { STB0899_IRQSTATUS_1           , 0x7c },
  57        { STB0899_IRQSTATUS_0           , 0xf4 },
  58        { STB0899_IRQMSK_3              , 0xf3 },
  59        { STB0899_IRQMSK_2              , 0xfc },
  60        { STB0899_IRQMSK_1              , 0xff },
  61        { STB0899_IRQMSK_0              , 0xff },
  62        { STB0899_IRQCFG                , 0x00 },
  63        { STB0899_I2CCFG                , 0x88 },
  64        { STB0899_I2CRPT                , 0x58 },
  65        { STB0899_IOPVALUE5             , 0x00 },
  66        { STB0899_IOPVALUE4             , 0x33 },
  67        { STB0899_IOPVALUE3             , 0x6d },
  68        { STB0899_IOPVALUE2             , 0x90 },
  69        { STB0899_IOPVALUE1             , 0x60 },
  70        { STB0899_IOPVALUE0             , 0x00 },
  71        { STB0899_GPIO00CFG             , 0x82 },
  72        { STB0899_GPIO01CFG             , 0x82 },
  73        { STB0899_GPIO02CFG             , 0x82 },
  74        { STB0899_GPIO03CFG             , 0x82 },
  75        { STB0899_GPIO04CFG             , 0x82 },
  76        { STB0899_GPIO05CFG             , 0x82 },
  77        { STB0899_GPIO06CFG             , 0x82 },
  78        { STB0899_GPIO07CFG             , 0x82 },
  79        { STB0899_GPIO08CFG             , 0x82 },
  80        { STB0899_GPIO09CFG             , 0x82 },
  81        { STB0899_GPIO10CFG             , 0x82 },
  82        { STB0899_GPIO11CFG             , 0x82 },
  83        { STB0899_GPIO12CFG             , 0x82 },
  84        { STB0899_GPIO13CFG             , 0x82 },
  85        { STB0899_GPIO14CFG             , 0x82 },
  86        { STB0899_GPIO15CFG             , 0x82 },
  87        { STB0899_GPIO16CFG             , 0x82 },
  88        { STB0899_GPIO17CFG             , 0x82 },
  89        { STB0899_GPIO18CFG             , 0x82 },
  90        { STB0899_GPIO19CFG             , 0x82 },
  91        { STB0899_GPIO20CFG             , 0x82 },
  92        { STB0899_SDATCFG               , 0xb8 },
  93        { STB0899_SCLTCFG               , 0xba },
  94        { STB0899_AGCRFCFG              , 0x1c }, /* 0x11 */
  95        { STB0899_GPIO22                , 0x82 }, /* AGCBB2CFG */
  96        { STB0899_GPIO21                , 0x91 }, /* AGCBB1CFG */
  97        { STB0899_DIRCLKCFG             , 0x82 },
  98        { STB0899_CLKOUT27CFG           , 0x7e },
  99        { STB0899_STDBYCFG              , 0x82 },
 100        { STB0899_CS0CFG                , 0x82 },
 101        { STB0899_CS1CFG                , 0x82 },
 102        { STB0899_DISEQCOCFG            , 0x20 },
 103        { STB0899_GPIO32CFG             , 0x82 },
 104        { STB0899_GPIO33CFG             , 0x82 },
 105        { STB0899_GPIO34CFG             , 0x82 },
 106        { STB0899_GPIO35CFG             , 0x82 },
 107        { STB0899_GPIO36CFG             , 0x82 },
 108        { STB0899_GPIO37CFG             , 0x82 },
 109        { STB0899_GPIO38CFG             , 0x82 },
 110        { STB0899_GPIO39CFG             , 0x82 },
 111        { STB0899_NCOARSE               , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
 112        { STB0899_SYNTCTRL              , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
 113        { STB0899_FILTCTRL              , 0x00 },
 114        { STB0899_SYSCTRL               , 0x01 },
 115        { STB0899_STOPCLK1              , 0x20 },
 116        { STB0899_STOPCLK2              , 0x00 },
 117        { STB0899_INTBUFSTATUS          , 0x00 },
 118        { STB0899_INTBUFCTRL            , 0x0a },
 119        { 0xffff                        , 0xff },
 120};
 121
 122static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = {
 123        { STB0899_DEMOD                 , 0x00 },
 124        { STB0899_RCOMPC                , 0xc9 },
 125        { STB0899_AGC1CN                , 0x01 },
 126        { STB0899_AGC1REF               , 0x10 },
 127        { STB0899_RTC                   , 0x23 },
 128        { STB0899_TMGCFG                , 0x4e },
 129        { STB0899_AGC2REF               , 0x34 },
 130        { STB0899_TLSR                  , 0x84 },
 131        { STB0899_CFD                   , 0xf7 },
 132        { STB0899_ACLC                  , 0x87 },
 133        { STB0899_BCLC                  , 0x94 },
 134        { STB0899_EQON                  , 0x41 },
 135        { STB0899_LDT                   , 0xf1 },
 136        { STB0899_LDT2                  , 0xe3 },
 137        { STB0899_EQUALREF              , 0xb4 },
 138        { STB0899_TMGRAMP               , 0x10 },
 139        { STB0899_TMGTHD                , 0x30 },
 140        { STB0899_IDCCOMP               , 0xfd },
 141        { STB0899_QDCCOMP               , 0xff },
 142        { STB0899_POWERI                , 0x0c },
 143        { STB0899_POWERQ                , 0x0f },
 144        { STB0899_RCOMP                 , 0x6c },
 145        { STB0899_AGCIQIN               , 0x80 },
 146        { STB0899_AGC2I1                , 0x06 },
 147        { STB0899_AGC2I2                , 0x00 },
 148        { STB0899_TLIR                  , 0x30 },
 149        { STB0899_RTF                   , 0x7f },
 150        { STB0899_DSTATUS               , 0x00 },
 151        { STB0899_LDI                   , 0xbc },
 152        { STB0899_CFRM                  , 0xea },
 153        { STB0899_CFRL                  , 0x31 },
 154        { STB0899_NIRM                  , 0x2b },
 155        { STB0899_NIRL                  , 0x80 },
 156        { STB0899_ISYMB                 , 0x1d },
 157        { STB0899_QSYMB                 , 0xa6 },
 158        { STB0899_SFRH                  , 0x2f },
 159        { STB0899_SFRM                  , 0x68 },
 160        { STB0899_SFRL                  , 0x40 },
 161        { STB0899_SFRUPH                , 0x2f },
 162        { STB0899_SFRUPM                , 0x68 },
 163        { STB0899_SFRUPL                , 0x40 },
 164        { STB0899_EQUAI1                , 0x02 },
 165        { STB0899_EQUAQ1                , 0xff },
 166        { STB0899_EQUAI2                , 0x04 },
 167        { STB0899_EQUAQ2                , 0x05 },
 168        { STB0899_EQUAI3                , 0x02 },
 169        { STB0899_EQUAQ3                , 0xfd },
 170        { STB0899_EQUAI4                , 0x03 },
 171        { STB0899_EQUAQ4                , 0x07 },
 172        { STB0899_EQUAI5                , 0x08 },
 173        { STB0899_EQUAQ5                , 0xf5 },
 174        { STB0899_DSTATUS2              , 0x00 },
 175        { STB0899_VSTATUS               , 0x00 },
 176        { STB0899_VERROR                , 0x86 },
 177        { STB0899_IQSWAP                , 0x2a },
 178        { STB0899_ECNT1M                , 0x00 },
 179        { STB0899_ECNT1L                , 0x00 },
 180        { STB0899_ECNT2M                , 0x00 },
 181        { STB0899_ECNT2L                , 0x00 },
 182        { STB0899_ECNT3M                , 0x0a },
 183        { STB0899_ECNT3L                , 0xad },
 184        { STB0899_FECAUTO1              , 0x06 },
 185        { STB0899_FECM                  , 0x01 },
 186        { STB0899_VTH12                 , 0xb0 },
 187        { STB0899_VTH23                 , 0x7a },
 188        { STB0899_VTH34                 , 0x58 },
 189        { STB0899_VTH56                 , 0x38 },
 190        { STB0899_VTH67                 , 0x34 },
 191        { STB0899_VTH78                 , 0x24 },
 192        { STB0899_PRVIT                 , 0xff },
 193        { STB0899_VITSYNC               , 0x19 },
 194        { STB0899_RSULC                 , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
 195        { STB0899_TSULC                 , 0x42 },
 196        { STB0899_RSLLC                 , 0x41 },
 197        { STB0899_TSLPL                 , 0x12 },
 198        { STB0899_TSCFGH                , 0x0c },
 199        { STB0899_TSCFGM                , 0x00 },
 200        { STB0899_TSCFGL                , 0x00 },
 201        { STB0899_TSOUT                 , 0x69 }, /* 0x0d for CAM */
 202        { STB0899_RSSYNCDEL             , 0x00 },
 203        { STB0899_TSINHDELH             , 0x02 },
 204        { STB0899_TSINHDELM             , 0x00 },
 205        { STB0899_TSINHDELL             , 0x00 },
 206        { STB0899_TSLLSTKM              , 0x1b },
 207        { STB0899_TSLLSTKL              , 0xb3 },
 208        { STB0899_TSULSTKM              , 0x00 },
 209        { STB0899_TSULSTKL              , 0x00 },
 210        { STB0899_PCKLENUL              , 0xbc },
 211        { STB0899_PCKLENLL              , 0xcc },
 212        { STB0899_RSPCKLEN              , 0xbd },
 213        { STB0899_TSSTATUS              , 0x90 },
 214        { STB0899_ERRCTRL1              , 0xb6 },
 215        { STB0899_ERRCTRL2              , 0x95 },
 216        { STB0899_ERRCTRL3              , 0x8d },
 217        { STB0899_DMONMSK1              , 0x27 },
 218        { STB0899_DMONMSK0              , 0x03 },
 219        { STB0899_DEMAPVIT              , 0x5c },
 220        { STB0899_PLPARM                , 0x19 },
 221        { STB0899_PDELCTRL              , 0x48 },
 222        { STB0899_PDELCTRL2             , 0x00 },
 223        { STB0899_BBHCTRL1              , 0x00 },
 224        { STB0899_BBHCTRL2              , 0x00 },
 225        { STB0899_HYSTTHRESH            , 0x77 },
 226        { STB0899_MATCSTM               , 0x00 },
 227        { STB0899_MATCSTL               , 0x00 },
 228        { STB0899_UPLCSTM               , 0x00 },
 229        { STB0899_UPLCSTL               , 0x00 },
 230        { STB0899_DFLCSTM               , 0x00 },
 231        { STB0899_DFLCSTL               , 0x00 },
 232        { STB0899_SYNCCST               , 0x00 },
 233        { STB0899_SYNCDCSTM             , 0x00 },
 234        { STB0899_SYNCDCSTL             , 0x00 },
 235        { STB0899_ISI_ENTRY             , 0x00 },
 236        { STB0899_ISI_BIT_EN            , 0x00 },
 237        { STB0899_MATSTRM               , 0xf0 },
 238        { STB0899_MATSTRL               , 0x02 },
 239        { STB0899_UPLSTRM               , 0x45 },
 240        { STB0899_UPLSTRL               , 0x60 },
 241        { STB0899_DFLSTRM               , 0xe3 },
 242        { STB0899_DFLSTRL               , 0x00 },
 243        { STB0899_SYNCSTR               , 0x47 },
 244        { STB0899_SYNCDSTRM             , 0x05 },
 245        { STB0899_SYNCDSTRL             , 0x18 },
 246        { STB0899_CFGPDELSTATUS1        , 0x19 },
 247        { STB0899_CFGPDELSTATUS2        , 0x2b },
 248        { STB0899_BBFERRORM             , 0x00 },
 249        { STB0899_BBFERRORL             , 0x01 },
 250        { STB0899_UPKTERRORM            , 0x00 },
 251        { STB0899_UPKTERRORL            , 0x00 },
 252        { 0xffff                        , 0xff },
 253};
 254
 255
 256
 257static struct stb0899_config az6027_stb0899_config = {
 258        .init_dev               = az6027_stb0899_s1_init_1,
 259        .init_s2_demod          = stb0899_s2_init_2,
 260        .init_s1_demod          = az6027_stb0899_s1_init_3,
 261        .init_s2_fec            = stb0899_s2_init_4,
 262        .init_tst               = stb0899_s1_init_5,
 263
 264        .demod_address          = 0xd0, /* 0x68, 0xd0 >> 1 */
 265
 266        .xtal_freq              = 27000000,
 267        .inversion              = IQ_SWAP_ON,
 268
 269        .lo_clk                 = 76500000,
 270        .hi_clk                 = 99000000,
 271
 272        .esno_ave               = STB0899_DVBS2_ESNO_AVE,
 273        .esno_quant             = STB0899_DVBS2_ESNO_QUANT,
 274        .avframes_coarse        = STB0899_DVBS2_AVFRAMES_COARSE,
 275        .avframes_fine          = STB0899_DVBS2_AVFRAMES_FINE,
 276        .miss_threshold         = STB0899_DVBS2_MISS_THRESHOLD,
 277        .uwp_threshold_acq      = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
 278        .uwp_threshold_track    = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
 279        .uwp_threshold_sof      = STB0899_DVBS2_UWP_THRESHOLD_SOF,
 280        .sof_search_timeout     = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
 281
 282        .btr_nco_bits           = STB0899_DVBS2_BTR_NCO_BITS,
 283        .btr_gain_shift_offset  = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
 284        .crl_nco_bits           = STB0899_DVBS2_CRL_NCO_BITS,
 285        .ldpc_max_iter          = STB0899_DVBS2_LDPC_MAX_ITER,
 286
 287        .tuner_get_frequency    = stb6100_get_frequency,
 288        .tuner_set_frequency    = stb6100_set_frequency,
 289        .tuner_set_bandwidth    = stb6100_set_bandwidth,
 290        .tuner_get_bandwidth    = stb6100_get_bandwidth,
 291        .tuner_set_rfsiggain    = NULL,
 292};
 293
 294static struct stb6100_config az6027_stb6100_config = {
 295        .tuner_address  = 0xc0,
 296        .refclock       = 27000000,
 297};
 298
 299
 300/* check for mutex FIXME */
 301static int az6027_usb_in_op(struct dvb_usb_device *d, u8 req,
 302                            u16 value, u16 index, u8 *b, int blen)
 303{
 304        int ret = -1;
 305        if (mutex_lock_interruptible(&d->usb_mutex))
 306                return -EAGAIN;
 307
 308        ret = usb_control_msg(d->udev,
 309                              usb_rcvctrlpipe(d->udev, 0),
 310                              req,
 311                              USB_TYPE_VENDOR | USB_DIR_IN,
 312                              value,
 313                              index,
 314                              b,
 315                              blen,
 316                              2000);
 317
 318        if (ret < 0) {
 319                warn("usb in operation failed. (%d)", ret);
 320                ret = -EIO;
 321        } else
 322                ret = 0;
 323
 324        deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
 325        debug_dump(b, blen, deb_xfer);
 326
 327        mutex_unlock(&d->usb_mutex);
 328        return ret;
 329}
 330
 331static int az6027_usb_out_op(struct dvb_usb_device *d,
 332                             u8 req,
 333                             u16 value,
 334                             u16 index,
 335                             u8 *b,
 336                             int blen)
 337{
 338        int ret;
 339
 340        deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
 341        debug_dump(b, blen, deb_xfer);
 342
 343        if (mutex_lock_interruptible(&d->usb_mutex))
 344                return -EAGAIN;
 345
 346        ret = usb_control_msg(d->udev,
 347                              usb_sndctrlpipe(d->udev, 0),
 348                              req,
 349                              USB_TYPE_VENDOR | USB_DIR_OUT,
 350                              value,
 351                              index,
 352                              b,
 353                              blen,
 354                              2000);
 355
 356        if (ret != blen) {
 357                warn("usb out operation failed. (%d)", ret);
 358                mutex_unlock(&d->usb_mutex);
 359                return -EIO;
 360        } else{
 361                mutex_unlock(&d->usb_mutex);
 362                return 0;
 363        }
 364}
 365
 366static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 367{
 368        int ret;
 369        u8 req;
 370        u16 value;
 371        u16 index;
 372        int blen;
 373
 374        deb_info("%s %d", __func__, onoff);
 375
 376        req = 0xBC;
 377        value = onoff;
 378        index = 0;
 379        blen = 0;
 380
 381        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 382        if (ret != 0)
 383                warn("usb out operation failed. (%d)", ret);
 384
 385        return ret;
 386}
 387
 388/* keys for the enclosed remote control */
 389static struct rc_map_table rc_map_az6027_table[] = {
 390        { 0x01, KEY_1 },
 391        { 0x02, KEY_2 },
 392};
 393
 394/* remote control stuff (does not work with my box) */
 395static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 396{
 397        return 0;
 398}
 399
 400/*
 401int az6027_power_ctrl(struct dvb_usb_device *d, int onoff)
 402{
 403        u8 v = onoff;
 404        return az6027_usb_out_op(d,0xBC,v,3,NULL,1);
 405}
 406*/
 407
 408static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
 409                                        int slot,
 410                                        int address)
 411{
 412        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 413        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 414
 415        int ret;
 416        u8 req;
 417        u16 value;
 418        u16 index;
 419        int blen;
 420        u8 *b;
 421
 422        if (slot != 0)
 423                return -EINVAL;
 424
 425        b = kmalloc(12, GFP_KERNEL);
 426        if (!b)
 427                return -ENOMEM;
 428
 429        mutex_lock(&state->ca_mutex);
 430
 431        req = 0xC1;
 432        value = address;
 433        index = 0;
 434        blen = 1;
 435
 436        ret = az6027_usb_in_op(d, req, value, index, b, blen);
 437        if (ret < 0) {
 438                warn("usb in operation failed. (%d)", ret);
 439                ret = -EINVAL;
 440        } else {
 441                ret = b[0];
 442        }
 443
 444        mutex_unlock(&state->ca_mutex);
 445        kfree(b);
 446        return ret;
 447}
 448
 449static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
 450                                         int slot,
 451                                         int address,
 452                                         u8 value)
 453{
 454        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 455        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 456
 457        int ret;
 458        u8 req;
 459        u16 value1;
 460        u16 index;
 461        int blen;
 462
 463        deb_info("%s %d", __func__, slot);
 464        if (slot != 0)
 465                return -EINVAL;
 466
 467        mutex_lock(&state->ca_mutex);
 468        req = 0xC2;
 469        value1 = address;
 470        index = value;
 471        blen = 0;
 472
 473        ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
 474        if (ret != 0)
 475                warn("usb out operation failed. (%d)", ret);
 476
 477        mutex_unlock(&state->ca_mutex);
 478        return ret;
 479}
 480
 481static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca,
 482                                      int slot,
 483                                      u8 address)
 484{
 485        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 486        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 487
 488        int ret;
 489        u8 req;
 490        u16 value;
 491        u16 index;
 492        int blen;
 493        u8 *b;
 494
 495        if (slot != 0)
 496                return -EINVAL;
 497
 498        b = kmalloc(12, GFP_KERNEL);
 499        if (!b)
 500                return -ENOMEM;
 501
 502        mutex_lock(&state->ca_mutex);
 503
 504        req = 0xC3;
 505        value = address;
 506        index = 0;
 507        blen = 2;
 508
 509        ret = az6027_usb_in_op(d, req, value, index, b, blen);
 510        if (ret < 0) {
 511                warn("usb in operation failed. (%d)", ret);
 512                ret = -EINVAL;
 513        } else {
 514                if (b[0] == 0)
 515                        warn("Read CI IO error");
 516
 517                ret = b[1];
 518                deb_info("read cam data = %x from 0x%x", b[1], value);
 519        }
 520
 521        mutex_unlock(&state->ca_mutex);
 522        kfree(b);
 523        return ret;
 524}
 525
 526static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca,
 527                                       int slot,
 528                                       u8 address,
 529                                       u8 value)
 530{
 531        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 532        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 533
 534        int ret;
 535        u8 req;
 536        u16 value1;
 537        u16 index;
 538        int blen;
 539
 540        if (slot != 0)
 541                return -EINVAL;
 542
 543        mutex_lock(&state->ca_mutex);
 544        req = 0xC4;
 545        value1 = address;
 546        index = value;
 547        blen = 0;
 548
 549        ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
 550        if (ret != 0) {
 551                warn("usb out operation failed. (%d)", ret);
 552                goto failed;
 553        }
 554
 555failed:
 556        mutex_unlock(&state->ca_mutex);
 557        return ret;
 558}
 559
 560static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
 561{
 562        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 563
 564        int ret;
 565        u8 req;
 566        u16 value;
 567        u16 index;
 568        int blen;
 569        u8 *b;
 570
 571        b = kmalloc(12, GFP_KERNEL);
 572        if (!b)
 573                return -ENOMEM;
 574
 575        req = 0xC8;
 576        value = 0;
 577        index = 0;
 578        blen = 1;
 579
 580        ret = az6027_usb_in_op(d, req, value, index, b, blen);
 581        if (ret < 0) {
 582                warn("usb in operation failed. (%d)", ret);
 583                ret = -EIO;
 584        } else{
 585                ret = b[0];
 586        }
 587        kfree(b);
 588        return ret;
 589}
 590
 591static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 592{
 593        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 594        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 595
 596        int ret, i;
 597        u8 req;
 598        u16 value;
 599        u16 index;
 600        int blen;
 601
 602        mutex_lock(&state->ca_mutex);
 603
 604        req = 0xC6;
 605        value = 1;
 606        index = 0;
 607        blen = 0;
 608
 609        ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
 610        if (ret != 0) {
 611                warn("usb out operation failed. (%d)", ret);
 612                goto failed;
 613        }
 614
 615        msleep(500);
 616        req = 0xC6;
 617        value = 0;
 618        index = 0;
 619        blen = 0;
 620
 621        ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
 622        if (ret != 0) {
 623                warn("usb out operation failed. (%d)", ret);
 624                goto failed;
 625        }
 626
 627        for (i = 0; i < 15; i++) {
 628                msleep(100);
 629
 630                if (CI_CamReady(ca, slot)) {
 631                        deb_info("CAM Ready");
 632                        break;
 633                }
 634        }
 635        msleep(5000);
 636
 637failed:
 638        mutex_unlock(&state->ca_mutex);
 639        return ret;
 640}
 641
 642static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 643{
 644        return 0;
 645}
 646
 647static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 648{
 649        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 650        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 651
 652        int ret;
 653        u8 req;
 654        u16 value;
 655        u16 index;
 656        int blen;
 657
 658        deb_info("%s", __func__);
 659        mutex_lock(&state->ca_mutex);
 660        req = 0xC7;
 661        value = 1;
 662        index = 0;
 663        blen = 0;
 664
 665        ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
 666        if (ret != 0) {
 667                warn("usb out operation failed. (%d)", ret);
 668                goto failed;
 669        }
 670
 671failed:
 672        mutex_unlock(&state->ca_mutex);
 673        return ret;
 674}
 675
 676static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
 677{
 678        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
 679        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 680        int ret;
 681        u8 req;
 682        u16 value;
 683        u16 index;
 684        int blen;
 685        u8 *b;
 686
 687        b = kmalloc(12, GFP_KERNEL);
 688        if (!b)
 689                return -ENOMEM;
 690        mutex_lock(&state->ca_mutex);
 691
 692        req = 0xC5;
 693        value = 0;
 694        index = 0;
 695        blen = 1;
 696
 697        ret = az6027_usb_in_op(d, req, value, index, b, blen);
 698        if (ret < 0) {
 699                warn("usb in operation failed. (%d)", ret);
 700                ret = -EIO;
 701        } else
 702                ret = 0;
 703
 704        if (!ret && b[0] == 1) {
 705                ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
 706                      DVB_CA_EN50221_POLL_CAM_READY;
 707        }
 708
 709        mutex_unlock(&state->ca_mutex);
 710        kfree(b);
 711        return ret;
 712}
 713
 714
 715static void az6027_ci_uninit(struct dvb_usb_device *d)
 716{
 717        struct az6027_device_state *state;
 718
 719        deb_info("%s", __func__);
 720
 721        if (NULL == d)
 722                return;
 723
 724        state = (struct az6027_device_state *)d->priv;
 725        if (NULL == state)
 726                return;
 727
 728        if (NULL == state->ca.data)
 729                return;
 730
 731        dvb_ca_en50221_release(&state->ca);
 732
 733        memset(&state->ca, 0, sizeof(state->ca));
 734}
 735
 736
 737static int az6027_ci_init(struct dvb_usb_adapter *a)
 738{
 739        struct dvb_usb_device *d = a->dev;
 740        struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
 741        int ret;
 742
 743        deb_info("%s", __func__);
 744
 745        mutex_init(&state->ca_mutex);
 746
 747        state->ca.owner                 = THIS_MODULE;
 748        state->ca.read_attribute_mem    = az6027_ci_read_attribute_mem;
 749        state->ca.write_attribute_mem   = az6027_ci_write_attribute_mem;
 750        state->ca.read_cam_control      = az6027_ci_read_cam_control;
 751        state->ca.write_cam_control     = az6027_ci_write_cam_control;
 752        state->ca.slot_reset            = az6027_ci_slot_reset;
 753        state->ca.slot_shutdown         = az6027_ci_slot_shutdown;
 754        state->ca.slot_ts_enable        = az6027_ci_slot_ts_enable;
 755        state->ca.poll_slot_status      = az6027_ci_poll_slot_status;
 756        state->ca.data                  = d;
 757
 758        ret = dvb_ca_en50221_init(&a->dvb_adap,
 759                                  &state->ca,
 760                                  0, /* flags */
 761                                  1);/* n_slots */
 762        if (ret != 0) {
 763                err("Cannot initialize CI: Error %d.", ret);
 764                memset(&state->ca, 0, sizeof(state->ca));
 765                return ret;
 766        }
 767
 768        deb_info("CI initialized.");
 769
 770        return 0;
 771}
 772
 773/*
 774static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
 775{
 776        az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6);
 777        return 0;
 778}
 779*/
 780
 781static int az6027_set_voltage(struct dvb_frontend *fe,
 782                              enum fe_sec_voltage voltage)
 783{
 784
 785        u8 buf;
 786        struct dvb_usb_adapter *adap = fe->dvb->priv;
 787
 788        struct i2c_msg i2c_msg = {
 789                .addr   = 0x99,
 790                .flags  = 0,
 791                .buf    = &buf,
 792                .len    = 1
 793        };
 794
 795        /*
 796         * 2   --18v
 797         * 1   --13v
 798         * 0   --off
 799         */
 800        switch (voltage) {
 801        case SEC_VOLTAGE_13:
 802                buf = 1;
 803                i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 804                break;
 805
 806        case SEC_VOLTAGE_18:
 807                buf = 2;
 808                i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 809                break;
 810
 811        case SEC_VOLTAGE_OFF:
 812                buf = 0;
 813                i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
 814                break;
 815
 816        default:
 817                return -EINVAL;
 818        }
 819        return 0;
 820}
 821
 822
 823static int az6027_frontend_poweron(struct dvb_usb_adapter *adap)
 824{
 825        int ret;
 826        u8 req;
 827        u16 value;
 828        u16 index;
 829        int blen;
 830
 831        req = 0xBC;
 832        value = 1; /* power on */
 833        index = 3;
 834        blen = 0;
 835
 836        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 837        if (ret != 0)
 838                return -EIO;
 839
 840        return 0;
 841}
 842static int az6027_frontend_reset(struct dvb_usb_adapter *adap)
 843{
 844        int ret;
 845        u8 req;
 846        u16 value;
 847        u16 index;
 848        int blen;
 849
 850        /* reset demodulator */
 851        req = 0xC0;
 852        value = 1; /* high */
 853        index = 3;
 854        blen = 0;
 855
 856        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 857        if (ret != 0)
 858                return -EIO;
 859
 860        req = 0xC0;
 861        value = 0; /* low */
 862        index = 3;
 863        blen = 0;
 864        msleep_interruptible(200);
 865
 866        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 867        if (ret != 0)
 868                return -EIO;
 869
 870        msleep_interruptible(200);
 871
 872        req = 0xC0;
 873        value = 1; /*high */
 874        index = 3;
 875        blen = 0;
 876
 877        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 878        if (ret != 0)
 879                return -EIO;
 880
 881        msleep_interruptible(200);
 882        return 0;
 883}
 884
 885static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff)
 886{
 887        int ret;
 888        u8 req;
 889        u16 value;
 890        u16 index;
 891        int blen;
 892
 893        /* TS passthrough */
 894        req = 0xC7;
 895        value = onoff;
 896        index = 0;
 897        blen = 0;
 898
 899        ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
 900        if (ret != 0)
 901                return -EIO;
 902
 903        return 0;
 904}
 905
 906static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
 907{
 908
 909        az6027_frontend_poweron(adap);
 910        az6027_frontend_reset(adap);
 911
 912        deb_info("adap = %p, dev = %p\n", adap, adap->dev);
 913        adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
 914
 915        if (adap->fe_adap[0].fe) {
 916                deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
 917                if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
 918                        deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
 919                        adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
 920                        az6027_ci_init(adap);
 921                } else {
 922                        adap->fe_adap[0].fe = NULL;
 923                }
 924        } else
 925                warn("no front-end attached\n");
 926
 927        az6027_frontend_tsbypass(adap, 0);
 928
 929        return 0;
 930}
 931
 932static struct dvb_usb_device_properties az6027_properties;
 933
 934static void az6027_usb_disconnect(struct usb_interface *intf)
 935{
 936        struct dvb_usb_device *d = usb_get_intfdata(intf);
 937        az6027_ci_uninit(d);
 938        dvb_usb_device_exit(intf);
 939}
 940
 941
 942static int az6027_usb_probe(struct usb_interface *intf,
 943                            const struct usb_device_id *id)
 944{
 945        return dvb_usb_device_init(intf,
 946                                   &az6027_properties,
 947                                   THIS_MODULE,
 948                                   NULL,
 949                                   adapter_nr);
 950}
 951
 952/* I2C */
 953static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
 954{
 955        struct dvb_usb_device *d = i2c_get_adapdata(adap);
 956        int i = 0, j = 0, len = 0;
 957        u16 index;
 958        u16 value;
 959        int length;
 960        u8 req;
 961        u8 *data;
 962
 963        data = kmalloc(256, GFP_KERNEL);
 964        if (!data)
 965                return -ENOMEM;
 966
 967        if (mutex_lock_interruptible(&d->i2c_mutex) < 0) {
 968                kfree(data);
 969                return -EAGAIN;
 970        }
 971
 972        if (num > 2)
 973                warn("more than 2 i2c messages at a time is not handled yet. TODO.");
 974
 975        for (i = 0; i < num; i++) {
 976
 977                if (msg[i].addr == 0x99) {
 978                        req = 0xBE;
 979                        index = 0;
 980                        value = msg[i].buf[0] & 0x00ff;
 981                        length = 1;
 982                        az6027_usb_out_op(d, req, value, index, data, length);
 983                }
 984
 985                if (msg[i].addr == 0xd0) {
 986                        /* write/read request */
 987                        if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
 988                                req = 0xB9;
 989                                index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
 990                                value = msg[i].addr + (msg[i].len << 8);
 991                                length = msg[i + 1].len + 6;
 992                                az6027_usb_in_op(d, req, value, index, data, length);
 993                                len = msg[i + 1].len;
 994                                for (j = 0; j < len; j++)
 995                                        msg[i + 1].buf[j] = data[j + 5];
 996
 997                                i++;
 998                        } else {
 999
1000                                /* demod 16bit addr */
1001                                req = 0xBD;
1002                                index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
1003                                value = msg[i].addr + (2 << 8);
1004                                length = msg[i].len - 2;
1005                                len = msg[i].len - 2;
1006                                for (j = 0; j < len; j++)
1007                                        data[j] = msg[i].buf[j + 2];
1008                                az6027_usb_out_op(d, req, value, index, data, length);
1009                        }
1010                }
1011
1012                if (msg[i].addr == 0xc0) {
1013                        if (msg[i].flags & I2C_M_RD) {
1014
1015                                req = 0xB9;
1016                                index = 0x0;
1017                                value = msg[i].addr;
1018                                length = msg[i].len + 6;
1019                                az6027_usb_in_op(d, req, value, index, data, length);
1020                                len = msg[i].len;
1021                                for (j = 0; j < len; j++)
1022                                        msg[i].buf[j] = data[j + 5];
1023
1024                        } else {
1025
1026                                req = 0xBD;
1027                                index = msg[i].buf[0] & 0x00FF;
1028                                value = msg[i].addr + (1 << 8);
1029                                length = msg[i].len - 1;
1030                                len = msg[i].len - 1;
1031
1032                                for (j = 0; j < len; j++)
1033                                        data[j] = msg[i].buf[j + 1];
1034
1035                                az6027_usb_out_op(d, req, value, index, data, length);
1036                        }
1037                }
1038        }
1039        mutex_unlock(&d->i2c_mutex);
1040        kfree(data);
1041
1042        return i;
1043}
1044
1045
1046static u32 az6027_i2c_func(struct i2c_adapter *adapter)
1047{
1048        return I2C_FUNC_I2C;
1049}
1050
1051static struct i2c_algorithm az6027_i2c_algo = {
1052        .master_xfer   = az6027_i2c_xfer,
1053        .functionality = az6027_i2c_func,
1054};
1055
1056static int az6027_identify_state(struct usb_device *udev,
1057                                 struct dvb_usb_device_properties *props,
1058                                 struct dvb_usb_device_description **desc,
1059                                 int *cold)
1060{
1061        u8 *b;
1062        s16 ret;
1063
1064        b = kmalloc(16, GFP_KERNEL);
1065        if (!b)
1066                return -ENOMEM;
1067
1068        ret = usb_control_msg(udev,
1069                                  usb_rcvctrlpipe(udev, 0),
1070                                  0xb7,
1071                                  USB_TYPE_VENDOR | USB_DIR_IN,
1072                                  6,
1073                                  0,
1074                                  b,
1075                                  6,
1076                                  USB_CTRL_GET_TIMEOUT);
1077
1078        *cold = ret <= 0;
1079        kfree(b);
1080        deb_info("cold: %d\n", *cold);
1081        return 0;
1082}
1083
1084
1085static struct usb_device_id az6027_usb_table[] = {
1086        { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) },
1087        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_DVBS2CI_V1) },
1088        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_DVBS2CI_V2) },
1089        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) },
1090        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
1091        { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
1092        { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V2) },
1093        { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V3) },
1094        { },
1095};
1096
1097MODULE_DEVICE_TABLE(usb, az6027_usb_table);
1098
1099static struct dvb_usb_device_properties az6027_properties = {
1100        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1101        .usb_ctrl = CYPRESS_FX2,
1102        .firmware            = "dvb-usb-az6027-03.fw",
1103        .no_reconnect        = 1,
1104
1105        .size_of_priv     = sizeof(struct az6027_device_state),
1106        .identify_state         = az6027_identify_state,
1107        .num_adapters = 1,
1108        .adapter = {
1109                {
1110                .num_frontends = 1,
1111                .fe = {{
1112                        .streaming_ctrl   = az6027_streaming_ctrl,
1113                        .frontend_attach  = az6027_frontend_attach,
1114
1115                        /* parameter for the MPEG2-data transfer */
1116                        .stream = {
1117                                .type = USB_BULK,
1118                                .count = 10,
1119                                .endpoint = 0x02,
1120                                .u = {
1121                                        .bulk = {
1122                                                .buffersize = 4096,
1123                                        }
1124                                }
1125                        },
1126                }},
1127                }
1128        },
1129/*
1130        .power_ctrl       = az6027_power_ctrl,
1131        .read_mac_address = az6027_read_mac_addr,
1132 */
1133        .rc.legacy = {
1134                .rc_map_table     = rc_map_az6027_table,
1135                .rc_map_size      = ARRAY_SIZE(rc_map_az6027_table),
1136                .rc_interval      = 400,
1137                .rc_query         = az6027_rc_query,
1138        },
1139
1140        .i2c_algo         = &az6027_i2c_algo,
1141
1142        .num_device_descs = 8,
1143        .devices = {
1144                {
1145                        .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
1146                        .cold_ids = { &az6027_usb_table[0], NULL },
1147                        .warm_ids = { NULL },
1148                }, {
1149                        .name = "TERRATEC S7",
1150                        .cold_ids = { &az6027_usb_table[1], NULL },
1151                        .warm_ids = { NULL },
1152                }, {
1153                        .name = "TERRATEC S7 MKII",
1154                        .cold_ids = { &az6027_usb_table[2], NULL },
1155                        .warm_ids = { NULL },
1156                }, {
1157                        .name = "Technisat SkyStar USB 2 HD CI",
1158                        .cold_ids = { &az6027_usb_table[3], NULL },
1159                        .warm_ids = { NULL },
1160                }, {
1161                        .name = "Technisat SkyStar USB 2 HD CI",
1162                        .cold_ids = { &az6027_usb_table[4], NULL },
1163                        .warm_ids = { NULL },
1164                }, {
1165                        .name = "Elgato EyeTV Sat",
1166                        .cold_ids = { &az6027_usb_table[5], NULL },
1167                        .warm_ids = { NULL },
1168                }, {
1169                        .name = "Elgato EyeTV Sat",
1170                        .cold_ids = { &az6027_usb_table[6], NULL },
1171                        .warm_ids = { NULL },
1172                }, {
1173                        .name = "Elgato EyeTV Sat",
1174                        .cold_ids = { &az6027_usb_table[7], NULL },
1175                        .warm_ids = { NULL },
1176                },
1177                { NULL },
1178        }
1179};
1180
1181/* usb specific object needed to register this driver with the usb subsystem */
1182static struct usb_driver az6027_usb_driver = {
1183        .name           = "dvb_usb_az6027",
1184        .probe          = az6027_usb_probe,
1185        .disconnect     = az6027_usb_disconnect,
1186        .id_table       = az6027_usb_table,
1187};
1188
1189module_usb_driver(az6027_usb_driver);
1190
1191MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>");
1192MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)");
1193MODULE_VERSION("1.0");
1194MODULE_LICENSE("GPL");
1195