• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* DVB USB compliant Linux driver for the
2  *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
3  *
4  * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
5  * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
6  *
7  * Thanks to GENPIX for the sample code used to implement this module.
8  *
9  * This module is based off the vp7045 and vp702x modules
10  *
11  *	This program is free software; you can redistribute it and/or modify it
12  *	under the terms of the GNU General Public License as published by the Free
13  *	Software Foundation, version 2.
14  *
15  * see Documentation/dvb/README.dvb-usb for more information
16  */
17 #include "gp8psk.h"
18 
19 struct gp8psk_fe_state {
20 	struct dvb_frontend fe;
21 	struct dvb_usb_device *d;
22 	u8 lock;
23 	u16 snr;
24 	unsigned long next_status_check;
25 	unsigned long status_check_interval;
26 };
27 
gp8psk_tuned_to_DCII(struct dvb_frontend * fe)28 static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe)
29 {
30 	struct gp8psk_fe_state *st = fe->demodulator_priv;
31 	u8 status;
32 	gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1);
33 	return status & bmDCtuned;
34 }
35 
gp8psk_set_tuner_mode(struct dvb_frontend * fe,int mode)36 static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode)
37 {
38 	struct gp8psk_fe_state *state = fe->demodulator_priv;
39 	return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0);
40 }
41 
gp8psk_fe_update_status(struct gp8psk_fe_state * st)42 static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
43 {
44 	u8 buf[6];
45 	if (time_after(jiffies,st->next_status_check)) {
46 		gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1);
47 		gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6);
48 		st->snr = (buf[1]) << 8 | buf[0];
49 		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
50 	}
51 	return 0;
52 }
53 
gp8psk_fe_read_status(struct dvb_frontend * fe,enum fe_status * status)54 static int gp8psk_fe_read_status(struct dvb_frontend *fe,
55 				 enum fe_status *status)
56 {
57 	struct gp8psk_fe_state *st = fe->demodulator_priv;
58 	gp8psk_fe_update_status(st);
59 
60 	if (st->lock)
61 		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
62 	else
63 		*status = 0;
64 
65 	if (*status & FE_HAS_LOCK)
66 		st->status_check_interval = 1000;
67 	else
68 		st->status_check_interval = 100;
69 	return 0;
70 }
71 
72 /* not supported by this Frontend */
gp8psk_fe_read_ber(struct dvb_frontend * fe,u32 * ber)73 static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
74 {
75 	(void) fe;
76 	*ber = 0;
77 	return 0;
78 }
79 
80 /* not supported by this Frontend */
gp8psk_fe_read_unc_blocks(struct dvb_frontend * fe,u32 * unc)81 static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
82 {
83 	(void) fe;
84 	*unc = 0;
85 	return 0;
86 }
87 
gp8psk_fe_read_snr(struct dvb_frontend * fe,u16 * snr)88 static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
89 {
90 	struct gp8psk_fe_state *st = fe->demodulator_priv;
91 	gp8psk_fe_update_status(st);
92 	/* snr is reported in dBu*256 */
93 	*snr = st->snr;
94 	return 0;
95 }
96 
gp8psk_fe_read_signal_strength(struct dvb_frontend * fe,u16 * strength)97 static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
98 {
99 	struct gp8psk_fe_state *st = fe->demodulator_priv;
100 	gp8psk_fe_update_status(st);
101 	/* snr is reported in dBu*256 */
102 	/* snr / 38.4 ~= 100% strength */
103 	/* snr * 17 returns 100% strength as 65535 */
104 	if (st->snr > 0xf00)
105 		*strength = 0xffff;
106 	else
107 		*strength = (st->snr << 4) + st->snr; /* snr*17 */
108 	return 0;
109 }
110 
gp8psk_fe_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * tune)111 static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
112 {
113 	tune->min_delay_ms = 800;
114 	return 0;
115 }
116 
gp8psk_fe_set_frontend(struct dvb_frontend * fe)117 static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
118 {
119 	struct gp8psk_fe_state *state = fe->demodulator_priv;
120 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
121 	u8 cmd[10];
122 	u32 freq = c->frequency * 1000;
123 	int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
124 
125 	deb_fe("%s()\n", __func__);
126 
127 	cmd[4] = freq         & 0xff;
128 	cmd[5] = (freq >> 8)  & 0xff;
129 	cmd[6] = (freq >> 16) & 0xff;
130 	cmd[7] = (freq >> 24) & 0xff;
131 
132 	/* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
133 	if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
134 		c->delivery_system = SYS_TURBO;
135 
136 	switch (c->delivery_system) {
137 	case SYS_DVBS:
138 		if (c->modulation != QPSK) {
139 			deb_fe("%s: unsupported modulation selected (%d)\n",
140 				__func__, c->modulation);
141 			return -EOPNOTSUPP;
142 		}
143 		c->fec_inner = FEC_AUTO;
144 		break;
145 	case SYS_DVBS2: /* kept for backwards compatibility */
146 		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
147 		break;
148 	case SYS_TURBO:
149 		deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
150 		break;
151 
152 	default:
153 		deb_fe("%s: unsupported delivery system selected (%d)\n",
154 			__func__, c->delivery_system);
155 		return -EOPNOTSUPP;
156 	}
157 
158 	cmd[0] =  c->symbol_rate        & 0xff;
159 	cmd[1] = (c->symbol_rate >>  8) & 0xff;
160 	cmd[2] = (c->symbol_rate >> 16) & 0xff;
161 	cmd[3] = (c->symbol_rate >> 24) & 0xff;
162 	switch (c->modulation) {
163 	case QPSK:
164 		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
165 			if (gp8psk_tuned_to_DCII(fe))
166 				gp8psk_bcm4500_reload(state->d);
167 		switch (c->fec_inner) {
168 		case FEC_1_2:
169 			cmd[9] = 0; break;
170 		case FEC_2_3:
171 			cmd[9] = 1; break;
172 		case FEC_3_4:
173 			cmd[9] = 2; break;
174 		case FEC_5_6:
175 			cmd[9] = 3; break;
176 		case FEC_7_8:
177 			cmd[9] = 4; break;
178 		case FEC_AUTO:
179 			cmd[9] = 5; break;
180 		default:
181 			cmd[9] = 5; break;
182 		}
183 		if (c->delivery_system == SYS_TURBO)
184 			cmd[8] = ADV_MOD_TURBO_QPSK;
185 		else
186 			cmd[8] = ADV_MOD_DVB_QPSK;
187 		break;
188 	case PSK_8: /* PSK_8 is for compatibility with DN */
189 		cmd[8] = ADV_MOD_TURBO_8PSK;
190 		switch (c->fec_inner) {
191 		case FEC_2_3:
192 			cmd[9] = 0; break;
193 		case FEC_3_4:
194 			cmd[9] = 1; break;
195 		case FEC_3_5:
196 			cmd[9] = 2; break;
197 		case FEC_5_6:
198 			cmd[9] = 3; break;
199 		case FEC_8_9:
200 			cmd[9] = 4; break;
201 		default:
202 			cmd[9] = 0; break;
203 		}
204 		break;
205 	case QAM_16: /* QAM_16 is for compatibility with DN */
206 		cmd[8] = ADV_MOD_TURBO_16QAM;
207 		cmd[9] = 0;
208 		break;
209 	default: /* Unknown modulation */
210 		deb_fe("%s: unsupported modulation selected (%d)\n",
211 			__func__, c->modulation);
212 		return -EOPNOTSUPP;
213 	}
214 
215 	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
216 		gp8psk_set_tuner_mode(fe, 0);
217 	gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10);
218 
219 	state->lock = 0;
220 	state->next_status_check = jiffies;
221 	state->status_check_interval = 200;
222 
223 	return 0;
224 }
225 
gp8psk_fe_send_diseqc_msg(struct dvb_frontend * fe,struct dvb_diseqc_master_cmd * m)226 static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
227 				    struct dvb_diseqc_master_cmd *m)
228 {
229 	struct gp8psk_fe_state *st = fe->demodulator_priv;
230 
231 	deb_fe("%s\n",__func__);
232 
233 	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
234 			m->msg, m->msg_len)) {
235 		return -EINVAL;
236 	}
237 	return 0;
238 }
239 
gp8psk_fe_send_diseqc_burst(struct dvb_frontend * fe,enum fe_sec_mini_cmd burst)240 static int gp8psk_fe_send_diseqc_burst(struct dvb_frontend *fe,
241 				       enum fe_sec_mini_cmd burst)
242 {
243 	struct gp8psk_fe_state *st = fe->demodulator_priv;
244 	u8 cmd;
245 
246 	deb_fe("%s\n",__func__);
247 
248 	/* These commands are certainly wrong */
249 	cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
250 
251 	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
252 			&cmd, 0)) {
253 		return -EINVAL;
254 	}
255 	return 0;
256 }
257 
gp8psk_fe_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)258 static int gp8psk_fe_set_tone(struct dvb_frontend *fe,
259 			      enum fe_sec_tone_mode tone)
260 {
261 	struct gp8psk_fe_state* state = fe->demodulator_priv;
262 
263 	if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
264 		 (tone == SEC_TONE_ON), 0, NULL, 0)) {
265 		return -EINVAL;
266 	}
267 	return 0;
268 }
269 
gp8psk_fe_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)270 static int gp8psk_fe_set_voltage(struct dvb_frontend *fe,
271 				 enum fe_sec_voltage voltage)
272 {
273 	struct gp8psk_fe_state* state = fe->demodulator_priv;
274 
275 	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
276 			 voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
277 		return -EINVAL;
278 	}
279 	return 0;
280 }
281 
gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend * fe,long onoff)282 static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff)
283 {
284 	struct gp8psk_fe_state* state = fe->demodulator_priv;
285 	return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0);
286 }
287 
gp8psk_fe_send_legacy_dish_cmd(struct dvb_frontend * fe,unsigned long sw_cmd)288 static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
289 {
290 	struct gp8psk_fe_state* state = fe->demodulator_priv;
291 	u8 cmd = sw_cmd & 0x7f;
292 
293 	if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
294 			NULL, 0)) {
295 		return -EINVAL;
296 	}
297 	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
298 			0, NULL, 0)) {
299 		return -EINVAL;
300 	}
301 
302 	return 0;
303 }
304 
gp8psk_fe_release(struct dvb_frontend * fe)305 static void gp8psk_fe_release(struct dvb_frontend* fe)
306 {
307 	struct gp8psk_fe_state *state = fe->demodulator_priv;
308 	kfree(state);
309 }
310 
311 static struct dvb_frontend_ops gp8psk_fe_ops;
312 
gp8psk_fe_attach(struct dvb_usb_device * d)313 struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
314 {
315 	struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
316 	if (s == NULL)
317 		goto error;
318 
319 	s->d = d;
320 	memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
321 	s->fe.demodulator_priv = s;
322 
323 	goto success;
324 error:
325 	return NULL;
326 success:
327 	return &s->fe;
328 }
329 
330 
331 static struct dvb_frontend_ops gp8psk_fe_ops = {
332 	.delsys = { SYS_DVBS },
333 	.info = {
334 		.name			= "Genpix DVB-S",
335 		.frequency_min		= 800000,
336 		.frequency_max		= 2250000,
337 		.frequency_stepsize	= 100,
338 		.symbol_rate_min        = 1000000,
339 		.symbol_rate_max        = 45000000,
340 		.symbol_rate_tolerance  = 500,  /* ppm */
341 		.caps = FE_CAN_INVERSION_AUTO |
342 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
343 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
344 			/*
345 			 * FE_CAN_QAM_16 is for compatibility
346 			 * (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
347 			 */
348 			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC
349 	},
350 
351 	.release = gp8psk_fe_release,
352 
353 	.init = NULL,
354 	.sleep = NULL,
355 
356 	.set_frontend = gp8psk_fe_set_frontend,
357 
358 	.get_tune_settings = gp8psk_fe_get_tune_settings,
359 
360 	.read_status = gp8psk_fe_read_status,
361 	.read_ber = gp8psk_fe_read_ber,
362 	.read_signal_strength = gp8psk_fe_read_signal_strength,
363 	.read_snr = gp8psk_fe_read_snr,
364 	.read_ucblocks = gp8psk_fe_read_unc_blocks,
365 
366 	.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
367 	.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
368 	.set_tone = gp8psk_fe_set_tone,
369 	.set_voltage = gp8psk_fe_set_voltage,
370 	.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
371 	.enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage
372 };
373