blob: 8781335ab92f2469dab33aa132ab1613d2c512a7 [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
Peter Beutner4d2858c2008-09-06 13:54:06 -030041static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030042 enum fe_status *status)
Peter Beutner4d2858c2008-09-06 13:54:06 -030043{
44 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
45 FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
46 return 0;
47}
48
49
50static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030051 enum fe_status *status)
Linus Torvalds1da177e2005-04-16 15:20:36 -070052{
Alex Woodsf961e712006-01-09 15:25:24 -020053 struct ttusbdecfe_state* state = fe->demodulator_priv;
54 u8 b[] = { 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00 };
56 u8 result[4];
57 int len, ret;
58
59 *status=0;
60
61 ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
62 if(ret)
63 return ret;
64
65 if(len != 4) {
Harvey Harrisone9815ce2008-04-08 23:20:00 -030066 printk(KERN_ERR "%s: unexpected reply\n", __func__);
Alex Woodsf961e712006-01-09 15:25:24 -020067 return -EIO;
68 }
69
70 switch(result[3]) {
71 case 1: /* not tuned yet */
72 case 2: /* no signal/no lock*/
73 break;
74 case 3: /* signal found and locked*/
75 *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
76 FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
77 break;
78 case 4:
79 *status = FE_TIMEDOUT;
80 break;
81 default:
82 pr_info("%s: returned unknown value: %d\n",
Harvey Harrisone9815ce2008-04-08 23:20:00 -030083 __func__, result[3]);
Alex Woodsf961e712006-01-09 15:25:24 -020084 return -EIO;
85 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87 return 0;
88}
89
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -030090static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -070091{
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -030092 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
94 u8 b[] = { 0x00, 0x00, 0x00, 0x03,
95 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x01,
97 0x00, 0x00, 0x00, 0xff,
98 0x00, 0x00, 0x00, 0xff };
99
Al Virod4f979a2008-05-21 00:31:31 -0300100 __be32 freq = htonl(p->frequency / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 memcpy(&b[4], &freq, sizeof (u32));
102 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
103
104 return 0;
105}
106
Alex Woodsf961e712006-01-09 15:25:24 -0200107static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
108 struct dvb_frontend_tune_settings* fesettings)
109{
110 fesettings->min_delay_ms = 1500;
111 /* Drift compensation makes no sense for DVB-T */
112 fesettings->step_size = 0;
113 fesettings->max_drift = 0;
114 return 0;
115}
116
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300117static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300119 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
121
122 u8 b[] = { 0x00, 0x00, 0x00, 0x01,
123 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x01,
125 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00 };
Al Virod4f979a2008-05-21 00:31:31 -0300132 __be32 freq;
133 __be32 sym_rate;
134 __be32 band;
135 __be32 lnb_voltage;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137 freq = htonl(p->frequency +
138 (state->hi_band ? LOF_HI : LOF_LO));
139 memcpy(&b[4], &freq, sizeof(u32));
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300140 sym_rate = htonl(p->symbol_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 memcpy(&b[12], &sym_rate, sizeof(u32));
142 band = htonl(state->hi_band ? LOF_HI : LOF_LO);
143 memcpy(&b[24], &band, sizeof(u32));
144 lnb_voltage = htonl(state->voltage);
145 memcpy(&b[28], &lnb_voltage, sizeof(u32));
146
147 state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
148
149 return 0;
150}
151
152static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
153{
154 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
155 u8 b[] = { 0x00, 0xff, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00 };
158
Dan Carpenterf2e323e2014-09-05 09:09:28 -0300159 if (cmd->msg_len > sizeof(b) - 4)
160 return -EINVAL;
161
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 memcpy(&b[4], cmd->msg, cmd->msg_len);
163
164 state->config->send_command(fe, 0x72,
165 sizeof(b) - (6 - cmd->msg_len), b,
166 NULL, NULL);
167
168 return 0;
169}
170
171
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300172static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend *fe,
173 enum fe_sec_tone_mode tone)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
175 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
176
177 state->hi_band = (SEC_TONE_ON == tone);
178
179 return 0;
180}
181
182
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300183static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend *fe,
184 enum fe_sec_voltage voltage)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
186 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
187
188 switch (voltage) {
189 case SEC_VOLTAGE_13:
190 state->voltage = 13;
191 break;
192 case SEC_VOLTAGE_18:
193 state->voltage = 18;
194 break;
195 default:
196 return -EINVAL;
197 }
198
199 return 0;
200}
201
202static void ttusbdecfe_release(struct dvb_frontend* fe)
203{
204 struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
205 kfree(state);
206}
207
208static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
209
210struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
211{
212 struct ttusbdecfe_state* state = NULL;
213
214 /* allocate memory for the internal state */
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800215 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700216 if (state == NULL)
217 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219 /* setup the state */
220 state->config = config;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300223 memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 state->frontend.demodulator_priv = state;
225 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226}
227
228static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
229
230struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
231{
232 struct ttusbdecfe_state* state = NULL;
233
234 /* allocate memory for the internal state */
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800235 state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
Adrian Bunk771e7152005-07-07 17:57:52 -0700236 if (state == NULL)
237 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239 /* setup the state */
240 state->config = config;
241 state->voltage = 0;
242 state->hi_band = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
244 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300245 memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 state->frontend.demodulator_priv = state;
247 return &state->frontend;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248}
249
250static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300251 .delsys = { SYS_DVBT },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 .info = {
253 .name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 .frequency_min = 51000000,
255 .frequency_max = 858000000,
256 .frequency_stepsize = 62500,
257 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
258 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
259 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
260 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
261 FE_CAN_HIERARCHY_AUTO,
262 },
263
264 .release = ttusbdecfe_release,
265
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300266 .set_frontend = ttusbdecfe_dvbt_set_frontend,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Alex Woodsf961e712006-01-09 15:25:24 -0200268 .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
269
Peter Beutner4d2858c2008-09-06 13:54:06 -0300270 .read_status = ttusbdecfe_dvbt_read_status,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271};
272
273static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300274 .delsys = { SYS_DVBS },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 .info = {
276 .name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 .frequency_min = 950000,
278 .frequency_max = 2150000,
279 .frequency_stepsize = 125,
Alex Woodsf961e712006-01-09 15:25:24 -0200280 .symbol_rate_min = 1000000, /* guessed */
281 .symbol_rate_max = 45000000, /* guessed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
283 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
Alex Woodsf961e712006-01-09 15:25:24 -0200284 FE_CAN_QPSK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 },
286
287 .release = ttusbdecfe_release,
288
Mauro Carvalho Chehabf1594512011-12-26 16:33:34 -0300289 .set_frontend = ttusbdecfe_dvbs_set_frontend,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Peter Beutner4d2858c2008-09-06 13:54:06 -0300291 .read_status = ttusbdecfe_dvbs_read_status,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
293 .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
294 .set_voltage = ttusbdecfe_dvbs_set_voltage,
295 .set_tone = ttusbdecfe_dvbs_set_tone,
296};
297
298MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
299MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
300MODULE_LICENSE("GPL");
301
302EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
303EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);