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
ttusbdecfe_dvbs_read_status(struct dvb_frontend * fe,enum fe_status * status)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
ttusbdecfe_dvbt_read_status(struct dvb_frontend * fe,enum fe_status * status)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
ttusbdecfe_dvbt_set_frontend(struct dvb_frontend * fe)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 = 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
ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * fesettings)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
ttusbdecfe_dvbs_set_frontend(struct dvb_frontend * fe)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 = 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
ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend * fe,struct dvb_diseqc_master_cmd * cmd)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 = 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
ttusbdecfe_dvbs_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)158 static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend *fe,
159 enum fe_sec_tone_mode tone)
160 {
161 struct ttusbdecfe_state *state = fe->demodulator_priv;
162
163 state->hi_band = (SEC_TONE_ON == tone);
164
165 return 0;
166 }
167
168
ttusbdecfe_dvbs_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)169 static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend *fe,
170 enum fe_sec_voltage voltage)
171 {
172 struct ttusbdecfe_state *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
ttusbdecfe_release(struct dvb_frontend * fe)188 static void ttusbdecfe_release(struct dvb_frontend* fe)
189 {
190 struct ttusbdecfe_state *state = fe->demodulator_priv;
191 kfree(state);
192 }
193
194 static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
195
ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config * config)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
ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config * config)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