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