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 15 struct 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 27 static 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 36 static 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 76 static 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 93 static 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 103 static 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 138 static 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 158 static 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 169 static 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 188 static void ttusbdecfe_release(struct dvb_frontend* fe) 189 { 190 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; 191 kfree(state); 192 } 193 194 static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops; 195 196 struct 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 214 static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops; 215 216 struct 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 236 static 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 259 static 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 284 MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver"); 285 MODULE_AUTHOR("Alex Woods/Andrew de Quincey"); 286 MODULE_LICENSE("GPL"); 287 288 EXPORT_SYMBOL(ttusbdecfe_dvbt_attach); 289 EXPORT_SYMBOL(ttusbdecfe_dvbs_attach); 290