Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)
0003  * receiver.
0004  *
0005  * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn>
0006  *
0007  * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
0008  */
0009 #include "az6027.h"
0010 
0011 #include "stb0899_drv.h"
0012 #include "stb0899_reg.h"
0013 #include "stb0899_cfg.h"
0014 
0015 #include "stb6100.h"
0016 #include "stb6100_cfg.h"
0017 #include <media/dvb_ca_en50221.h>
0018 
0019 int dvb_usb_az6027_debug;
0020 module_param_named(debug, dvb_usb_az6027_debug, int, 0644);
0021 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
0022 
0023 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0024 
0025 struct az6027_device_state {
0026     struct dvb_ca_en50221 ca;
0027     struct mutex ca_mutex;
0028     u8 power_state;
0029 };
0030 
0031 static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
0032 
0033     /* 0x0000000b, SYSREG */
0034     { STB0899_DEV_ID        , 0x30 },
0035     { STB0899_DISCNTRL1     , 0x32 },
0036     { STB0899_DISCNTRL2     , 0x80 },
0037     { STB0899_DISRX_ST0     , 0x04 },
0038     { STB0899_DISRX_ST1     , 0x00 },
0039     { STB0899_DISPARITY     , 0x00 },
0040     { STB0899_DISSTATUS     , 0x20 },
0041     { STB0899_DISF22        , 0x99 },
0042     { STB0899_DISF22RX      , 0xa8 },
0043     /* SYSREG ? */
0044     { STB0899_ACRPRESC      , 0x11 },
0045     { STB0899_ACRDIV1       , 0x0a },
0046     { STB0899_ACRDIV2       , 0x05 },
0047     { STB0899_DACR1         , 0x00 },
0048     { STB0899_DACR2         , 0x00 },
0049     { STB0899_OUTCFG        , 0x00 },
0050     { STB0899_MODECFG       , 0x00 },
0051     { STB0899_IRQSTATUS_3       , 0xfe },
0052     { STB0899_IRQSTATUS_2       , 0x03 },
0053     { STB0899_IRQSTATUS_1       , 0x7c },
0054     { STB0899_IRQSTATUS_0       , 0xf4 },
0055     { STB0899_IRQMSK_3      , 0xf3 },
0056     { STB0899_IRQMSK_2      , 0xfc },
0057     { STB0899_IRQMSK_1      , 0xff },
0058     { STB0899_IRQMSK_0      , 0xff },
0059     { STB0899_IRQCFG        , 0x00 },
0060     { STB0899_I2CCFG        , 0x88 },
0061     { STB0899_I2CRPT        , 0x58 },
0062     { STB0899_IOPVALUE5     , 0x00 },
0063     { STB0899_IOPVALUE4     , 0x33 },
0064     { STB0899_IOPVALUE3     , 0x6d },
0065     { STB0899_IOPVALUE2     , 0x90 },
0066     { STB0899_IOPVALUE1     , 0x60 },
0067     { STB0899_IOPVALUE0     , 0x00 },
0068     { STB0899_GPIO00CFG     , 0x82 },
0069     { STB0899_GPIO01CFG     , 0x82 },
0070     { STB0899_GPIO02CFG     , 0x82 },
0071     { STB0899_GPIO03CFG     , 0x82 },
0072     { STB0899_GPIO04CFG     , 0x82 },
0073     { STB0899_GPIO05CFG     , 0x82 },
0074     { STB0899_GPIO06CFG     , 0x82 },
0075     { STB0899_GPIO07CFG     , 0x82 },
0076     { STB0899_GPIO08CFG     , 0x82 },
0077     { STB0899_GPIO09CFG     , 0x82 },
0078     { STB0899_GPIO10CFG     , 0x82 },
0079     { STB0899_GPIO11CFG     , 0x82 },
0080     { STB0899_GPIO12CFG     , 0x82 },
0081     { STB0899_GPIO13CFG     , 0x82 },
0082     { STB0899_GPIO14CFG     , 0x82 },
0083     { STB0899_GPIO15CFG     , 0x82 },
0084     { STB0899_GPIO16CFG     , 0x82 },
0085     { STB0899_GPIO17CFG     , 0x82 },
0086     { STB0899_GPIO18CFG     , 0x82 },
0087     { STB0899_GPIO19CFG     , 0x82 },
0088     { STB0899_GPIO20CFG     , 0x82 },
0089     { STB0899_SDATCFG       , 0xb8 },
0090     { STB0899_SCLTCFG       , 0xba },
0091     { STB0899_AGCRFCFG      , 0x1c }, /* 0x11 */
0092     { STB0899_GPIO22        , 0x82 }, /* AGCBB2CFG */
0093     { STB0899_GPIO21        , 0x91 }, /* AGCBB1CFG */
0094     { STB0899_DIRCLKCFG     , 0x82 },
0095     { STB0899_CLKOUT27CFG       , 0x7e },
0096     { STB0899_STDBYCFG      , 0x82 },
0097     { STB0899_CS0CFG        , 0x82 },
0098     { STB0899_CS1CFG        , 0x82 },
0099     { STB0899_DISEQCOCFG        , 0x20 },
0100     { STB0899_GPIO32CFG     , 0x82 },
0101     { STB0899_GPIO33CFG     , 0x82 },
0102     { STB0899_GPIO34CFG     , 0x82 },
0103     { STB0899_GPIO35CFG     , 0x82 },
0104     { STB0899_GPIO36CFG     , 0x82 },
0105     { STB0899_GPIO37CFG     , 0x82 },
0106     { STB0899_GPIO38CFG     , 0x82 },
0107     { STB0899_GPIO39CFG     , 0x82 },
0108     { STB0899_NCOARSE       , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
0109     { STB0899_SYNTCTRL      , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
0110     { STB0899_FILTCTRL      , 0x00 },
0111     { STB0899_SYSCTRL       , 0x01 },
0112     { STB0899_STOPCLK1      , 0x20 },
0113     { STB0899_STOPCLK2      , 0x00 },
0114     { STB0899_INTBUFSTATUS      , 0x00 },
0115     { STB0899_INTBUFCTRL        , 0x0a },
0116     { 0xffff            , 0xff },
0117 };
0118 
0119 static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = {
0120     { STB0899_DEMOD         , 0x00 },
0121     { STB0899_RCOMPC        , 0xc9 },
0122     { STB0899_AGC1CN        , 0x01 },
0123     { STB0899_AGC1REF       , 0x10 },
0124     { STB0899_RTC           , 0x23 },
0125     { STB0899_TMGCFG        , 0x4e },
0126     { STB0899_AGC2REF       , 0x34 },
0127     { STB0899_TLSR          , 0x84 },
0128     { STB0899_CFD           , 0xf7 },
0129     { STB0899_ACLC          , 0x87 },
0130     { STB0899_BCLC          , 0x94 },
0131     { STB0899_EQON          , 0x41 },
0132     { STB0899_LDT           , 0xf1 },
0133     { STB0899_LDT2          , 0xe3 },
0134     { STB0899_EQUALREF      , 0xb4 },
0135     { STB0899_TMGRAMP       , 0x10 },
0136     { STB0899_TMGTHD        , 0x30 },
0137     { STB0899_IDCCOMP       , 0xfd },
0138     { STB0899_QDCCOMP       , 0xff },
0139     { STB0899_POWERI        , 0x0c },
0140     { STB0899_POWERQ        , 0x0f },
0141     { STB0899_RCOMP         , 0x6c },
0142     { STB0899_AGCIQIN       , 0x80 },
0143     { STB0899_AGC2I1        , 0x06 },
0144     { STB0899_AGC2I2        , 0x00 },
0145     { STB0899_TLIR          , 0x30 },
0146     { STB0899_RTF           , 0x7f },
0147     { STB0899_DSTATUS       , 0x00 },
0148     { STB0899_LDI           , 0xbc },
0149     { STB0899_CFRM          , 0xea },
0150     { STB0899_CFRL          , 0x31 },
0151     { STB0899_NIRM          , 0x2b },
0152     { STB0899_NIRL          , 0x80 },
0153     { STB0899_ISYMB         , 0x1d },
0154     { STB0899_QSYMB         , 0xa6 },
0155     { STB0899_SFRH          , 0x2f },
0156     { STB0899_SFRM          , 0x68 },
0157     { STB0899_SFRL          , 0x40 },
0158     { STB0899_SFRUPH        , 0x2f },
0159     { STB0899_SFRUPM        , 0x68 },
0160     { STB0899_SFRUPL        , 0x40 },
0161     { STB0899_EQUAI1        , 0x02 },
0162     { STB0899_EQUAQ1        , 0xff },
0163     { STB0899_EQUAI2        , 0x04 },
0164     { STB0899_EQUAQ2        , 0x05 },
0165     { STB0899_EQUAI3        , 0x02 },
0166     { STB0899_EQUAQ3        , 0xfd },
0167     { STB0899_EQUAI4        , 0x03 },
0168     { STB0899_EQUAQ4        , 0x07 },
0169     { STB0899_EQUAI5        , 0x08 },
0170     { STB0899_EQUAQ5        , 0xf5 },
0171     { STB0899_DSTATUS2      , 0x00 },
0172     { STB0899_VSTATUS       , 0x00 },
0173     { STB0899_VERROR        , 0x86 },
0174     { STB0899_IQSWAP        , 0x2a },
0175     { STB0899_ECNT1M        , 0x00 },
0176     { STB0899_ECNT1L        , 0x00 },
0177     { STB0899_ECNT2M        , 0x00 },
0178     { STB0899_ECNT2L        , 0x00 },
0179     { STB0899_ECNT3M        , 0x0a },
0180     { STB0899_ECNT3L        , 0xad },
0181     { STB0899_FECAUTO1      , 0x06 },
0182     { STB0899_FECM          , 0x01 },
0183     { STB0899_VTH12         , 0xb0 },
0184     { STB0899_VTH23         , 0x7a },
0185     { STB0899_VTH34         , 0x58 },
0186     { STB0899_VTH56         , 0x38 },
0187     { STB0899_VTH67         , 0x34 },
0188     { STB0899_VTH78         , 0x24 },
0189     { STB0899_PRVIT         , 0xff },
0190     { STB0899_VITSYNC       , 0x19 },
0191     { STB0899_RSULC         , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
0192     { STB0899_TSULC         , 0x42 },
0193     { STB0899_RSLLC         , 0x41 },
0194     { STB0899_TSLPL         , 0x12 },
0195     { STB0899_TSCFGH        , 0x0c },
0196     { STB0899_TSCFGM        , 0x00 },
0197     { STB0899_TSCFGL        , 0x00 },
0198     { STB0899_TSOUT         , 0x69 }, /* 0x0d for CAM */
0199     { STB0899_RSSYNCDEL     , 0x00 },
0200     { STB0899_TSINHDELH     , 0x02 },
0201     { STB0899_TSINHDELM     , 0x00 },
0202     { STB0899_TSINHDELL     , 0x00 },
0203     { STB0899_TSLLSTKM      , 0x1b },
0204     { STB0899_TSLLSTKL      , 0xb3 },
0205     { STB0899_TSULSTKM      , 0x00 },
0206     { STB0899_TSULSTKL      , 0x00 },
0207     { STB0899_PCKLENUL      , 0xbc },
0208     { STB0899_PCKLENLL      , 0xcc },
0209     { STB0899_RSPCKLEN      , 0xbd },
0210     { STB0899_TSSTATUS      , 0x90 },
0211     { STB0899_ERRCTRL1      , 0xb6 },
0212     { STB0899_ERRCTRL2      , 0x95 },
0213     { STB0899_ERRCTRL3      , 0x8d },
0214     { STB0899_DMONMSK1      , 0x27 },
0215     { STB0899_DMONMSK0      , 0x03 },
0216     { STB0899_DEMAPVIT      , 0x5c },
0217     { STB0899_PLPARM        , 0x19 },
0218     { STB0899_PDELCTRL      , 0x48 },
0219     { STB0899_PDELCTRL2     , 0x00 },
0220     { STB0899_BBHCTRL1      , 0x00 },
0221     { STB0899_BBHCTRL2      , 0x00 },
0222     { STB0899_HYSTTHRESH        , 0x77 },
0223     { STB0899_MATCSTM       , 0x00 },
0224     { STB0899_MATCSTL       , 0x00 },
0225     { STB0899_UPLCSTM       , 0x00 },
0226     { STB0899_UPLCSTL       , 0x00 },
0227     { STB0899_DFLCSTM       , 0x00 },
0228     { STB0899_DFLCSTL       , 0x00 },
0229     { STB0899_SYNCCST       , 0x00 },
0230     { STB0899_SYNCDCSTM     , 0x00 },
0231     { STB0899_SYNCDCSTL     , 0x00 },
0232     { STB0899_ISI_ENTRY     , 0x00 },
0233     { STB0899_ISI_BIT_EN        , 0x00 },
0234     { STB0899_MATSTRM       , 0xf0 },
0235     { STB0899_MATSTRL       , 0x02 },
0236     { STB0899_UPLSTRM       , 0x45 },
0237     { STB0899_UPLSTRL       , 0x60 },
0238     { STB0899_DFLSTRM       , 0xe3 },
0239     { STB0899_DFLSTRL       , 0x00 },
0240     { STB0899_SYNCSTR       , 0x47 },
0241     { STB0899_SYNCDSTRM     , 0x05 },
0242     { STB0899_SYNCDSTRL     , 0x18 },
0243     { STB0899_CFGPDELSTATUS1    , 0x19 },
0244     { STB0899_CFGPDELSTATUS2    , 0x2b },
0245     { STB0899_BBFERRORM     , 0x00 },
0246     { STB0899_BBFERRORL     , 0x01 },
0247     { STB0899_UPKTERRORM        , 0x00 },
0248     { STB0899_UPKTERRORL        , 0x00 },
0249     { 0xffff            , 0xff },
0250 };
0251 
0252 
0253 
0254 static struct stb0899_config az6027_stb0899_config = {
0255     .init_dev       = az6027_stb0899_s1_init_1,
0256     .init_s2_demod      = stb0899_s2_init_2,
0257     .init_s1_demod      = az6027_stb0899_s1_init_3,
0258     .init_s2_fec        = stb0899_s2_init_4,
0259     .init_tst       = stb0899_s1_init_5,
0260 
0261     .demod_address      = 0xd0, /* 0x68, 0xd0 >> 1 */
0262 
0263     .xtal_freq      = 27000000,
0264     .inversion      = IQ_SWAP_ON,
0265 
0266     .lo_clk         = 76500000,
0267     .hi_clk         = 99000000,
0268 
0269     .esno_ave       = STB0899_DVBS2_ESNO_AVE,
0270     .esno_quant     = STB0899_DVBS2_ESNO_QUANT,
0271     .avframes_coarse    = STB0899_DVBS2_AVFRAMES_COARSE,
0272     .avframes_fine      = STB0899_DVBS2_AVFRAMES_FINE,
0273     .miss_threshold     = STB0899_DVBS2_MISS_THRESHOLD,
0274     .uwp_threshold_acq  = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
0275     .uwp_threshold_track    = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
0276     .uwp_threshold_sof  = STB0899_DVBS2_UWP_THRESHOLD_SOF,
0277     .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
0278 
0279     .btr_nco_bits       = STB0899_DVBS2_BTR_NCO_BITS,
0280     .btr_gain_shift_offset  = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
0281     .crl_nco_bits       = STB0899_DVBS2_CRL_NCO_BITS,
0282     .ldpc_max_iter      = STB0899_DVBS2_LDPC_MAX_ITER,
0283 
0284     .tuner_get_frequency    = stb6100_get_frequency,
0285     .tuner_set_frequency    = stb6100_set_frequency,
0286     .tuner_set_bandwidth    = stb6100_set_bandwidth,
0287     .tuner_get_bandwidth    = stb6100_get_bandwidth,
0288     .tuner_set_rfsiggain    = NULL,
0289 };
0290 
0291 static struct stb6100_config az6027_stb6100_config = {
0292     .tuner_address  = 0xc0,
0293     .refclock   = 27000000,
0294 };
0295 
0296 
0297 /* check for mutex FIXME */
0298 static int az6027_usb_in_op(struct dvb_usb_device *d, u8 req,
0299                 u16 value, u16 index, u8 *b, int blen)
0300 {
0301     int ret = -1;
0302     if (mutex_lock_interruptible(&d->usb_mutex))
0303         return -EAGAIN;
0304 
0305     ret = usb_control_msg(d->udev,
0306                   usb_rcvctrlpipe(d->udev, 0),
0307                   req,
0308                   USB_TYPE_VENDOR | USB_DIR_IN,
0309                   value,
0310                   index,
0311                   b,
0312                   blen,
0313                   2000);
0314 
0315     if (ret < 0) {
0316         warn("usb in operation failed. (%d)", ret);
0317         ret = -EIO;
0318     } else
0319         ret = 0;
0320 
0321     deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
0322     debug_dump(b, blen, deb_xfer);
0323 
0324     mutex_unlock(&d->usb_mutex);
0325     return ret;
0326 }
0327 
0328 static int az6027_usb_out_op(struct dvb_usb_device *d,
0329                  u8 req,
0330                  u16 value,
0331                  u16 index,
0332                  u8 *b,
0333                  int blen)
0334 {
0335     int ret;
0336 
0337     deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
0338     debug_dump(b, blen, deb_xfer);
0339 
0340     if (mutex_lock_interruptible(&d->usb_mutex))
0341         return -EAGAIN;
0342 
0343     ret = usb_control_msg(d->udev,
0344                   usb_sndctrlpipe(d->udev, 0),
0345                   req,
0346                   USB_TYPE_VENDOR | USB_DIR_OUT,
0347                   value,
0348                   index,
0349                   b,
0350                   blen,
0351                   2000);
0352 
0353     if (ret != blen) {
0354         warn("usb out operation failed. (%d)", ret);
0355         mutex_unlock(&d->usb_mutex);
0356         return -EIO;
0357     } else{
0358         mutex_unlock(&d->usb_mutex);
0359         return 0;
0360     }
0361 }
0362 
0363 static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
0364 {
0365     int ret;
0366     u8 req;
0367     u16 value;
0368     u16 index;
0369     int blen;
0370 
0371     deb_info("%s %d", __func__, onoff);
0372 
0373     req = 0xBC;
0374     value = onoff;
0375     index = 0;
0376     blen = 0;
0377 
0378     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0379     if (ret != 0)
0380         warn("usb out operation failed. (%d)", ret);
0381 
0382     return ret;
0383 }
0384 
0385 /* keys for the enclosed remote control */
0386 static struct rc_map_table rc_map_az6027_table[] = {
0387     { 0x01, KEY_1 },
0388     { 0x02, KEY_2 },
0389 };
0390 
0391 /* remote control stuff (does not work with my box) */
0392 static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
0393 {
0394     *state = REMOTE_NO_KEY_PRESSED;
0395     return 0;
0396 }
0397 
0398 /*
0399 int az6027_power_ctrl(struct dvb_usb_device *d, int onoff)
0400 {
0401     u8 v = onoff;
0402     return az6027_usb_out_op(d,0xBC,v,3,NULL,1);
0403 }
0404 */
0405 
0406 static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
0407                     int slot,
0408                     int address)
0409 {
0410     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0411     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0412 
0413     int ret;
0414     u8 req;
0415     u16 value;
0416     u16 index;
0417     int blen;
0418     u8 *b;
0419 
0420     if (slot != 0)
0421         return -EINVAL;
0422 
0423     b = kmalloc(12, GFP_KERNEL);
0424     if (!b)
0425         return -ENOMEM;
0426 
0427     mutex_lock(&state->ca_mutex);
0428 
0429     req = 0xC1;
0430     value = address;
0431     index = 0;
0432     blen = 1;
0433 
0434     ret = az6027_usb_in_op(d, req, value, index, b, blen);
0435     if (ret < 0) {
0436         warn("usb in operation failed. (%d)", ret);
0437         ret = -EINVAL;
0438     } else {
0439         ret = b[0];
0440     }
0441 
0442     mutex_unlock(&state->ca_mutex);
0443     kfree(b);
0444     return ret;
0445 }
0446 
0447 static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
0448                      int slot,
0449                      int address,
0450                      u8 value)
0451 {
0452     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0453     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0454 
0455     int ret;
0456     u8 req;
0457     u16 value1;
0458     u16 index;
0459     int blen;
0460 
0461     deb_info("%s %d", __func__, slot);
0462     if (slot != 0)
0463         return -EINVAL;
0464 
0465     mutex_lock(&state->ca_mutex);
0466     req = 0xC2;
0467     value1 = address;
0468     index = value;
0469     blen = 0;
0470 
0471     ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
0472     if (ret != 0)
0473         warn("usb out operation failed. (%d)", ret);
0474 
0475     mutex_unlock(&state->ca_mutex);
0476     return ret;
0477 }
0478 
0479 static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca,
0480                       int slot,
0481                       u8 address)
0482 {
0483     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0484     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0485 
0486     int ret;
0487     u8 req;
0488     u16 value;
0489     u16 index;
0490     int blen;
0491     u8 *b;
0492 
0493     if (slot != 0)
0494         return -EINVAL;
0495 
0496     b = kmalloc(12, GFP_KERNEL);
0497     if (!b)
0498         return -ENOMEM;
0499 
0500     mutex_lock(&state->ca_mutex);
0501 
0502     req = 0xC3;
0503     value = address;
0504     index = 0;
0505     blen = 2;
0506 
0507     ret = az6027_usb_in_op(d, req, value, index, b, blen);
0508     if (ret < 0) {
0509         warn("usb in operation failed. (%d)", ret);
0510         ret = -EINVAL;
0511     } else {
0512         if (b[0] == 0)
0513             warn("Read CI IO error");
0514 
0515         ret = b[1];
0516         deb_info("read cam data = %x from 0x%x", b[1], value);
0517     }
0518 
0519     mutex_unlock(&state->ca_mutex);
0520     kfree(b);
0521     return ret;
0522 }
0523 
0524 static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca,
0525                        int slot,
0526                        u8 address,
0527                        u8 value)
0528 {
0529     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0530     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0531 
0532     int ret;
0533     u8 req;
0534     u16 value1;
0535     u16 index;
0536     int blen;
0537 
0538     if (slot != 0)
0539         return -EINVAL;
0540 
0541     mutex_lock(&state->ca_mutex);
0542     req = 0xC4;
0543     value1 = address;
0544     index = value;
0545     blen = 0;
0546 
0547     ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
0548     if (ret != 0) {
0549         warn("usb out operation failed. (%d)", ret);
0550         goto failed;
0551     }
0552 
0553 failed:
0554     mutex_unlock(&state->ca_mutex);
0555     return ret;
0556 }
0557 
0558 static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
0559 {
0560     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0561 
0562     int ret;
0563     u8 req;
0564     u16 value;
0565     u16 index;
0566     int blen;
0567     u8 *b;
0568 
0569     b = kmalloc(12, GFP_KERNEL);
0570     if (!b)
0571         return -ENOMEM;
0572 
0573     req = 0xC8;
0574     value = 0;
0575     index = 0;
0576     blen = 1;
0577 
0578     ret = az6027_usb_in_op(d, req, value, index, b, blen);
0579     if (ret < 0) {
0580         warn("usb in operation failed. (%d)", ret);
0581         ret = -EIO;
0582     } else{
0583         ret = b[0];
0584     }
0585     kfree(b);
0586     return ret;
0587 }
0588 
0589 static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
0590 {
0591     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0592     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0593 
0594     int ret, i;
0595     u8 req;
0596     u16 value;
0597     u16 index;
0598     int blen;
0599 
0600     mutex_lock(&state->ca_mutex);
0601 
0602     req = 0xC6;
0603     value = 1;
0604     index = 0;
0605     blen = 0;
0606 
0607     ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
0608     if (ret != 0) {
0609         warn("usb out operation failed. (%d)", ret);
0610         goto failed;
0611     }
0612 
0613     msleep(500);
0614     req = 0xC6;
0615     value = 0;
0616     index = 0;
0617     blen = 0;
0618 
0619     ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
0620     if (ret != 0) {
0621         warn("usb out operation failed. (%d)", ret);
0622         goto failed;
0623     }
0624 
0625     for (i = 0; i < 15; i++) {
0626         msleep(100);
0627 
0628         if (CI_CamReady(ca, slot)) {
0629             deb_info("CAM Ready");
0630             break;
0631         }
0632     }
0633     msleep(5000);
0634 
0635 failed:
0636     mutex_unlock(&state->ca_mutex);
0637     return ret;
0638 }
0639 
0640 static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
0641 {
0642     return 0;
0643 }
0644 
0645 static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
0646 {
0647     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0648     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0649 
0650     int ret;
0651     u8 req;
0652     u16 value;
0653     u16 index;
0654     int blen;
0655 
0656     deb_info("%s", __func__);
0657     mutex_lock(&state->ca_mutex);
0658     req = 0xC7;
0659     value = 1;
0660     index = 0;
0661     blen = 0;
0662 
0663     ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
0664     if (ret != 0) {
0665         warn("usb out operation failed. (%d)", ret);
0666         goto failed;
0667     }
0668 
0669 failed:
0670     mutex_unlock(&state->ca_mutex);
0671     return ret;
0672 }
0673 
0674 static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
0675 {
0676     struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
0677     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0678     int ret;
0679     u8 req;
0680     u16 value;
0681     u16 index;
0682     int blen;
0683     u8 *b;
0684 
0685     b = kmalloc(12, GFP_KERNEL);
0686     if (!b)
0687         return -ENOMEM;
0688     mutex_lock(&state->ca_mutex);
0689 
0690     req = 0xC5;
0691     value = 0;
0692     index = 0;
0693     blen = 1;
0694 
0695     ret = az6027_usb_in_op(d, req, value, index, b, blen);
0696     if (ret < 0) {
0697         warn("usb in operation failed. (%d)", ret);
0698         ret = -EIO;
0699     } else
0700         ret = 0;
0701 
0702     if (!ret && b[0] == 1) {
0703         ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
0704               DVB_CA_EN50221_POLL_CAM_READY;
0705     }
0706 
0707     mutex_unlock(&state->ca_mutex);
0708     kfree(b);
0709     return ret;
0710 }
0711 
0712 
0713 static void az6027_ci_uninit(struct dvb_usb_device *d)
0714 {
0715     struct az6027_device_state *state;
0716 
0717     deb_info("%s", __func__);
0718 
0719     if (NULL == d)
0720         return;
0721 
0722     state = (struct az6027_device_state *)d->priv;
0723     if (NULL == state)
0724         return;
0725 
0726     if (NULL == state->ca.data)
0727         return;
0728 
0729     dvb_ca_en50221_release(&state->ca);
0730 
0731     memset(&state->ca, 0, sizeof(state->ca));
0732 }
0733 
0734 
0735 static int az6027_ci_init(struct dvb_usb_adapter *a)
0736 {
0737     struct dvb_usb_device *d = a->dev;
0738     struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
0739     int ret;
0740 
0741     deb_info("%s", __func__);
0742 
0743     mutex_init(&state->ca_mutex);
0744 
0745     state->ca.owner         = THIS_MODULE;
0746     state->ca.read_attribute_mem    = az6027_ci_read_attribute_mem;
0747     state->ca.write_attribute_mem   = az6027_ci_write_attribute_mem;
0748     state->ca.read_cam_control  = az6027_ci_read_cam_control;
0749     state->ca.write_cam_control = az6027_ci_write_cam_control;
0750     state->ca.slot_reset        = az6027_ci_slot_reset;
0751     state->ca.slot_shutdown     = az6027_ci_slot_shutdown;
0752     state->ca.slot_ts_enable    = az6027_ci_slot_ts_enable;
0753     state->ca.poll_slot_status  = az6027_ci_poll_slot_status;
0754     state->ca.data          = d;
0755 
0756     ret = dvb_ca_en50221_init(&a->dvb_adap,
0757                   &state->ca,
0758                   0, /* flags */
0759                   1);/* n_slots */
0760     if (ret != 0) {
0761         err("Cannot initialize CI: Error %d.", ret);
0762         memset(&state->ca, 0, sizeof(state->ca));
0763         return ret;
0764     }
0765 
0766     deb_info("CI initialized.");
0767 
0768     return 0;
0769 }
0770 
0771 /*
0772 static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
0773 {
0774     az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6);
0775     return 0;
0776 }
0777 */
0778 
0779 static int az6027_set_voltage(struct dvb_frontend *fe,
0780                   enum fe_sec_voltage voltage)
0781 {
0782 
0783     u8 buf;
0784     struct dvb_usb_adapter *adap = fe->dvb->priv;
0785 
0786     struct i2c_msg i2c_msg = {
0787         .addr   = 0x99,
0788         .flags  = 0,
0789         .buf    = &buf,
0790         .len    = 1
0791     };
0792 
0793     /*
0794      * 2   --18v
0795      * 1   --13v
0796      * 0   --off
0797      */
0798     switch (voltage) {
0799     case SEC_VOLTAGE_13:
0800         buf = 1;
0801         i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
0802         break;
0803 
0804     case SEC_VOLTAGE_18:
0805         buf = 2;
0806         i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
0807         break;
0808 
0809     case SEC_VOLTAGE_OFF:
0810         buf = 0;
0811         i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
0812         break;
0813 
0814     default:
0815         return -EINVAL;
0816     }
0817     return 0;
0818 }
0819 
0820 
0821 static int az6027_frontend_poweron(struct dvb_usb_adapter *adap)
0822 {
0823     int ret;
0824     u8 req;
0825     u16 value;
0826     u16 index;
0827     int blen;
0828 
0829     req = 0xBC;
0830     value = 1; /* power on */
0831     index = 3;
0832     blen = 0;
0833 
0834     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0835     if (ret != 0)
0836         return -EIO;
0837 
0838     return 0;
0839 }
0840 static int az6027_frontend_reset(struct dvb_usb_adapter *adap)
0841 {
0842     int ret;
0843     u8 req;
0844     u16 value;
0845     u16 index;
0846     int blen;
0847 
0848     /* reset demodulator */
0849     req = 0xC0;
0850     value = 1; /* high */
0851     index = 3;
0852     blen = 0;
0853 
0854     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0855     if (ret != 0)
0856         return -EIO;
0857 
0858     req = 0xC0;
0859     value = 0; /* low */
0860     index = 3;
0861     blen = 0;
0862     msleep_interruptible(200);
0863 
0864     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0865     if (ret != 0)
0866         return -EIO;
0867 
0868     msleep_interruptible(200);
0869 
0870     req = 0xC0;
0871     value = 1; /*high */
0872     index = 3;
0873     blen = 0;
0874 
0875     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0876     if (ret != 0)
0877         return -EIO;
0878 
0879     msleep_interruptible(200);
0880     return 0;
0881 }
0882 
0883 static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff)
0884 {
0885     int ret;
0886     u8 req;
0887     u16 value;
0888     u16 index;
0889     int blen;
0890 
0891     /* TS passthrough */
0892     req = 0xC7;
0893     value = onoff;
0894     index = 0;
0895     blen = 0;
0896 
0897     ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
0898     if (ret != 0)
0899         return -EIO;
0900 
0901     return 0;
0902 }
0903 
0904 static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
0905 {
0906 
0907     az6027_frontend_poweron(adap);
0908     az6027_frontend_reset(adap);
0909 
0910     deb_info("adap = %p, dev = %p\n", adap, adap->dev);
0911     adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
0912 
0913     if (adap->fe_adap[0].fe) {
0914         deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
0915         if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
0916             deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
0917             adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
0918             az6027_ci_init(adap);
0919         } else {
0920             adap->fe_adap[0].fe = NULL;
0921         }
0922     } else
0923         warn("no front-end attached\n");
0924 
0925     az6027_frontend_tsbypass(adap, 0);
0926 
0927     return 0;
0928 }
0929 
0930 static struct dvb_usb_device_properties az6027_properties;
0931 
0932 static void az6027_usb_disconnect(struct usb_interface *intf)
0933 {
0934     struct dvb_usb_device *d = usb_get_intfdata(intf);
0935     az6027_ci_uninit(d);
0936     dvb_usb_device_exit(intf);
0937 }
0938 
0939 
0940 static int az6027_usb_probe(struct usb_interface *intf,
0941                 const struct usb_device_id *id)
0942 {
0943     return dvb_usb_device_init(intf,
0944                    &az6027_properties,
0945                    THIS_MODULE,
0946                    NULL,
0947                    adapter_nr);
0948 }
0949 
0950 /* I2C */
0951 static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
0952 {
0953     struct dvb_usb_device *d = i2c_get_adapdata(adap);
0954     int i = 0, j = 0, len = 0;
0955     u16 index;
0956     u16 value;
0957     int length;
0958     u8 req;
0959     u8 *data;
0960 
0961     data = kmalloc(256, GFP_KERNEL);
0962     if (!data)
0963         return -ENOMEM;
0964 
0965     if (mutex_lock_interruptible(&d->i2c_mutex) < 0) {
0966         kfree(data);
0967         return -EAGAIN;
0968     }
0969 
0970     if (num > 2)
0971         warn("more than 2 i2c messages at a time is not handled yet. TODO.");
0972 
0973     for (i = 0; i < num; i++) {
0974 
0975         if (msg[i].addr == 0x99) {
0976             req = 0xBE;
0977             index = 0;
0978             value = msg[i].buf[0] & 0x00ff;
0979             length = 1;
0980             az6027_usb_out_op(d, req, value, index, data, length);
0981         }
0982 
0983         if (msg[i].addr == 0xd0) {
0984             /* write/read request */
0985             if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
0986                 req = 0xB9;
0987                 index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
0988                 value = msg[i].addr + (msg[i].len << 8);
0989                 length = msg[i + 1].len + 6;
0990                 az6027_usb_in_op(d, req, value, index, data, length);
0991                 len = msg[i + 1].len;
0992                 for (j = 0; j < len; j++)
0993                     msg[i + 1].buf[j] = data[j + 5];
0994 
0995                 i++;
0996             } else {
0997 
0998                 /* demod 16bit addr */
0999                 req = 0xBD;
1000                 index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
1001                 value = msg[i].addr + (2 << 8);
1002                 length = msg[i].len - 2;
1003                 len = msg[i].len - 2;
1004                 for (j = 0; j < len; j++)
1005                     data[j] = msg[i].buf[j + 2];
1006                 az6027_usb_out_op(d, req, value, index, data, length);
1007             }
1008         }
1009 
1010         if (msg[i].addr == 0xc0) {
1011             if (msg[i].flags & I2C_M_RD) {
1012 
1013                 req = 0xB9;
1014                 index = 0x0;
1015                 value = msg[i].addr;
1016                 length = msg[i].len + 6;
1017                 az6027_usb_in_op(d, req, value, index, data, length);
1018                 len = msg[i].len;
1019                 for (j = 0; j < len; j++)
1020                     msg[i].buf[j] = data[j + 5];
1021 
1022             } else {
1023 
1024                 req = 0xBD;
1025                 index = msg[i].buf[0] & 0x00FF;
1026                 value = msg[i].addr + (1 << 8);
1027                 length = msg[i].len - 1;
1028                 len = msg[i].len - 1;
1029 
1030                 for (j = 0; j < len; j++)
1031                     data[j] = msg[i].buf[j + 1];
1032 
1033                 az6027_usb_out_op(d, req, value, index, data, length);
1034             }
1035         }
1036     }
1037     mutex_unlock(&d->i2c_mutex);
1038     kfree(data);
1039 
1040     return i;
1041 }
1042 
1043 
1044 static u32 az6027_i2c_func(struct i2c_adapter *adapter)
1045 {
1046     return I2C_FUNC_I2C;
1047 }
1048 
1049 static struct i2c_algorithm az6027_i2c_algo = {
1050     .master_xfer   = az6027_i2c_xfer,
1051     .functionality = az6027_i2c_func,
1052 };
1053 
1054 static int az6027_identify_state(struct usb_device *udev,
1055                  const struct dvb_usb_device_properties *props,
1056                  const struct dvb_usb_device_description **desc,
1057                  int *cold)
1058 {
1059     u8 *b;
1060     s16 ret;
1061 
1062     b = kmalloc(16, GFP_KERNEL);
1063     if (!b)
1064         return -ENOMEM;
1065 
1066     ret = usb_control_msg(udev,
1067                   usb_rcvctrlpipe(udev, 0),
1068                   0xb7,
1069                   USB_TYPE_VENDOR | USB_DIR_IN,
1070                   6,
1071                   0,
1072                   b,
1073                   6,
1074                   USB_CTRL_GET_TIMEOUT);
1075 
1076     *cold = ret <= 0;
1077     kfree(b);
1078     deb_info("cold: %d\n", *cold);
1079     return 0;
1080 }
1081 
1082 
1083 enum {
1084     AZUREWAVE_AZ6027,
1085     TERRATEC_DVBS2CI_V1,
1086     TERRATEC_DVBS2CI_V2,
1087     TECHNISAT_USB2_HDCI_V1,
1088     TECHNISAT_USB2_HDCI_V2,
1089     ELGATO_EYETV_SAT,
1090     ELGATO_EYETV_SAT_V2,
1091     ELGATO_EYETV_SAT_V3,
1092 };
1093 
1094 static struct usb_device_id az6027_usb_table[] = {
1095     DVB_USB_DEV(AZUREWAVE, AZUREWAVE_AZ6027),
1096     DVB_USB_DEV(TERRATEC, TERRATEC_DVBS2CI_V1),
1097     DVB_USB_DEV(TERRATEC, TERRATEC_DVBS2CI_V2),
1098     DVB_USB_DEV(TECHNISAT, TECHNISAT_USB2_HDCI_V1),
1099     DVB_USB_DEV(TECHNISAT, TECHNISAT_USB2_HDCI_V2),
1100     DVB_USB_DEV(ELGATO, ELGATO_EYETV_SAT),
1101     DVB_USB_DEV(ELGATO, ELGATO_EYETV_SAT_V2),
1102     DVB_USB_DEV(ELGATO, ELGATO_EYETV_SAT_V3),
1103     { }
1104 };
1105 
1106 MODULE_DEVICE_TABLE(usb, az6027_usb_table);
1107 
1108 static struct dvb_usb_device_properties az6027_properties = {
1109     .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1110     .usb_ctrl = CYPRESS_FX2,
1111     .firmware            = "dvb-usb-az6027-03.fw",
1112     .no_reconnect        = 1,
1113 
1114     .size_of_priv     = sizeof(struct az6027_device_state),
1115     .identify_state     = az6027_identify_state,
1116     .num_adapters = 1,
1117     .adapter = {
1118         {
1119         .num_frontends = 1,
1120         .fe = {{
1121             .streaming_ctrl   = az6027_streaming_ctrl,
1122             .frontend_attach  = az6027_frontend_attach,
1123 
1124             /* parameter for the MPEG2-data transfer */
1125             .stream = {
1126                 .type = USB_BULK,
1127                 .count = 10,
1128                 .endpoint = 0x02,
1129                 .u = {
1130                     .bulk = {
1131                         .buffersize = 4096,
1132                     }
1133                 }
1134             },
1135         }},
1136         }
1137     },
1138 /*
1139     .power_ctrl       = az6027_power_ctrl,
1140     .read_mac_address = az6027_read_mac_addr,
1141  */
1142     .rc.legacy = {
1143         .rc_map_table     = rc_map_az6027_table,
1144         .rc_map_size      = ARRAY_SIZE(rc_map_az6027_table),
1145         .rc_interval      = 400,
1146         .rc_query         = az6027_rc_query,
1147     },
1148 
1149     .i2c_algo         = &az6027_i2c_algo,
1150 
1151     .num_device_descs = 8,
1152     .devices = {
1153         {
1154             .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
1155             .cold_ids = { &az6027_usb_table[AZUREWAVE_AZ6027], NULL },
1156             .warm_ids = { NULL },
1157         }, {
1158             .name = "TERRATEC S7",
1159             .cold_ids = { &az6027_usb_table[TERRATEC_DVBS2CI_V1], NULL },
1160             .warm_ids = { NULL },
1161         }, {
1162             .name = "TERRATEC S7 MKII",
1163             .cold_ids = { &az6027_usb_table[TERRATEC_DVBS2CI_V2], NULL },
1164             .warm_ids = { NULL },
1165         }, {
1166             .name = "Technisat SkyStar USB 2 HD CI",
1167             .cold_ids = { &az6027_usb_table[TECHNISAT_USB2_HDCI_V1], NULL },
1168             .warm_ids = { NULL },
1169         }, {
1170             .name = "Technisat SkyStar USB 2 HD CI",
1171             .cold_ids = { &az6027_usb_table[TECHNISAT_USB2_HDCI_V2], NULL },
1172             .warm_ids = { NULL },
1173         }, {
1174             .name = "Elgato EyeTV Sat",
1175             .cold_ids = { &az6027_usb_table[ELGATO_EYETV_SAT], NULL },
1176             .warm_ids = { NULL },
1177         }, {
1178             .name = "Elgato EyeTV Sat",
1179             .cold_ids = { &az6027_usb_table[ELGATO_EYETV_SAT_V2], NULL },
1180             .warm_ids = { NULL },
1181         }, {
1182             .name = "Elgato EyeTV Sat",
1183             .cold_ids = { &az6027_usb_table[ELGATO_EYETV_SAT_V3], NULL },
1184             .warm_ids = { NULL },
1185         },
1186         { NULL },
1187     }
1188 };
1189 
1190 /* usb specific object needed to register this driver with the usb subsystem */
1191 static struct usb_driver az6027_usb_driver = {
1192     .name       = "dvb_usb_az6027",
1193     .probe      = az6027_usb_probe,
1194     .disconnect = az6027_usb_disconnect,
1195     .id_table   = az6027_usb_table,
1196 };
1197 
1198 module_usb_driver(az6027_usb_driver);
1199 
1200 MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>");
1201 MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)");
1202 MODULE_VERSION("1.0");
1203 MODULE_LICENSE("GPL");