xref: /linux/drivers/media/usb/ttusb-dec/ttusbdecfe.c (revision e0bf6c5ca2d3281f231c5f0c9bf145e9513644de)
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 	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 
50 static 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 
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, 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 
182 static 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 
200 static void ttusbdecfe_release(struct dvb_frontend* fe)
201 {
202 	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
203 	kfree(state);
204 }
205 
206 static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
207 
208 struct 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 
226 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
227 
228 struct 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 
248 static 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 
271 static 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 
296 MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
297 MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
298 MODULE_LICENSE("GPL");
299 
300 EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
301 EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
302