ec614ea8de224c3587b0c3b4d0d5cf145b05b24b
[linux-2.6-block.git] / drivers / media / dvb / firesat / firesat_fe.c
1 /*
2  * FireDTV driver (formerly known as FireSAT)
3  *
4  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
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
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16
17 #include <dvb_frontend.h>
18
19 #include "avc_api.h"
20 #include "cmp.h"
21 #include "firesat.h"
22
23 static int firesat_dvb_init(struct dvb_frontend *fe)
24 {
25         int result;
26         struct firesat *firesat = fe->sec_priv;
27 //      printk("fdi: 1\n");
28         firesat->isochannel = firesat->adapter->num; //<< 1 | (firesat->subunit & 0x1); // ### ask IRM
29 //      printk("fdi: 2\n");
30         result = try_CMPEstablishPPconnection(firesat, firesat->subunit, firesat->isochannel);
31         if (result != 0) {
32                 printk(KERN_ERR "Could not establish point to point "
33                        "connection.\n");
34                 return -1;
35         }
36 //      printk("fdi: 3\n");
37
38         result = setup_iso_channel(firesat);
39 //      printk("fdi: 4. Result was %d\n", result);
40         return result;
41 }
42
43 static int firesat_sleep(struct dvb_frontend *fe)
44 {
45         struct firesat *firesat = fe->sec_priv;
46
47         tear_down_iso_channel(firesat);
48         try_CMPBreakPPconnection(firesat, firesat->subunit, firesat->isochannel);
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
58         return AVCLNBControl(firesat, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
59                              LNBCONTROL_DONTCARE, 1, cmd);
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
85 static int firesat_read_status (struct dvb_frontend *fe, fe_status_t *status)
86 {
87         struct firesat *firesat = fe->sec_priv;
88         ANTENNA_INPUT_INFO info;
89
90         if (AVCTunerStatus(firesat, &info))
91                 return -EINVAL;
92
93         if (info.NoRF) {
94                 *status = 0;
95         } else {
96                 *status = FE_HAS_SIGNAL |
97                         FE_HAS_VITERBI  |
98                         FE_HAS_SYNC     |
99                         FE_HAS_CARRIER  |
100                         FE_HAS_LOCK;
101         }
102
103         return 0;
104 }
105
106 static int firesat_read_ber(struct dvb_frontend *fe, u32 *ber)
107 {
108         struct firesat *firesat = fe->sec_priv;
109         ANTENNA_INPUT_INFO info;
110
111         if (AVCTunerStatus(firesat, &info))
112                 return -EINVAL;
113
114         *ber = (info.BER[0] << 24) |
115                 (info.BER[1] << 16) |
116                 (info.BER[2] <<  8) |
117                 info.BER[3];
118
119         return 0;
120 }
121
122 static int firesat_read_signal_strength (struct dvb_frontend *fe, u16 *strength)
123 {
124         struct firesat *firesat = fe->sec_priv;
125         ANTENNA_INPUT_INFO info;
126
127         if (AVCTunerStatus(firesat, &info))
128                 return -EINVAL;
129
130         *strength = info.SignalStrength << 8;
131
132         return 0;
133 }
134
135 static int firesat_read_snr(struct dvb_frontend *fe, u16 *snr)
136 {
137         struct firesat *firesat = fe->sec_priv;
138         ANTENNA_INPUT_INFO info;
139
140         if (AVCTunerStatus(firesat, &info))
141                 return -EINVAL;
142
143         *snr = (info.CarrierNoiseRatio[0] << 8) +
144                 info.CarrierNoiseRatio[1];
145         *snr *= 257;
146         // C/N[dB] = -10 * log10(snr / 65535)
147
148         return 0;
149 }
150
151 static int firesat_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
152 {
153         return -EOPNOTSUPP;
154 }
155
156 static int firesat_set_frontend(struct dvb_frontend *fe,
157                                 struct dvb_frontend_parameters *params)
158 {
159         struct firesat *firesat = fe->sec_priv;
160
161         if (AVCTuner_DSD(firesat, params, NULL) != ACCEPTED)
162                 return -EINVAL;
163         else
164                 return 0; //not sure of this...
165 }
166
167 static int firesat_get_frontend(struct dvb_frontend *fe,
168                                 struct dvb_frontend_parameters *params)
169 {
170         return -EOPNOTSUPP;
171 }
172
173 static struct dvb_frontend_info firesat_S_frontend_info;
174 static struct dvb_frontend_info firesat_C_frontend_info;
175 static struct dvb_frontend_info firesat_T_frontend_info;
176
177 static struct dvb_frontend_ops firesat_ops = {
178
179         .init                           = firesat_dvb_init,
180         .sleep                          = firesat_sleep,
181
182         .set_frontend                   = firesat_set_frontend,
183         .get_frontend                   = firesat_get_frontend,
184
185         .read_status                    = firesat_read_status,
186         .read_ber                       = firesat_read_ber,
187         .read_signal_strength           = firesat_read_signal_strength,
188         .read_snr                       = firesat_read_snr,
189         .read_ucblocks                  = firesat_read_uncorrected_blocks,
190
191         .diseqc_send_master_cmd         = firesat_diseqc_send_master_cmd,
192         .diseqc_send_burst              = firesat_diseqc_send_burst,
193         .set_tone                       = firesat_set_tone,
194         .set_voltage                    = firesat_set_voltage,
195 };
196
197 int firesat_frontend_attach(struct firesat *firesat, struct dvb_frontend *fe)
198 {
199         switch (firesat->type) {
200         case FireSAT_DVB_S:
201                 firesat->frontend_info = &firesat_S_frontend_info;
202                 break;
203         case FireSAT_DVB_C:
204                 firesat->frontend_info = &firesat_C_frontend_info;
205                 break;
206         case FireSAT_DVB_T:
207                 firesat->frontend_info = &firesat_T_frontend_info;
208                 break;
209         default:
210                 printk(KERN_ERR "firedtv: no frontend for model type 0x%x\n",
211                        firesat->type);
212                 firesat->frontend_info = NULL;
213         }
214         fe->ops = firesat_ops;
215         fe->ops.info = *(firesat->frontend_info);
216         fe->dvb = firesat->adapter;
217
218         return 0;
219 }
220
221 static struct dvb_frontend_info firesat_S_frontend_info = {
222
223         .name                   = "FireDTV DVB-S Frontend",
224         .type                   = FE_QPSK,
225
226         .frequency_min          = 950000,
227         .frequency_max          = 2150000,
228         .frequency_stepsize     = 125,
229         .symbol_rate_min        = 1000000,
230         .symbol_rate_max        = 40000000,
231
232         .caps                   = FE_CAN_INVERSION_AUTO         |
233                                   FE_CAN_FEC_1_2                |
234                                   FE_CAN_FEC_2_3                |
235                                   FE_CAN_FEC_3_4                |
236                                   FE_CAN_FEC_5_6                |
237                                   FE_CAN_FEC_7_8                |
238                                   FE_CAN_FEC_AUTO               |
239                                   FE_CAN_QPSK,
240 };
241
242 static struct dvb_frontend_info firesat_C_frontend_info = {
243
244         .name                   = "FireDTV DVB-C Frontend",
245         .type                   = FE_QAM,
246
247         .frequency_min          = 47000000,
248         .frequency_max          = 866000000,
249         .frequency_stepsize     = 62500,
250         .symbol_rate_min        = 870000,
251         .symbol_rate_max        = 6900000,
252
253         .caps                   = FE_CAN_INVERSION_AUTO         |
254                                   FE_CAN_QAM_16                 |
255                                   FE_CAN_QAM_32                 |
256                                   FE_CAN_QAM_64                 |
257                                   FE_CAN_QAM_128                |
258                                   FE_CAN_QAM_256                |
259                                   FE_CAN_QAM_AUTO,
260 };
261
262 static struct dvb_frontend_info firesat_T_frontend_info = {
263
264         .name                   = "FireDTV DVB-T Frontend",
265         .type                   = FE_OFDM,
266
267         .frequency_min          = 49000000,
268         .frequency_max          = 861000000,
269         .frequency_stepsize     = 62500,
270
271         .caps                   = FE_CAN_INVERSION_AUTO         |
272                                   FE_CAN_FEC_2_3                |
273                                   FE_CAN_TRANSMISSION_MODE_AUTO |
274                                   FE_CAN_GUARD_INTERVAL_AUTO    |
275                                   FE_CAN_HIERARCHY_AUTO,
276 };