root/drivers/media/usb/dvb-usb/cinergyT2-fe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. compute_tps
  2. cinergyt2_fe_read_status
  3. cinergyt2_fe_read_ber
  4. cinergyt2_fe_read_unc_blocks
  5. cinergyt2_fe_read_signal_strength
  6. cinergyt2_fe_read_snr
  7. cinergyt2_fe_init
  8. cinergyt2_fe_sleep
  9. cinergyt2_fe_get_tune_settings
  10. cinergyt2_fe_set_frontend
  11. cinergyt2_fe_release
  12. cinergyt2_fe_attach

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
   4  *
   5  * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
   6  *
   7  * Based on the dvb-usb-framework code and the
   8  * original Terratec Cinergy T2 driver by:
   9  *
  10  * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
  11  *                  Holger Waechtler <holger@qanu.de>
  12  *
  13  *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
  14  */
  15 
  16 #include "cinergyT2.h"
  17 
  18 
  19 /*
  20  *  convert linux-dvb frontend parameter set into TPS.
  21  *  See ETSI ETS-300744, section 4.6.2, table 9 for details.
  22  *
  23  *  This function is probably reusable and may better get placed in a support
  24  *  library.
  25  *
  26  *  We replace erroneous fields by default TPS fields (the ones with value 0).
  27  */
  28 
  29 static uint16_t compute_tps(struct dtv_frontend_properties *op)
  30 {
  31         uint16_t tps = 0;
  32 
  33         switch (op->code_rate_HP) {
  34         case FEC_2_3:
  35                 tps |= (1 << 7);
  36                 break;
  37         case FEC_3_4:
  38                 tps |= (2 << 7);
  39                 break;
  40         case FEC_5_6:
  41                 tps |= (3 << 7);
  42                 break;
  43         case FEC_7_8:
  44                 tps |= (4 << 7);
  45                 break;
  46         case FEC_1_2:
  47         case FEC_AUTO:
  48         default:
  49                 /* tps |= (0 << 7) */;
  50         }
  51 
  52         switch (op->code_rate_LP) {
  53         case FEC_2_3:
  54                 tps |= (1 << 4);
  55                 break;
  56         case FEC_3_4:
  57                 tps |= (2 << 4);
  58                 break;
  59         case FEC_5_6:
  60                 tps |= (3 << 4);
  61                 break;
  62         case FEC_7_8:
  63                 tps |= (4 << 4);
  64                 break;
  65         case FEC_1_2:
  66         case FEC_AUTO:
  67         default:
  68                 /* tps |= (0 << 4) */;
  69         }
  70 
  71         switch (op->modulation) {
  72         case QAM_16:
  73                 tps |= (1 << 13);
  74                 break;
  75         case QAM_64:
  76                 tps |= (2 << 13);
  77                 break;
  78         case QPSK:
  79         default:
  80                 /* tps |= (0 << 13) */;
  81         }
  82 
  83         switch (op->transmission_mode) {
  84         case TRANSMISSION_MODE_8K:
  85                 tps |= (1 << 0);
  86                 break;
  87         case TRANSMISSION_MODE_2K:
  88         default:
  89                 /* tps |= (0 << 0) */;
  90         }
  91 
  92         switch (op->guard_interval) {
  93         case GUARD_INTERVAL_1_16:
  94                 tps |= (1 << 2);
  95                 break;
  96         case GUARD_INTERVAL_1_8:
  97                 tps |= (2 << 2);
  98                 break;
  99         case GUARD_INTERVAL_1_4:
 100                 tps |= (3 << 2);
 101                 break;
 102         case GUARD_INTERVAL_1_32:
 103         default:
 104                 /* tps |= (0 << 2) */;
 105         }
 106 
 107         switch (op->hierarchy) {
 108         case HIERARCHY_1:
 109                 tps |= (1 << 10);
 110                 break;
 111         case HIERARCHY_2:
 112                 tps |= (2 << 10);
 113                 break;
 114         case HIERARCHY_4:
 115                 tps |= (3 << 10);
 116                 break;
 117         case HIERARCHY_NONE:
 118         default:
 119                 /* tps |= (0 << 10) */;
 120         }
 121 
 122         return tps;
 123 }
 124 
 125 struct cinergyt2_fe_state {
 126         struct dvb_frontend fe;
 127         struct dvb_usb_device *d;
 128 
 129         unsigned char data[64];
 130         struct mutex data_mutex;
 131 
 132         struct dvbt_get_status_msg status;
 133 };
 134 
 135 static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
 136                                     enum fe_status *status)
 137 {
 138         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 139         int ret;
 140 
 141         mutex_lock(&state->data_mutex);
 142         state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
 143 
 144         ret = dvb_usb_generic_rw(state->d, state->data, 1,
 145                                  state->data, sizeof(state->status), 0);
 146         if (!ret)
 147                 memcpy(&state->status, state->data, sizeof(state->status));
 148         mutex_unlock(&state->data_mutex);
 149 
 150         if (ret < 0)
 151                 return ret;
 152 
 153         *status = 0;
 154 
 155         if (0xffff - le16_to_cpu(state->status.gain) > 30)
 156                 *status |= FE_HAS_SIGNAL;
 157         if (state->status.lock_bits & (1 << 6))
 158                 *status |= FE_HAS_LOCK;
 159         if (state->status.lock_bits & (1 << 5))
 160                 *status |= FE_HAS_SYNC;
 161         if (state->status.lock_bits & (1 << 4))
 162                 *status |= FE_HAS_CARRIER;
 163         if (state->status.lock_bits & (1 << 1))
 164                 *status |= FE_HAS_VITERBI;
 165 
 166         if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
 167                         (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
 168                 *status &= ~FE_HAS_LOCK;
 169 
 170         return 0;
 171 }
 172 
 173 static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
 174 {
 175         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 176 
 177         *ber = le32_to_cpu(state->status.viterbi_error_rate);
 178         return 0;
 179 }
 180 
 181 static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
 182 {
 183         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 184 
 185         *unc = le32_to_cpu(state->status.uncorrected_block_count);
 186         return 0;
 187 }
 188 
 189 static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
 190                                                 u16 *strength)
 191 {
 192         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 193 
 194         *strength = (0xffff - le16_to_cpu(state->status.gain));
 195         return 0;
 196 }
 197 
 198 static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
 199 {
 200         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 201 
 202         *snr = (state->status.snr << 8) | state->status.snr;
 203         return 0;
 204 }
 205 
 206 static int cinergyt2_fe_init(struct dvb_frontend *fe)
 207 {
 208         return 0;
 209 }
 210 
 211 static int cinergyt2_fe_sleep(struct dvb_frontend *fe)
 212 {
 213         deb_info("cinergyt2_fe_sleep() Called\n");
 214         return 0;
 215 }
 216 
 217 static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
 218                                 struct dvb_frontend_tune_settings *tune)
 219 {
 220         tune->min_delay_ms = 800;
 221         return 0;
 222 }
 223 
 224 static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
 225 {
 226         struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
 227         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 228         struct dvbt_set_parameters_msg *param;
 229         int err;
 230 
 231         mutex_lock(&state->data_mutex);
 232 
 233         param = (void *)state->data;
 234         param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
 235         param->tps = cpu_to_le16(compute_tps(fep));
 236         param->freq = cpu_to_le32(fep->frequency / 1000);
 237         param->flags = 0;
 238 
 239         switch (fep->bandwidth_hz) {
 240         default:
 241         case 8000000:
 242                 param->bandwidth = 8;
 243                 break;
 244         case 7000000:
 245                 param->bandwidth = 7;
 246                 break;
 247         case 6000000:
 248                 param->bandwidth = 6;
 249                 break;
 250         }
 251 
 252         err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param),
 253                                  state->data, 2, 0);
 254         if (err < 0)
 255                 err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
 256 
 257         mutex_unlock(&state->data_mutex);
 258         return (err < 0) ? err : 0;
 259 }
 260 
 261 static void cinergyt2_fe_release(struct dvb_frontend *fe)
 262 {
 263         struct cinergyt2_fe_state *state = fe->demodulator_priv;
 264         kfree(state);
 265 }
 266 
 267 static const struct dvb_frontend_ops cinergyt2_fe_ops;
 268 
 269 struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
 270 {
 271         struct cinergyt2_fe_state *s = kzalloc(sizeof(
 272                                         struct cinergyt2_fe_state), GFP_KERNEL);
 273         if (s == NULL)
 274                 return NULL;
 275 
 276         s->d = d;
 277         memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
 278         s->fe.demodulator_priv = s;
 279         mutex_init(&s->data_mutex);
 280         return &s->fe;
 281 }
 282 
 283 
 284 static const struct dvb_frontend_ops cinergyt2_fe_ops = {
 285         .delsys = { SYS_DVBT },
 286         .info = {
 287                 .name                   = DRIVER_NAME,
 288                 .frequency_min_hz       = 174 * MHz,
 289                 .frequency_max_hz       = 862 * MHz,
 290                 .frequency_stepsize_hz  = 166667,
 291                 .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2
 292                         | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
 293                         | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8
 294                         | FE_CAN_FEC_AUTO | FE_CAN_QPSK
 295                         | FE_CAN_QAM_16 | FE_CAN_QAM_64
 296                         | FE_CAN_QAM_AUTO
 297                         | FE_CAN_TRANSMISSION_MODE_AUTO
 298                         | FE_CAN_GUARD_INTERVAL_AUTO
 299                         | FE_CAN_HIERARCHY_AUTO
 300                         | FE_CAN_RECOVER
 301                         | FE_CAN_MUTE_TS
 302         },
 303 
 304         .release                = cinergyt2_fe_release,
 305 
 306         .init                   = cinergyt2_fe_init,
 307         .sleep                  = cinergyt2_fe_sleep,
 308 
 309         .set_frontend           = cinergyt2_fe_set_frontend,
 310         .get_tune_settings      = cinergyt2_fe_get_tune_settings,
 311 
 312         .read_status            = cinergyt2_fe_read_status,
 313         .read_ber               = cinergyt2_fe_read_ber,
 314         .read_signal_strength   = cinergyt2_fe_read_signal_strength,
 315         .read_snr               = cinergyt2_fe_read_snr,
 316         .read_ucblocks          = cinergyt2_fe_read_unc_blocks,
 317 };

/* [<][>][^][v][top][bottom][index][help] */