1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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:
68 case 2:
69 break;
70 case 3:
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
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
211 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
212 if (state == NULL)
213 return NULL;
214
215
216 state->config = config;
217
218
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
231 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
232 if (state == NULL)
233 return NULL;
234
235
236 state->config = config;
237 state->voltage = 0;
238 state->hi_band = 0;
239
240
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,
277 .symbol_rate_max = 45000000,
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