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  */
17 
18 #include <media/dvb_frontend.h>
19 #include "ttusbdecfe.h"
20 
21 
22 #define LOF_HI			10600000
23 #define LOF_LO			9750000
24 
25 struct ttusbdecfe_state {
26 
27 	/* configuration settings */
28 	const struct ttusbdecfe_config* config;
29 
30 	struct dvb_frontend frontend;
31 
32 	u8 hi_band;
33 	u8 voltage;
34 };
35 
36 
37 static 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 
46 static 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:  /* not tuned yet */
68 		case 2:  /* no signal/no lock*/
69 			break;
70 		case 3:	 /* signal found and locked*/
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 
86 static 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 
103 static 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 		/* Drift compensation makes no sense for DVB-T */
108 		fesettings->step_size = 0;
109 		fesettings->max_drift = 0;
110 		return 0;
111 }
112 
113 static 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 
148 static 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 
168 static 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 
179 static 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 
198 static void ttusbdecfe_release(struct dvb_frontend* fe)
199 {
200 	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
201 	kfree(state);
202 }
203 
204 static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
205 
206 struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
207 {
208 	struct ttusbdecfe_state* state = NULL;
209 
210 	/* allocate memory for the internal state */
211 	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
212 	if (state == NULL)
213 		return NULL;
214 
215 	/* setup the state */
216 	state->config = config;
217 
218 	/* create dvb_frontend */
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 
224 static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
225 
226 struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
227 {
228 	struct ttusbdecfe_state* state = NULL;
229 
230 	/* allocate memory for the internal state */
231 	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
232 	if (state == NULL)
233 		return NULL;
234 
235 	/* setup the state */
236 	state->config = config;
237 	state->voltage = 0;
238 	state->hi_band = 0;
239 
240 	/* create dvb_frontend */
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 
246 static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
247 	.delsys = { SYS_DVBT },
248 	.info = {
249 		.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
250 		.frequency_min_hz	=  51 * MHz,
251 		.frequency_max_hz	= 858 * MHz,
252 		.frequency_stepsize_hz	= 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 
269 static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
270 	.delsys = { SYS_DVBS },
271 	.info = {
272 		.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
273 		.frequency_min_hz	=  950 * MHz,
274 		.frequency_max_hz	= 2150 * MHz,
275 		.frequency_stepsize_hz	=  125 * kHz,
276 		.symbol_rate_min        = 1000000,  /* guessed */
277 		.symbol_rate_max        = 45000000, /* guessed */
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 
294 MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
295 MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
296 MODULE_LICENSE("GPL");
297 
298 EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
299 EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
300