blob: a5a46175fa0969e302e59e75e14afa5a2e5cf2ab [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * TTUSB DEC Frontend Driver
3 *
4 * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22#include "dvb_frontend.h"
23#include "ttusbdecfe.h"
24
25
26#define LOF_HI 10600000
27#define LOF_LO 9750000
28
29struct ttusbdecfe_state {
30
31 struct dvb_frontend_ops ops;
32
33 /* configuration settings */
34 const struct ttusbdecfe_config* config;
35
36 struct dvb_frontend frontend;
37
38 u8 hi_band;
39 u8 voltage;
40};
41
42
43static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
44{
Alex Woodsf961e712006-01-09 15:25:24 -020045 struct ttusbdecfe_state* state = fe->demodulator_priv;
46 u8 b[] = { 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00 };
48 u8 result[4];
49 int len, ret;
50
51 *status=0;
52
53 ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
54 if(ret)
55 return ret;
56
57 if(len != 4) {
58 printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
59 return -EIO;
60 }
61
62 switch(result[3]) {
63 case 1: /* not tuned yet */
64 case 2: /* no signal/no lock*/
65 break;
66 case 3: /* signal found and locked*/
67 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
68 FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
69 break;
70 case 4:
71 *status = FE_TIMEDOUT;
72 break;
73 default:
74 pr_info("%s: returned unknown value: %d\n",
75 __FUNCTION__, result[3]);
76 return -EIO;
77 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79 return 0;
80}
81
82static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
83{
84 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
85 u8 b[] = { 0x00, 0x00, 0x00, 0x03,
86 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x01,
88 0x00, 0x00, 0x00, 0xff,
89 0x00, 0x00, 0x00, 0xff };
90
91 u32 freq = htonl(p->frequency / 1000);
92 memcpy(&b[4], &freq, sizeof (u32));
93 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
94
95 return 0;
96}
97
Alex Woodsf961e712006-01-09 15:25:24 -020098static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
99 struct dvb_frontend_tune_settings* fesettings)
100{
101 fesettings->min_delay_ms = 1500;
102 /* Drift compensation makes no sense for DVB-T */
103 fesettings->step_size = 0;
104 fesettings->max_drift = 0;
105 return 0;
106}
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
109{
110 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
111
112 u8 b[] = { 0x00, 0x00, 0x00, 0x01,
113 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x01,
115 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00 };
122 u32 freq;
123 u32 sym_rate;
124 u32 band;
125 u32 lnb_voltage;
126
127 freq = htonl(p->frequency +
128 (state->hi_band ? LOF_HI : LOF_LO));
129 memcpy(&b[4], &freq, sizeof(u32));
130 sym_rate = htonl(p->u.qam.symbol_rate);
131 memcpy(&b[12], &sym_rate, sizeof(u32));
132 band = htonl(state->hi_band ? LOF_HI : LOF_LO);
133 memcpy(&b[24], &band, sizeof(u32));
134 lnb_voltage = htonl(state->voltage);
135 memcpy(&b[28], &lnb_voltage, sizeof(u32));
136
137 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
138
139 return 0;
140}
141
142static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
143{
144 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
145 u8 b[] = { 0x00, 0xff, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00 };
148
149 memcpy(&b[4], cmd->msg, cmd->msg_len);
150
151 state->config->send_command(fe, 0x72,
152 sizeof(b) - (6 - cmd->msg_len), b,
153 NULL, NULL);
154
155 return 0;
156}
157
158
159static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t 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, fe_sec_voltage_t voltage)
170{
171 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
172
173 switch (voltage) {
174 case SEC_VOLTAGE_13:
175 state->voltage = 13;
176 break;
177 case SEC_VOLTAGE_18:
178 state->voltage = 18;
179 break;
180 default:
181 return -EINVAL;
182 }
183
184 return 0;
185}
186
187static void ttusbdecfe_release(struct dvb_frontend* fe)
188{
189 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
190 kfree(state);
191}
192
193static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
194
195struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
196{
197 struct ttusbdecfe_state* state = NULL;
198
199 /* allocate memory for the internal state */
200 state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700201 if (state == NULL)
202 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204 /* setup the state */
205 state->config = config;
206 memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
207
208 /* create dvb_frontend */
209 state->frontend.ops = &state->ops;
210 state->frontend.demodulator_priv = state;
211 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212}
213
214static 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 = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700222 if (state == NULL)
223 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
225 /* setup the state */
226 state->config = config;
227 state->voltage = 0;
228 state->hi_band = 0;
229 memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
230
231 /* create dvb_frontend */
232 state->frontend.ops = &state->ops;
233 state->frontend.demodulator_priv = state;
234 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
237static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
238
239 .info = {
240 .name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
241 .type = FE_OFDM,
242 .frequency_min = 51000000,
243 .frequency_max = 858000000,
244 .frequency_stepsize = 62500,
245 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
246 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
247 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
248 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
249 FE_CAN_HIERARCHY_AUTO,
250 },
251
252 .release = ttusbdecfe_release,
253
254 .set_frontend = ttusbdecfe_dvbt_set_frontend,
255
Alex Woodsf961e712006-01-09 15:25:24 -0200256 .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 .read_status = ttusbdecfe_read_status,
259};
260
261static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
262
263 .info = {
264 .name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
265 .type = FE_QPSK,
266 .frequency_min = 950000,
267 .frequency_max = 2150000,
268 .frequency_stepsize = 125,
Alex Woodsf961e712006-01-09 15:25:24 -0200269 .symbol_rate_min = 1000000, /* guessed */
270 .symbol_rate_max = 45000000, /* guessed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
272 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
Alex Woodsf961e712006-01-09 15:25:24 -0200273 FE_CAN_QPSK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 },
275
276 .release = ttusbdecfe_release,
277
278 .set_frontend = ttusbdecfe_dvbs_set_frontend,
279
280 .read_status = ttusbdecfe_read_status,
281
282 .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
283 .set_voltage = ttusbdecfe_dvbs_set_voltage,
284 .set_tone = ttusbdecfe_dvbs_set_tone,
285};
286
287MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
288MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
289MODULE_LICENSE("GPL");
290
291EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
292EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);