linux/drivers/media/usb/ttusb-dec/ttusbdecfe.c
<<
>>
Prefs
   1/*
   2 * TTUSB DEC Frontend Driver
   3 *
   4 * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 */
  17
  18#include <media/dvb_frontend.h>
  19#include "ttusbdecfe.h"
  20
  21
  22#define LOF_HI                  10600000
  23#define LOF_LO                  9750000
  24
  25struct ttusbdecfe_state {
  26
  27        /* configuration settings */
  28        const struct ttusbdecfe_config* config;
  29
  30        struct dvb_frontend frontend;
  31
  32        u8 hi_band;
  33        u8 voltage;
  34};
  35
  36
  37static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
  38                                       enum fe_status *status)
  39{
  40        *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
  41                FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
  42        return 0;
  43}
  44
  45
  46static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
  47                                       enum fe_status *status)
  48{
  49        struct ttusbdecfe_state* state = fe->demodulator_priv;
  50        u8 b[] = { 0x00, 0x00, 0x00, 0x00,
  51                   0x00, 0x00, 0x00, 0x00 };
  52        u8 result[4];
  53        int len, ret;
  54
  55        *status=0;
  56
  57        ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
  58        if(ret)
  59                return ret;
  60
  61        if(len != 4) {
  62                printk(KERN_ERR "%s: unexpected reply\n", __func__);
  63                return -EIO;
  64        }
  65
  66        switch(result[3]) {
  67                case 1:  /* not tuned yet */
  68                case 2:  /* no signal/no lock*/
  69                        break;
  70                case 3:  /* signal found and locked*/
  71                        *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
  72                        FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
  73                        break;
  74                case 4:
  75                        *status = FE_TIMEDOUT;
  76                        break;
  77                default:
  78                        pr_info("%s: returned unknown value: %d\n",
  79                                __func__, result[3]);
  80                        return -EIO;
  81        }
  82
  83        return 0;
  84}
  85
  86static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
  87{
  88        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
  89        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
  90        u8 b[] = { 0x00, 0x00, 0x00, 0x03,
  91                   0x00, 0x00, 0x00, 0x00,
  92                   0x00, 0x00, 0x00, 0x01,
  93                   0x00, 0x00, 0x00, 0xff,
  94                   0x00, 0x00, 0x00, 0xff };
  95
  96        __be32 freq = htonl(p->frequency / 1000);
  97        memcpy(&b[4], &freq, sizeof (u32));
  98        state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
  99
 100        return 0;
 101}
 102
 103static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
 104                                        struct dvb_frontend_tune_settings* fesettings)
 105{
 106                fesettings->min_delay_ms = 1500;
 107                /* Drift compensation makes no sense for DVB-T */
 108                fesettings->step_size = 0;
 109                fesettings->max_drift = 0;
 110                return 0;
 111}
 112
 113static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
 114{
 115        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 116        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 117
 118        u8 b[] = { 0x00, 0x00, 0x00, 0x01,
 119                   0x00, 0x00, 0x00, 0x00,
 120                   0x00, 0x00, 0x00, 0x01,
 121                   0x00, 0x00, 0x00, 0x00,
 122                   0x00, 0x00, 0x00, 0x00,
 123                   0x00, 0x00, 0x00, 0x00,
 124                   0x00, 0x00, 0x00, 0x00,
 125                   0x00, 0x00, 0x00, 0x00,
 126                   0x00, 0x00, 0x00, 0x00,
 127                   0x00, 0x00, 0x00, 0x00 };
 128        __be32 freq;
 129        __be32 sym_rate;
 130        __be32 band;
 131        __be32 lnb_voltage;
 132
 133        freq = htonl(p->frequency +
 134               (state->hi_band ? LOF_HI : LOF_LO));
 135        memcpy(&b[4], &freq, sizeof(u32));
 136        sym_rate = htonl(p->symbol_rate);
 137        memcpy(&b[12], &sym_rate, sizeof(u32));
 138        band = htonl(state->hi_band ? LOF_HI : LOF_LO);
 139        memcpy(&b[24], &band, sizeof(u32));
 140        lnb_voltage = htonl(state->voltage);
 141        memcpy(&b[28], &lnb_voltage, sizeof(u32));
 142
 143        state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
 144
 145        return 0;
 146}
 147
 148static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 149{
 150        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 151        u8 b[] = { 0x00, 0xff, 0x00, 0x00,
 152                   0x00, 0x00, 0x00, 0x00,
 153                   0x00, 0x00 };
 154
 155        if (cmd->msg_len > sizeof(b) - 4)
 156                return -EINVAL;
 157
 158        memcpy(&b[4], cmd->msg, cmd->msg_len);
 159
 160        state->config->send_command(fe, 0x72,
 161                                    sizeof(b) - (6 - cmd->msg_len), b,
 162                                    NULL, NULL);
 163
 164        return 0;
 165}
 166
 167
 168static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend *fe,
 169                                    enum fe_sec_tone_mode tone)
 170{
 171        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 172
 173        state->hi_band = (SEC_TONE_ON == tone);
 174
 175        return 0;
 176}
 177
 178
 179static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend *fe,
 180                                       enum fe_sec_voltage voltage)
 181{
 182        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 183
 184        switch (voltage) {
 185        case SEC_VOLTAGE_13:
 186                state->voltage = 13;
 187                break;
 188        case SEC_VOLTAGE_18:
 189                state->voltage = 18;
 190                break;
 191        default:
 192                return -EINVAL;
 193        }
 194
 195        return 0;
 196}
 197
 198static void ttusbdecfe_release(struct dvb_frontend* fe)
 199{
 200        struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
 201        kfree(state);
 202}
 203
 204static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
 205
 206struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
 207{
 208        struct ttusbdecfe_state* state = NULL;
 209
 210        /* allocate memory for the internal state */
 211        state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
 212        if (state == NULL)
 213                return NULL;
 214
 215        /* setup the state */
 216        state->config = config;
 217
 218        /* create dvb_frontend */
 219        memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
 220        state->frontend.demodulator_priv = state;
 221        return &state->frontend;
 222}
 223
 224static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
 225
 226struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
 227{
 228        struct ttusbdecfe_state* state = NULL;
 229
 230        /* allocate memory for the internal state */
 231        state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
 232        if (state == NULL)
 233                return NULL;
 234
 235        /* setup the state */
 236        state->config = config;
 237        state->voltage = 0;
 238        state->hi_band = 0;
 239
 240        /* create dvb_frontend */
 241        memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
 242        state->frontend.demodulator_priv = state;
 243        return &state->frontend;
 244}
 245
 246static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
 247        .delsys = { SYS_DVBT },
 248        .info = {
 249                .name                   = "TechnoTrend/Hauppauge DEC2000-t Frontend",
 250                .frequency_min          = 51000000,
 251                .frequency_max          = 858000000,
 252                .frequency_stepsize     = 62500,
 253                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 254                        FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 255                        FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
 256                        FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
 257                        FE_CAN_HIERARCHY_AUTO,
 258        },
 259
 260        .release = ttusbdecfe_release,
 261
 262        .set_frontend = ttusbdecfe_dvbt_set_frontend,
 263
 264        .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
 265
 266        .read_status = ttusbdecfe_dvbt_read_status,
 267};
 268
 269static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
 270        .delsys = { SYS_DVBS },
 271        .info = {
 272                .name                   = "TechnoTrend/Hauppauge DEC3000-s Frontend",
 273                .frequency_min          = 950000,
 274                .frequency_max          = 2150000,
 275                .frequency_stepsize     = 125,
 276                .symbol_rate_min        = 1000000,  /* guessed */
 277                .symbol_rate_max        = 45000000, /* guessed */
 278                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 279                        FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 280                        FE_CAN_QPSK
 281        },
 282
 283        .release = ttusbdecfe_release,
 284
 285        .set_frontend = ttusbdecfe_dvbs_set_frontend,
 286
 287        .read_status = ttusbdecfe_dvbs_read_status,
 288
 289        .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
 290        .set_voltage = ttusbdecfe_dvbs_set_voltage,
 291        .set_tone = ttusbdecfe_dvbs_set_tone,
 292};
 293
 294MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
 295MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
 296MODULE_LICENSE("GPL");
 297
 298EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
 299EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
 300