1/*
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	/* 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_dvbs_read_status(struct dvb_frontend *fe,
42	fe_status_t *status)
43{
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,
51	fe_status_t *status)
52{
53	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) {
66		printk(KERN_ERR "%s: unexpected reply\n", __func__);
67		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",
83				__func__, result[3]);
84			return -EIO;
85	}
86
87	return 0;
88}
89
90static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
91{
92	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
93	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
100	__be32 freq = htonl(p->frequency / 1000);
101	memcpy(&b[4], &freq, sizeof (u32));
102	state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
103
104	return 0;
105}
106
107static 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
117static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
118{
119	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
120	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 };
132	__be32 freq;
133	__be32 sym_rate;
134	__be32 band;
135	__be32 lnb_voltage;
136
137	freq = htonl(p->frequency +
138	       (state->hi_band ? LOF_HI : LOF_LO));
139	memcpy(&b[4], &freq, sizeof(u32));
140	sym_rate = htonl(p->symbol_rate);
141	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
159	if (cmd->msg_len > sizeof(b) - 4)
160		return -EINVAL;
161
162	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
172static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
173{
174	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
175
176	state->hi_band = (SEC_TONE_ON == tone);
177
178	return 0;
179}
180
181
182static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
183{
184	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
185
186	switch (voltage) {
187	case SEC_VOLTAGE_13:
188		state->voltage = 13;
189		break;
190	case SEC_VOLTAGE_18:
191		state->voltage = 18;
192		break;
193	default:
194		return -EINVAL;
195	}
196
197	return 0;
198}
199
200static void ttusbdecfe_release(struct dvb_frontend* fe)
201{
202	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
203	kfree(state);
204}
205
206static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
207
208struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
209{
210	struct ttusbdecfe_state* state = NULL;
211
212	/* allocate memory for the internal state */
213	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
214	if (state == NULL)
215		return NULL;
216
217	/* setup the state */
218	state->config = config;
219
220	/* create dvb_frontend */
221	memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
222	state->frontend.demodulator_priv = state;
223	return &state->frontend;
224}
225
226static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
227
228struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
229{
230	struct ttusbdecfe_state* state = NULL;
231
232	/* allocate memory for the internal state */
233	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
234	if (state == NULL)
235		return NULL;
236
237	/* setup the state */
238	state->config = config;
239	state->voltage = 0;
240	state->hi_band = 0;
241
242	/* create dvb_frontend */
243	memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
244	state->frontend.demodulator_priv = state;
245	return &state->frontend;
246}
247
248static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
249	.delsys = { SYS_DVBT },
250	.info = {
251		.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
252		.frequency_min		= 51000000,
253		.frequency_max		= 858000000,
254		.frequency_stepsize	= 62500,
255		.caps =	FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
256			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
257			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
258			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
259			FE_CAN_HIERARCHY_AUTO,
260	},
261
262	.release = ttusbdecfe_release,
263
264	.set_frontend = ttusbdecfe_dvbt_set_frontend,
265
266	.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
267
268	.read_status = ttusbdecfe_dvbt_read_status,
269};
270
271static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
272	.delsys = { SYS_DVBS },
273	.info = {
274		.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
275		.frequency_min		= 950000,
276		.frequency_max		= 2150000,
277		.frequency_stepsize	= 125,
278		.symbol_rate_min        = 1000000,  /* guessed */
279		.symbol_rate_max        = 45000000, /* guessed */
280		.caps =	FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
281			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
282			FE_CAN_QPSK
283	},
284
285	.release = ttusbdecfe_release,
286
287	.set_frontend = ttusbdecfe_dvbs_set_frontend,
288
289	.read_status = ttusbdecfe_dvbs_read_status,
290
291	.diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
292	.set_voltage = ttusbdecfe_dvbs_set_voltage,
293	.set_tone = ttusbdecfe_dvbs_set_tone,
294};
295
296MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
297MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
298MODULE_LICENSE("GPL");
299
300EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
301EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
302