blob: a6fb1d6a7b5dd168394933b9abb609ae3c7f6c19 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 /* configuration settings */
32 const struct ttusbdecfe_config* config;
33
34 struct dvb_frontend frontend;
35
36 u8 hi_band;
37 u8 voltage;
38};
39
40
41static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
42{
Alex Woodsf961e712006-01-09 15:25:24 -020043 struct ttusbdecfe_state* state = fe->demodulator_priv;
44 u8 b[] = { 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00 };
46 u8 result[4];
47 int len, ret;
48
49 *status=0;
50
51 ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
52 if(ret)
53 return ret;
54
55 if(len != 4) {
56 printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
57 return -EIO;
58 }
59
60 switch(result[3]) {
61 case 1: /* not tuned yet */
62 case 2: /* no signal/no lock*/
63 break;
64 case 3: /* signal found and locked*/
65 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
66 FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
67 break;
68 case 4:
69 *status = FE_TIMEDOUT;
70 break;
71 default:
72 pr_info("%s: returned unknown value: %d\n",
73 __FUNCTION__, result[3]);
74 return -EIO;
75 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77 return 0;
78}
79
80static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
81{
82 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
83 u8 b[] = { 0x00, 0x00, 0x00, 0x03,
84 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x01,
86 0x00, 0x00, 0x00, 0xff,
87 0x00, 0x00, 0x00, 0xff };
88
89 u32 freq = htonl(p->frequency / 1000);
90 memcpy(&b[4], &freq, sizeof (u32));
91 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
92
93 return 0;
94}
95
Alex Woodsf961e712006-01-09 15:25:24 -020096static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
97 struct dvb_frontend_tune_settings* fesettings)
98{
99 fesettings->min_delay_ms = 1500;
100 /* Drift compensation makes no sense for DVB-T */
101 fesettings->step_size = 0;
102 fesettings->max_drift = 0;
103 return 0;
104}
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
107{
108 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
109
110 u8 b[] = { 0x00, 0x00, 0x00, 0x01,
111 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x01,
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 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00 };
120 u32 freq;
121 u32 sym_rate;
122 u32 band;
123 u32 lnb_voltage;
124
125 freq = htonl(p->frequency +
126 (state->hi_band ? LOF_HI : LOF_LO));
127 memcpy(&b[4], &freq, sizeof(u32));
128 sym_rate = htonl(p->u.qam.symbol_rate);
129 memcpy(&b[12], &sym_rate, sizeof(u32));
130 band = htonl(state->hi_band ? LOF_HI : LOF_LO);
131 memcpy(&b[24], &band, sizeof(u32));
132 lnb_voltage = htonl(state->voltage);
133 memcpy(&b[28], &lnb_voltage, sizeof(u32));
134
135 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
136
137 return 0;
138}
139
140static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
141{
142 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
143 u8 b[] = { 0x00, 0xff, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00 };
146
147 memcpy(&b[4], cmd->msg, cmd->msg_len);
148
149 state->config->send_command(fe, 0x72,
150 sizeof(b) - (6 - cmd->msg_len), b,
151 NULL, NULL);
152
153 return 0;
154}
155
156
157static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
158{
159 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
160
161 state->hi_band = (SEC_TONE_ON == tone);
162
163 return 0;
164}
165
166
167static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
168{
169 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
170
171 switch (voltage) {
172 case SEC_VOLTAGE_13:
173 state->voltage = 13;
174 break;
175 case SEC_VOLTAGE_18:
176 state->voltage = 18;
177 break;
178 default:
179 return -EINVAL;
180 }
181
182 return 0;
183}
184
185static void ttusbdecfe_release(struct dvb_frontend* fe)
186{
187 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
188 kfree(state);
189}
190
191static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
192
193struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
194{
195 struct ttusbdecfe_state* state = NULL;
196
197 /* allocate memory for the internal state */
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800198 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700199 if (state == NULL)
200 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 /* setup the state */
203 state->config = config;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300206 memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 state->frontend.demodulator_priv = state;
208 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209}
210
211static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
212
213struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
214{
215 struct ttusbdecfe_state* state = NULL;
216
217 /* allocate memory for the internal state */
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800218 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700219 if (state == NULL)
220 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222 /* setup the state */
223 state->config = config;
224 state->voltage = 0;
225 state->hi_band = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300228 memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 state->frontend.demodulator_priv = state;
230 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231}
232
233static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
234
235 .info = {
236 .name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
237 .type = FE_OFDM,
238 .frequency_min = 51000000,
239 .frequency_max = 858000000,
240 .frequency_stepsize = 62500,
241 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
242 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
243 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
244 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
245 FE_CAN_HIERARCHY_AUTO,
246 },
247
248 .release = ttusbdecfe_release,
249
250 .set_frontend = ttusbdecfe_dvbt_set_frontend,
251
Alex Woodsf961e712006-01-09 15:25:24 -0200252 .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 .read_status = ttusbdecfe_read_status,
255};
256
257static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
258
259 .info = {
260 .name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
261 .type = FE_QPSK,
262 .frequency_min = 950000,
263 .frequency_max = 2150000,
264 .frequency_stepsize = 125,
Alex Woodsf961e712006-01-09 15:25:24 -0200265 .symbol_rate_min = 1000000, /* guessed */
266 .symbol_rate_max = 45000000, /* guessed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
268 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
Alex Woodsf961e712006-01-09 15:25:24 -0200269 FE_CAN_QPSK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 },
271
272 .release = ttusbdecfe_release,
273
274 .set_frontend = ttusbdecfe_dvbs_set_frontend,
275
276 .read_status = ttusbdecfe_read_status,
277
278 .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
279 .set_voltage = ttusbdecfe_dvbs_set_voltage,
280 .set_tone = ttusbdecfe_dvbs_set_tone,
281};
282
283MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
284MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
285MODULE_LICENSE("GPL");
286
287EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
288EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);