Commit | Line | Data |
---|---|---|
df4846c3 | 1 | /* |
612262a5 | 2 | * FireDTV driver (formerly known as FireSAT) |
df4846c3 | 3 | * |
612262a5 SR |
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> |
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | |
df4846c3 HK |
6 | * |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | */ | |
12 | ||
c81c8b68 | 13 | #include <linux/errno.h> |
612262a5 | 14 | #include <linux/kernel.h> |
8ae83cdf | 15 | #include <linux/string.h> |
612262a5 SR |
16 | #include <linux/types.h> |
17 | ||
18 | #include <dvb_frontend.h> | |
c81c8b68 | 19 | |
c81c8b68 GKH |
20 | #include "avc_api.h" |
21 | #include "cmp.h" | |
612262a5 | 22 | #include "firesat.h" |
c81c8b68 GKH |
23 | |
24 | static int firesat_dvb_init(struct dvb_frontend *fe) | |
25 | { | |
26 | struct firesat *firesat = fe->sec_priv; | |
8ae83cdf SR |
27 | int err; |
28 | ||
29 | /* FIXME - allocate free channel at IRM */ | |
30 | firesat->isochannel = firesat->adapter.num; | |
31 | ||
32 | err = cmp_establish_pp_connection(firesat, firesat->subunit, | |
33 | firesat->isochannel); | |
34 | if (err) { | |
df4846c3 HK |
35 | printk(KERN_ERR "Could not establish point to point " |
36 | "connection.\n"); | |
8ae83cdf | 37 | return err; |
df4846c3 | 38 | } |
df4846c3 | 39 | |
8ae83cdf | 40 | return setup_iso_channel(firesat); |
c81c8b68 GKH |
41 | } |
42 | ||
43 | static int firesat_sleep(struct dvb_frontend *fe) | |
44 | { | |
45 | struct firesat *firesat = fe->sec_priv; | |
46 | ||
df4846c3 | 47 | tear_down_iso_channel(firesat); |
8ae83cdf | 48 | cmp_break_pp_connection(firesat, firesat->subunit, firesat->isochannel); |
c81c8b68 GKH |
49 | firesat->isochannel = -1; |
50 | return 0; | |
51 | } | |
52 | ||
53 | static int firesat_diseqc_send_master_cmd(struct dvb_frontend *fe, | |
54 | struct dvb_diseqc_master_cmd *cmd) | |
55 | { | |
56 | struct firesat *firesat = fe->sec_priv; | |
57 | ||
8ae83cdf SR |
58 | return avc_lnb_control(firesat, LNBCONTROL_DONTCARE, |
59 | LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd); | |
c81c8b68 GKH |
60 | } |
61 | ||
62 | static int firesat_diseqc_send_burst(struct dvb_frontend *fe, | |
63 | fe_sec_mini_cmd_t minicmd) | |
64 | { | |
65 | return 0; | |
66 | } | |
67 | ||
68 | static int firesat_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | |
69 | { | |
70 | struct firesat *firesat = fe->sec_priv; | |
71 | ||
72 | firesat->tone = tone; | |
73 | return 0; | |
74 | } | |
75 | ||
76 | static int firesat_set_voltage(struct dvb_frontend *fe, | |
77 | fe_sec_voltage_t voltage) | |
78 | { | |
79 | struct firesat *firesat = fe->sec_priv; | |
80 | ||
81 | firesat->voltage = voltage; | |
82 | return 0; | |
83 | } | |
84 | ||
8ae83cdf | 85 | static int firesat_read_status(struct dvb_frontend *fe, fe_status_t *status) |
c81c8b68 GKH |
86 | { |
87 | struct firesat *firesat = fe->sec_priv; | |
88 | ANTENNA_INPUT_INFO info; | |
89 | ||
8ae83cdf | 90 | if (avc_tuner_status(firesat, &info)) |
c81c8b68 GKH |
91 | return -EINVAL; |
92 | ||
8ae83cdf | 93 | if (info.NoRF) |
c81c8b68 | 94 | *status = 0; |
8ae83cdf SR |
95 | else |
96 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | | |
97 | FE_HAS_CARRIER | FE_HAS_LOCK; | |
c81c8b68 GKH |
98 | return 0; |
99 | } | |
100 | ||
df4846c3 | 101 | static int firesat_read_ber(struct dvb_frontend *fe, u32 *ber) |
c81c8b68 GKH |
102 | { |
103 | struct firesat *firesat = fe->sec_priv; | |
104 | ANTENNA_INPUT_INFO info; | |
105 | ||
8ae83cdf | 106 | if (avc_tuner_status(firesat, &info)) |
c81c8b68 GKH |
107 | return -EINVAL; |
108 | ||
8ae83cdf SR |
109 | *ber = info.BER[0] << 24 | info.BER[1] << 16 | |
110 | info.BER[2] << 8 | info.BER[3]; | |
c81c8b68 GKH |
111 | return 0; |
112 | } | |
113 | ||
114 | static int firesat_read_signal_strength (struct dvb_frontend *fe, u16 *strength) | |
115 | { | |
116 | struct firesat *firesat = fe->sec_priv; | |
117 | ANTENNA_INPUT_INFO info; | |
c81c8b68 | 118 | |
8ae83cdf | 119 | if (avc_tuner_status(firesat, &info)) |
c81c8b68 GKH |
120 | return -EINVAL; |
121 | ||
df4846c3 | 122 | *strength = info.SignalStrength << 8; |
c81c8b68 GKH |
123 | return 0; |
124 | } | |
125 | ||
126 | static int firesat_read_snr(struct dvb_frontend *fe, u16 *snr) | |
127 | { | |
df4846c3 HK |
128 | struct firesat *firesat = fe->sec_priv; |
129 | ANTENNA_INPUT_INFO info; | |
130 | ||
8ae83cdf | 131 | if (avc_tuner_status(firesat, &info)) |
df4846c3 HK |
132 | return -EINVAL; |
133 | ||
8ae83cdf SR |
134 | /* C/N[dB] = -10 * log10(snr / 65535) */ |
135 | *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1]; | |
df4846c3 | 136 | *snr *= 257; |
df4846c3 | 137 | return 0; |
c81c8b68 GKH |
138 | } |
139 | ||
140 | static int firesat_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks) | |
141 | { | |
142 | return -EOPNOTSUPP; | |
143 | } | |
144 | ||
145 | static int firesat_set_frontend(struct dvb_frontend *fe, | |
146 | struct dvb_frontend_parameters *params) | |
147 | { | |
148 | struct firesat *firesat = fe->sec_priv; | |
149 | ||
8ae83cdf SR |
150 | /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */ |
151 | if (avc_tuner_dsd(firesat, params) != ACCEPTED) | |
c81c8b68 GKH |
152 | return -EINVAL; |
153 | else | |
8ae83cdf | 154 | return 0; /* not sure of this... */ |
c81c8b68 GKH |
155 | } |
156 | ||
157 | static int firesat_get_frontend(struct dvb_frontend *fe, | |
158 | struct dvb_frontend_parameters *params) | |
159 | { | |
160 | return -EOPNOTSUPP; | |
161 | } | |
162 | ||
8ae83cdf SR |
163 | void firesat_frontend_init(struct firesat *firesat) |
164 | { | |
165 | struct dvb_frontend_ops *ops = &firesat->fe.ops; | |
166 | struct dvb_frontend_info *fi = &ops->info; | |
c81c8b68 | 167 | |
8ae83cdf SR |
168 | ops->init = firesat_dvb_init; |
169 | ops->sleep = firesat_sleep; | |
c81c8b68 | 170 | |
8ae83cdf SR |
171 | ops->set_frontend = firesat_set_frontend; |
172 | ops->get_frontend = firesat_get_frontend; | |
c81c8b68 | 173 | |
8ae83cdf SR |
174 | ops->read_status = firesat_read_status; |
175 | ops->read_ber = firesat_read_ber; | |
176 | ops->read_signal_strength = firesat_read_signal_strength; | |
177 | ops->read_snr = firesat_read_snr; | |
178 | ops->read_ucblocks = firesat_read_uncorrected_blocks; | |
c81c8b68 | 179 | |
8ae83cdf SR |
180 | ops->diseqc_send_master_cmd = firesat_diseqc_send_master_cmd; |
181 | ops->diseqc_send_burst = firesat_diseqc_send_burst; | |
182 | ops->set_tone = firesat_set_tone; | |
183 | ops->set_voltage = firesat_set_voltage; | |
c81c8b68 | 184 | |
c81c8b68 GKH |
185 | switch (firesat->type) { |
186 | case FireSAT_DVB_S: | |
8ae83cdf SR |
187 | fi->type = FE_QPSK; |
188 | ||
189 | fi->frequency_min = 950000; | |
190 | fi->frequency_max = 2150000; | |
191 | fi->frequency_stepsize = 125; | |
192 | fi->symbol_rate_min = 1000000; | |
193 | fi->symbol_rate_max = 40000000; | |
194 | ||
195 | fi->caps = FE_CAN_INVERSION_AUTO | | |
196 | FE_CAN_FEC_1_2 | | |
197 | FE_CAN_FEC_2_3 | | |
198 | FE_CAN_FEC_3_4 | | |
199 | FE_CAN_FEC_5_6 | | |
200 | FE_CAN_FEC_7_8 | | |
201 | FE_CAN_FEC_AUTO | | |
202 | FE_CAN_QPSK; | |
c81c8b68 | 203 | break; |
8ae83cdf | 204 | |
c81c8b68 | 205 | case FireSAT_DVB_C: |
8ae83cdf SR |
206 | fi->type = FE_QAM; |
207 | ||
208 | fi->frequency_min = 47000000; | |
209 | fi->frequency_max = 866000000; | |
210 | fi->frequency_stepsize = 62500; | |
211 | fi->symbol_rate_min = 870000; | |
212 | fi->symbol_rate_max = 6900000; | |
213 | ||
214 | fi->caps = FE_CAN_INVERSION_AUTO | | |
215 | FE_CAN_QAM_16 | | |
216 | FE_CAN_QAM_32 | | |
217 | FE_CAN_QAM_64 | | |
218 | FE_CAN_QAM_128 | | |
219 | FE_CAN_QAM_256 | | |
220 | FE_CAN_QAM_AUTO; | |
c81c8b68 | 221 | break; |
8ae83cdf | 222 | |
c81c8b68 | 223 | case FireSAT_DVB_T: |
8ae83cdf SR |
224 | fi->type = FE_OFDM; |
225 | ||
226 | fi->frequency_min = 49000000; | |
227 | fi->frequency_max = 861000000; | |
228 | fi->frequency_stepsize = 62500; | |
229 | ||
230 | fi->caps = FE_CAN_INVERSION_AUTO | | |
231 | FE_CAN_FEC_2_3 | | |
232 | FE_CAN_TRANSMISSION_MODE_AUTO | | |
233 | FE_CAN_GUARD_INTERVAL_AUTO | | |
234 | FE_CAN_HIERARCHY_AUTO; | |
c81c8b68 | 235 | break; |
8ae83cdf | 236 | |
c81c8b68 | 237 | default: |
8ae83cdf | 238 | printk(KERN_ERR "FireDTV: no frontend for model type %d\n", |
612262a5 | 239 | firesat->type); |
c81c8b68 | 240 | } |
8ae83cdf | 241 | strcpy(fi->name, firedtv_model_names[firesat->type]); |
c81c8b68 | 242 | |
8ae83cdf SR |
243 | firesat->fe.dvb = &firesat->adapter; |
244 | firesat->fe.sec_priv = firesat; | |
c81c8b68 | 245 | } |