1 /* DVB USB compliant Linux driver for the
2 * - GENPIX 8pks/qpsk USB2.0 DVB-S module
4 * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
6 * Thanks to GENPIX for the sample code used to implement this module.
8 * This module is based off the vp7045 and vp702x modules
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation, version 2.
14 * see Documentation/dvb/README.dvb-usb for more information
18 struct gp8psk_fe_state
{
19 struct dvb_frontend fe
;
21 struct dvb_usb_device
*d
;
25 unsigned long next_snr_check
;
28 static int gp8psk_fe_read_status(struct dvb_frontend
* fe
, fe_status_t
*status
)
30 struct gp8psk_fe_state
*st
= fe
->demodulator_priv
;
33 if (gp8psk_usb_in_op(st
->d
, GET_SIGNAL_LOCK
, 0, 0, &lock
,1))
37 *status
= FE_HAS_LOCK
| FE_HAS_SYNC
| FE_HAS_VITERBI
| FE_HAS_SIGNAL
| FE_HAS_CARRIER
;
44 /* not supported by this Frontend */
45 static int gp8psk_fe_read_ber(struct dvb_frontend
* fe
, u32
*ber
)
52 /* not supported by this Frontend */
53 static int gp8psk_fe_read_unc_blocks(struct dvb_frontend
* fe
, u32
*unc
)
60 static int gp8psk_fe_read_snr(struct dvb_frontend
* fe
, u16
*snr
)
62 struct gp8psk_fe_state
*st
= fe
->demodulator_priv
;
65 if (time_after(jiffies
,st
->next_snr_check
)) {
66 gp8psk_usb_in_op(st
->d
,GET_SIGNAL_STRENGTH
,0,0,buf
,2);
67 *snr
= (int)(buf
[1]) << 8 | buf
[0];
68 /* snr is reported in dBu*256 */
69 /* snr / 38.4 ~= 100% strength */
70 /* snr * 17 returns 100% strength as 65535 */
72 *snr
= (*snr
<<4) + *snr
; // snr * 17
75 st
->next_snr_check
= jiffies
+ (10*HZ
)/1000;
82 static int gp8psk_fe_read_signal_strength(struct dvb_frontend
* fe
, u16
*strength
)
84 return gp8psk_fe_read_snr(fe
, strength
);
87 static int gp8psk_fe_get_tune_settings(struct dvb_frontend
* fe
, struct dvb_frontend_tune_settings
*tune
)
89 tune
->min_delay_ms
= 800;
93 static int gp8psk_fe_set_frontend(struct dvb_frontend
* fe
,
94 struct dvb_frontend_parameters
*fep
)
96 struct gp8psk_fe_state
*state
= fe
->demodulator_priv
;
98 u32 freq
= fep
->frequency
* 1000;
100 cmd
[4] = freq
& 0xff;
101 cmd
[5] = (freq
>> 8) & 0xff;
102 cmd
[6] = (freq
>> 16) & 0xff;
103 cmd
[7] = (freq
>> 24) & 0xff;
105 switch(fe
->ops
.info
.type
) {
107 cmd
[0] = fep
->u
.qpsk
.symbol_rate
& 0xff;
108 cmd
[1] = (fep
->u
.qpsk
.symbol_rate
>> 8) & 0xff;
109 cmd
[2] = (fep
->u
.qpsk
.symbol_rate
>> 16) & 0xff;
110 cmd
[3] = (fep
->u
.qpsk
.symbol_rate
>> 24) & 0xff;
111 cmd
[8] = ADV_MOD_DVB_QPSK
;
112 cmd
[9] = 0x03; /*ADV_MOD_FEC_XXX*/
115 // other modes are unsuported right now
125 gp8psk_usb_out_op(state
->d
,TUNE_8PSK
,0,0,cmd
,10);
127 state
->next_snr_check
= jiffies
;
132 static int gp8psk_fe_get_frontend(struct dvb_frontend
* fe
,
133 struct dvb_frontend_parameters
*fep
)
139 static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend
* fe
,
140 struct dvb_diseqc_master_cmd
*m
)
142 struct gp8psk_fe_state
*st
= fe
->demodulator_priv
;
144 deb_fe("%s\n",__FUNCTION__
);
146 if (gp8psk_usb_out_op(st
->d
,SEND_DISEQC_COMMAND
, m
->msg
[0], 0,
147 m
->msg
, m
->msg_len
)) {
153 static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend
* fe
,
154 fe_sec_mini_cmd_t burst
)
156 struct gp8psk_fe_state
*st
= fe
->demodulator_priv
;
159 deb_fe("%s\n",__FUNCTION__
);
161 /* These commands are certainly wrong */
162 cmd
= (burst
== SEC_MINI_A
) ? 0x00 : 0x01;
164 if (gp8psk_usb_out_op(st
->d
,SEND_DISEQC_COMMAND
, cmd
, 0,
171 static int gp8psk_fe_set_tone (struct dvb_frontend
* fe
, fe_sec_tone_mode_t tone
)
173 struct gp8psk_fe_state
* state
= fe
->demodulator_priv
;
175 if (gp8psk_usb_out_op(state
->d
,SET_22KHZ_TONE
,
176 (tone
== SEC_TONE_ON
), 0, NULL
, 0)) {
182 static int gp8psk_fe_set_voltage (struct dvb_frontend
* fe
, fe_sec_voltage_t voltage
)
184 struct gp8psk_fe_state
* state
= fe
->demodulator_priv
;
186 if (gp8psk_usb_out_op(state
->d
,SET_LNB_VOLTAGE
,
187 voltage
== SEC_VOLTAGE_18
, 0, NULL
, 0)) {
193 static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend
* fe
, unsigned long sw_cmd
)
195 struct gp8psk_fe_state
* state
= fe
->demodulator_priv
;
196 u8 cmd
= sw_cmd
& 0x7f;
198 if (gp8psk_usb_out_op(state
->d
,SET_DN_SWITCH
, cmd
, 0,
202 if (gp8psk_usb_out_op(state
->d
,SET_LNB_VOLTAGE
, !!(sw_cmd
& 0x80),
210 static void gp8psk_fe_release(struct dvb_frontend
* fe
)
212 struct gp8psk_fe_state
*state
= fe
->demodulator_priv
;
216 static struct dvb_frontend_ops gp8psk_fe_ops
;
218 struct dvb_frontend
* gp8psk_fe_attach(struct dvb_usb_device
*d
)
220 struct gp8psk_fe_state
*s
= kzalloc(sizeof(struct gp8psk_fe_state
), GFP_KERNEL
);
225 memcpy(&s
->fe
.ops
, &gp8psk_fe_ops
, sizeof(struct dvb_frontend_ops
));
226 s
->fe
.demodulator_priv
= s
;
236 static struct dvb_frontend_ops gp8psk_fe_ops
= {
238 .name
= "Genpix 8psk-USB DVB-S",
240 .frequency_min
= 950000,
241 .frequency_max
= 2150000,
242 .frequency_stepsize
= 100,
243 .symbol_rate_min
= 1000000,
244 .symbol_rate_max
= 45000000,
245 .symbol_rate_tolerance
= 500, /* ppm */
246 .caps
= FE_CAN_INVERSION_AUTO
|
247 FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
248 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
| FE_CAN_FEC_AUTO
|
252 .release
= gp8psk_fe_release
,
257 .set_frontend
= gp8psk_fe_set_frontend
,
258 .get_frontend
= gp8psk_fe_get_frontend
,
259 .get_tune_settings
= gp8psk_fe_get_tune_settings
,
261 .read_status
= gp8psk_fe_read_status
,
262 .read_ber
= gp8psk_fe_read_ber
,
263 .read_signal_strength
= gp8psk_fe_read_signal_strength
,
264 .read_snr
= gp8psk_fe_read_snr
,
265 .read_ucblocks
= gp8psk_fe_read_unc_blocks
,
267 .diseqc_send_master_cmd
= gp8psk_fe_send_diseqc_msg
,
268 .diseqc_send_burst
= gp8psk_fe_send_diseqc_burst
,
269 .set_tone
= gp8psk_fe_set_tone
,
270 .set_voltage
= gp8psk_fe_set_voltage
,
271 .dishnetwork_send_legacy_command
= gp8psk_fe_send_legacy_dish_cmd
,