xref: /linux/drivers/media/usb/ttusb-dec/ttusbdecfe.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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 
29 struct 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 
41 static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
42 				       enum fe_status *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 
50 static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
51 				       enum fe_status *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 
90 static 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 
107 static 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 
117 static 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 
152 static 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 
172 static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend *fe,
173 				    enum fe_sec_tone_mode tone)
174 {
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 
183 static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend *fe,
184 				       enum fe_sec_voltage voltage)
185 {
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 
202 static void ttusbdecfe_release(struct dvb_frontend* fe)
203 {
204 	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
205 	kfree(state);
206 }
207 
208 static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
209 
210 struct 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 */
215 	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
216 	if (state == NULL)
217 		return NULL;
218 
219 	/* setup the state */
220 	state->config = config;
221 
222 	/* create dvb_frontend */
223 	memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
224 	state->frontend.demodulator_priv = state;
225 	return &state->frontend;
226 }
227 
228 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
229 
230 struct 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 */
235 	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
236 	if (state == NULL)
237 		return NULL;
238 
239 	/* setup the state */
240 	state->config = config;
241 	state->voltage = 0;
242 	state->hi_band = 0;
243 
244 	/* create dvb_frontend */
245 	memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
246 	state->frontend.demodulator_priv = state;
247 	return &state->frontend;
248 }
249 
250 static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
251 	.delsys = { SYS_DVBT },
252 	.info = {
253 		.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
254 		.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 
266 	.set_frontend = ttusbdecfe_dvbt_set_frontend,
267 
268 	.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
269 
270 	.read_status = ttusbdecfe_dvbt_read_status,
271 };
272 
273 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
274 	.delsys = { SYS_DVBS },
275 	.info = {
276 		.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
277 		.frequency_min		= 950000,
278 		.frequency_max		= 2150000,
279 		.frequency_stepsize	= 125,
280 		.symbol_rate_min        = 1000000,  /* guessed */
281 		.symbol_rate_max        = 45000000, /* guessed */
282 		.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 |
284 			FE_CAN_QPSK
285 	},
286 
287 	.release = ttusbdecfe_release,
288 
289 	.set_frontend = ttusbdecfe_dvbs_set_frontend,
290 
291 	.read_status = ttusbdecfe_dvbs_read_status,
292 
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 
298 MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
299 MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
300 MODULE_LICENSE("GPL");
301 
302 EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
303 EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
304