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