linux/drivers/media/dvb/dvb-usb/vp702x-fe.c
<<
>>
Prefs
   1/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
   2 * DVB-S receiver.
   3 *
   4 * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
   5 *                    Metzler Brothers Systementwicklung GbR
   6 *
   7 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
   8 *
   9 * Thanks to Twinhan who kindly provided hardware and information.
  10 *
  11 * This file can be removed soon, after the DST-driver is rewritten to provice
  12 * the frontend-controlling separately.
  13 *
  14 *      This program is free software; you can redistribute it and/or modify it
  15 *      under the terms of the GNU General Public License as published by the Free
  16 *      Software Foundation, version 2.
  17 *
  18 * see Documentation/dvb/README.dvb-usb for more information
  19 *
  20 */
  21#include "vp702x.h"
  22
  23struct vp702x_fe_state {
  24        struct dvb_frontend fe;
  25        struct dvb_usb_device *d;
  26
  27        struct dvb_frontend_ops ops;
  28
  29        fe_sec_voltage_t voltage;
  30        fe_sec_tone_mode_t tone_mode;
  31
  32        u8 lnb_buf[8];
  33
  34        u8 lock;
  35        u8 sig;
  36        u8 snr;
  37
  38        unsigned long next_status_check;
  39        unsigned long status_check_interval;
  40};
  41
  42static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
  43{
  44        u8 buf[10];
  45        if (time_after(jiffies,st->next_status_check)) {
  46                vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
  47
  48                st->lock = buf[4];
  49                vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
  50                vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
  51
  52                st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
  53        }
  54        return 0;
  55}
  56
  57static u8 vp702x_chksum(u8 *buf,int f, int count)
  58{
  59        u8 s = 0;
  60        int i;
  61        for (i = f; i < f+count; i++)
  62                s += buf[i];
  63        return ~s+1;
  64}
  65
  66static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
  67{
  68        struct vp702x_fe_state *st = fe->demodulator_priv;
  69        vp702x_fe_refresh_state(st);
  70        deb_fe("%s\n",__func__);
  71
  72        if (st->lock == 0)
  73                *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
  74        else
  75                *status = 0;
  76
  77        if (*status & FE_HAS_LOCK)
  78                st->status_check_interval = 1000;
  79        else
  80                st->status_check_interval = 250;
  81        return 0;
  82}
  83
  84/* not supported by this Frontend */
  85static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
  86{
  87        struct vp702x_fe_state *st = fe->demodulator_priv;
  88        vp702x_fe_refresh_state(st);
  89        *ber = 0;
  90        return 0;
  91}
  92
  93/* not supported by this Frontend */
  94static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
  95{
  96        struct vp702x_fe_state *st = fe->demodulator_priv;
  97        vp702x_fe_refresh_state(st);
  98        *unc = 0;
  99        return 0;
 100}
 101
 102static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
 103{
 104        struct vp702x_fe_state *st = fe->demodulator_priv;
 105        vp702x_fe_refresh_state(st);
 106
 107        *strength = (st->sig << 8) | st->sig;
 108        return 0;
 109}
 110
 111static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
 112{
 113        u8 _snr;
 114        struct vp702x_fe_state *st = fe->demodulator_priv;
 115        vp702x_fe_refresh_state(st);
 116
 117        _snr = (st->snr & 0x1f) * 0xff / 0x1f;
 118        *snr = (_snr << 8) | _snr;
 119        return 0;
 120}
 121
 122static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 123{
 124        deb_fe("%s\n",__func__);
 125        tune->min_delay_ms = 2000;
 126        return 0;
 127}
 128
 129static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
 130                                  struct dvb_frontend_parameters *fep)
 131{
 132        struct vp702x_fe_state *st = fe->demodulator_priv;
 133        u32 freq = fep->frequency/1000;
 134        /*CalFrequency*/
 135/*      u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
 136        u64 sr;
 137        u8 cmd[8] = { 0 },ibuf[10];
 138
 139        cmd[0] = (freq >> 8) & 0x7f;
 140        cmd[1] =  freq       & 0xff;
 141        cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
 142
 143        sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
 144        do_div(sr,88000);
 145        cmd[3] = (sr >> 12) & 0xff;
 146        cmd[4] = (sr >> 4)  & 0xff;
 147        cmd[5] = (sr << 4)  & 0xf0;
 148
 149        deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
 150                        fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
 151                        (unsigned long) sr, (unsigned long) sr);
 152
 153/*      if (fep->inversion == INVERSION_ON)
 154                cmd[6] |= 0x80; */
 155
 156        if (st->voltage == SEC_VOLTAGE_18)
 157                cmd[6] |= 0x40;
 158
 159/*      if (fep->u.qpsk.symbol_rate > 8000000)
 160                cmd[6] |= 0x20;
 161
 162        if (fep->frequency < 1531000)
 163                cmd[6] |= 0x04;
 164
 165        if (st->tone_mode == SEC_TONE_ON)
 166                cmd[6] |= 0x01;*/
 167
 168        cmd[7] = vp702x_chksum(cmd,0,7);
 169
 170        st->status_check_interval = 250;
 171        st->next_status_check = jiffies;
 172
 173        vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
 174
 175        if (ibuf[2] == 0 && ibuf[3] == 0)
 176                deb_fe("tuning failed.\n");
 177        else
 178                deb_fe("tuning succeeded.\n");
 179
 180        return 0;
 181}
 182
 183static int vp702x_fe_init(struct dvb_frontend *fe)
 184{
 185        struct vp702x_fe_state *st = fe->demodulator_priv;
 186        deb_fe("%s\n",__func__);
 187        vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
 188        return 0;
 189}
 190
 191static int vp702x_fe_sleep(struct dvb_frontend *fe)
 192{
 193        deb_fe("%s\n",__func__);
 194        return 0;
 195}
 196
 197static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
 198                                  struct dvb_frontend_parameters *fep)
 199{
 200        deb_fe("%s\n",__func__);
 201        return 0;
 202}
 203
 204static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 205                                    struct dvb_diseqc_master_cmd *m)
 206{
 207        struct vp702x_fe_state *st = fe->demodulator_priv;
 208        u8 cmd[8],ibuf[10];
 209        memset(cmd,0,8);
 210
 211        deb_fe("%s\n",__func__);
 212
 213        if (m->msg_len > 4)
 214                return -EINVAL;
 215
 216        cmd[1] = SET_DISEQC_CMD;
 217        cmd[2] = m->msg_len;
 218        memcpy(&cmd[3], m->msg, m->msg_len);
 219        cmd[7] = vp702x_chksum(cmd,0,7);
 220
 221        vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
 222
 223        if (ibuf[2] == 0 && ibuf[3] == 0)
 224                deb_fe("diseqc cmd failed.\n");
 225        else
 226                deb_fe("diseqc cmd succeeded.\n");
 227
 228        return 0;
 229}
 230
 231static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 232{
 233        deb_fe("%s\n",__func__);
 234        return 0;
 235}
 236
 237static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 238{
 239        struct vp702x_fe_state *st = fe->demodulator_priv;
 240        u8 ibuf[10];
 241        deb_fe("%s\n",__func__);
 242
 243        st->tone_mode = tone;
 244
 245        if (tone == SEC_TONE_ON)
 246                st->lnb_buf[2] = 0x02;
 247        else
 248                st->lnb_buf[2] = 0x00;
 249
 250        st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
 251
 252        vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
 253        if (ibuf[2] == 0 && ibuf[3] == 0)
 254                deb_fe("set_tone cmd failed.\n");
 255        else
 256                deb_fe("set_tone cmd succeeded.\n");
 257
 258        return 0;
 259}
 260
 261static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
 262                voltage)
 263{
 264        struct vp702x_fe_state *st = fe->demodulator_priv;
 265        u8 ibuf[10];
 266        deb_fe("%s\n",__func__);
 267
 268        st->voltage = voltage;
 269
 270        if (voltage != SEC_VOLTAGE_OFF)
 271                st->lnb_buf[4] = 0x01;
 272        else
 273                st->lnb_buf[4] = 0x00;
 274
 275        st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
 276
 277        vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
 278        if (ibuf[2] == 0 && ibuf[3] == 0)
 279                deb_fe("set_voltage cmd failed.\n");
 280        else
 281                deb_fe("set_voltage cmd succeeded.\n");
 282
 283        return 0;
 284}
 285
 286static void vp702x_fe_release(struct dvb_frontend* fe)
 287{
 288        struct vp702x_fe_state *st = fe->demodulator_priv;
 289        kfree(st);
 290}
 291
 292static struct dvb_frontend_ops vp702x_fe_ops;
 293
 294struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
 295{
 296        struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
 297        if (s == NULL)
 298                goto error;
 299
 300        s->d = d;
 301
 302        memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
 303        s->fe.demodulator_priv = s;
 304
 305        s->lnb_buf[1] = SET_LNB_POWER;
 306        s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
 307
 308        return &s->fe;
 309error:
 310        return NULL;
 311}
 312
 313
 314static struct dvb_frontend_ops vp702x_fe_ops = {
 315        .info = {
 316                .name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
 317                .type           = FE_QPSK,
 318                .frequency_min       = 950000,
 319                .frequency_max       = 2150000,
 320                .frequency_stepsize  = 1000,   /* kHz for QPSK frontends */
 321                .frequency_tolerance = 0,
 322                .symbol_rate_min     = 1000000,
 323                .symbol_rate_max     = 45000000,
 324                .symbol_rate_tolerance = 500,  /* ppm */
 325                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 326                FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
 327                FE_CAN_QPSK |
 328                FE_CAN_FEC_AUTO
 329        },
 330        .release = vp702x_fe_release,
 331
 332        .init  = vp702x_fe_init,
 333        .sleep = vp702x_fe_sleep,
 334
 335        .set_frontend = vp702x_fe_set_frontend,
 336        .get_frontend = vp702x_fe_get_frontend,
 337        .get_tune_settings = vp702x_fe_get_tune_settings,
 338
 339        .read_status = vp702x_fe_read_status,
 340        .read_ber = vp702x_fe_read_ber,
 341        .read_signal_strength = vp702x_fe_read_signal_strength,
 342        .read_snr = vp702x_fe_read_snr,
 343        .read_ucblocks = vp702x_fe_read_unc_blocks,
 344
 345        .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
 346        .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
 347        .set_tone = vp702x_fe_set_tone,
 348        .set_voltage = vp702x_fe_set_voltage,
 349};
 350