linux/drivers/media/usb/dvb-usb/dtt200u-fe.c
<<
>>
Prefs
   1/* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/
   2 * Typhoon/ Yuan DVB-T USB2.0 receiver.
   3 *
   4 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
   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 "dtt200u.h"
  13
  14struct dtt200u_fe_state {
  15        struct dvb_usb_device *d;
  16
  17        fe_status_t stat;
  18
  19        struct dtv_frontend_properties fep;
  20        struct dvb_frontend frontend;
  21};
  22
  23static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
  24{
  25        struct dtt200u_fe_state *state = fe->demodulator_priv;
  26        u8 st = GET_TUNE_STATUS, b[3];
  27
  28        dvb_usb_generic_rw(state->d,&st,1,b,3,0);
  29
  30        switch (b[0]) {
  31                case 0x01:
  32                        *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
  33                                FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
  34                        break;
  35                case 0x00: /* pending */
  36                        *stat = FE_TIMEDOUT; /* during set_frontend */
  37                        break;
  38                default:
  39                case 0x02: /* failed */
  40                        *stat = 0;
  41                        break;
  42        }
  43        return 0;
  44}
  45
  46static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
  47{
  48        struct dtt200u_fe_state *state = fe->demodulator_priv;
  49        u8 bw = GET_VIT_ERR_CNT,b[3];
  50        dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
  51        *ber = (b[0] << 16) | (b[1] << 8) | b[2];
  52        return 0;
  53}
  54
  55static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
  56{
  57        struct dtt200u_fe_state *state = fe->demodulator_priv;
  58        u8 bw = GET_RS_UNCOR_BLK_CNT,b[2];
  59
  60        dvb_usb_generic_rw(state->d,&bw,1,b,2,0);
  61        *unc = (b[0] << 8) | b[1];
  62        return 0;
  63}
  64
  65static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
  66{
  67        struct dtt200u_fe_state *state = fe->demodulator_priv;
  68        u8 bw = GET_AGC, b;
  69        dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
  70        *strength = (b << 8) | b;
  71        return 0;
  72}
  73
  74static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
  75{
  76        struct dtt200u_fe_state *state = fe->demodulator_priv;
  77        u8 bw = GET_SNR,br;
  78        dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
  79        *snr = ~((br << 8) | br);
  80        return 0;
  81}
  82
  83static int dtt200u_fe_init(struct dvb_frontend* fe)
  84{
  85        struct dtt200u_fe_state *state = fe->demodulator_priv;
  86        u8 b = SET_INIT;
  87        return dvb_usb_generic_write(state->d,&b,1);
  88}
  89
  90static int dtt200u_fe_sleep(struct dvb_frontend* fe)
  91{
  92        return dtt200u_fe_init(fe);
  93}
  94
  95static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
  96{
  97        tune->min_delay_ms = 1500;
  98        tune->step_size = 0;
  99        tune->max_drift = 0;
 100        return 0;
 101}
 102
 103static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
 104{
 105        struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
 106        struct dtt200u_fe_state *state = fe->demodulator_priv;
 107        int i;
 108        fe_status_t st;
 109        u16 freq = fep->frequency / 250000;
 110        u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
 111
 112        switch (fep->bandwidth_hz) {
 113        case 8000000:
 114                bwbuf[1] = 8;
 115                break;
 116        case 7000000:
 117                bwbuf[1] = 7;
 118                break;
 119        case 6000000:
 120                bwbuf[1] = 6;
 121                break;
 122        default:
 123                return -EINVAL;
 124        }
 125
 126        dvb_usb_generic_write(state->d,bwbuf,2);
 127
 128        freqbuf[1] = freq & 0xff;
 129        freqbuf[2] = (freq >> 8) & 0xff;
 130        dvb_usb_generic_write(state->d,freqbuf,3);
 131
 132        for (i = 0; i < 30; i++) {
 133                msleep(20);
 134                dtt200u_fe_read_status(fe, &st);
 135                if (st & FE_TIMEDOUT)
 136                        continue;
 137        }
 138
 139        return 0;
 140}
 141
 142static int dtt200u_fe_get_frontend(struct dvb_frontend* fe)
 143{
 144        struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
 145        struct dtt200u_fe_state *state = fe->demodulator_priv;
 146        memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
 147        return 0;
 148}
 149
 150static void dtt200u_fe_release(struct dvb_frontend* fe)
 151{
 152        struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
 153        kfree(state);
 154}
 155
 156static struct dvb_frontend_ops dtt200u_fe_ops;
 157
 158struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
 159{
 160        struct dtt200u_fe_state* state = NULL;
 161
 162        /* allocate memory for the internal state */
 163        state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
 164        if (state == NULL)
 165                goto error;
 166
 167        deb_info("attaching frontend dtt200u\n");
 168
 169        state->d = d;
 170
 171        memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 172        state->frontend.demodulator_priv = state;
 173
 174        return &state->frontend;
 175error:
 176        return NULL;
 177}
 178
 179static struct dvb_frontend_ops dtt200u_fe_ops = {
 180        .delsys = { SYS_DVBT },
 181        .info = {
 182                .name                   = "WideView USB DVB-T",
 183                .frequency_min          = 44250000,
 184                .frequency_max          = 867250000,
 185                .frequency_stepsize     = 250000,
 186                .caps = FE_CAN_INVERSION_AUTO |
 187                                FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 188                                FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 189                                FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
 190                                FE_CAN_TRANSMISSION_MODE_AUTO |
 191                                FE_CAN_GUARD_INTERVAL_AUTO |
 192                                FE_CAN_RECOVER |
 193                                FE_CAN_HIERARCHY_AUTO,
 194        },
 195
 196        .release = dtt200u_fe_release,
 197
 198        .init = dtt200u_fe_init,
 199        .sleep = dtt200u_fe_sleep,
 200
 201        .set_frontend = dtt200u_fe_set_frontend,
 202        .get_frontend = dtt200u_fe_get_frontend,
 203        .get_tune_settings = dtt200u_fe_get_tune_settings,
 204
 205        .read_status = dtt200u_fe_read_status,
 206        .read_ber = dtt200u_fe_read_ber,
 207        .read_signal_strength = dtt200u_fe_read_signal_strength,
 208        .read_snr = dtt200u_fe_read_snr,
 209        .read_ucblocks = dtt200u_fe_read_unc_blocks,
 210};
 211